diff --git a/chains/aztec/contracts/train/Nargo.toml b/chains/aztec/contracts/train/Nargo.toml index 1089196..d4797b2 100644 --- a/chains/aztec/contracts/train/Nargo.toml +++ b/chains/aztec/contracts/train/Nargo.toml @@ -5,6 +5,6 @@ authors = [""] compiler_version = ">=0.25.0" [dependencies] -aztec = { git="https://github.com/AztecProtocol/aztec-packages/", tag="v3.0.0-devnet.2", directory="noir-projects/aztec-nr/aztec" } -token = { git="https://github.com/AztecProtocol/aztec-packages/", tag="v3.0.0-devnet.2", directory="noir-projects/noir-contracts/contracts/app/token_contract" } +aztec = { git="https://github.com/AztecProtocol/aztec-packages/", tag="v3.0.0-devnet.20251212", directory="noir-projects/aztec-nr/aztec" } +token = { git="https://github.com/AztecProtocol/aztec-packages/", tag="v3.0.0-devnet.20251212", directory="noir-projects/noir-contracts/contracts/app/token_contract" } sha256 = { tag = "v0.2.1", git = "https://github.com/noir-lang/sha256" } \ No newline at end of file diff --git a/chains/aztec/contracts/train/src/main.nr b/chains/aztec/contracts/train/src/main.nr index b7da577..19a637a 100644 --- a/chains/aztec/contracts/train/src/main.nr +++ b/chains/aztec/contracts/train/src/main.nr @@ -9,7 +9,6 @@ // @@@@@ @@@ @@@@@@@@@ @@@ @@@ @@@ @@@ mod lib; -mod types; use dep::aztec::macros::aztec; #[aztec] @@ -17,6 +16,7 @@ pub contract Train { use std::meta::derive; use aztec::macros::{ + events::event, functions::{external, initializer, view}, storage::storage, }; @@ -29,7 +29,54 @@ pub contract Train { use dep::token::Token; use crate::lib::{bytes_to_u128_limbs, u128_limbs_to_bytes}; - use crate::types::events::{DstLocked, SrcLocked, TokenRedeemed, TokenRefunded}; + + // Events + #[event] + pub struct SrcLocked { + pub swap_id: Field, + pub hashlock: [u8; 32], + pub dst_chain: str<30>, + pub dst_address: str<90>, + pub dst_asset: str<30>, + pub sender: AztecAddress, + pub src_receiver: AztecAddress, + pub src_asset: str<30>, + pub amount: u128, + pub timelock: u64, + } + + #[event] + pub struct DstLocked { + pub swap_id: Field, + pub htlc_id: Field, + pub hashlock: [u8; 32], + pub dst_chain: str<30>, + pub dst_address: str<90>, + pub dst_asset: str<30>, + pub sender: AztecAddress, + pub src_receiver: AztecAddress, + pub src_asset: str<30>, + pub amount: u128, + pub reward: u128, + pub reward_timelock: u64, + pub timelock: u64, + } + + #[event] + pub struct TokenRefunded { + pub swap_id: Field, + pub htlc_id: Field, + } + + #[event] + pub struct TokenRedeemed { + pub swap_id: Field, + pub htlc_id: Field, + pub redeem_address: AztecAddress, + pub secret_high: u128, + pub secret_low: u128, + pub hashlock: [u8; 32], + } #[derive(Eq, Packable, Serialize, Deserialize)] pub struct HTLC_Public { @@ -74,12 +121,12 @@ pub contract Train { ) { assert(amount > 0, "FundsNotSent"); - let htlc_public_current = storage.contracts.at(swap_id).at(0).read(); + let htlc_public_current = self.storage.contracts.at(swap_id).at(0).read(); assert(htlc_public_current.sender == AztecAddress::zero(), "SwapAlreadyInitialized"); - assert(context.timestamp() + 1800 < timelock, "InvalidTimelock"); + assert(self.context.timestamp() + 1800 < timelock, "InvalidTimelock"); let hashlock_tuple = (hashlock_high, hashlock_low); - let sender = context.msg_sender().expect(f"Sender must not be none!"); + let sender = self.msg_sender().expect(f"Sender must not be none!"); let htlc_public = HTLC_Public { amount: amount, token: token, @@ -94,16 +141,15 @@ pub contract Train { reward: 0 as u128, reward_timelock: 0 as u64, }; - storage.contracts.at(swap_id).at(0).write(htlc_public); + self.storage.contracts.at(swap_id).at(0).write(htlc_public); // Transfer tokens from sender to contract - Token::at(token).transfer_in_public(sender, context.this_address(), amount, 0).call(&mut context); + self.call(Token::at(token).transfer_in_public(sender, self.address, amount, 0)); // Track this swap for the user - let sender = context.msg_sender().expect(f"Sender must not be none!"); - let current_count = storage.user_swaps_count.at(sender).read(); - storage.user_swaps.at(sender).at(current_count).write(swap_id); - storage.user_swaps_count.at(sender).write(current_count + 1); + let current_count = self.storage.user_swaps_count.at(sender).read(); + self.storage.user_swaps.at(sender).at(current_count).write(swap_id); + self.storage.user_swaps_count.at(sender).write(current_count + 1); let hashlock = u128_limbs_to_bytes(hashlock_high, hashlock_low); let log_msg = SrcLocked { @@ -112,21 +158,21 @@ pub contract Train { dst_chain: dst_chain, dst_address: dst_address, dst_asset: dst_asset, - sender: context.msg_sender().expect(f"Sender must not be none!"), + sender: sender, src_receiver: src_receiver, src_asset: src_asset, amount: amount, timelock: timelock, }; - context.emit_public_log(log_msg.pack()); + self.emit(log_msg); } #[external("public")] fn refund(swap_id: Field, htlc_id: Field) { - let htlc_public = storage.contracts.at(swap_id).at(htlc_id).read(); + let htlc_public = self.storage.contracts.at(swap_id).at(htlc_id).read(); assert(htlc_public.claimed == 1, "AlreadyClaimed"); - assert(htlc_public.timelock < context.timestamp(), "NotPassedTimelock"); + assert(htlc_public.timelock < self.context.timestamp(), "NotPassedTimelock"); let refund_amount = if htlc_public.reward != 0 { htlc_public.amount + htlc_public.reward @@ -135,13 +181,13 @@ pub contract Train { }; // Transfer tokens back to sender - Token::at(htlc_public.token).transfer_in_public( - context.this_address(), + self.call(Token::at(htlc_public.token).transfer_in_public( + self.address, htlc_public.sender, refund_amount, 0 - ).call(&mut context); - + )); + let modified_htlc_public = HTLC_Public { amount: htlc_public.amount, token: htlc_public.token, @@ -157,9 +203,9 @@ pub contract Train { reward_timelock: htlc_public.reward_timelock, }; - storage.contracts.at(swap_id).at(htlc_id).write(modified_htlc_public); + self.storage.contracts.at(swap_id).at(htlc_id).write(modified_htlc_public); let log_msg = TokenRefunded { swap_id, htlc_id }; - context.emit_public_log(log_msg.pack()); + self.emit(log_msg); } #[external("public")] @@ -187,14 +233,14 @@ pub contract Train { // Enforce reward >= 10% of amount: reward * 10 >= amount assert(reward * 10 >= amount, "InvalidRewardAmount"); - let htlc_public_current = storage.contracts.at(swap_id).at(htlc_id).read(); + let htlc_public_current = self.storage.contracts.at(swap_id).at(htlc_id).read(); assert(htlc_public_current.sender == AztecAddress::zero(), "HTLCAlreadyExists"); - assert(context.timestamp() + 900 < timelock, "InvalidTimelock"); + assert(self.context.timestamp() + 900 < timelock, "InvalidTimelock"); assert(reward_timelock <= timelock, "InvalidRewardTimelock"); - assert(reward_timelock > context.timestamp(), "InvalidRewardTimelock"); + assert(reward_timelock > self.context.timestamp(), "InvalidRewardTimelock"); let hashlock_tuple = (hashlock_high, hashlock_low); - let sender = context.msg_sender().expect(f"Sender must not be none!"); + let sender = self.msg_sender().expect(f"Sender must not be none!"); let htlc_public = HTLC_Public { amount: amount, token: token, @@ -209,10 +255,10 @@ pub contract Train { reward: reward, reward_timelock: reward_timelock, }; - storage.contracts.at(swap_id).at(htlc_id).write(htlc_public); + self.storage.contracts.at(swap_id).at(htlc_id).write(htlc_public); // Transfer tokens from sender to contract - Token::at(token).transfer_in_public(sender, context.this_address(), total_amount, 0).call(&mut context); + self.call(Token::at(token).transfer_in_public(sender, self.address, total_amount, 0)); let hashlock = u128_limbs_to_bytes(hashlock_high, hashlock_low); let log_msg = DstLocked { @@ -222,7 +268,7 @@ pub contract Train { dst_chain: dst_chain, dst_address: dst_address, dst_asset: dst_asset, - sender: context.msg_sender().expect(f"Sender must not be none!"), + sender: sender, src_receiver: src_receiver, src_asset: src_asset, amount: amount, @@ -231,15 +277,15 @@ pub contract Train { timelock: timelock, }; - context.emit_public_log(log_msg.pack()); + self.emit(log_msg); } #[external("public")] fn redeem(swap_id: Field, htlc_id: Field, secret_high: u128, secret_low: u128) { let secret = u128_limbs_to_bytes(secret_high, secret_low); - let caller = context.msg_sender().expect(f"Sender must not be none!"); + let caller = self.msg_sender().expect(f"Sender must not be none!"); - let mut htlc_public = storage.contracts.at(swap_id).at(htlc_id).read(); + let htlc_public = self.storage.contracts.at(swap_id).at(htlc_id).read(); assert(htlc_public.amount > 0, "HTLCNotExists"); let hashed_secret = sha256::sha256_var(secret, secret.len() as u64); let hashed_secret_tuple = bytes_to_u128_limbs(hashed_secret); @@ -264,55 +310,55 @@ pub contract Train { reward_timelock: htlc_public.reward_timelock, }; - storage.contracts.at(swap_id).at(htlc_id).write(modified_htlc_public); + self.storage.contracts.at(swap_id).at(htlc_id).write(modified_htlc_public); // Handle token transfers based on reward logic if htlc_public.reward == 0 { // No reward: transfer amount to src_receiver - Token::at(htlc_public.token).transfer_in_public( - context.this_address(), + self.call(Token::at(htlc_public.token).transfer_in_public( + self.address, htlc_public.src_receiver, htlc_public.amount, 0 - ).call(&mut context); - } else if htlc_public.reward_timelock > context.timestamp() { + )); + } else if htlc_public.reward_timelock > self.context.timestamp() { // Before reward timelock: amount to src_receiver, reward back to sender - Token::at(htlc_public.token).transfer_in_public( - context.this_address(), + self.call(Token::at(htlc_public.token).transfer_in_public( + self.address, htlc_public.src_receiver, htlc_public.amount, 0 - ).call(&mut context); - Token::at(htlc_public.token).transfer_in_public( - context.this_address(), + )); + self.call(Token::at(htlc_public.token).transfer_in_public( + self.address, htlc_public.sender, htlc_public.reward, 0 - ).call(&mut context); + )); } else { // After reward timelock if caller == htlc_public.src_receiver { // src_receiver gets amount + reward - Token::at(htlc_public.token).transfer_in_public( - context.this_address(), + self.call(Token::at(htlc_public.token).transfer_in_public( + self.address, htlc_public.src_receiver, htlc_public.amount + htlc_public.reward, 0 - ).call(&mut context); + )); } else { // amount to src_receiver, reward to caller - Token::at(htlc_public.token).transfer_in_public( - context.this_address(), + self.call(Token::at(htlc_public.token).transfer_in_public( + self.address, htlc_public.src_receiver, htlc_public.amount, 0 - ).call(&mut context); - Token::at(htlc_public.token).transfer_in_public( - context.this_address(), + )); + self.call(Token::at(htlc_public.token).transfer_in_public( + self.address, caller, htlc_public.reward, 0 - ).call(&mut context); + )); } } @@ -325,25 +371,25 @@ pub contract Train { hashlock: u128_limbs_to_bytes(htlc_public.hashlock_high, htlc_public.hashlock_low), }; - context.emit_public_log(log_msg.pack()); + self.emit(log_msg); } #[external("public")] #[view] fn has_htlc(swap_id: Field, htlc_id: Field) -> pub bool { - let htlc = storage.contracts.at(swap_id).at(htlc_id).read(); + let htlc = self.storage.contracts.at(swap_id).at(htlc_id).read(); htlc.sender != AztecAddress::zero() } #[external("public")] #[view] fn get_htlc(swap_id: Field, htlc_id: Field) -> pub HTLC_Public { - storage.contracts.at(swap_id).at(htlc_id).read() + self.storage.contracts.at(swap_id).at(htlc_id).read() } #[external("public")] #[view] fn get_user_swaps_count(user: AztecAddress) -> pub Field { - storage.user_swaps_count.at(user).read() + self.storage.user_swaps_count.at(user).read() } } diff --git a/chains/aztec/contracts/train/src/types.nr b/chains/aztec/contracts/train/src/types.nr deleted file mode 100644 index 7b505fc..0000000 --- a/chains/aztec/contracts/train/src/types.nr +++ /dev/null @@ -1 +0,0 @@ -pub(crate) mod events; diff --git a/chains/aztec/contracts/train/src/types/events.nr b/chains/aztec/contracts/train/src/types/events.nr deleted file mode 100644 index 5e54b30..0000000 --- a/chains/aztec/contracts/train/src/types/events.nr +++ /dev/null @@ -1,233 +0,0 @@ -use crate::lib::{bytes_to_u128_limbs, u128_limbs_to_bytes}; -use dep::aztec::protocol_types::address::AztecAddress; -use dep::aztec::protocol_types::traits::{FromField, Packable, Serialize}; - -#[derive(Serialize)] -pub struct SrcLocked { - pub swap_id: Field, - pub hashlock: [u8; 32], - pub dst_chain: str<30>, - pub dst_address: str<90>, - pub dst_asset: str<30>, - pub sender: AztecAddress, - pub src_receiver: AztecAddress, - pub src_asset: str<30>, - pub amount: u128, - pub timelock: u64, -} - -impl Packable for SrcLocked { - let N: u32 = 13; - fn pack(self) -> [Field; Self::N] { - let zero: Field = 0; - let mut out = [zero; 13]; - out[0] = 0x1A2B3C4D; // Event signature - out[1] = self.swap_id; - - let (hashlock_high, hashlock_low) = bytes_to_u128_limbs(self.hashlock); - out[2] = hashlock_high as Field; - out[3] = hashlock_low as Field; - - out[4] = self.sender.inner; - out[5] = self.src_receiver.inner; - out[6] = self.amount as Field; - out[7] = self.timelock as Field; - - let src_asset_byte_array = self.src_asset.as_bytes(); - let mut src_asset_byte_array_filled = [0 as u8; 30]; - for i in 0..src_asset_byte_array.len() { - src_asset_byte_array_filled[i] = src_asset_byte_array[i]; - } - out[8] = Field::from_be_bytes::<30>(src_asset_byte_array_filled); - - let dst_chain_byte_array = self.dst_chain.as_bytes(); - let mut dst_chain_byte_array_filled = [0 as u8; 30]; - for i in 0..dst_chain_byte_array.len() { - dst_chain_byte_array_filled[i] = dst_chain_byte_array[i]; - } - out[9] = Field::from_be_bytes::<30>(dst_chain_byte_array_filled); - - let dst_asset_byte_array = self.dst_asset.as_bytes(); - let mut dst_asset_byte_array_filled = [0 as u8; 30]; - for i in 0..dst_asset_byte_array.len() { - dst_asset_byte_array_filled[i] = dst_asset_byte_array[i]; - } - out[10] = Field::from_be_bytes::<30>(dst_asset_byte_array_filled); - - let dst_address_byte_array = self.dst_address.as_bytes(); - let mut dst_address_byte_array_filled_1 = [0 as u8; 30]; - let mut dst_address_byte_array_filled_2 = [0 as u8; 30]; - let mut dst_address_byte_array_filled_3 = [0 as u8; 30]; - - for i in 0..30 { - dst_address_byte_array_filled_1[i] = dst_address_byte_array[i]; - dst_address_byte_array_filled_2[i] = dst_address_byte_array[i + 30]; - dst_address_byte_array_filled_3[i] = dst_address_byte_array[i + 60]; - } - - out[11] = Field::from_be_bytes::<30>(dst_address_byte_array_filled_2); - out[12] = Field::from_be_bytes::<30>(dst_address_byte_array_filled_3); - out - } - - fn unpack(fields: [Field; Self::N]) -> Self { - assert(false, "unpack not implemented"); - SrcLocked { - swap_id: fields[1], - hashlock: [0 as u8; 32], - dst_chain: "000000000000000000000000000000", - dst_address: "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - dst_asset: "000000000000000000000000000000", - sender: AztecAddress::zero(), - src_receiver: AztecAddress::zero(), - src_asset: "000000000000000000000000000000", - amount: 0 as u128, - timelock: 0 as u64, - } - } -} - -#[derive(Serialize)] -pub struct DstLocked { - pub swap_id: Field, - pub htlc_id: Field, - pub hashlock: [u8; 32], - pub dst_chain: str<30>, - pub dst_address: str<90>, - pub dst_asset: str<30>, - pub sender: AztecAddress, - pub src_receiver: AztecAddress, - pub src_asset: str<30>, - pub amount: u128, - pub reward: u128, - pub reward_timelock: u64, - pub timelock: u64, -} - -impl Packable for DstLocked { - let N: u32 = 15; - fn pack(self) -> [Field; Self::N] { - let zero: Field = 0; - let mut out = [zero; 15]; - out[0] = 0x2B3C4D5E; // Event signature - out[1] = self.swap_id; - out[2] = self.htlc_id; - - let (hashlock_high, hashlock_low) = bytes_to_u128_limbs(self.hashlock); - out[3] = hashlock_high as Field; - out[4] = hashlock_low as Field; - - out[5] = self.sender.inner; - out[6] = self.src_receiver.inner; - out[7] = self.amount as Field; - out[8] = self.reward as Field; - out[9] = self.reward_timelock as Field; - out[10] = self.timelock as Field; - - let src_asset_byte_array = self.src_asset.as_bytes(); - let mut src_asset_byte_array_filled = [0 as u8; 30]; - for i in 0..src_asset_byte_array.len() { - src_asset_byte_array_filled[i] = src_asset_byte_array[i]; - } - out[11] = Field::from_be_bytes::<30>(src_asset_byte_array_filled); - - let dst_chain_byte_array = self.dst_chain.as_bytes(); - let mut dst_chain_byte_array_filled = [0 as u8; 30]; - for i in 0..dst_chain_byte_array.len() { - dst_chain_byte_array_filled[i] = dst_chain_byte_array[i]; - } - out[12] = Field::from_be_bytes::<30>(dst_chain_byte_array_filled); - - let dst_asset_byte_array = self.dst_asset.as_bytes(); - let mut dst_asset_byte_array_filled = [0 as u8; 30]; - for i in 0..dst_asset_byte_array.len() { - dst_asset_byte_array_filled[i] = dst_asset_byte_array[i]; - } - out[13] = Field::from_be_bytes::<30>(dst_asset_byte_array_filled); - - // Note: dst_address omitted for brevity in this packed format - out[14] = 0; - out - } - - fn unpack(fields: [Field; Self::N]) -> Self { - assert(false, "unpack not implemented"); - DstLocked { - swap_id: fields[1], - htlc_id: fields[2], - hashlock: [0 as u8; 32], - dst_chain: "000000000000000000000000000000", - dst_address: "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - dst_asset: "000000000000000000000000000000", - sender: AztecAddress::zero(), - src_receiver: AztecAddress::zero(), - src_asset: "000000000000000000000000000000", - amount: 0 as u128, - reward: 0 as u128, - reward_timelock: 0 as u64, - timelock: 0 as u64, - } - } -} - -#[derive(Serialize)] -pub struct TokenRefunded { - pub swap_id: Field, - pub htlc_id: Field, -} - -impl Packable for TokenRefunded { - let N: u32 = 3; - fn pack(self) -> [Field; Self::N] { - let mut out = [0 as Field; 3]; - out[0] = 0x2D17C6B8; - out[1] = self.swap_id; - out[2] = self.htlc_id; - out - } - - fn unpack(fields: [Field; Self::N]) -> Self { - TokenRefunded { swap_id: fields[1], htlc_id: fields[2] } - } -} - -#[derive(Serialize)] -pub struct TokenRedeemed { - pub swap_id: Field, - pub htlc_id: Field, - pub redeem_address: AztecAddress, - pub secret_high: u128, - pub secret_low: u128, - pub hashlock: [u8; 32], -} - -impl Packable for TokenRedeemed { - let N: u32 = 8; - fn pack(self) -> [Field; Self::N] { - let mut out = [0 as Field; 8]; - out[0] = 0x4F8B9A3E; - out[1] = self.swap_id; - out[2] = self.htlc_id; - out[3] = self.redeem_address.inner; - - out[4] = self.secret_high as Field; - out[5] = self.secret_low as Field; - - let (hashlock_high, hashlock_low) = bytes_to_u128_limbs(self.hashlock); - out[6] = hashlock_high as Field; - out[7] = hashlock_low as Field; - - out - } - - fn unpack(fields: [Field; Self::N]) -> Self { - let swap_id = fields[1]; - let htlc_id = fields[2]; - let redeem_address = AztecAddress::from_field(fields[3]); - let secret_high = fields[4] as u128; - let secret_low = fields[5] as u128; - let hashlock = u128_limbs_to_bytes(fields[6] as u128, fields[7] as u128); - - TokenRedeemed { swap_id, htlc_id, redeem_address, secret_high, secret_low, hashlock } - } -} diff --git a/chains/aztec/contracts/train/target/train-Train.json b/chains/aztec/contracts/train/target/train-Train.json index 27702db..bf23636 100644 --- a/chains/aztec/contracts/train/target/train-Train.json +++ b/chains/aztec/contracts/train/target/train-Train.json @@ -1 +1,2905 @@ -{"transpiled":true,"noir_version":"1.0.0-beta.14+82ec52a8c755d30ce655a2005834186a4acfa0c7-aztec","name":"Train","functions":[{"name":"constructor","is_unconstrained":true,"custom_attributes":["external","initializer","public"],"abi":{"parameters":[],"return_type":null,"error_types":{"9967937311635654895":{"error_kind":"string","string":"Initialization hash does not match"},"14415304921900233953":{"error_kind":"string","string":"Initializer address is not the contract deployer"},"14990209321349310352":{"error_kind":"string","string":"attempt to add with overflow"},"15764276373176857197":{"error_kind":"string","string":"Stack too deep"},"16431471497789672479":{"error_kind":"string","string":"Index out of bounds"}}},"bytecode":"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","debug_symbols":"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"},{"name":"get_htlc","is_unconstrained":true,"custom_attributes":["external","view","public"],"abi":{"parameters":[{"name":"swap_id","type":{"kind":"field"},"visibility":"private"},{"name":"htlc_id","type":{"kind":"field"},"visibility":"private"}],"return_type":{"abi_type":{"kind":"struct","path":"Train::HTLC_Public","fields":[{"name":"amount","type":{"kind":"integer","sign":"unsigned","width":128}},{"name":"token","type":{"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress","fields":[{"name":"inner","type":{"kind":"field"}}]}},{"name":"hashlock_high","type":{"kind":"integer","sign":"unsigned","width":128}},{"name":"hashlock_low","type":{"kind":"integer","sign":"unsigned","width":128}},{"name":"secret_high","type":{"kind":"integer","sign":"unsigned","width":128}},{"name":"secret_low","type":{"kind":"integer","sign":"unsigned","width":128}},{"name":"sender","type":{"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress","fields":[{"name":"inner","type":{"kind":"field"}}]}},{"name":"src_receiver","type":{"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress","fields":[{"name":"inner","type":{"kind":"field"}}]}},{"name":"timelock","type":{"kind":"integer","sign":"unsigned","width":64}},{"name":"claimed","type":{"kind":"integer","sign":"unsigned","width":8}},{"name":"reward","type":{"kind":"integer","sign":"unsigned","width":128}},{"name":"reward_timelock","type":{"kind":"integer","sign":"unsigned","width":64}}]},"visibility":"public"},"error_types":{"459713770342432051":{"error_kind":"string","string":"Not initialized"},"2718955667607728260":{"error_kind":"string","string":"Function get_htlc can only be called statically"},"13455385521185560676":{"error_kind":"string","string":"Storage slot 0 not allowed. Storage slots must start from 1."},"15764276373176857197":{"error_kind":"string","string":"Stack too deep"}}},"bytecode":"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","debug_symbols":"tZvdbhTLDoXfZa5zUT8uu4pX2UIoQNiKFAWUDUc6Qrz7Kbu9PBOOutR7JtzAl5XpNWXXj92F+Hn6/PDxx98fHp+/fP3n9O6vn6ePL49PT49/f3j6+un+++PX56n+PCX9I5d+ekd3p1zr6Z3o3/PnnCYQT8gTWgYMB6YJ+hCr0iaIOPRyeleKgjiMDOANSsoAKBlKboDhUAjQHXSkG+hX1AmtO3AB4FcCRaB0KJ0dRgI0wNigJgL4V9RcAWo4s1FLBrBDTQACDAeqADzeCgAKw5Cbg8BQXKGkTzUFdrAcGkApUAoUG5gBAYaDDcygO9jAWIEdOAHIwZLZ704t6a+GAgG6Qy4AdrCBGcxwalYYDjqwDaAQFILSoDQomqhaFIaDEABKr4DuMObAalXgDVij2IAcdLorKYiDDn4D/dKZKNasbtAdNJkGNoMGnmcWAkDpFeCZ5+GZ5+GZl5QAnnkpnnkhz7wQATzz0grAMy+cAZ55Yc+hCAGgdCgdyoAyXOnJM9+T57lnAkApFeCZ79Uz36tnvlMCeOZ706dEQTM/I+26uw10O2zQHDR1NE+toduB5sBGTgACdAdN3QbiUGdaqCo0Bx3PBlAalAaFoTAU0bUxFBpgONjyM9Avnetn6CxvoGPWszfpyegUmo1/o+nV9NhNmlGnDqqh1dAoND1uNtLj3IlBGolTC9Jv0yM9SQ3qoB5aD22ENsQpa0RODNKpcWpB+LasB76TOlclXS9OAqIc1EA6R04UFC5cg8JFwkUYZHGIkTgVPW+dQsuh5dD0dHBqID0fnChogGyOupGAbI42aiCdBdbCXLSicjZqQcOpphokIB2p04ySNcpaUlAD1dBqaBQahdZC0zXE1j/oGnJqIAlNTxenAdI1xM1IQBbbRs2J9MxjNuogi2gjHYFm0uqd0wBpxjdqmBlqmBkraE5nDTNDQkHdZ8EKnhODtH8wsppnc9S05FrGm+V0IwrqICpBmK2mI7XstoaMN05BoUloEloPrYdmOSUjzIxVOqezhpnhTEHdZ4H11HRikMW2kT47lHQ9SzLqIF0lG2kB2kizK9oXWrmTasROVvCcKKiDtCo7zayJdaA6+04MqqHV0Cg0Cq2FpsVGdBasVDq1oAHS3Shs1EG6NmQYCWhA6xbRRtOvV6MB0ow7hVZCK6HV0GpomnGnDtKMb6Qrxym+V0KT8JPw01Ov6+wPPZ97M9Lf6l4YNqqN9Ns0oqG1xyk0G5V9zkZlpA2Jk4A0z9sTzCAJTU/l7XM9B4WmO2/7nK5spZJSCmrb5+YLRwo6awOfs4g2Cq0SPlcHiEKjjs+1GhQaV3yOO0hCEwH1EhTayEEeZbEa6jRHP5K9MKWg0AqizAVR5hqaRjSy0QBRaIQorXI6hcaIMjOizBKaIMrca5BgVLoDnKBZfRv2UqfrdOgrV9F1MJqRfo6UbB2YJg2kJ5zTWRsg7VCdoFlFdBKQnRb2Eqm5chogexneSMfCSnoW65lTrNI5nTXNqdhLKQWFpnkZ3ajjCZx6k8TJ3uqcGKTvdU6hlRREQXCmGi4Uz1olSUYDxDVIQJrxobNK3TuKQoOCoDXN6exSDXtgPqt6MM+Vq1gKnkJVLK3moNAoBTVQC61RUAdxOHO4SDzbEWkbNQiRsu4qp+Yxc/HeaRK+g2toVRAda9kGnlW7KbGYreJtT3EKwshYQhMKQm65h9ZjFKMEwdlqpBOeFY1AX4QmCcjebjZqQXpzk3SJW8kje5hLUGhiMW03KBzYz6ruwvl+oTgSnhoUNJx6oqAO0gXjFBpezyYxqKagcKF41m5OdHt1e7/dqAUNkNjy1P3fh78IT/J343kNlIMsJt329h4JvFAtfbq3rR5uT5UOsiuqjUKjEiSgFlqLUXAKCmcOF4lnB0K12ufkodak+9NJPOia9KjTh+eJmILO2vDwqlU64Flt1YOuVuy2p7gECUhCEwb1HBTaiFEMCoJzTnDJdrU1fv26O+EC88P3l4cHvb+8uNGc95zf7l8enr+f3j3/eHq6O/3n/umHfeifb/fP9vf3+5f527kBHp4/z7+n4ZfHpwelX3fnp9P+o3NQqfvjk0cPi/ki/MokL0yKvs9vHnPfX1i0VxZlYdGT9qGbx9xP51Akv/Ko+x6z8rXhHlXPzT2PVSi1EIZRiXZDaW8QCv/hUIp2vx5K2p+Vvm8x+35YzMZ/7A1iLAKZLUVBILOpuDkQ2g9ksczHvG5wi3l/NvYX+WKJ6imItTG57c5rXq3RWvVG1PNRqe+ZHA2m5d1gVtt+dqKR01k8a5i032JZLNLZP2Acs3+4mJf++vjJshhIY6Q0lXDQWX7lsFqj8zIDa3Tev5898njtsVqlsUZnTxoOpb7ORVkkdL4MYM+X+aqz77FY561gy887luscRkxIbtfFUToGMd8uyr4Hrea0oCLpLdCVHjzCo4/rPGbxjXOj9H0PWa0urIx5u3KVw7xwx2Zt141h1uUSJZr357Uu5pWIsT6JLqv8+BfppHNpbFdOa40VOrFf5fEWoeQaKzRTv26nSI6jSxb7tfKf9ZhXkBELS7/OQ6LO6w3fvse4daesHI7tlJXD0Z1C5ebltUznOB888x/ndoexLK4tIRSeveBucaVFJ8pSMQ7JF4Vtvn+89liMgySa2Vlo++44jjcb1PaaDeq3Nxs0bm02Wrq92Wj51majldubjVZvbTaWDoeajWUcB5uNxrc3G2uPY83G0uNgs9FuPkLbzUdoe4MjlG8/QtfpPNZsrD2ONRsrj7cI5WCzsdwpBxsF7n/W42izsfQ42GxIvnWnrByO7ZSVw9GdIrf3sst0Hmw2lsX1YLMhcqzZqCnvNhuyWqI9R0Ho9aJhGdc2GxfB/NZs9LS6pYlL0XlJU3fH0VdlPo0aJmm03duzXlYmORaZcr3ShMbZZP/iam1S4vZrMu2brHNSLnIitGuyfOHJLe5XOfM5sfNu7V+4lHp2KRcXk//nstp8fXBsvnyenXnredyDY+Pkufuu8uiC06yPtO+wnt+ezvM7rl0k3N7A5HxlPE3y7rUzrZpsjiNtct29d17WiBT3rOXKKsMYxJB2a51aOCx7wkNRLB0ORXGwL1041JujqDdHUW+OYnkZeCiKpcOhKA5eSP7u8H7+eP/p8eXV/6v4pVYvj/cfnx78xy8/nj9d/Pb7f7/hN/h/Gd9evn56+Pzj5UGdzv85Y/7xFwvfzX/zf393yvYj0x3z0B+z/jhbdh7j/S8dzP8A"},{"name":"get_user_swaps_count","is_unconstrained":true,"custom_attributes":["external","view","public"],"abi":{"parameters":[{"name":"user","type":{"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress","fields":[{"name":"inner","type":{"kind":"field"}}]},"visibility":"private"}],"return_type":{"abi_type":{"kind":"field"},"visibility":"public"},"error_types":{"459713770342432051":{"error_kind":"string","string":"Not initialized"},"3781809441605198943":{"error_kind":"string","string":"Function get_user_swaps_count can only be called statically"},"13455385521185560676":{"error_kind":"string","string":"Storage slot 0 not allowed. Storage slots must start from 1."},"15764276373176857197":{"error_kind":"string","string":"Stack too deep"}}},"bytecode":"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","debug_symbols":"tZnbbhs5DIbfxde+kEhRh7xKURRp6hYBDCdwkwUWRd59SQ1/2c5iBNdpb+JvONE/POkw9q/Nt93X1x9fHg/fn35u7j792nw9Pu73jz++7J8e7l8enw5q/bUJ9qfq37TdVNncle2m6VUM+ln1M243MbBDjICsoCMimUUMmgOnzR2RQXNIDKgOAovAkmHJxaFEQHYwLxcQgD2CtxuKAZAAuEWwECwMC1eHRIDiIBGQHTIekQVggpoNKgyoDpUA2aFFgAB8OIcEgCUyoDgQAWARGyUG1aHnsAMsBZYCS3esQ3bojnWQBVIIAHtENqgOkQDZoSezKojdagbZoWesQwJUh+5YBw2HNZxUIyA7NFiaWyREACwRFksUa0uINeQC2YFhYXFIAaCOMRtUB4tigexg5eZk0BzM+QXsoZoosax2sKmzgCyQoyc891IaUAR4CTLDwl6CnALAS5CTlyALAbwEuXgJcvMS5OYlKCEAEsBLUCIDvASFIsDTWxgWhiXBkmARWMRLUHIEeAlKgaV4CUoNAC9BqV6C0gjgJajBRhUDK4FGWm2ad7B5sUBxsNSlYIuZCiZ1rGYCZIcSAAnQHKqmJdlDa3EwfxZwSwsEgCXCEmEha5JmUBx6MjsIwB6qjdSsyguYz7YE2wq5ACzdeQNLppAtz7RE2mzKdGgBkAA6XNjW8OjBx2B1dho21pGSOgkoDZv5J9KpYUT3cKEKysNmy/hChQYNWx0e2FLuNJQbVGLA2L7hWI/HSGFQGlRBrCMkG4m3vpKA8rDZkiSlUwOVYbPlUrpeZYywflgI00wJNrKlySmD4rBFGdRAxIOGCo+xgihJ0iBESdbRTtnjpZowto5ntGHrfWCxsW3mTsNm7dvjXTYcG8EUB8Er5mFjRMQpDDrZ4AELDxrKeaiUPvbtbbvBmeTLy3G3syPJ2SFFjy7P98fd4WVzd3jd77ebf+73r/2ffj7fH/rny/1R72rD7w7f9FMFvz/ud0Zv29PosD5UWy1UH67c6pDQzrwQiRMRsgm6aFAuZxJyIUETiRpKhEYN9RRKiRcavK7BJNJcQ7nImsYsFKYENzil1VDkD4SS/3IoVHmEEtarUtclSi2Q0O2prTnRJoFwtjV7CYRz+3AgaT2QSZvrRoUObTG19SaftCg1ZvSGsqzWNc56lNnON54PTnVN5NpgJK4GE6YpLWPaUwunssi7WCZNmrnAj5zorC71cvmJZeKILeJLSgMNBavyhcKsR9OIpAidAuHYLjVmXTp6VA/4Q4H4Mhc0SahucJjzRKGta0z6XAhTXjjcptBGQaLcFofuooiDzyryP400qylhR4pyNl9/TyO3oVHbbRr6YjnWDarrGmXWXegMPfnfpNAS5rueaW9S0H2Zxhad1+vKk7qmlNGfKZ3v8u030plOW6PcWFYeHapYb9L4E6FEHh0aU71tppQ4lq4yma+c/65GzHnEkku9TaOMfT7qRr+u0T46U2YK182UmcK1MyXRh9trms52WngaradzurlKQChZz4Krm2uanERzYfih3XV2UIjv0jFr0RrHhlA5n6Xj+neMy8PG2Q777rCR6uzgNN5T9NzEq36k2Tavr9hDJDRZPdBKmInQ6USrb0xxVSTODhx5lFeZV4/F0/kSxjGQbpxxGU60Ih+dsxOF6f54VRRThauiuHKPfq/wWS/vHx6PF78evJnU8fH+637nl99fDw9nd1/+fcYd/PrwfHx62H17Pe5M6fQThP75pG201W+6P9uXQHqp5/Gtfl1ul9Hu6pfu+tLw+c2c+Q8="},{"name":"has_htlc","is_unconstrained":true,"custom_attributes":["external","view","public"],"abi":{"parameters":[{"name":"swap_id","type":{"kind":"field"},"visibility":"private"},{"name":"htlc_id","type":{"kind":"field"},"visibility":"private"}],"return_type":{"abi_type":{"kind":"boolean"},"visibility":"public"},"error_types":{"459713770342432051":{"error_kind":"string","string":"Not initialized"},"13455385521185560676":{"error_kind":"string","string":"Storage slot 0 not allowed. Storage slots must start from 1."},"15764276373176857197":{"error_kind":"string","string":"Stack too deep"},"16190783185788596410":{"error_kind":"string","string":"Function has_htlc can only be called statically"}}},"bytecode":"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","debug_symbols":"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"},{"name":"lock_dst","is_unconstrained":true,"custom_attributes":["external","public"],"abi":{"parameters":[{"name":"swap_id","type":{"kind":"field"},"visibility":"private"},{"name":"htlc_id","type":{"kind":"field"},"visibility":"private"},{"name":"hashlock_high","type":{"kind":"integer","sign":"unsigned","width":128},"visibility":"private"},{"name":"hashlock_low","type":{"kind":"integer","sign":"unsigned","width":128},"visibility":"private"},{"name":"reward","type":{"kind":"integer","sign":"unsigned","width":128},"visibility":"private"},{"name":"reward_timelock","type":{"kind":"integer","sign":"unsigned","width":64},"visibility":"private"},{"name":"timelock","type":{"kind":"integer","sign":"unsigned","width":64},"visibility":"private"},{"name":"src_receiver","type":{"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress","fields":[{"name":"inner","type":{"kind":"field"}}]},"visibility":"private"},{"name":"token","type":{"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress","fields":[{"name":"inner","type":{"kind":"field"}}]},"visibility":"private"},{"name":"total_amount","type":{"kind":"integer","sign":"unsigned","width":128},"visibility":"private"},{"name":"src_asset","type":{"kind":"string","length":30},"visibility":"private"},{"name":"dst_chain","type":{"kind":"string","length":30},"visibility":"private"},{"name":"dst_asset","type":{"kind":"string","length":30},"visibility":"private"},{"name":"dst_address","type":{"kind":"string","length":90},"visibility":"private"}],"return_type":null,"error_types":{"361444214588792908":{"error_kind":"string","string":"attempt to multiply with overflow"},"459713770342432051":{"error_kind":"string","string":"Not initialized"},"1998584279744703196":{"error_kind":"string","string":"attempt to subtract with overflow"},"2360858009427093503":{"error_kind":"string","string":"InvalidTimelock"},"3380315280177356474":{"error_kind":"string","string":"FundsNotSent"},"4736483829072576196":{"error_kind":"string","string":"HTLCAlreadyExists"},"7413154743021792023":{"error_kind":"string","string":"InvalidRewardAmount"},"13455385521185560676":{"error_kind":"string","string":"Storage slot 0 not allowed. Storage slots must start from 1."},"14576755381182599325":{"error_kind":"fmtstring","length":24,"item_types":[]},"14990209321349310352":{"error_kind":"string","string":"attempt to add with overflow"},"15764276373176857197":{"error_kind":"string","string":"Stack too deep"},"16431471497789672479":{"error_kind":"string","string":"Index out of bounds"},"16884080922827299127":{"error_kind":"string","string":"InvalidRewardTimelock"}}},"bytecode":"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","debug_symbols":"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"},{"name":"lock_src","is_unconstrained":true,"custom_attributes":["external","public"],"abi":{"parameters":[{"name":"swap_id","type":{"kind":"field"},"visibility":"private"},{"name":"hashlock_high","type":{"kind":"integer","sign":"unsigned","width":128},"visibility":"private"},{"name":"hashlock_low","type":{"kind":"integer","sign":"unsigned","width":128},"visibility":"private"},{"name":"timelock","type":{"kind":"integer","sign":"unsigned","width":64},"visibility":"private"},{"name":"src_receiver","type":{"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress","fields":[{"name":"inner","type":{"kind":"field"}}]},"visibility":"private"},{"name":"token","type":{"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress","fields":[{"name":"inner","type":{"kind":"field"}}]},"visibility":"private"},{"name":"amount","type":{"kind":"integer","sign":"unsigned","width":128},"visibility":"private"},{"name":"src_asset","type":{"kind":"string","length":30},"visibility":"private"},{"name":"dst_chain","type":{"kind":"string","length":30},"visibility":"private"},{"name":"dst_asset","type":{"kind":"string","length":30},"visibility":"private"},{"name":"dst_address","type":{"kind":"string","length":90},"visibility":"private"}],"return_type":null,"error_types":{"459713770342432051":{"error_kind":"string","string":"Not initialized"},"1998584279744703196":{"error_kind":"string","string":"attempt to subtract with overflow"},"2360858009427093503":{"error_kind":"string","string":"InvalidTimelock"},"3380315280177356474":{"error_kind":"string","string":"FundsNotSent"},"13455385521185560676":{"error_kind":"string","string":"Storage slot 0 not allowed. Storage slots must start from 1."},"14576755381182599325":{"error_kind":"fmtstring","length":24,"item_types":[]},"14990209321349310352":{"error_kind":"string","string":"attempt to add with overflow"},"15764276373176857197":{"error_kind":"string","string":"Stack too deep"},"16431471497789672479":{"error_kind":"string","string":"Index out of bounds"},"17552554873437466887":{"error_kind":"string","string":"SwapAlreadyInitialized"}}},"bytecode":"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","debug_symbols":"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"},{"name":"process_message","is_unconstrained":true,"custom_attributes":["external","utility"],"abi":{"parameters":[{"name":"message_ciphertext","type":{"kind":"struct","path":"std::collections::bounded_vec::BoundedVec","fields":[{"name":"storage","type":{"kind":"array","length":17,"type":{"kind":"field"}}},{"name":"len","type":{"kind":"integer","sign":"unsigned","width":32}}]},"visibility":"private"},{"name":"message_context","type":{"kind":"struct","path":"aztec::messages::processing::message_context::MessageContext","fields":[{"name":"tx_hash","type":{"kind":"field"}},{"name":"unique_note_hashes_in_tx","type":{"kind":"struct","path":"std::collections::bounded_vec::BoundedVec","fields":[{"name":"storage","type":{"kind":"array","length":64,"type":{"kind":"field"}}},{"name":"len","type":{"kind":"integer","sign":"unsigned","width":32}}]}},{"name":"first_nullifier_in_tx","type":{"kind":"field"}},{"name":"recipient","type":{"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress","fields":[{"name":"inner","type":{"kind":"field"}}]}}]},"visibility":"private"}],"return_type":null,"error_types":{"344423948968719440":{"error_kind":"fmtstring","length":98,"item_types":[{"kind":"integer","sign":"unsigned","width":32},{"kind":"integer","sign":"unsigned","width":32},{"kind":"field"}]},"361444214588792908":{"error_kind":"string","string":"attempt to multiply with overflow"},"992401946138144806":{"error_kind":"string","string":"Attempted to read past end of BoundedVec"},"1998584279744703196":{"error_kind":"string","string":"attempt to subtract with overflow"},"3080037330898348111":{"error_kind":"fmtstring","length":132,"item_types":[{"kind":"integer","sign":"unsigned","width":32}]},"4261968856572588300":{"error_kind":"string","string":"Value does not fit in field"},"4440399188109668273":{"error_kind":"string","string":"Input length must be a multiple of 32"},"7564993426627941149":{"error_kind":"fmtstring","length":48,"item_types":[{"kind":"field"},{"kind":"field"}]},"7995966536718645961":{"error_kind":"fmtstring","length":61,"item_types":[{"kind":"field"},{"kind":"field"}]},"8992688621799713766":{"error_kind":"string","string":"Invalid public keys hint for address"},"9791669845391776238":{"error_kind":"string","string":"0 has a square root; you cannot claim it is not square"},"9885968605480832328":{"error_kind":"string","string":"Attempted to read past the length of a CapsuleArray"},"9921926525851912681":{"error_kind":"fmtstring","length":98,"item_types":[]},"10791800398362570014":{"error_kind":"string","string":"extend_from_bounded_vec out of bounds"},"11021520179822076911":{"error_kind":"string","string":"Attempted to delete past the length of a CapsuleArray"},"12469291177396340830":{"error_kind":"string","string":"call to assert_max_bit_size"},"12913276134398371456":{"error_kind":"string","string":"push out of bounds"},"13450089406971132036":{"error_kind":"fmtstring","length":144,"item_types":[{"kind":"integer","sign":"unsigned","width":32}]},"14067204867181196045":{"error_kind":"fmtstring","length":75,"item_types":[]},"14990209321349310352":{"error_kind":"string","string":"attempt to add with overflow"},"15764276373176857197":{"error_kind":"string","string":"Stack too deep"},"16431471497789672479":{"error_kind":"string","string":"Index out of bounds"},"16792019527863081935":{"error_kind":"fmtstring","length":77,"item_types":[{"kind":"integer","sign":"unsigned","width":32}]},"17154023812102399658":{"error_kind":"fmtstring","length":128,"item_types":[{"kind":"integer","sign":"unsigned","width":32}]},"17803644318014042523":{"error_kind":"fmtstring","length":58,"item_types":[{"kind":"field"}]}}},"bytecode":"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","debug_symbols":"TJ3LsjS7bpzf5Yw9aIIEQOpVPHD4qlCEQorwZaSX9yokwcyJ95fW+ZmoYiG7uhrd6z/+8T/+53/7f//8X/7l3/7Xv/+ff/zTf/6Pf/y3//0v//qv//LP/+Vf//2//9f/+y///m9//7//8Y/f9//sv/93/qd/7PGPf4q//9g//mn9/WfiPwv/8X/80/77T+A/if9s/OfUf84P/xn4j+E/E/9Z+A9WOVjlYJWDVQ5WGb/f/e+4/7X733n/u+5//f437n/z/nff/971xl1v3PXGXW/c9cZdb9z1xl1v3PXGXW/c9eyuZ3c9u+vZXc/uenbXs7ue3fXsrmd3vXnXm3e9edebd71515t3vXnXm3e9edebd71111t3vXXXW3e9dddbd71111t3vXXXW3c9v+v5Xc/ven7X87ue3/X8rud3Pb/r+V0v7npx14u/9cbvg9mwGrzhb80xP8iG3XAu5N+6Iz74W9i+f5XWMBtWgzdEw9/Ktj7YDefC1x6Ab2X/wBpmw1fzdzhfowCi4W/lOT7YDefC1zKA0WANs2E1eEM09MqnVz53Zfu6aM4PRoM1zIbV4A3RkA274VwYvfLolUevPHrl0SuPXnn0yqNXHr3y6JWtV7Ze2Xpl65WtV7Ze+euv6R9kw244F74eA4wGa5gNq8EbeuXZK89eefbKq1devfLqlVevvHrl1SuvXnn1yqtXXr2y98reK3uv7L2y98reK3uv7L2y98reK0evHL1y9MrRK0evHL1y9MrRK0evHL1y9srZK2evnL1y9srZK2evnL1y9srZK+9eeffKu1fevfLulXevvHvl3SvvXnn3yqdXPr1y9eD+YDasBm+IhmzYDQcwqwcLRoM1zIbV8LfyGh9EQzb8rbzig3Ph60HAaLCG2bAavCEasqFXHr2y9cp2E2maNcyG1eAN0ZANu+Em0py/hl559sqzV/56cJ0PvCEasmE3nAtfDwJGgzXMhl559cqrV1698teD/vvgXPh6EDAarGE2rAZviIZs6JW9V45e+etBzw+sYTasBm+IhmzYDefC14OAXjl75eyVs1fOXjl75eyVs1fOXnn3yrtX3r3y7pV3r7x75d0r715598q7Vz698umVT698euXTK59e+fTKp1c+vfK5K6/fr2E0WMNsWA3eEA3ZsBt65dErj1559MqjVx698uiVR688euXRK49e2Xpl65WtV7Ze2Xpl65WtV7Ze2Xpl65Vnrzx75dkrz1559sqzV5698uyVZ688e+XVK69eefXKq1devfLqlVevvHrl1SuvXtl7Ze+VvVf2Xtl7Ze+VvVf2Xtl7Ze+Vo1fuHlzdg6t7cHUPru7B1T24ugdX9+DqHlzdg6t7cHUPru7B1T24ugdX9+DqHlzdg6t7cHUPru7B1T24ugdX9+DqHlzdg6t7cHUPru7B1T24ugdX9+DqHlzdg6t7cHUPru7B1T24uge9e9C7B7170LsHvXvQuwe9e9C7B7170LsHvXvQuwe9e9C7B7170LsHvXvQuwe9e9C7B7170LsHvXvQuwe9e9C7B7170LsHvXvQuwe9e9C7B7170LsHvXvQuwe9e9C7B7170LsHvXvQuwe9e9C7B7170LsHvXvQuwe9e9C7B7170LsHvXvQuwe9e9C7B7170LsHvXvQuwe9e9C7B7170LsHvXvQuwe9e9C7B7170LsHvXvQuwe9e9C7B7170LsHvXvQuwe9e9C7B7170LsHvXvQuwe9e9C7B7170LsHvXvQuwe9e9C7B7170LsHvXvQuwe9e9C7B7170LsHo3swugejezC6B6N7MLoHo3swugejezC6B6N7MLoHo3swugejezC6B6N7MLoHo3swugejezC6B6N7MLoHo3swugejezC6B6N7MLoHo3swugejezC6B6N7MLoHo3swugejezC6B6N7MLoHo3swugejezC6B6N7MLoHo3swugejezC6B6N7MLoHo3swugejezC6B6N7MLoHo3swugejezC6B6N7MLoHo3swugejezC6B6N7MLoHo3swugejezC6B6N7MLoHo3swugejezC6B6N7MLoHo3swugejezC6B6N7MLoHo3swugejezC6B6N7MLoHo3swugejezC6B7N7MLsHs3swuwezezC7B7N7MLsHs3swuwezezC7B7N7MLsHs3swuwezezC7B7N7MLsHs3swuwezezC7B7N7MLsHs3swuwezezC7B7N7MLsHs3swuwezezC7B7N7MLsHs3swuwezezC7B7N7MLsHs3swuwezezC7B7N7MLsHs3swuwezezC7B7N7MLsHs3swuwezezC7B7N7MLsHs3swuwezezC7B7N7MLsHs3swuwezezC7B7N7MLsHs3swuwezezC7B7N7MLsHs3swuwez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qmEjr3dUNWzk9Taqho0ag/itUG8qatio8TysPr44iLVuHVD1Zr3zqQEir3dUNUB0sXrz4iAacRIX0YlBLLc64urNi+dh9Wa93akBokYjTuLnVu9maoCoMYifW72FqQGixvOw+rje7tQAUaMRJ3ERnVhudVKrjy9uYrnVqa4+vjiIRnRirVDbEudhdWy9YaqhoEYjfvV6nZ3q44tODGISN/E8rD6+OIhGpNum26bbptum26bbptuh26Hboduh26Hboduh26HboVv18fd20msoqHEQy20WTuIilpsXBrHcduEmnofV3RcHsdxO4SR+bt/7Qq+hII+qrHr+e2PjNRTUuImfW6wPq+cvDuLn9t3bew0FNS6iE4OYDysJvsfOXoM+HnUU1fNRpVfPXwxiEr96sw6oeh5YPX9xEI34uWUdZvV81lmvns8qp3o+y6J6HljdvetMVh/vWqw6dtdi1bEXN/GrbNd2V8deHEQjTuIiOrHc6vTVK+/F/bBaGpVVS180YlnUqa6WvujEz+Lgf5vETfwO6FQ51dIXP7dTR1wtfXESP7dT10619MUgJnETz8Nq6YuDaMRJpNuh26Hboduh23luNZvTOIhGnMRFdGIQk1huXngeVktfLLcsNOIkltsudGIQk1hup/DPLb43Cl6zOfG9O/CazWk04vxwFi6iE4OYxE08D+ePOIhGpNuk26TbLLdRmMRNPA/XjziIRpzEcquzvpwYxHKLwk08D/1HLLfaITfiJAaxVqht+UIhRm3LFwqNRpzEb4VRO/S9jMeos5M/4iAacRIX8TviUYeZQUziJp6H+0ccRCOWW53fvYhODGK51enbm1hudf2eH3EQPzerU/L1fOMiOjGI2VjTMvHdunvNxcT3YYjXXEx89+teczGNQUziV+93F+81F3Nx/IiDaMTPbVYNXx83OjGISdzEz+278fb6PbjGQTRiuZVx9fFFJ5ZbFn5uqyyqjy9+bqtOVPXxxc9t1TmrPr44iYvoxCAmcRPPw+rji3RbdFt0W3RbdFt0W3RbdFt0c7o53ZxuTjenm9PN6eZ0c7o53YJuQbegW9At6BZ0C7oF3YJuQbekW9It6Vb5sOqqrny46MQglltdO5UPF8/DyoeLg2jESVxEJwaRbptum26Hboduh26Hboduh26n1v1ypwaa/j65KDRirbALF9GJQUziJp6HlQTfmyuvISVsQA0p4fzWkFLjJp6H1fPfGxCvIaVGI07iu3ZqSKkxiEncxHftzPkjjlcDeh44iYvor4bq+YtJpBt7frLnJ3t+sucne36y5+d6V+pcPJOLZ3LxTFbPowbnmXSeSfb8ZM9P9vxkz0/2/GTPT/b8ZM9P9HzVEDyTwTMZPJPBM1k9X28na6Cpsc4k1t3E87B6/mIdmxcacRIX0YlBTOImlls1TvX8RV7g1ehePVSNftGJQeSlUY1+kZt1uFmHm3V42R9e9oebdbhZh5t1uFmHm3XeZtUUU+MgGrGOYhcGMYl1FKfwW7fegtfPsjUOohEncRGdGMR8WKFQb+1ruqnRiJNY69ZRVChcDGIS6yYHeB5WKFwcRCNO4iI6sW72gOdhtf/FQayjmIV1EwkMYhK/desBRU03XaxGv1hnxwvfDXJNNzUuIt2cbk63avSL73Z8xY84iHQLWlQf11uCGnRqPA+rjwM4iHVK6uKqPr64iF/pWZdG9fHFJH5u9QykBp0uVh9fHMTPLaveaumLi+jEcqtTXc1bz1Zq/KlxEGvdKJzERXRiEJO4ieX2nZ0aimocRCNO4iI6MR5Wx9YDoJqEinoAVJNQjU4MYhI38SuyHgvVJFTjIBpxEhfRiUEst1m4iedhdezFQTTi7G2psapGJwaxzvqXJfUrZvfsVJtenMRFrNJXIU9JtSmw2vRiFVlu1aYXJ7FOSRRyA5wb4NwAp5vTLehWbXrRiNzu4HYH3YIW+Z4NOh67AY1Yi+3CRXTiV3o9YKvBrMZN/EqvR0g1mNU4iF/p9QipBrMaF9GJQUziJp6H1bwXB5Fuh26Hboduh26Hbodu57nVuFbjIBpxEhfRiUEstyjcxPOwuruelNVoV2O5ZeEkLuKfW9ajtBrtaswPrXATz4ffDtVoV+Mg2odVztfzjYvoxCDmw1nrVmWzVqijmLXCKXRiEJP41VuPZGoi7OL3etw4iEb83OqpT02ENToxiEncxHKrGvxHHEQjfm71+KYmwhqd+LnVDUZNhGU9camJsMbPzeqcfe3f+LlZnb6v/RsncRGdGMQkbuJ5mD8i3ZJuSbekW9It6ZZ0S7ol3TbdNt023TbdNt023TbdNt023TbdDt0O3Q7dDt0O3Q7dDt0O3Q7dTrl9V3X9xFjjIBrxc6snZfUTY41ODGISN/E8/PKhcRCNSLdBt0G3QbdBt0G3QTejm9GtkuD7AN9r2i2/+V+vabfGWuF7Ga9pt8ZBNOIkLqITa90vmGqCDRtQE2z3/FbPX1xEJ9YRe2ESN/E89Hft1ARboxEncRGdGMQk7leO89oJXjvBayd4bNXz3/SC11xbY52dWrd6/mISN/FzqyenNe3WOIhGnMRFdGIQP7d69lrTbher0bFZ1ej13rRG3BoncRH9bcDmZm1u1uZmbW5WNfrFQeRmsdGTjZ5s9GSjJxs92eh5Xqzs349YRzELF9GJdaJWYZ0oL9zE87Ba+uIgGnESF9GJtW4UnofVvBcHsdato6gX94uL6MR6ad6FSdzE8xAv+cBBNOIkLmL2R98YZrt4HtZLfj2+qWG2RiN+6zr+t4voxNqLcqv2v7iJ31HU/EMNvjUOovWH8hh8u7iITgxiEjfxPKyP3y8OIt2CbkG3oFvQLegWdAu6Jd2Sbkm3pFvSLelW7e91VVf7X9zE0yMLGJK7WGeyrr5KgouTWPtWe1FJcDGISdzE87CS4OIgGnES6Xboduh26Hbodp5bjcNlPUqrwbesR141+Jb1RKsG3xo38Tysnq9HSPWLXI1GnMRFLDcvDGISy62KrCQAVhJcLLcsNOIkLqITg5jETTwPKwku0m3SrZKgHgvVQF3WA6AaqGsMYhI38TysfLg4iEacRLpVPtQTohqoa0xiudVmVT4AKx8ullud9bo9uDiJn1s9zKiBusYgfm71/KEG6hrPw7o9qGcKNVDXaMTPrd6N1y9yNTqx3Kqcuj24uImfW73JrOG7xkH83Gpeo4bvGhfxz23XG8cavmtM4v6w3L58uPjlQ+Of265HqzV81ziJ68M6Z18+NAbxc6u3XDV813gefvmw69P1Gr5rNOLnVu/Javiu0YmfW93e1vBd4yZ+bt89V9TwXeMgfm7f9/Wihu8aF/Fz+17Ro4bvGpP4uX0v41HDdxe/LGn83L7XrKjhu8ZJ/Ny+rI4avmsM4uf2PWqPGr5rPA+/LNlRi31Z0mjEz+3r7qjhu0YnBjGJm3gezh9xEI1It0m3SbcvS3bW2fmypHETP7esHfqypHEQP7ddZ+fLksZF/Nx27dCXJY1J/Nx27fGXJRe/LGn83E6dvi9LGifxczvl9mVJYxD/3M731Cdq1K/xPPyy5HxDRlGjfo1GnB+W25cljU78czsDiyVxEz+3UYt9WdI4iJ/bqJP6ZUnjIn5uo05JBjEf1vuLrJNa9w9ZB1/3DxedGMQkbuJ5WPcPF6veunaOESdxEZ0YxCRu4nd2vmdBUZN8jYP4uX1xFTXJ17iI9XochUFM4iaeh7jXAJbbLDTiJJYb/rdODOJ3bN9vhERN8jWeh1bHtgsH0Yif2/dOLWqSr9GJQUziJp6HXz40DqIR6TbpNuk2y62ObZ5X5FpEJwYxiZvIFbwqAw6iEauyU7iITgxiEjfxPKzuvjiIRqRb0K26e9XVV919MYmbeB5Wd1/83OrFp+b7GidxEcstC4OYxHKryr47heN12X893/i5fQMHUfN9jZ+bVzlfEjQ6MYhJ3MTz8PyIg2hEuh26Hboduh26Hbqd51ZTf42DaMRJXEQnBjGJm0i3QbdBt0G3QbdBt0G3QbdBt0G3QTejm9HN6GZ0M7oZ3YxuRjejWyVB3dnULGDjIBrxJYExCYxJYDOISdzElzs1C9g4iHUUqzA7Vmq+7zj+B+dh5cPFQTTiJC5inYdaN3h+g0ccPOLq+YuLWOc3C4OYxE3kbibdkruZ3M3kbiZ3M7mb1fOooXr+4iZyN9HzVQN6HmhEurHnjT1v7Hljzxt73tjzdnjtHJ7JwzN5eCbR81XD4Zk8PJPseWPPG3t+sucne36y5yd7fv7evk30PDCISXz7NtHzheNHpBt7frLnJ3t+sucne36y5yd7fo63b9N+xEE04iSW2y50YrmdwiRu4nlYPV9vS2oWsNGIk7iITgxiEj+3ejdTs4AXq+etjNfsLqypv/ON8kRN/TUGMYncocUdcu6QD6IRJ3ERuUPOHXLukHOHnFcfU2MGr4fg9RC8HiofvgdLUfN9jZtYZ6fOQ+VDVGWVDxeNOImL6MQgJnE/3P3EJWqor3ESF9GJQax1awsrCS6eh5UE3xOiqKG+RiN+R/E9AIoa6mt0YhCTuImnsYb6GgfRiJO4iE4MYhI3kW6DboNug26DbpUE3wP4qFG/U2+NatSvMYmbeB5WElwcRCNO4iLSzfpJWdQAYOMm9pOyqAHAxkGsJ2V1FPXM8eIiOjGISdzE87CeOV4cRLotulUS1NVXA4CnninUAODfg7HCQTTiJH4rfEM7UUN9Z9cOVR9fHEQjTuIifucXp6+6+2ISN/E8rO6+OIhGrHpP4SI6MYjlVjtU3X2x3o3X2cG7fOAgGnES69jq/FbHfg9Goyb5Gidx3SenUZN8jUFM4iaexprkaxxEI07iIjoxiEncRLoNug26DboNug26DboNug26DboNuhndjG5Gt+rYemBVA4CNTgxiEjfxu6K+J9NRA4CN377Vc64aAGycxEV0YhCTuInnYb12X6TbKrdVOIn9JD1qQrAxiPmw+vgb7YqaBTynTlQ9rfvVYu7EIOZ9+B01C9h4HkY9Ha8iv+5uNOIkLqITg5jETTwPk25Jt+rjb7wsagDwfI/7A3+P9FfPFPEHSS/XX+tpHsKr2IqzuFbfW/iQz094CJvwLK4zdZawC4dwCm/h8xh/dbQZvqPYhKfwEoZvFIcwfHfxFj7k8RMewiY8hZewC4ew+I7+PCRq8O9iPcW/2J+HRA3+NU5iffpyCp0YxCRu4nlYT/EvDqIRJ5Fuk24TZ6+4/ojXr54o46+L/r5PiQJ/XrR5CbtwrfP95Evgz4b+Ru24m/AUXsIuHMJ1tusBNv56aPMh19/pah7CJjyFlzB8Z3EIp/AWhm/tfv6Ex/0wK/A3QX/YfzT05UNGQ+MSQENftvuRV9TUXuMiOhFrF6OZ6zFzzeLhU7GaxWtcRO9PxQIfvAGTWB+8VZfhg7cPEx+8AQfRiJO4iE4MYhI3kW5o0Xrsjb/h+TP8/9cmfZNCgb/i2byFD9mwzimudb45u8Cf52xO4S18yPVn9ZrrbNcu4I90Nk/hJezCIZzCWxj1f3uBP9bZPIRNGL6zeAnD14tDOIW38CH7T3gIm/AUXsLi6+/D1prYa9zE92FrTew1DuJ3ha26EOqF+eIiOjGISdzE87BemC8OIt2SbomzV/Wgj6tT8Cc5f/W8H3+Ts9mEp3Ct843zBf7W5q+e9OOPbTYPYROewku4zjbqxAvz5RTewucx/uxm8xA2Yfj+ipewC4cwfL14C8P360r8Uc1ffRqBv6rZHMIpvIUP2X7CQ9iEp7D41uttPS2rWbzGJO7+5L5m8S7W6+3FmgiwQiNO4iI6MYhJ3MTzsD41v0i3RTf0eH2Cgz+a+bv//3WWcCDo5ctD2ISxTu0UXmjrERz+HuZlvNBeHsImPIXrbNejR/xVzOYQTuEtfMh4ob08hOFbe5FTeAm7MHxr9/Eqfbl8v+GxwN/IvIzuvjyEy7ceXOLvZDYvYRcO4RTewoeMNLg8hMW3XtpryKJm7hqdGD1kUTN3jZtYsxnfhtcP0zUOohEncRGdGMQkbiLdBt1w810PcPFnMH/1wBN/B/NXTybxhzCbDxm9fxnrnOJap54oHryyX97Ch4xX9stDuM52Pac7eGW/vIRdOIRTeAsfMl7Zv8nBOHhlv2zCUxi+s9iFsX6dT7wi1/4evCJfduEQTuEtfMjo+stD2ITFt16Z61l/Dcs1BrEGk6r2emW+eB7WK3O1Wg3LNRpxEhfRiUFM4iaeh5tum27o5XpIeNCz9ZTwoGc3/jeHjJ69PIRrnXqOd/CKXE/kDl6RL5/m/OEV+fIQNuE6299zo/zhFfmyC4dwCm/hQ8Zb5cvwtWITnsJLGL5ZHMLwPcVb+JDRxZfL93v4kz+8gl+ewkvYhUM4hbfwIaPrL4vv7IG0xPjbxUXsgbTE+NvFJNZA2iw8D+uF/OIgGnESF9GJQUwi3Rbd8Mp+anfQ+6eKR++fqhO9f3kLHzJ6/NRu4hX8G1zNH17BL6fwFj5kvIJf/s72+B5gZQ2tPZ7CS9iFQziFtzB860rGK/jlIWzC8K3d30sY69f53Fv4kKvrm4ewCWP9Ov9nCeO46jyfEIZv1Xa2MHy/vaght8fw3cUmDN9TvITL95sqzBp1e1y+36OfrGG3x+X7PeLJGnd7XL7fY5GsgbfH5fs9BsoaeXsMXy8OYfhG8RaGbx2j/YThW8doJgzfOkZbwuVrdYyVEs09H5vjzcfmePOxOd58bI43H5vjzcdmzb/9rVZnqe4Kml0YjnUG6q6geQsfct0VNA9hE57CS9iFxXeJr2P9OvOOdepsO9apM+wuHMIpvIWl/pD6Q+oPqT+k/pD6Q+oPqT+k/pDzFuKb4oskwTEiMXCMKfWn1J+HvH/CQ1jq31L/lvq31L+l/i31b6l/S/1H6j9y3o74HvFFYuAYkQx1jPZj/fYbwiY8hZcw67dfCKfwFmb9Nn7CQ9iEp/ASFt8hvkiAOkZDp+MYTeo3qd9cOIRTeAtj/S89asTtcb1AA404iYuItb88MPTu94wwa3Kt5suzfsWucRJ76jzrV+wag/jlU72E15Rb43lYM+4XB9GIk7iITgwi3Zxu6ODv68hp6NRZxaNTZ9WJTr2cwpuM1/xZu4fX9lk7gNf2yyGcwlv4kNGps848OvWyCU/hJezCIZzC8K2rD50KRqdeHsLlu2r30amXy3fV+cRr/uUQTuEtfB5PdPblIWzCU3gJ1zcNfoVBTGJ9r2EUnofjR6wr7BQacRIX0YlBTOImnof1udlFuhnd0N/fl4Bzoo+/J4s50cff0+Kc6OPLQ9iEsc4uxjq1Pl6Hwejly0PYhKdwnW2vc4XX4cshnMJb+JDx+nx5CMM3i6fwEnZh+Nbu43X7MnzrPOB1G4zXba9/i673Oj/4Ekud8vcllpzvSyw535dYEiNtF5O4iedhDb1cHES6Jd2QGFEXKhLjcgin8BY+ZCTG5SFswlMYvnX+kRiXQziFt/Aho9OjrlV0+uUtfB4vdPrlIYw6o3iS8dr7PQnLhdfeyyaM//0pXsIu3F9CSoygXdzE/hJSYgTt4iDW/tViNdBycRGdGMQkbuJ5WAMtFweRbpNuuOPOKhgd/T1vy4WO/p6Z5UJHXzbhKYx16syjQ7PONjr08hA24Sm8hOtsf0+VcqFDL6fwFj5kdOjlIWzC8F3FS9iFQxi+dd7wen25fOvpzsKddT38WHgdv2zCU3gJu3AIp/AWPuQtvjWnXm//alKtcRLre2N1DrYTg1gXdG1CTadePA9rOvXiIBpxEhfRiUGk23lujl6up0SOV+d6Tua47677Scd99+UU3mT0+PfnYtPRy/XsytHLl0M4hbfwIeMddt2aOt5hXzbhKbyEXTiEUxj1n+JDxuv15SEM31U8hff9enU6hkYLMTQKHESsUecenX15CbtwCKfwFj5kJMHlISy+Lr4uvi6+Lr4uvi6+Lr4hviG+Ib5IgnqK50iCevrmSILLIZzCW/iQkQSXh7AJT2HxrR+6uRjEJO77rfes0beLNa168dvYehRZP37XOImL6MQgJnETz8P6pupFuh264f4d9dSrt9XdMYbd7BvESwy7NQ9hE/biVYx1vPiQx094CJvwFF7FWezCIZzCW/iQ7Sc8hOE7i6fwEnZh+O7iFC7fuqGoObbmSoLmIWzCU3gJu3AIp7D41oP5eoxZP3vXOIg1P1fHUe/ZLy5izc+NwiAmcRPPw3rPfnEQjTiJi0g3p5vj7BUHzlLVFjhLdXXFEnbhEMY6X27Ur9T9ce14TuEl7MIhnMI426f4kPdPeAib8BRewi4M37rydwpv4UOud+1WT34xLddcvvWstgbjHodwrW91btH1l2v9elaV6PrLQxjre/EUXsIuHMIpvIUPGSlxeQiL7xDfIb5DfIf4DvEd4jvE18TXxNfE18TXxNfEFylRz/Uwh9e8hQ8ZKXF5CNe3FoDxLue8AQDewrzkMWJn9UgQo3S4hDFK1+zCKHkXp/AWRsnfpYpRuvtvfQibsPi6+Lr4egin8BY+5BDfEC/EQD2mTMTA5RSuNb9xxEzEA7huAZqHcK1fDwcTsXF5CbswfKtFEA/1EA0Ddc1DGOvXfiEeLi9hFw7hFN7C8K1zgni4PIRNeAovYReOxxius3qYiCE6qweCGKJrduEQTuEtXDXXQ72N1r88hE14Ci9hFw5h+M7iLXzIaP3LQ9iE59s7DN01u3AIY1++uN1oa5w3vPhfnsJLGMeyiuVcocfB6PHLqLl8lwlPYZyrKJY9WrJHS/Zoie8SXxdf9P5lE5Zrw+XacPF18UJf180jxvCaTXgKY826JtHjdcOIcbtm3nhi3M7q8SjG7ZpNGDXX+UeP33/rwiEsvim+Kb77JzyETXgKi+8WL/S117lCX18ewrVmPRLd6OvLS9iFa32vaxu3A5e38Hl80Pvf2GEe9P43WpkHvX/ZhbF+FKfwFj5k9P7lIWzC8M3iJezCIZzCW/iQ0fuXseYprn9bj00xaNd8yHjpvjyETbhq/ubEEoN2zS4cwim8hQ8ZvX8ZvrVH6P3LU3gJu3AIJ/cOvX/5kNH7l7Evo9h53vCafjmFtzCOpa6lkHOFHr+8hFFz+eL1/XIK41zVdRKyRyl7lLJHKb4pvim+6P3LISzXRsq1keK7xQuP3Q/YhUM4hbFmXZP4QK4eaR18IHd5CqPmXezCIYya6/yfLf/2PTLbGNVrHsImPIWXsAuHcApv8hAv9PX3gHtjDK/ZhetYvgffG2N4zVv4kNHX34PvjTG8ZhOewvBdxVjfi7fwIaP3v/vzjXG7ZhOewkvYhUMYvlm8hQ8ZvX95CJvwFF7CWPN8jNfuXecWvXx5Ci9hFw7hqnnXOUePXz5kvL5fHsImPIWXMHxrj9D7l1N4Cx8yev/y4N6h9y9P4SWMfanrE32N84bX9MtD2IRxLHUtbTlXuG+/vIVRc/ni9f3yEMa5quvkyB4d2aMje3TE94jvEV+8vhdjAK95CJvwFHZhfNDixYeMHr88hLFmFuODnCgO4RRGzbv4kNHjl1HzKTb+W5vCS1h8TXxNfPGI//Ihz5/wEBbfKV7o61PnCn19+ZDR19+QysaYXLMJT+Ha9++jiI0xueYQTmH4ftfkQO+f2gv0/uUpjPWrfvT+5RBO4S18yOj9y/CtfUfvX57CS9iFQziFNxl9feoaqNfu+atzW73cnMJb+JCrx5tHcZ3z6vHmKbyEXTiEU3gLw7f26PyEh7AJT+El7Nw79P7lFN6PMVZn9fqL8TmcN4zPNbtwCONYvmsJY3I4VxiTazZh1Fy+Ywm7MM5VFKf82y3MParfi3ssvia+NoWXsAuHsPiaeN1Rm108hZewC2PNLH4jONs4grONIzi75un+/vf1b9cUXsKoGf/7kH+bwltYfF18XXzdhKfwEnZh8XXxqr6eo85V9XXzFK5j+T6L2Bi2aw7hFK59/x7/7/phueZ6TW8ewvCtaxK9P+q6Qu9fTmGsX9cbeh+M3r88hE14Ci9h+Na+o/cvp/AWPmT0/uUhbMJYs855vXbP75H/xiBd8xA24Sm8hKvm70v3uybpHqfwFj5k9P7lIWzC8J3FS9iFQziFt/B5ezfR+5eHsAljX0ZxvvOGMbvmQ54/YRzLKpZzNV04hFFz+c4tfMgL5yqKZY+W7NGSPVriu8R3ie9K4S0s14bLteHi6+KFvp5VGz6uv7yFDzmwZhZjIBW8hF0YNe/iFN7CqLnOPz6Wx7+9g7ZgExbfFN8UXw7g7skB3D05gLsnB3D3Hae7LF7o61nnCn19OYXrWGZd8+hrMPr68hCufZ91beM1/fISdmH41jWJ3v+eM2+M1jUPYawfxVN4CbtwCKfwFobvd04wotc8hE14Ci9hFw4y+vp7Br4XXru/58N7oZcvu3AIp/AWrpq/zwL2Qo9fHsImPIWXsAuHMHxn8RY+ZPT+5SFswpN7h96/7MIhjH358g1De/e8uQlP4SWMY1nFcq78kNHjl1Fz+eL1/fIUxrmq6yRkj0L2KGSPQnxDfFN88fp+2YTl2ki5NlJ8U7zwmr7qGsNret2nLbymX57CS9iFQziFkSfwOuTzEx7CJjyFl7AL4ysedZ7R+3Xf5ej9y0PYhOu4vs8INkb0ml04hFN4Cx/y/WpMFA9hE57CS9iFQziFNxmje3XsGN27x3XzAbyEXViOy+S4TI7L5LiQD5eHsAnLcU05rinHNeW4phzXlOOah7zkfC45n/ercHXsS44LOXA5hbewHJfLcbkcl8txuVwnLteJy3Xiclwux+VyXC7HFXJcIccVcp2EnM+Q83m/IlfHHnJcIdd/yvWfcv2nHFfKcaUcV8pxpVwnKddJynWSclxbjmvLcW05ri3HteW4tlwnW87nlvOJr97XM437q3aXTXgK47hG8fvy8r6/Xnf5PMZA3/w+B9wY6Gs2YZy3Wbzk37pwCKfwFhZffCX/8hA24SksvkO88F7g+yxyY7iveQjjWKJ4Ci9hF8Y1kMUpvIUP+WZF1YN7hu+zrY0hvmYXrvW/z4M2hviat/Ah457h8hA24fL9vpKx8Rt2zS4cwim8hQ8ZWXEZa9Y14Pi3dW5xz3D5kHHPcHkImzBqrnOOe4bLLhzCKbyFDxk5cBm+tUfIgctTeAm7cAgn9+7mAPiQcV9xGdebFzvPG+4ZLqfwFsax1LV05FzhfcHlJYz1yxfvCy6ncK1fn51hrA//FmN9zUPYhKfwEnbhEE7hLSy+Q7zuT23MYhcO4RTGsXzXJEbz6mdD9v0pvMtTuGquzwExmtccwlVzffZ3fyLv/ttDxk9qXBbfKb5TfPFDOpddOIRTWHyXeKGvE7yEXRjHEsUpvIUPGX1dnwNiZq/ZhKcwfHcx1j/FW/iQ0fv1eVCi9y+b8BRewi4cwuW7a9/R+5cPGb1/eQib8BRewlizrgG8L8D5Ry9fnsJL2IVDGDXXOUePXz5kPBO4PIRNeAovYfjWHqH3L6fwFj6PMb/XPN7e4cfxmqfwEsb15sXnnTfM7DUPYRPGsexinivM5jVvYaxfvnh9vzyEa/367Ayzefff2hJ2YfE18TXxxes7GK/vl4ewCYvvFC/0deUwZvYu3x/IAg9hHMsortyo3MZsXnMKV831OSBm8y6jxy9XzfXZ3/1ZPPzb+4Na4CUsvi6+Lr73B7XAh3x/UAs8hMU3xAt9XZ9FYmav+ZDR1/W5IWb2mk14Cte+1/0wZvaaQziF4VvXJHq/PtvCbF7zFP7WX/V5EH4KrzmEU3gLH3L1fvMorn2v3m+ewkvYhUM4hffj+r27P57F+LerOIRTeAsf8vgJo+YoNuEpvIRdOIRTeAvD99sjzOY1D2ETnsJL2N/e4Qf0mlN4k9Hv9dkoZvbueZtL2IVDGMfyXUuYzbvnag1hE8b65buWsAvX+vXZGWbz+t/KHi3ZIxdfF18XX5/CS1iuDZdrw8XXxev+PGadq/vzmOAl7MI4lrom789g1l7fn8EED+GquT4HxGxe8xKumuuzv3N/BhP/NoW3sPhu8d3iix/RujyFl7ALi+8WL/R1fRaJmb3mKYxjwf/ehUM4hWvf63NAzOwVH8zsNQ9h+O5irH+KQziFa/3v86CDn9G7jN6/PIRNeAov4fL9vnJ0ML/XnMJb+JDR+5eHsAljzVmMf7s+nj/hIWzCU3gJo+YoDuEU3sKHjN6/PIRNGL61R+j9yy4cwim8hQ/3Dr1/eQibMK43L06eN9/Chxw/YRxLXUsh5ypcOISxfvnGFj7k6v016zpJ2aOUPUrZoxTfFN8U30zhLSzXxpZrY4vvFi/+qPXBzF7zFj5kvKZPcOXG99nQ+fFHrc/v/qg1uGqe4BTewlXz99nfGfdHra14CJvwFF7CLhzCKbyFD3mI7xAv9PX3WeTBzF5zCuNYoviQ0deXh3Dt+/c54MHMXvMSdmH47mKs/11XmM1rHsK1/vd50MHP3DUvYRcO4RTewuVb1wDm95qHsAlP4SXswkFGX6+6BvDavercopcvu3AIp/AWRs11ztHjl4ewCU/hJezCIQzf2iP0/uVDRu9fHsImPLl36P3LLhzCuN6+fMPM3j1v24Sn8BLGsdS1tOVc4b4djB6/jPXLF6/vl6dwre91nRzZoyN7dGSPjvge+mJOr3kIm/AUXsIuTC/M7NWfkDiY2Ws24SmMYxnFlRuV25jNaz5k9Pj3OcLBbF6zCVfN3+cLB7N5/W9dOITF18TXxJd/0uLY/ZMWYBOewuI7xQt97XWu0NeXhzCOJYqn8BJ24dr377ODg5m95i18yOj97/OFg9m85bUX6P3LLlzrR9WP3r+8hQ8ZvX95CJtw+UbtO3r/sguHcApv4UNG71/GmnUN4LU76tyily8fMl67Lw9hE0bNdc7R45ddOIRTeAsfMnr/Mnxrj9D7l6fwEnbhEE7uHXr/8nmMub5mXG9e7O+8YWavOYW3MI7lu5Ywm4dzhdm85iWM9csXr++XU7jW/57nHMzm3X9rP+EhLL4mvia+eH2/HMIpvIXFd4oXXtO/zwsOZvbW98z/YGavOYW38CGj9y8PYeRknVv8oP3lJezCIZzCW/iQ69czrLa6fj3j4iLioOpg0fiXU3gLHzIa//IQNuEpvITFN8Q3xDfEN8Q3xTfFN8U3xTfFF3/zYoBDOIW3MHzrXOFN/QBP4SWM44riEE5hHFcWH/5bfFh/eQiL7xHfI754U3A5hFN4C9MXw37NOFe72IVDuI7l+2DlYKiv+ZDxZv9y7dH3QcnBUF/zFF7C5ft9aesshMP38P8shAMY4XAZ669iE57CS9iFQziF4VvnBOEAxpuCy0PYhKfwEnZhrPldAxjeW7vOLW4ALi9hFw7hFK6aT51z3ACAcQNweQib8BRewi5cvqf2CPlweQsfMvLh8hA27h3y4fISdmH0zvdigaG+e97Q+5dNeArjWOpaSjlXuDG4fMi4MTjlixuDyyaMc1XXyZY92rJHW/Zoi+8W3y2+uDG4PITl2jhybRzxPeJ1/7Tkd7x+/7QkeAibMI7Fiys3vgfRx++fkARvYezvl2MY3msewjhXWTz5b++fkAS7sPgO8R3iizcFYPxdjMtD2ITF18QLff19WHMwsHcZfX35W9O/D1YOBvaap/AS9uJRHMIpvIVPcZ3/hfWrtjWFlzDWX8UhnMJb+JCr95uHMHxr330KL2EXDuEU3sKHHFizroHAv61zGym8hQ85f8JDuGoedc6rx5uXsAuHcApv4UOu3vdRe1S932zCU3gJu3Bw73YKb+FDRr9/Hx4dDODd83ZcOIRTGMfyXUsYwMO5wgBe8xRGzbPYhUMY52oVb/m33CMM4DWL7xDfIb5jCbtwCKew+Jp4Gc6/F+NYotiFQziFt/Ahz5/wuH9N+QT+JjRwEhfRiUFM4n5Yf/25bodq7q5xEhcRx5LF+/4J9VOzdRfrzz9fxIVaJwdNfXkK40SdYuc/DWIS6eh0DDq+P/t+4v3Z9xPvz76feH/2/UTQLWiBBq9PdjBl12zCVb/VhY0Gv+zCIVwbXe96MGXXfMho8MvwrYscjVxviDBx1xzCWL82E418+ZDPT3gIm/AUhm9tNJr9cgin8BY+jzGJ1zyEseYprn9bT6UwTXcZjXx5CJvwFK6a65MFTNw1h3AKb+FDRlNfHsLwncVTeAm7cAin8H57h0m8y2j2y0MY+zKKg+cNL+KXt/AhLxzLKpZzhRfxyy6MmssXL+KXtzDO1XedYOLu/luXPXLZIxdfF18XX7yIX05huTZcro0Q3xCvwJp1jeHF/XIKb2Gs+WURpuyah7AJ/x1L1oPDGrJrdGIQk7iJ52H9TO5FnKPaM/T8ZRcO4TqehX+7hQ8ZPX/573i8Ho7VAF7jJC6iE4OYxN2ICTuvT3IwYdc8hZewC4cw6v76DFN1Xp9aYKrO64k+fgmv2YWxjhenMM5LFB8y+vsy6s9iE57CS9iFQziF4VvnB/0NRn9fHsImPIW/LUGZaHWcHrT6ZTltaPX6YAaDd80mPIWXcB1WfZCDgbzmFN7C5VsfcmAgr3kIl299kICBvOYlDN/aLkTA5RSGb10miID6sAEDeV4fJGAgz+uDBAzkNU9hrF/Hizi4vIUPGXFQ7YkhvHtJ4iX/sguH8CZ/L+dIzpq7a5zEb58rTmvorjGISdzE8/Dr9MZBNGLVWR9IYKiuOYW3cJ2H78fXDn4Ur3kIm3AdzShcRCcGMYmbeB6OH3EQv3XrXUCN2zXiYMApvIUPGb1fT9AxbddswlN4CbvwdzwDmMRNPA+/vm8cRCNO4iI6EUfjxYeMlr88hHE0UTyFl7ALf0dT72JqDK9xE8/Dr90bB9GIk4jdyeIU3sKHjJa+PIT/Vse70BrFa1xEJwYxiXUsv8LzMH/EQTTiJOJY6rhw516fEWHOrnkI1yrVHdXrFxfRiUFM4iaeh9XrFweRboduh26Hboduh26Hbqfd/h5Nocu/j8A+MVUsFa6iTtX30dQnUsVWcUTgZr/FUGEqpgpUgEJxR9AiVKQKVDAhjghEQ4uhwnpbPzFVLBWuIlSkiq3iiJg/FTjSBbFUuAocqUPgSANiqzgiEBstcKQJYSqmiqUCFaBQ3C9sbAluGFpsFUcE7hlaDBWmYqpYKlyFVvDlTH2S8fEWPuQvZ9bG8X8589iEv6DZOMmVNM0uHMIpvIUPOX/CQ9iExTfFF08RNq5ihM79vyB17qHhiWCLqWKpwGrYTrxR+J7Sf2KoMBVTxVLhKmo3DqIANxgttopDgeG/J4YKUzFVoIKAcBWhIlWgggFxRCB/zoRABQ5hKqaKpcJVhIpUsVUcEcifFlqB1cufgafwEq5XQJRvIZzC32V5j/cLnuYvdx4PYROewkvYhUM4hcV3ii/S5mBrkClnQ+D8HYhUsVUcEZUc8cPSlQ+B1zCMDD6RKraKI6JuRZ4YJRaEqZgqlgpXESpSxVaBCnB950/FUGEqUAGulFwqUAHOaIaKVLFVHBH7p2KoMBVVwcCJr5R5wlWEilSxVRwRlUxP1KWJM3VMeAovYRcOYTjU1mLEMMaEmCpqqQC7cAin8BY+5PETHsImjBO1IHCiHCJVbBVHhP1UDBWmAgcIU1sqXEWoQAUJsVUcEfOnYqgwFVMFKtgQqOBAhIpUsVUcEeunYshWLt3kpZu8lgpXESpSxVZxRGgEYaDxiaXCVZSP/SAkgkwjyG4EXVE+hgUQQS2WivKx+29CF0gVW4VWkFpBagU3gq6YKpYKV6EVpJoiWwwnEdnSYqrAweFSRra0CBWponwMlzKy5QpkS4uhAhXgGj3wwTV6QkWqgA8uPiQMBAYcnxgqTMVUsVRUBfMHESpSxVZxRNS9zRNDhanA0gaBBerEY97xiaHCVEwVSwUOwSFCRarYKo4IpEuLocJUoIKAWCpcRahIFVvF4QZjTvKJocJUYOcWRMoZRWy0OCL8pwIHlxB6EhEbLUIFfFAB7mlaHBEIlImrKnQbQ7cxdBtDKwitILQCBEqLrUIvpNQLKbWCVFM8a8G7k5mpYqs4InCzsnApb3mrMvdS4SrqENaASBVbRR3Cwv7om6Wpb5amvlma+mZp6pulqW+WMBD5RKrYKg4Ffg3xCVNR+7MmRKhIFTg4hzgikBQthoq6QlZATBVLhatABQkBHxSKQGkxVMDnQEwVS4WrCBWpYquoCryuEExLPjFUmIqpYqlwFSECSeEGgQVw4hEOLVxFqEgVWwUOAVuC2GgxVJiKqWKpcBWhAhVgGxEoLY4IBEqLocJUTNlgBEoLVxEqsHOVoxin7DOKW48WU8VSgYPDxZd6EvEe5wrERgv4oALch7SYKuCDq2rrNm7dxq3buLWCrRUcrQD3IS1MhV5IRy+koxUcMcWYZcQPopaOAWEqpoqlIkUgHMIghgqsBlNEQNTOYSAywiGGClOBCgJiqXAVIT5o9P6/bBVHBBq9xff+C7tY85OPp/AS1uPHvcE9ZNwbXLH0zKxa6zIOJSFwKFgZDd8iVWwVRwQavsVQgZN5IKaKpaIqwFN6zE0GHqVjcDLwjByTk4GH3zU6ue71VM9Nm4fwd8rw7hV/qjjyCnhgk3GP0GKrOCJwj9BiqDAVdZR4iI05yydcBSrADuC5R+KcIRPwEBvDlrFxZr5MWHjHXNOWj034z2Ti3XtNVT5O4XLAI1uMVbZAz+P5LYYsnzAVdYx4ZIv5yydcRR0j7oMwgvnEVnEo8POIT1QFeK6K+cwnpoqlwlWEilSxRSA08PSv5i7rd2o+xj8xiK3iiECa4GkmfgjxCRS9IKaKpQJFO0SoSBVbxRGBNGkxVKCCgJgqlgpXESpSxebJwZuNFqZiqlgqYLMhQkWq2Cr+DrR+eOqPv6h5PIRNeAovYRcOYZxICNw6tBgqTMVU8R1h/rDjlTNPhIpUsVUcEZUz+cP5qpx5wlRMFagA5ytdRahABag6t4ojou49Ek83MfWZeCqJH1pMJCr+sPITS4WrCBUp4sAHh3CGClMxVSwVToHRzcQDK/xC4hNliodPmN5MPLnB+OYTpmKqWCpchOH/siBcRahIFVvFETF/KoYKUzFVaAVTK5hawdQKplYwtYIFH4fAagGB1TZEqtgqsFpdSJjCfGKoMBVTxVJRPngOhNnKnNjGas2cqLpa84mpolbD23cMYT4RKlLFVnFEoDXxTAejmE+gApwqtGaLpQI+uGDRZngGgp9AfAKrGQRWwwlBm7VwFaGifPDQAXOYTxwRaEA8TcCPIT5hKrSCoxUcreBoBSdVbNnTI1cIfhXxiaHCVEwVwYsCA5r3osDvId6txw8iPmEqJvcU05tPuIpQkSq2isPrADOcTwxuPaY4n5gqghcFBjPvdYDJzCcGLwrMZt7Ti+HMJ5YKVxHcekxuPrFVHG49hjefGCq0gqUVLK1gaQVLrhD8KGHi0c9Ga7YIFSgUZxSt2eKIQGu2GCpMxVSxVLgKVIBC0bQttoojAu3cYqioCvCeBL9r+MRS4SqqAscFi3ZusVVUBXg6gp83fGKoQAW43tDOLZYKV4EKcFmiafHuE5OXTwwVpqJ88C4ff6o48Y4Vv4eYeF+KH0R8IlVsFVUB3mPjRxGfGCpMBSpwCJgmBExRKHobbz8xoZl5Fzgi0NsthgpTMVUsFVUB3oLidxGfQAUoB/cHLY4I5EGLocJUVAV4S4ffUHzCVYSKqmCjUORBiyMCeYC3gRjtfMJUoIKAQAWoDXnQIlSkiq3iiMA9Bd434ccWnzAVU8VS4SpCRarYKo6I0ApCKwitAJGG9034FcYnUgSiBm+P8AOKT6ACHDai5gpETYuhwlRMFTgHB+KrbWNSA7+k+ESq2CqOiIqaJ4YKUzFVLBVawdEKjlZwtILDCgZ+e/EJ+AwIrGYQ3NOBMc8njggESr1pHxjzfMJUTBVLhatABVekChzPNT0i7KcCx+MQWC0gUgWOB0eKpKgNHhjZfGKoMBXwSYilwlXEu5AGhjmf2Cq0gqUVLK1gaQVIiisc184VU8VSgRzF2UEHt0gVW8URgQ5uUVfvwIVUHfzEVLFUuIpQkSLqpmQPXJY5VJiKqWKpcBWhIlVsFUfE1gq2VrC1gq0VbK1gawVbK9hawdYKtlZwtIKjFRyt4GgFRys4WsHRCo5WcLSCIxVgiPOJocJUTBVLhasIFaliq9AKhlYwtIKhFQytYGgFQysYWsHQCoZWMLQC0wpMKzCtwLQC0wpMKzCtwLQC0wpMK5hawdQKplYwtYKpFUytYGoFUyuYWsHUCpZWsLSCpRUsrWBpBUsrWFrB0gqWVrC0AtcKXCtwrcC1AtcKXCtwrcC1AtcKXCsIrSC0gtAKQisIrSC0gtAKQisIrSC0As3EoZk4NBOHZuLQTByaiUMzcWgmDs3EoZk4NBOHZuLQTByaieNm4oRwFaFiM/3HjUGIG4NXDBWmYqpYKlxFqEgVWsGRCuz3UzFUmIqpYqlwFaEiVWwVWsHQCoZWMLSCoRUMrWBoBUMrGFrB0AqGVmBagWkFphWYVmBagWkFphWYVmBagWkFUyuYWsHUCqZWMLWCqRVMrWBqBVMrmFrB0gqWVrC0gqUVLK1gaQVLK1hawdIKllbgWoFrBa4VuFbgWoFrBa4VuFbgWoFrBaEV6A2g6Q2g6Q2g6Q2g6Q2g6Q2g6Q2ghVYQWkFqBakVpFaQWkFqBakVpFaQWkFqBakVbK1gawVbK9hawdYKtlawtYKtFWgmmmaiaSaaZqJpJppmot1MDAhXESpQwYbYKg7FvJmYEEOFqZgqlgpXURXU50wDM7BPbBVHBDKxxVBhKqaKpcJVaAVDKxhaATKxPh0bGKJ9YqgwFVPFUoEKJkSoSBWoYEEcEcjEFkMFfBxCV0O+tTgikG+GLUG+tTAVOB5cB8i3Fq4iVKCCA7FVHBHItxblM3GqkFUTu4CsarFV4BrFAjerrhgqTMVUsVS4ClSA04usarFVHBHIqhZDhamYKpYKV6EVpFaQWkFqBVsr2FrB1gq2VrC1AmTVxBWCrGqRKraKIwJZ1WKoMBVTxVKhFRytAFk1cZEjq+qToYHx2iswXvvEUGEqpoqlwlWEilSxVaCCunYwhfvEUIEKEmKqWCqqgvoAaWAK94lUURWsu/QRgaxqMVSYiqliqXAVoSJVaAXIqhqiHZjPfWKoMBVTxVLhKkJFqtgqtIKlFSytAPlWI34DA75PLBWoAFuCfGuRKraKIwL51mKoMBVTxVKhFbhW4FoBMtFxUSATr0AmtqgKarBzYMD3iamiKqgPgwYGfJ8IFVVB4owiE1scEcjERAXIxBamYqpYKlxFqEgVW8URsbWCrRVsrQCZWJ8MDUwIP+EqUAGueGRii62iKtgIB2Rii6GiKtjYRmRii6WiKjgoFJnYIlVUBXjIjJ9rvQKDxE98FRw8aMcg8RNTxSqxIFxFqPgqOHj7j99zfeKIqEw8NR41MHz8hKmoCvAajF91fcJVVAW4r8IPuz6xVVQFuCnBKPMTQ0VVgPsQjDI/sVRUBXj9wSjzE6liqzgiKhOfGCpMxVSxVGgFUyuYWkFl4lk4o5WJLSoTn6gKFna7MvGJqaIqQHRiBvqJUFEVIGowA/3EEVGZeBzXTmXiE6ZiqlgqXEWoSBVbxRERWkFoBaEVhFYQWkFoBaEVhFYQWkFoBakVpFaQWkFqBakVpFaQWkFqBakVpFawtYKNCnCRb1MxVVQFgd2uTHwiVKSKreKIqEx8YqgwFVOFVnC0gqMVHFQQEFvFocAE9ak5h4EJ6idMBSo4EEuFq6gK8i6dKraKqiCxNDKxxVBRFdQswcCP3T6xVFQFNUsw8Hu3T6SIezc4IHDP94NYKlxFqEgVW8URgXu+FnU8NeE+MFz9xFSxVLiKUJEqtoo6ozX0MPAH6Z8YKlABdgH51mKpwL2/QYSKVIEKsPVIsYPDRoq1mCqWClcRKlLFVnFEIMVaaAWhFYRWEFpBaAWhFYRWEFpBaAWpFaRWkFpBagWpFaRWkFpBagWpFaRWsLWCrRVsrWBrBVsr2FrB1gq2VrC1gq0VHK3gaAVHKzhawdEKjlZwtIKjFRyt4EgF+IHeJ4YKUzFVLBWuIlSkiq1CKxhawdAKhlYwtIKhFQytYGgFQysYWsHQCkwrMK3AtALTCkwrMK3AtALTCkwrMK1gagVTK5hawdQKplYwtYKpFUytYGoFUytYWsHSCpZWsLSCpRUsrWBpBUsrWFrB0gpcK9BMTM3E1ExMzcTUTEzNxNRMTM3EvJlYL215M/GKocJUTBVLhasIFakCFSyII+Jm4hWowCBMxVSxVLiKUJEqtooj4mbiFVrB1gq2VnAzMSBcRaj4q8B+eHdYw/IUR8SXiRRDhamYKpYKVxEqtIKjFRypoIbl/8SCmDyEffPNIVIFVtsQR8T4qRgqTMVUUceD97Q1LE8RKlJFVYAPyGtY/gn7qagKBg7OTMVUgQpwcOYqQkWqQAU4VYYKcDwTPgdiqlgqXEX54JOUGqP/EzjSWT746KLG6P8EKlg/FUOFqagKDIWupcJVhApUgONZMEWhXqb45KF+AflPoFAvU7yrrt9AplgqXEWoSBVbRVWAp8f1U8gUJhds6NUbS4WrCBWpYqs4Im5WXTFUaAWpFaRWkFpBagWJw8a5zq3iiNg4bOzCHipMxVSxVLiKUJEqtooj4mgFRytAVuFJyUZWtVgqXEWoSBVVwcLZQVZBHGRVi6ECFSTEVLFUoIIDURXgiUx9R4CiKsBDmIN8uwL5hmfeB/nWwlRMFUuFqwgVqWKrOCJMKzCtwLQC0wpMKzCtwLQC0wpMKzCtYGoFUyuYWsHUCqZWMLWCqRVMrWBqBVMrWFrB0gqWVrC0gqUVLK1gaQVLK1hawdIKXCtwrcC1AtcKXCtwrQAxWF/SGQcx2GKrOCJC7hzqCwMUpmKqWCpcRahIFXLnUD8c/VfBgsBqV+B4HCJUpIqt4ohAvrUYKnDe0Ohb92fr2dl6dpBVLYYK7A/yAFnVYqlwFXqFHK3g6BVyeIXY7/dTMVSYivlqsx+yqoWrCBX5arPfzaorjoihFQytYGgFklX2k6yyn2SV/SSr7DdSyhlbxRFhPxVDajNTMVVoBaYVmFYgWWU/ySr7me7C1HMwh5Rzs+oK3YWpuzBdartZdYXuwtQKplawtIKlu7B0F5buwtJzsPQcLL0Olu7C0l1Yuguuu3CzakOYClRwIJYKVxEqqoJAbciqFkcEsqrFUGEqpoqloioIHAKyqgXu37AL+XtJYT9kVX1Oa/XVCIqpYqnQ3U7d7dTdTu251J67KXaFXvFbd3vrbm/d7a27vfWK33rFb73etl5vR6835Ft9CG0/5FsLV4EzivOGfAtUjXxrcSgG8q3FUGEqpoqlwlXwGbHhaw4t8MSsxVBhKqaKpcJVhIpUoRUMrcC0AtMKTCswrcC0AtMKTCswrcC0AtMKplYwtYKpFUytYGoFUyuYWsHUCqZWMLWCpRUsrWBpBUsrWFrB0gqWVrC0gqUVLK3AtQLXClwrcK3AtQLXClwrcK3AtQLXCkIrCK0gtILQCkIrCK0gtILQCkIrCK0gtYLUClIrSK0gtYLUClIrSK0gtYLUCrZWsLWCrRVsrWBrBVsr2FrB1gq2VrC1gqMVHK3gaAVHKzhawdEKjlZwtIKjFRypAN95eGKoMBVTxVLhKkJFqtgqtALNRNNMNM1E00w0zUTTTDTNRNNMNM1E00w0zUTTTDTNRNNMNM1E00w0zUTTTDTNRNNMNM1E00w0zUTTTDTNRNNMNM1E00w0zUTTTDTNRNNMNM1E00w0zUTTTDTNRNNMNM1E00w0zUTTTDTNRNNMNM1E00w0zUTTTDTNRNNMNM1E00w0zUTTTDTNRNNMNM1E00w0zUTTTDTNRNNMNM1E00w0zUTTTDTNRNNMNM1E00w0zUTTTDTNRNNMNM1E00w0zUTTTDTNRNNMNM1E00w0zUTTTDTNRNNMNM1E00w0zUTTTJyaiVMzcWomTs3EqZk4NROnZuLUTJyaiVMzceLdbv34hk28221hKqaKpcJVhIpUsVUcEaYVmFZgWoFpBaYVmFZgWoFpBaYVmFYwObti9zsPLUzFVLFUuIqqoEZTbeLdboutoipI/Bu8220xVNQ5qB/dtIl3uy2WClcRKlLFVnFE4N1ui6FCK3CtwLUC1wpcK3CtwLUC1wpCKwitILQCvNutX3GxiXe79eMBNvFut0WoSBVbxRGB98EthgpTMVVoBcmJdrvfrWiRKjhPbve7FVfsnwpcibhGMUfcYqpYKlxFqEgVW8URgTniFlrB0QrwPrgGzmzi3W7e/wvOaB3pwrvdFkOFqajV6o9z2cKTufopHFt4MncFsqrFUGEqporanxpSs4WsahEqUsVWcUQgq1oMFajgBzFVLBWuAhU4RKrA/kyII+Jm1RVDhalABbU/C+lSc962kC4tTAW/pWD6LQXrbylcESpSxVZxRNxvKVwxVJgKrcC1AtcKXCtwrcC1AtcKQisIrSC0gtAKQisIrSC0gtAKQisIrSC1gtQKkC54QV5IlxZLhasIFamirt5zlz4i8JTt4ILFU7YWpmKqWCpcRahIFVvFEXG0Any+cHDF4/OFFvy2it1vKbRwFaECPnXFO9IFjzfxjQN8V8TwjYMnXAW/92H4xsETW0XtaU3kGr5x8MRQYSqmiqXCVYSKVLFVaAWmFSB36isYVt8e+J43QmQJHELdCT1xRNRz/ydmiQmB1RZEqtgqjoj1UzFUWAls1poqlgpXESpSxVZxRDgqMIihwlRMFagA1467ClSAc+2pYqs4IuKnYqgwFVPFUuEqtALkDjIe3wR44ohA7iDj8U2AJ0wFvhnkEEuFqwgVqWKrOCJwV9NiqDAVWsHWCipdxsClXBkyBjarMmQMXKOVIU9MFUsFVqula0L/e74NMVSYiqliqXAVtT810GQ1oU+xVRwR46diqDAVUwUqWBCuIlSkClRwII4IZEgNHlogNuyKVLFV1AI1bGWB2GhRG4wQwlD+E1PFUgGf2p9AbBiqXvwimd0B+xZTBb9IZhiwPy1CRb0pRqPfAfsWRwQeELUYKkzFVLFUuIpQoRW4VoBwMFyWiID6erwFIsBwqhABLVLFFlFvX0YNnFmNxH+fgEC4ilCRKraKI6JuI8bEid9DhamYKpYKVxEqUgWOB9foPiIQAS2GClSA3UYEtEAF6NPjKkJFqtgqDkUiNloMFaZiqlgq8FXDAREqUgW+7GgQR4R82dHuSDwC8o7Et5gqlgpXESpSxVZxROBhdgutwLQCw7lOCJzRA1FndOF/hgxpMVSYilpt4bBx64G3PIlbjyuQIS2GClMxVdT+1K8OW+LWo0WoSBVbxRGBW48WQwUqwAbj1qPFUuEqUAGuHdx6tEAF1fWJ2wg8P0hkSAtXESpSxVZxRNTDkSeGClOhFSS/XGt37LxFqOCXa+2Onbc4IvDAGK+Ad+y8hamYKpYKVxEqUsVWcUQcreBoBUgXx2YhQzA5ghHyUbNfhhHyKzBC/sRQgdUCAqslxFZxROA2osVQYSqwPwdiqXAVoSJVbBVHhP1UoAKHMBVTxVJRFdQ3LA0j5E9UBZhqwQj5E0cEMqRFVYAJFQyXPzFVLBWuIlSkiq3iiEDutNAK7pefUdv98vMVS0Vdo0gk/Eb7E6kCX78eEEcE7l1aDBWmYqpYKlxFqEgVWoFrBXhjgxmZjdzBuMpG7uCp+0butNgqjgikC96jb9y74J34xr1Li1SxVRwRuHdpUfuDR8kYB39iqlgqXEWoSBVbBY4HjYF7lxZDhalABbh2kC4t4FPhgAHugUevGOB+YqlwFaEiVWwVRwTSpcVQoRXgbsOuWCpcRV1VuGU796cVrtgqkP517Zz70wpXDBWmYqpYKlxFqEgVW4VWMLUCZAieX2MYe+D5NYaxBx4/Yxj7iSMCSdGiVsOjZAxWD7z1xWD1E1vFEYG7jRZDRe0P3uRjsPqJpcJVhIpUsVUcEXjQUV8aNwxWP2EqpgpUgIsCSdGiKqgv4BkGq5/YKo4I3KHgWSdGrp8wFVPFUuEqQkWq2CqOiK0V3J88QG33Jw+umCrqGsWdA34L/olQgezF9YY7lBZHBO5QWgwVpmKqWCpcRajQCg4rmBjTHvV76xPD2KMe5E4MY496KDsxjP1EqtgikC71YGBisHoc+OAOpUWoSBVbxRFRdyhWjzcnBqufMBVTxVLhKkJFqkAFCXFE4A6lxVCBCgxiqoDPgkgVW8URsX4qhgr4YH/WVIEjxS4sV4EKUOhKFagAm7WOCEcFOPE+VFQF9e5wYnz6iapg4CRWIj1RFQyckEqkJ6qCgYuvEqlFJZINHHYl0hOoAIcdUwUqwGGHq0AFOOxIFagAhx1HRKICHHYOFVWB4bArkZ6oCgyHXYn0RHXjRKF4z9Riqzgi8J6pxVCBCnAS91SxVKCC+29CRarYKo6Iut95YqgwFVPFUqEVHK3gwKf2B+PTVq/OE+PTVncbE+PTT7iKUJEq5HhqsPqJ8VMxVJiKqWKpcBWhIlVoBUMrQFbdw0Yi3cM2PR7T47Gt4oiYPxV6PFOPZ+rxTD2eqccz9XimHs/U45l6PEvP6NIKllaARLqHjdy5h730eFyPB7nTwlToFeJ6PK7H43o8rsfjejyuxxN6PKHHE3o8oWc0tILQCpAu97CRIfewU48n9XhSr/jUKz71Ckm9QhI+B+KIkB9ymnd4uYWpmCrKpx4/z4E8qKfH8w4iO5bGHUoLU1GrBRaQH2WaQ36Uad5BZMch4A6lxVZxKO4gcouhwlRMFUuFqwgVUoEhKepr3tOQB/UsehryAEFsyIMWoSJF4N6lHqNOwx3KhA/uUFq4ilCRKraK2p96wDoNedBiqDAVU8VS4SpCBSoIiK3iiEAetEAFA8JUoIIJsVS4ilCRKraKIwIZ0mKoMBVaAZ6hBKrGM5QWoaKukMA24hlKiyMCA8KBrceAcAtTMVUsFa4iVKSKreKISK0gtQKky8KljAxZODhkyMIhIEOu2D8VQwVWOxC1muNywT1FiyMC9xQthgpTUfvjaEDcU7RwFaEiVWwVh6IGdylwPBvCVEwVSwUqmBChAhUkxFaBCrAA0gVpiR8rx8/ETfxY+RNTxVLhKkJFqtgqjgg8kWmhFZhWgKyqvzY4Mbj7hKsIFaliqzgikFUthgpTgQqwWciqFq4iVKSKLQLpgnbGqO0TqWKrOCKQLi1QNTYY6dIC/wa7jXuKFkNF/Zt6PjoxHPvEUlG7nTBFHrRIFbXbiQqQB1cgD1rUbtfU68QPjz8xVSwVriJUpIqt4ojAfUgLrWBrBXjHkth6ZEiis5Ah9Rh1TmRIi6HCVGA1nB3kwT0HyAMIDLo+MVSYiqkC+3MgXEWoSBVbxRGBPGgxVKACh5gqlgpXURXUnOrEcOwTVUE9wJsYjrWNf4M7lBZDhamYKpYKVxEqUsVWoRXcLzehtvvlpitMBb5OsSCWCleBr1MYRKrYKo6I++WmK4YKUzFVLBWuQitYWgEypCa85sJ9SD05nQvvZTa2Hu9lWoSKFIF0qQGguZAhBz7IkBauIlSkiq2i9ufgjOJ5SIuhwlRMFUuFqwgVqADXKO5DWhwRuA9pgQpw7eB5SAuM9OKEYFi+xRGBYfkWWA29jQxpMVUsFa4iVKSKreJQOHKnxVBhKqaKpcJVhIpUsVVoBUMrGFoBcgdPdR25g+ewjtxp4SpCRarYKo4I5E6LocJUaAX4Udr6aHbiR7efCBUYwnWIreKIwFB+/bTCxI9uP2EqpoqlwlWEilSxVRwRSytYWkG9M5o1BjwxNjvxXBljs/N3/2dHRKXLE0MFVsNhO1bDBvtWcUTET8VQYSpmiQ2xVLiKUJEqtoojIn8qUAE2OE3FVLFUoAJcOxkqqgI8pa4RWIojonLniaHCVEwVS4WrCBVawf0DAThSZNUVyKoWdYXg/gA/hv3EVIFhebQzRu9bhIpUsVUcCvwY9hNDhamYKpYKV4FzXZcyxmYnnu5jbHbigT7GZp9YKlwFVsPShtU2hKmYKpYKVxEqan/wdB8ztE8cEfVe5omhwlRMFUsFKgiIUJEqtgpUUNcO5m6fQAU4vciQFq6ifAwnHunSAkeK04t0uQLp0gI+KMdNxVSxVLiKUJEqtoojAonUQisIrSC0gtAKQisIrSC0gtAKQitIrSC1gtQKUitIrQCJhCfBmOJ9IlVsFUcEEqkFvjuGPb1Rc/8voSJVaMtsLI0r/mjLHG2Zoy1zcAgHIlSkivLBo2QM4d4FMIT7xFBhKqaKpcJVhIpUsVVoBUNNkS54zJ1IlxahopauGeeZyJ0WR0Td1TxRPnh6nEikFlPFUoEKHAI+AXFEIHdawCchTMVUsVS4ilCRKlABThVy5wrkTouhwlRMFUuFq6il8cQZo7YTD4wxavvEUuEqQkWqqEPA895EoFyBQGkxVJiKqWKpcBWoANuIQGmxVRwRCJQWQ4XJBiNQWiwVrgI7V3mQSIp7RnHv0sJUTBU4OFx8W08iYqPFEXHggwrOUGEq4IOr6ug2Ht3Go9t4tIKjFRypABO5TwwVpmKqWCpCBW5B6xxgPPeJocJUYOkNgRvNgEgVWwUOodISQ7hPDBXlg0fjGMLtBRAbLVyFVmBagWkFJrf7GMJ9YqgwFVrBVFMkBd5VY7q2BZKiRS2Nh+b46eYnpoqlonzwGSV+uvmJVLFVoALsDwLFUSgCpcVSAZ+ECBWpYqs4IhAoLYYKVIArBIHSYqlwFaEiVWwVRwSSAh+zYtR24nE6Rm2f2CqOCMRGi6GiDgHvTzFq+8RS4SpCRarYKo4IBAreymPU9glTMVUsFa4iZIMRKC22ikOBH1ue+JgIE7n3jGIi94lQkSpwcHXxYe72nkTM3T4xVcAHFeA+pEWogE9CbF1AthE/nPyEVmBagWkFCJQWriJUpAqtYKopPr45VywVriJUYOm6lDFqex9I4nePnzAVOIQDsVS4ijoEfKyC8dy3wFZxRLhW4FqBawU+VSwVriJUaAWupkgKfBCCudsnloo6OHxEgrnbJ1LFVlFXCD4iwdztE0OFqUAFuJQRKPhYBdO1T2wV8ME1ikBpMVSYiqliqXAVqABXCAKlxVZxRCBQWgwVpmKqqKXrw5OFXzeeNSi+MDb7hKmYKpYKV1GHUB9qLAzUPrFVHBG4D2kxVJiKqQIVLAhXESpSxVZxRCBQaoMXhnCfMBVTBXbOILacUdx6XIHYaDFU4OAcQk8i3rG0SBXwQQW4D7kC9yEt4JMQuo1Lt3HpNi6tYGkFSyvAfUiLI8L1QnK9kFwrcDVFUtwzivG1FkcEPgxqgaU3BD4uxJHiw6AWoQKHcCC2iiMCsXGwPzlkgTQVU4VWkFpBagX4MKjFVnFE7J8KrWCrKZLi4CQiKVpsFXVwBy2DpGgxVJiKukIOGgO3Hi1cRahABXUp4+eEZ33GsvBzwk+YCvgkxFLhKkJFqtgqjggESo3rL8zDPmEqpoqlwlWEihRRSbHqc4xVvxP8/aAUhKsIFaliqzgiKjZWfcKxMAL7hKmYKpYKVxEqUgUqWBBHxPqpGCpMxVSxZIMRKC1CRarAzlWOYh62z6hPFUuFq8DB4eJzPYnxUzFUwAcVxFSxVMAHV1XoNoZuY+g2hlaQWkFqBWkqpgq9kFIvpNQKUk3v+NqBMBVTxVKBpXEpy2DbGjLYtoYMtq0ajv1+AQ3CVEwVdQjj/hvXBUJFqtAKjlRgv5+KocJUTBVLhasQU8zDrvqgatXP71KYijq4+g7HwqTsE64iVNQVUp//rPr5XYojwn4qUIFDwCcgXEWogE9CbBVHBAKlxVBhKqYKVLAhXEWoSBVbxRGBQGkxVNTShi2pG4xlOPEVDi3qBuOJocJUTBV1CIYtQWy0CBWpYqs4IhAoLYYKVIBtRKC0WCpcRahIFVs2GIFyBQKlxVCBnTOIkDOaqWKrOCI2Dg4X39aTuJcKVwEfVLBTxVYBH1xVR7fx6DYe3cajFRyt4GgFJ1SkCr2QjlxImJR9wlRgVD0hQkWq2CqwdF3K+IVaDLGvOaaKpQKHcCBCRaqoQ6jPmRZ+obYXuKP3VwwVWoFpBaYVyFD+mjKUv6YM5a8pQ/nrDrpeMdUUSTFxEpEULUJFHVx9gLQwwfrEEYGkaFFXSH2AtPDTs09MFUsFKnAI+ATEEYFAaQEf7CkCpcVUsVS4ilCRKlABThUC5QoESouhwlRMFUuFq6ilFy4X3GAsnHiEQ4ulwlWEilRRh7CwJYiNKxAbLYYKUzFVLBWuAhVgGxEoLbaKIwKB0mKoMNlgBEqLpcJVYOcqRzFDe88oZmifMBVTBQ7OIeQkYlL2iSMC9yH1adLCpOwTpgI+CbF0AVcRKrSCoRUMrQD3IS2GClMxVWgFpqa49ajPjNbCrQfuOhduPVqYiqliqXAVoQJZBdP79Z0rjoj79Z0rhgpTMVUsFfhaGnYBgYI7yIVAuQKB0mKoqCN1rIZAabFUuIpQkSq2CnwxDhfF/aLfFUOFqZgqlgpXESpSBMZm7wlJPVLkToupYqnQI0090tQjTT1S5M4VyJ0WQ4Ue6dYj3XqkW49065FuPdK9Vei5Pnqu75eFcUKOHinSpUWoSBV6pEeOFAO1TwwVpmKqWCrkSO9AbYtUsVXIkd6B2hZDhamYKoInBGOz90gxNvuE9A/GZp/QIzU9UtMjNT1ScxWhIlXokZoe6dQjnXqkU4906pHOpULP9dRzjZ9awaOj+zu0LYYKU4EjNQj+vMS6vzbbYqvAGa3XU7+JdMVQgTO6IKYsgB9haeEqtALXClwrwI+wXIEfYWkxVJgKrSDUFG+G6sPuhRnaFngz1AIHh3N9Q+iKqWKpwOWCc31D6IpUsVWgAtSGW5zABYtbnBZLRfkELj7c4rRIFVvFEYFbnBZDBSrAFYJbnBZLhasIFaliqzgU+LXZVZ87L/ym7KqPgBd+U/aJreKIwC1Oi6ECh5AQU8VS4SpCRarYKo4IpEt9ALswUPuEqZgqlgpXEdxgDNQ+sVUcEbj5qQ/iFyZl+4ziFqdFqEgVWLouPszD9knEO6MWU0X5JCrAO6MWoaJ86gPYhUnZt4Buo+s2ulbgWoFrBbjFaeEq9EJyvZBcKwg1vT/XhBNyf67pClcRKnBwuJTxo0z44O3+KG0LU1GHUJ8uLwy6PuEqcBLhgx9l6gW2iiNiawVbK9haAX7yrcVS4SpChVaw1RRJkVdMFUsFDg4tg6RokSq2irpC6tPlhRHYJ4YKU4EKDkT54INRDLo+sVWUDz47TARKi6HCVEwVS4WrQAUGkSq2iiMCgdJiqDAVUwWWrssFg64L+4NB1ydMxVSxVLgKHEJCpIqt4ojAo5YWQ4WpmCpQAbYRgdIiVKSKreKIQKDcDUagtDAVUwWu0YDYckbxdOUKxEaLoQJL4+ILPYl4KNsiVZQPPhzGoGsL3Ie0KB98AItB114gdRtTtzG1gtQKUivAfUiLI2LrhbT1QtpawVbT++OQqPr+OOQVRwR+HLIFDg6X8v0JSBwpfr66RaioQ8Cnyxh0feJQYNB14QPl+9OzWGDfH5S8YqpYKlxFqEgVW8URcX9Q8gqtYKgpkgIfdmME9omtAgdXLYMR2CeGClNRVwju/TEC+4SrCBWooC5lDLo6PhjFoOsTpmKWwPFUoDzhKkJFqtgqjoiFCgxiqDAVU8VS4SpCRYpwLI3LxbEATry7ilCRKraKIyJwCNiSGCpMxVSxVLiKUJEqUAG2MY6I/KkYKkzFVLFkg9NVhIpUgWu0chQjsH1G91SxVLgKLI2Lb+tJPD8VQ0X54MNhDLo+sVSUDz6AxaDrW0C38eg2Hqng/H4qhgpTMVUsFa4iVIjp/+/t3Xal2ZUrvXfZ17pIHoPRr2I0GrKsNgRsSA212oDR0Ls7i6NIjr/mqqioTE7rYovfmn9FBk8jmWSQfB49i0H98+jZAYkhMyBzEdAVCZ+k+jy+GvA8vvoJPQtYXUag64TEgELMgMIGKoMwsAeRPUjsAQ6HHBAZEkNmYA8SPxRKgcVuhMBOiAzI3PM3maEwVIbeQrC6jBDYCUpQDgZ4oID+HCyMItB1QmXoz8HaIc6hnaAEEJQBgSEyJAZ4gBYCQRlQGYShMSgBBGVAYIBpNBeBARS8KEE7GAJDZEgMyAKqBLIxoDIIQ2NQAgjKgMAAD1CNEJQBmaEwVAZhaFTBEJQOBZGyEwID2mgF1FmiBSGwExqDEgSYVsAqxIJA1wmFoT8nwYM+DpnQGPpz+jpGQaDrMBADQ2RgDyJ7ENmDWBmEoTEoQWIPEj+UrtEoCIGdIAyNAZkD0DUa5aBrNMrxvEbjCT0L6QmVQRhQiKif5zUa+MvzGo0nBAb2oLAHhT14XqPxhMogDI2BPaj8UChFQiFCKQZUBmROAI1BCaAUA3oL6avLBSGwExJDZoAHaMoQlIyWCEF5AgRlQH9ORhuFoAxIDJmhMFQGYYAHaCEQlCdAUAYEhsiQGDJDYYDp3lwQ6Fr6EnBBoOuEzFAYKoMwIAsCUALIxoDAEBkSQ2YoDPCgAYShMSgBBGVAYIirggMEZUBmKAxoo11HEQI7ShTfMgMiQ2KAaQVwIeKLZYASYBxS4AHGIQMiQ39OX0AqCHSdBrgaM1djZg8ye5DZA4xDBgQGbkiFG1JhDwo/FEoB9UcI7ITAEBmQuQjoioQ3BgJdJzSGnoW+mlQQ6DohMKAQUT846P5pgK4AK4GuACtB2ANhD4Q9oCvASnheAfaEwBAZ2IPGD4VSFBQilOIJUIoByBy6DJRiQGLIDL2FFHQMDD0GCENjgAe9KSPQtfRVhIJA1wmZoT+nrwyVCEEZIAyNQQkgKAMCAzyIgMSQGQpDZRCGxqAEUIq+3FEQ6Fr6vH9BoOuExqAEkI0BgQFZEEBiyAyFoTIIQ2NQAghKXyYqCHSdEBkSQ2YoDJUqGIIyoDEoATSkf2sWhMCOEsW3zIDKIAwwjcZXuRDxxTIgMfTnCDzAOGRAZejPEbSqytVYuRqFq1HYA2EPhD3AOGRAYeCGJNyQhD1o/FAMPQTNEkOPvuRTEAI7oTIIQ2NQAgjKgK5V+BBACOyExJAZCkNlEIa2IOF4oz4xXRKONxqQGJDTAigMlUEYGoMSQFAGBIbIkBjYg8AeBPYgsAeBPQjsQWQPInsQ2YPIHuAKsPCEwlAZhAEe9D6H4FjcwFpw8OuExICcCqAwVAbktAEaG1ACxJQMYA8ye5DZA3wZDSgMlUEY2IPCD8UIpa/pFUTKTigMPXMN7Q26M6AxKAHmUPoiWkGk7ITIkBi6B33HaEnQnYa+AN0ZoATQnYY6he4MiAyJITMUhsoAD1BU0J0BSgARGhAYIkNiyAwwjeaC4UpDwWO4MiAxZIbCUBl6Fp5KgeHKAF2AsNkJgSEyJIbM0D3o60wFR89OEIbGoATQnQFhVTACaickhsyAbB8AXSWKSNkJgSEyIHMJQIWIk2MnNAZkAR5gIDMgMKAQC4CqEWGzEwoDe5DYg8QeYCDzBAxkBgSGyMAeZH7o8xZ0lMHzFnTA8xb0JwQGZK4CuiIdyPbzrvMnCAPagQCUALIxAIWI+nnedQ4Dz7vOn5AZ2IPKHlT2AF9GA5QA0SYDAgN7IPxQKIWiEKEUA5SgK0U90GW6UkyIDIkhd0DH6AOZCZVBGFoH1I/iOXBUI0NiwHPQRrUwVAZhaAy6ACGwE+BBBUSGxJAZCkNlEIZGEGC6AWBAAZVBGBqDEsSDoWehL24VxLZOSAyZoTBUBmFoDN2Dvs5UENs6ITBEhsSQGcqqYMS2ThCGRpCR7QOQqERzZigMlQGZ640P4ayjEEtgiAzIAjwomaEwoBDRqgpXY+FqLFyNlT2o7EFlD2piyAzckCo3pMoeVH6ooH7QLAWZE0BmKAyVQRgagxJ0QTn0CYEhMiSGzFAYKoMQ9O+fAyM7hLNOiAyJATlFo+iycWCYh6DVCbqgQjb6ml6pkI0BkaGXKNZy+vGuy0BhqAzC0BjYg3AwBIbIkBjYg8APhaD0FcKCcNYJgaFnru9MLQhnnZAZCkNvLvhURDjrhMagBBAULN/gFNja4/0LYlsnFAY8RwDC0BiUABoyIDBEBnjQAJmhMFQGYWgMSgDdGdBNY+YUQasVU4gIWp2gBJCNAYEhMvQsYAUKsa0TCkNlEIbGoARyMMADVCPUZUBiyAyFoTIIVTDUZYASYLgyADWHdo1xyLNEMQ4ZIAyNAZlD41MuRIxDBmQGPAceYBwyQBjwHLQqpWpEbOuEwBAZEkNmKAyVQRgaA3sQ+KH98pyGAunhrAtgugGEoTEoAQRlQGCIDD1zWLHB8a4TCkP3AKtwiHqd0BjgQRdixMNOCAx9vuqZbRxaPyAzFIbKIAyNQQlwaP2AwNCfA7HrUa8LkNMIEIbGoAQQlAGBITKgrDMgMxQGeAB3oEgDGgM86BKA4NgJgaGXdXxCYsgMhaEyCENjUIJ+fc+EwICcVkBhqAzIqQAagxJAd7AsieDYCShrNDF8Jg3IDN0DrAMK5GmAMDQGJejjnQmBoXuAVUUcIzshMxSGyiAMvazx+dIw34vPvob53h54WBrmewdkhsJQGYShMTzqVPBV3WNoFwSGyAAPIiAzFIbKIAyNQQn6FWATAgNK9AmFoTKgRBOgMSgBtArrmgi1nYA6LYDEkBngASoLw6IBwtAYlADDogGBAR6gfjAsGpAZCkNlEIZHWQvUv8fdnnAAep3mJySGzFAYKoMwNIbeqvCS6BG5CwJDZOgepCdkhsJQGYShMShB16oJgYFblXCrEm5Vwq1KuFUJt6rGrapxq2rcqhq3qsatqnGratyqGreqxq2qcatSblXKrUq5VSm3KuVWpdyqlFuVcqtSalU9PHe0qh6eO9pBD89dkBkKQ2UQhsZArUrDwRAYIgO1qh7Fu6AwVAZhaAzUqnp874LAgBJF6Ty16gmVQRhQpwpQgqdWPSEw9JxiTN6jeBdkhsJQGYShMShBH1dN6G0HC/4I6Z1QGCqDMDSGntMK0xhXDQgMkQEeCCAzFAZ4gOLFuGpAY+geYH0bwb4V69sI9q1YQ0aw74TEkBkKQyXAhxqWjXF27QQYyIDCAAMFcGYhPbvCQ4NmWlf6oUAzHSgdKY0noCwhJViq7CG7uDOg9IjdmQ6U7paQpYeMzHSmdKF0pbRQGg9GHeAzrUNFpG7tq40VkboTIkPPRl/jqT04F8fkV8TmotAqYnMnBIbI0OujwUCfwplQGCr/RhgaA3sQ2QMoQ1/UrAjHnVAZuum+Y68iHHeCEkAZBgSGyNAzp8gCRjEDCkNl6B70JbiKqN0JSoBRTF/Zqji4tioeilHMgMSQGQpDZRCGxqAE0AxF04FmDIAHaC3QjAGZoTA8PJADmeuaMaExKEHXjAmBITIkhtwBtd01YwLaAUq0woMnNAYlkIMhMOChaHySGQoDsl0BwtAY8FAUbzsY8FAUYosMiaF7ENBnuw5NqAzC0BiUoA92JnQPAlpvH+xMSAyZoTBUBpRBb2LhKUgVEJYeIFR4QmLIDIWhMghDm9Jfw1PFAE8Ve0JggIrBUajYgMxQGCqDMDQGJXiq2BNQohGQGQpDZRAG1GkBKEE6GAJDZEgM8EABhaEyCEP3oK8aVEQUD+iSNqF7EFE/XdImJIbuQZ//qIgoloj66ZImEY52SZvQGJSgHAyB4fGSxVMesjWSdSVlJdtK6kxCNyLaMnRjQGB4vOWRt4eEjGReybKSdSVlJiEPEQ0GItBn4Gs/xzY//1FZybqSp5WM8n90/pHUmXx0/JEMKxlXEs9DVaPLD+iVk57/rDLIApxai+F8Rciu9H0qFSG7Ex6loEjCVgIIQ2NQgnAwhFF2PVx3JNNK5pUsK1lXUleRxxhXkSMuV/qEf8XRtBNQHgVQGZCHCjjzUFA0j+76TD4660iGlYwrmVYStuEcOlyCc48OV/GPHt1tJONKPqyglB8dbSTLStaVlJVsK4nnAdC9BvRWj2aDk2gnJIbuPdonTpWVjCaAt/+ARykgV3j3P4sP7/4BmaEw4CloD3j3D2gMStWEPjwgMLAHwh4IeyDsgbAHwh4IeyDsQWMPGnvQ2IPGHjT2oLEHGAgMkNm/Gveixr1IuRdhGDAgLsBRsdIn02tClx6QGR5d65msKykr2VZSZ/LRlUcyrGRcybSSeSXX08J6WlhPC+tpYT0totEJIDBEBuRSAZmhF3mfia8Ii50gDI1BCfCeHhAYugd94qwiYHZCZugeQBwQMDtBGLoHBVUI2XgC3tMDHmXekIwrmVYyr2RZybqSsN1VESfISkFhQwgKclcyQ2GoDMgDTOPTYYASQDwGBIZHLmAL4gElQ1TshMLQn983fFTEy05oDP35FcUG8RjQn19RAhCPAYnh8fqGZw/pGMm6krKSbSV1JiELFaWLzl+ff0Ee0HrxFTCgMSgBun9FIaD7D4gMiSEzPHLxTNaVlJV85ALV8pioQLKHyY5kWMm4kmkl+/P6HFNFeOyEyqAEfWQvfSqqItR1wqMGBMmyknUle8n12aWKU2MnKAFUBDMTiIWdgGdXQGJATvAcqAimbRAlK5icQZSsYHIGUbITlKAPIGCrDyCeybiS/Qn4PkKsq/RomopYV8F8CWJdBR/NiHWVhpxgzN7gPEbmmBXJGJkPEIbzORWZeqjCM/kYNoxkL5H2BNhBvh/9Hm25h7WOZPdVkWf0eUyzIKh1QmRIDL3UMeeCoNYJlUEYGoMSoNcPCAx4DgoVr3/M7SBAVRSFig6syBze6wMyQ2FoBOimmMFBGOoEWEPRYnyOqRkEjrYei1gRODohMeQOAVAYKoOs5yBwdP5FCfoIfUJgiKt0cHbqhMxQGKgMEF/6zDbiSycEhrzaGqJIsSJaEUXaMG2EKNIJjUEJ0sEQGCIDShRep8xQGOBBAcADZC7BA2QhwQNk4dlVUafPrvqEyIDnPKEyCMOjk8GZ3lWR7F31mew5wRwRQkYbpnh6yGhFSfau+kx2XzFNgXDRFlAmvatOiAyJoZdWwNN7V51QGYShMSiBHAyBAc9B2Qusoewb/hnKvuGfoexbYagMwnC6IyiBx5v2mXy8Z0cyrGRcybSSeSXLStaVlJVcT9P5tB78OZJhJeNKppXMK1lWsq6krGRbyfW0sJ4W1tPCelpYTwvraY/+jLd1D+58Jh99eSTDSsaVTCuZV7KsZF1JWcn1tLieltbT0npaWk9L62lpPS2tp6X1tLSeltbT0npaXk/L62l5PS2vp+X1tD5QRsRVxbGhDTNniMBsmHVCnGXDBAZCHhumbRDyOCEy9M6HGZAe8oghTA94HMm6krKSbSV1Jh8fsyMZVjKuZFrJ9bS2ntZfdA0TRLW/6Bq+QHucI8YoPcpxJPNKlpWsKykr2VZSR7LHNY5kWMm4kmkl80qWlawrKSvZVnI97dFXMLjq4YwjGVfy8bSKZF7JspIoIZiLKCH8tI87G757EKo4ITMUhsogDI1BCfAaHBAY2IPEHiT2AK9BzGbh6M4JwtAYlCAfDIEhMiSGzMAeZPYgsweZPcjsQWEPHtNgGGP0EMaRTCuZV7KsZF1J2Abg9YiZmx6EiHFsD0EcybKSpxUMjnvw4Ui2ldSZfKjCSIaV7CWD6TkEFjbMyCGwcIIS9GmrhgktBBZOiAyJITMUhsogDI1BCZQ9UPZA4QE6hSaGzAAPUIVaGeABakPhAWqjL7W3HnJYcWznhMDQPcDsCo7tnNA9wEQJju1smChByCGG4Yg4HOlGaV3pHsIz0oHSeEIF9JzgcxBndDZMeOCMzgHxYOg5wewxzuickBgyQ2Hoz8GMCcIDG8aHCA9smDFBeOCEzFAYKoMwNAYlgD4MgAcocujDgMQAD1AZ0IcBlUEY4AHKGvrwBOjDgF49eEyPGxzpROlHzBE+IBA0ONKV0kLpRmld6R4viI8KhAuOdKQ08o1WgSH3gMJQGZQAYwh8z+MozgmwhpYkhaEy9Jw8f9IorSvdDkoHSkdKJ0pnShdKV0rTcxs9t9FzlZ6r9Fyl5yo9V+m5Ss9Veq7Sc5Weq+u5/dDOmQ6UjpTuZY1xIU7snFAYelljnI0b7Cc0hl6nWAtXfKwP6H0GE1U42HNCYsgMhQEewGuo0AB4oIDuAeazcORnw3QVjvycEBm6B5jIQrDghMLwKP7w/IlQulFaV/oxqpnpQGk8IQF6TjCWU+gPxm0K/XkC9GdAYEBOUEjQnwGZoTBUhp4VZLFHJ4fnf8fzUaxQHwwQEAo44dFY4zP9MIWBZA/dCxjO9Mi9mY6U7u5isgtxexMKQ2UQhsagBPhcwQQZDumcEBny8vghLjNdKd1zVZFulNaVxugF81c40nNCZHhkWPFexZGeE5BhlDZGLwOEoT//aUxXukvMSAdKR0onSmdKF0pXSgul6bk6nys9OHCmA6UjpROlM6ULpSulhdKN0vTcQM8N9NyuLNrnBAVRhBMyQ+kQAZVBGFqHBFCCriwTAgM8yAB4UACPvGc48BCWma6UxuMroDEoQToYAkNkSAyZoTBUBvYgsQeJPegxyH01Xnqg4UxHSidKZ0oXSldKC6UfFZ9RpA8lGulyUBoZF0BkSAyZARlHaymVQQjqwdCtBTjWZUoDqqvL1ITKIARdjDTAa4E1NBDJDIWhMghDY+iVElAp7WAIDJEhMWSGwlAZ4AH6RWsMSqAHAzxAwWtkgAcoXs0MheHROCrKsKvRSDdK60z3yMCZDpTGExTQc9IDygQxfhqf/0wJ+uhlQmDoOenRZYIYvwmZoTBUBnhQAY1BCaAxAwJDZOgeJOSnj14mFIbK0D1IyA9kZoASQGYSvIbM9HeiIPpvAjwogMwAD+AoZGaAMDQGJcgHQ2CIDIkhM7AHmT3I7EFmDzJ7UNiDwh4U9qCwB4U9KOxBYQ8Ke1DYg8IeVPagsgeVPajsQWUPKntQ2YPKHlT2oLIHwh4IeyDsgbAHwh4IeyDsAZStjwcFB5JOUAIo24BH11b8vn+7jXSidKZ0oXSltFC6UVpXGrKF0QWiFTVBR7Qy9Gzg3YWjRyfoAsQxTggMkSEx9OdgfIB4xWfZIV7xWSg4YHRCZEgMvVr6nJvggNEJlUEYGj+UPYgHQ2CIDIkhMxTy7SlRTxCGxqDkGyRqQGBgDxJ7kNgDlqjIEhVZoiJLVEzUNGPmWshcC5lrARL19C1zLWSuBZaoyBIVWaIiS1RkiYosUZElKrJExadEwbfCtVC4FgrXQuFagERhJIaoywmohQyIDIkhM6AMYBoSNUAYGoMSQKIGBIbIAA8aIDNwN4Mq9SlaQajlBCWAKg3gxofx1gCu+sZV37jqG3fAxh2wcdU3rnrlqleueuWqV6565eav3PyVGx+Eq8f9nQs0B0Ng6M/p09SCOE7tIYWCOM4JhaEyCENjUAKI3YDAgOckQGGoDMKA52SAEkDSBgQGjLqQbUjagMxQGCqDMDQGJYBw4WsBEZsTMkNhQE4LACNyeA15GhAYUHMVkBgyA0pUAJUNCENjYA8Ke1DYA8jTgMSQGQoDe1D4odAdfLPhINMJiQGZU0Bh6KbxzYCQzQmNoWeuovFBdwYEhu5BhW/QnQGZoTDAA1QjRGhAY1ACiFBFZUFqKioLUjOgMOA5KBBIzYDGoASQmgGBITLAA5QopGZAYagMwtAYdAFOQp3QTfcQTMFBptonoQUHmU5QAmjIgMAQGXoW+sS14CDTCYWhMghDY1ACqMsAeFAAkSExZIbCUBlkVTBiPCcoAQZMA1BzCVCoRCEoA4ShMSBzvfEhuHMUIgRlQGbAc+ABBGWAMOA5DcDVWLgaC1djYQ8Ke1DYAwjKgMrADalwQyrsQeWH1jkDLj0YdKYrpR+fGvj875GgM60rDSlp+AGkZEBk6NlqeDakZEBh6E9HxfQZ7JFulNaV7otjIx0oHSmdKJ0pXShNz2303EbPbfRcpecqPVfpuUrPVXqu0nOVnqv0XKXn6npuPwV1plHYCRAZEgMKuwAKQ29DfRVHEMs6oTH0NtTXXQSxrBPggQIiQ/egB1YIYlknFIae/edPhNKN0rrS/bSMkQ6UxhMCoOekr6gIolhVURSQlCdAUgYEhp4TRSFhKDMgMxSGygAPGqAxKAEGOQMCQ2R4bEA5MLnfj0xdUBgqg3RAfh6atEAJHpp0Arx+aNIJaFwPTVoAD1DpJTPAAzhaKoMwNAYlqAdDYIgMiSEzsAeVPajsQWUPKnsg7IGwB8IeCHsg7IGwB8IeCHsg7IGwB409aOxBYw8ae9DYg8YeNPagsQeNPWjsgbIHyh4oe6DwAH1OM0NhqAyPbl2ev2+U1pnucbozHSgdKZ0onSldKN0ziCWPHoN7QgBEhp4NTPf3SNwFhaEyCENjUIKI5yQAVUsPxx2F0gNyFzQGJUi9WvCh0ANzF0SGxEANowfoLqgMwtAYqGH0UN0FgSGSozkxZIbCwGUAieqx51IhUQNQol17KiRqQGCIDCgDmIZEDSgMlUEYGoMSQKIGdA/wzVshUQMyVT1UCcOoClUaIAyNQakahateuOqFq1646qFKAwoDVz2rUmVVqqxKlVWpsipVVqXKqlRZlSq0J6JjQHsGKAG0B6PJCu2J8BraMyAxZIbCUBmEoTHogh7kfEIBJIbMUBjwnAoQhsagBBg7YWCCU1wnRIbEkBkKQ2UQhkbQh0nhmY6UTpR+6CmaSg+LnulKaeRRAY1BCRA+lJAOlI6U7kWMRT2BXg0oDHWE9QjObh3pRmld6b64P9KB0pHSidKZ0oXS9NxMz8303EzPLfTcQs8t9NxCzy303ELPLfTcQs8t9NxCz4UuYdFToEsDIgOiq1A9CFcagNJGG4BIDRCGPhhHneDLD+l+IOJIB0pHSidK4wloA5AaLMUKpAarrwKpGRAZEgPaDYoCA6ABlUEYGgM86FolEKEBgaHHBMFpxCI905nSPSYIpYVYpGdaKN0orTPdEIv0TAdKR0onSmdKF0pXSiPTCuiZxrJcgx49oR83MCEwRIbEkBkKQ2UQBvYAwyUsuvSA6wWBAR4EQGLIDPAgAyqDEGAgNaAH+DzTmdKF0pXSQulGaV1pBBY908hHAUSGxJAZCkNlEIbGgJLszbRhmDQgMMCDCkgMmaG3JZRqV6KRFko3SutKI2rymcaz0fYgRAMSQ3821kIahGhAZei5x6JNw2hpgBJgtIRVkobR0oDI0D3AwkiDHD3/8lAgLFv1GOuRxI9RjlCfAZmhMFQGYeju16dpJYD6DAgM3QNMdTYMgQZkhu4BpuMbhkADhAEeoPlgCAToQdcLAgM8qAB40AB4jgKEoTEoASQH07AKycF8pEJyMMeskBxMESskZ0BhqAzdA0zqKiRngBJAcgbAA+QHKiNwFCrTI7JFoTKYolSoDKbQFCozoDEoAfRnQGCIDN2DBt8wMBpAjVXx7TagMShBPhgCAx6KbEOUBmQGZBsFAlEaIAyNQQkgSgMCQ2RIDJmBPSjsAb7dMMZVfLsNUAKMkQYEhsjQPUDwjEKaBhSGygAPBNAYlADSpPC6SxN2KInieLQBqQM6Bo5IG1A6wFEckzZAGBqDEvTR1YTAEBkSQ2ZgDxp70NiDxh409kDZA2UPlD1Q9kDZA2UPlD1Q9kDZA10etB7xvSAwRIbEkBkKQ2UQhsbAHgT2ILAHgT0I7EFgDwJ7ENiDwB4E9iCwB5E9iPAgASJDYsgMjyFCV86G8O+RFko3SutK9+/CkQ6UjpROlEYGMwCyBsjIRgEEhsiQGDJDYagMKC54ULhaChdK4UIphaEyoFoE0BiUoB4M3DAqe1C5YVRuGJUbRuWGUblh1Ea+VSWQg4EbxlOi4NtTop6QGdgDYQ+EPRBumsJNs3HTbFwGjZtm41poXAuNa+EpUfCtcS00roXGHih7oOyBci0o14JyLSiXgXI7eErUE7gWlGohHNQOwlOinhAZyIPAEhVYogJLVGCJCixRgSUqsESFQO0ghMiQGDJDYYAHDSAM8EABSvCUqCcEhu5BgG+QqAGZoTBUBmFoDErQR2qYqGo9eHxBV6oD6bKEIkCq+jRZ6xHiCxqDEmSu7MyVnbmyc2LIDIWhMnBlZ67szJVduLJLYIgM3NwKN7fCzQ3y1ufvG06KHQB5G4ACRblB3gK8hrwNyAyFoTIIQ2NQAsjbAHyEohYwYT6gMFQGYWgMeA6aKERsQGDoOY1oOxCxAZmh57SvBrQAERsgDI1BCSBiAwJDZEgMmYE9UPZA2QNlD5Q8iMfBEBgiQ2LIDIUBHkQAPMiAxqAEELEBgSEyJIbMUBgqA3vQQxQKXOshCs90D1EY6b6WmZCOlE6U7muZyG8fYI10pbRQulFaV7oPsEY6UDpSOlGanpvoudCsvsrRIpSpn6XTIpSpHwbcIpRpQGYoDN1an9BvESqT8ByozIDEkBkKQ2XotZFQitCfAUoA/RkQGCJDYsgMyI8CKoMwNAZ4gJYC/RnQdx1WpCOlE6UzpQulkX1UDWQk4S+QkQGFoW9GQ056YNNIN0rrSvfAppEOlI6UTpTOlC6UpucqPVfpubqem46D0oHSkdKJ0pnShdKV0kLpRml6bqDnBnpuoOcGem6g50Ip+jpBw8m7E4ShMSgBhjsDetvs89otYbgzoFd1xkMx3BlQGCqDMDQGJcBwZ0BgiAzsQYIHGVAYeuEjO33WfKQbpXWloSh9OrvhRN1nU+8R26FP9bQesD3TjdJ9w1OXlh6tPdOB0o9qbHhaX4Mb6UzpQulKaaF0o7SudJ/5HulAaXpupedCP/q2jpagEhm5gUoUuI2PsAGRITF0a3jZJIxF8FZJGIsMCAyRITFkhl4bBVWDscgAYWgMSoCxyIDAEBngARo6xiIDCkNlgAdoKRiLDIAHvawzxiIDAkNkSAyZoTBUBmFoDOxBX/DvQUcNgdsjHSn9WJ7Fxweitke6UPqx1N/DmhpCtke6UVpXusdrj3SgdKR0onSmdKE0PTfSc6Eaff/BCb38KnIDbahwG9owoDIIAb6F+hJFyxhX9LWHljGuGFAYKoMwNIZeGz1svGV88QwIDJEhMWSGwlAZ4EECNAYlwFhkADxAS8FYZECvmop0/z0+OzM0YkBg6L8XVAI0YsCjbiMe2UOtR7pSWlYayiGoGuiDPP/SLcHFvi9jpCuluyU0jL4pY6R1pfuWDIwpcYbvSEdKJ0pnShdKV0oLpRuldaZ77PRMB0r3Ou4rT62gZ2MSsqBny/OfKQG+MgYEBlhTQLfWV5FawThggBJgHDAgMESGXht9GaoVjAMGFIbKIAyNQQnQowcgPw0QGRJDZoAHCVAZ4EEBNAYlgAoMCAyRITFkhsJQGdiDvkEDg+MeCz3SfXvGSD9aR0J99s0ZI50o/WiVGIv3KOiZrpQWSjdK60r3TagjHSgdKZ0oTc+t9Fx8fzRkANqAMQfCmJ+DJoQxT8gMhaFb6wH1DSHJQdE4MH4YkBgyQ2GoDL02FN0N44cBSoDxw4DAEBkSQ2aAB+g6GD8MEIbGAA96iVaMHwbAAwHAmgKEoTEoARRjQGCIDIkhMxQG9qAPCTAE76HJM60r3YcEGGn3A4VnOlL60cwwyO9nCs90oXSltFC6UVpXuu+yGOlA6Uhpem6i53bliH2BtCESOWK6EZHIERPNiESekBgyA6whqwXWKiAwRIbEkBkKQ+3QAMLQGJSgHgyBITIkBniAGq2FoTIIAzxAS6lK0EcTz2EoQownRIbE0D3AjDhCjCdUBmFoDErQDobAEBkSA3vwvIUU6UppofSjZWJkVXHNMdK45fiZfrTMisrEHcfPdKJ0pnShdKW0ULpRWmdacBHgMx0oHSmNks0AlN/zLyi/nrUeULwgMEQGWFNAt4YZZ+mjkAF9FDIhMESGxNBrAzO0PXR4QWUQhsagBOlgCAzITwMkhsxQGOBBAggBtARznD30Nz3Hgj32d4EwNAYlgJYMCAyRITFkBvagjx/wEd6jgGe6UfrRnLAc3qOAZzpQ+tGcMDWAEOCRzpQulK6UFko3SutK932fIx0oTc8Vei70AZ8JiP6NmBZG9G/ErC6ifydEhsTQrWGGFpG8EROsiOSdEBgiQ2LIDL02MBLs0bwLhKEx6IIe0bsgMEQGeBABmaEwVAZ4IIDGAA96H0dg74TAEBm6B5hkRGDvhMJQGYShMSgBtGRAYIgM7AEuKSlIF0pXSj9aJr7OcL7ySOtKP28VQzpQOlI6UTpTulC6Uloo3SitK53puZmei1FIRg1CU/LzLyg/ZA2a8gRoyoDAAGuodYw1eqBvaxhrDFACjDUGBIbI0GsDc4sI0J1QGCqDMDQGJcBYYwA8QG1hrDEgMWQGeICWAi0ZgOd0KWjQkgGBITIkhsyA56B+oDIDkFPUQmsM8ACOQn8GwANUFvRnADxAwUN/BsADdFHoz4DuQUUhQn8GdA8wB4dY3gndA8y0IZZ3QvcAk1EK/RnQPcCEHKJ8J8CDAmgM8KBnG1G+E+CBACIDPGiAzAAPFFAZugeY9UKU74Q+xkIaFw0/04HSkdKJ0pnS/dmYPUOw7wRhwLNRLhjFPAGjmAGBITIkhsxQGCqDMLAHiT3AFxEkE1G8T21EFG/EVBWieCc0BiWAFg3g/BTOT+H8FM5P4fwUzk/h/BTOT+H8VC7Ryh5U9gAq9cw2tOiZ7cr5Ec4PtGhAZEgMnB/h/AjnRzg/wvkRzk/j/DTOT+P8NC7Rxh409gBa9Mw2FOeZbeX8KOcHijOgMHALUc6Pcn505UcRXTshMESGxJAZCkNlEIZGAF3p2VZEyiLbikhZZEERKTtBGBqDEsSDAc9pgMjQBxGKdKZ0oXSlNJ4BgBb0mV3FkccN+cJB6890ofTDUkN2cf76M90o/dDAPu+qx/NyGKQDpSOlE6UzpQulK6WF0o3S9NxCz4Um9CNgFMGx8y+9Jp5ZQ88foATo+QNgDZWMUUhDHWEUMqAxKAF6/oDAgNpA1aDnD8gMhaEyCENjUAL0/GdtoecPiAyJoXugaCno+QO6B31eVRHoOqExKAHGJwMCQ2RIDJmhMLAHOBALlY3zsJ5pnemA07Ai0oHSkdJ9A/SBdKZ0oXSltFC6UVpXGnuvn+lA6Uhpem6g50I1+uEwihDV2GeFFSGqsW8IUYSoTkgMmQHWuoQg3DT2eVxFuOmEyJAYMkNheNRGOlDSfawwoTEoQZ8LmRAYIkNigAcCKAyVQRjgAWo4K0GBByidEhjgAQwUeIByw8FYGelC6UppoXSjtK708whQpAOlI6UTpem5lZ7b1SgFtJeuRhMagxJ0NZoQGCJDYsgMhQEeoIJEGBqDErSDITDgN2jlTQn0YAgMkSExwGtUqpYFiApNfZ5SERU6ITPgNwqoDMLQY3MD0rrS2HX4TPdNYBHpSOlE6R4XfCBdKF0pLZRulNaVxl7DZzpQOlI6UZqeG+m5/VsjRUBXiRThaVeJ1Kc1tYd3LsgMhQHWetUgwjNF1AZ6/IDEkBkKQ2XotdEn+RSxnxOUAD1+QGCIDIkhM8CDDKgMwtAY4AFaSj0YugcJJdq/KFLCb/qIY0JmKAyVQRgagxKg9w8IDOwB4tWRa4SrP9OF0tiWiLRQulEae2B7GsctPNOB0pHSidKZ0oXSldJC6UZpeq7Sc6EPCY1QUX7Pv6D8kDVtDLqgB4wu6Nb6CQOaoA99UlET9GFAY1CCrhATAkOvjb4iqT0SdEFmKAyVQRgagxJE5EcBgSEyJAZ4kAGFoEeD94ke7WGdMx0pnSgNSxVQGCqDMDQGJcCYYkBgiAyJgT3I7EFmDzJ7kNmDzB4U9qCwB4U9KOxBYQ+gMH3OVRMUJqOtQWEGNAYlgMIMCAyRITFkhsLAHvRjOfEd1c/4nWld6X44C76bejTpTEdK98BUNIAecz7ShdKV0kLpRmld6X4g50gHSkdK03MbPbehZNG2Mc4o6IQYZxT8M4wzBiSGzNCt9clbRSxo6vO1iljQCZEhMWSGwtBro8/kKmJBJzQGJYDCDAgMkSExwIMEKAyVQRjgQQMoARSmz3JqhsIMiAyJITMUhsogDI1BCRJ70JdmDjjdl2ZGOlH6Mdw+UIV9LmSkK6Ufw3wM3HDK70jrSve5kJEOlI6UTpTOlC6UrpSm52Z6LtSmT78r4kdTRW6gKRVuQ1MGCEMjgHL0qXTN0IeKxgF9GFAZhKExKAFGIH1eXRFNOiEyJIbMUBgqgzDAA3QdfH88Ad8fAwJD90DQUvpYZEL3QFC8UIwBjaE/R1Dw0JIB/TmYRMzQkgGJAc+BO/hmGVAZhKEx6IIC/RkQGCJDYsgMhaEyCENjYA8CexDYg8AeBPYgsAeBPQjsQWAPoD+YiUWU6wDoz4DAEBkSQ9/+BMtPXXn+QQmeuvKEwADLAqAegxjVCcKAHDSAEmBcMwA5UEAkAxjXDMgM7EFmDzJ7kBsD9Vkc2DshMLAHhR8KccFMM07inaAEGLDgVYyTeCdEhsTQn4MhB07inVAZhAEe9F6GQNWEiU4Eqk5IDHgO6hSyM6AyCENjUALIzgB4gKKC7AxIDJmhMFQGYWgEUBpMAyM2NWF6EbGpE4ShMegCxKZO6FnA5GmFngxIDJmhMFQGYWgM8KBXI+JZJwSGyJAYMkNZFYx41gnC0AggIVhPqBAKlGjFQGVAYagMyFxvfDhedxQiZGNAZEAW4AE+lAYUBhRiBQgbaAxcjZk9yOxBZg8gKAMyQ2GoDOxB5odCKTAwRoTrhMxQGGBaABhVItv1YAgMyEIDJIbMgCygfiAbw4AwNAb2QNgDYQ8kMiSGzFAY2APhh3alyJiSQ4DqhMSQO6DLdKWYUBmEoXVAx+hDlwF96DIhMMAD1I/iOXBUK4Mw4Dloo6oLelTqgsAQGRJDZoAHAqgMwtAYlCAcDIEhMsC0AroBzIAjfnVCYIgMiSEz9Cz0PXeK+NUJwtAYlCAdDIEhMsCDBMgMhaEyCENj0FXBiGydEBgiA2ouAIRKNDcGJSgHAzKXAVyIpTBUBmQBHpTGoAQVhYhWVbkaK1dj5Wqs7EFlDyp7UIWhMXBDEm5Iwh4IPxRKkZ8gDI1BCRpMoyljgIF5RpxnO6EwIAsNIAyNAVlA/SjNZyIKdkJkYA+UPVD2QCuDMDQGmlFFFOyEyNDrB6sZCG+dIAw9c1jnQHjrACjFgMDQWwjWORDeOiEzFAZ4kAF4Tm+JCGKdEBjwnApIDJmhMFQGYWgM8KC3EJxbOyEwRIbEkBkKQyWAUmAFBAfT5oSChzgMKAyVQRgaQ88C1lMQyTohMESGxJAZCkNlgAeoRgjKACWAoAwIDJEhUQVDUAYUhsqAmkO7hlI8S1QiQ2LIDMgcGp9wIYoSQDYGIAvwAOOQAYkBhYhW1bgaG1dj42ps7EFjD5Q9wDhkQGTghqTckJQ9UHoo4lWf65GIV50QGRIDTAsAa34V0BiUALKBFSNEpU6IDMiCAjIbKAyVgT0I7EFgD/D5MiAwRIbEwB5EfiiUAi8WBJ1OCAw9cz38XBF0OiEzFIbeQrAyhaDTCY1BCSAoWH/CobIZEzc4VHZCYcBzkB8IyoDGoAQQlAGBITLAA7QQCMqAwlAZhKExKAEEZQBMo7lggFFQ8BCHAUqAAcaAwBAZehawnIEI1AmFoTIIQ2NQAgjKAHiAaoSgDEgMmaEwVAahCoagDFACCMoA1FwAFCpRfMsMEIbGgMydjS8eCDrthfiAxJAZkIUCqAzCgEKsACUD4WAIDOxBYA8Ce4BxyIDKIAyNgT2I/NBnlFkDFIbKIAwwLR1W/NkDIkNiQBZgALIxoDIgC8/fNDagBPlgYA8ye5DZg5wZCkNlEAb2oPBDoRQVhQilGFAYeuYe6+UPEIbGoARQisfyzwMCQ2RIDPAATRmCUtESISgDlACCUtFGISgDIkNiyAyFoTLAA7QQCMoAJYCgDAgMkSExZAaYRpVggCEoeIjDgMSQGQpDZehZEFQJZGOALsABrBMCQ2RIDJkBHiRAZRCGxqAEEJQBYVUwDmCdkBgyA2ouAHSVKMJWJwSGyIDMZQAVIsJWJzQGZAEeYBwyIDCgECuAqhEBrRMKA3uQ2IPEHmAc8gSMQwYEhsjAHmR+KJSiwVHshHkCZGNAYIBpASBK/AmVQRiQhQZQAsjGAGQB9YP9Lk8Dz3j4J2QG9qCyB5U9WJHyD1CCFSn/gMDAHgg/FErRUIhQigFKAKVo6DJQigGRITH0FtLQMTD0GFAZhAEeoClDUBpaIgRlQGLAc1CnEJQBlUEYGoMuwGGoE+CBACJDYsgMhaEyCEMjgFI0BXQDegAqgzA0BiWAbAzoWdAIiAyJITMUhsogDI0BHvRqjBCUAYEhMiSGzFBWBUcIygBhaATQkBYAiUoU3zIDCkNlQOZ640O46yhEfLEMiAzIAjzAOGRAYUAholUVrsbC1Vi4Git7UNmDyh5gHDIgM3BDqtyQKntQ+aEYeiiaJYYeGHUikHVCYagMwtAYlOC5pwYPfe6peUJkSAyZoTBUBiHAzhm8zSIEBSPICEEZkBgyw+M55XhaqwzC0Bh0AWJeJwQG7EurgMSQGQpDZRCGxqAE2Nk7IK0CQTTsM6fpqTtPqAzCQDlFNOyAyDmNnNOuOxMSQ2bgnEbOaeScRs5p5JwmzmkKDFzWicv6uVcXBZI4p1CXAUoAqRnAOc2c08w5zZzTXBgqgzBwTjPntHBOC+e0cE4L57Rwqypc1oXL+rmLFwVSOac1MESGxMA5rZzTyjmtnNPKrapyqxJuVcI5Fc6pcE6FcyqcU+GcCrcq4bIWLmsoUhZAYsgMhQE5DYB5rsMJUKQBgQFtJwISQ2ZAiSZAZQPC0BjIA8TVTggMkSExZIbCUBnooQiYLUcGRIbEgMxVQGGoDMKA5iIAJXiK0BMCAzyAbxHPUUBlEIb+nHAAlKBLzYTAEBkSQ2boHoQAqAzC0BiUIB8MgSEywHQCwAAKvhwMgSEyJIbMgCygSkplEIbGoAT1YAgMkQEeoBqhLgMKQ2UQhsagVMFPdXlCYIgMaKMFIFSi0hiUoB0MyBwaX+NCbIWhMuA58KA1BiXoglIiWpVyNSpXo3I1Knug7IGyBxjiDGgM1JAQKDshMCSGrhQpAYShMShBQOYCoCtSgjWcHjCgMPQsxAgQhsbQsxDxHOwQfhrADuEBkYE9iOxBZA8wdhkgDI1BCRJ7kPihUIr4hMogDMhcBSgBlGJAYOgtJAogMWSGwgAPGgDP6S0Rga4TAkN/TjoAiSEzFIbKIAyNoXuQ0EIgKAMCQ2RIDJmhMFQCKMWzWQoMoOAhDgMKQ2UQhsaALKBKIBsDAkNkSAyZoTBUBniAaoSgDFACCMqAwBAZElUwBGVAYagMaKNdRxEC+yxRhMBOSAyZAZlrACpEBLoOgGwMwHMUEBkSQ39OPgCFDVQGYWAPAnsQ2QOMQwZEhsSQGdiDyA+FUkD9EQI7ITIkBmQuALoi4Y2BQNcJSgDZyBEQGCJDz0JG/WCVZxgoDJWBPcjsQWYPnqc0PiEwRIbEwB4UfiiUIqMQoRQDAgMyVwGJITMUht5CMPZHCOyExqAEEBSMlRHoWjIqC4IyoDD052DtEAe2TmgMSgBBGRAYIkP3oKCFQFAGFIbKIAyNQQkgKANgGs0FAwwsASPQdYIuQKDrhMAQGZCFCsgMhaEyCENjUAIIygB4IIDIkBgyQ2GoDLIqGCe9TlACCMoAtNECKKtEEQI7QRgaAzLXGx8CXUch4otlQGbAc+ABxiEDhKE/BwuwCHQdBjJXY+ZqzOxBZg8ye4BxyIDKIAyNgT0o/NDn2dAoxOfZ0E+oDMKAzPWmLM8ToNEonidAPyEx9CxgdRmBrhMqQ88CFpTleQL004ASYJVnAHsg7IGwB5gPGVAYKoMwsAeNHwqlwGI3QmAnFAZk7vkbYWgMSgClwOoyQmAnRIbEAA/QlCEoWBhFoOsEXYBA14K1Qxz3OiEyJIbMUBgqQ/dAAqAxKAEEZUBgiAyJITPAdG8uCHQtWAJGoOuExJAZCkNlQBYqoDEoAaZABgSGyJAYMgM8EEBlEIbGoAQQlAGBKhiCMiAxZAa00QJQKlF8ywwIDJEBmWsALkR8sQxoDHgOPMA4ZEBg6M/BOgYCXYeBytVYuRore1DZg8oeYBzyBIxDBnBDEm5Iwh4IP3TdO/EAJcC9NAMCAzL3hPK351UTD6gMwtCz0J6gBJCNAT0LWFBuz3snnn9JDJmBPVD2QNmD570TT9AF+rx34gmBITJkhl4/WOxGCOwEJYBSYEUaIbATIkNi6C0Eq8sIgZ1QGYQBHvSmjEDXgoVRBLpOSAz9OVg7xCGsEyqDMDQGJYCgDOgeoLkgHnZCYsgMhaEyCEMjgFJg3RmBrgVLwAh0nSAMjUEJIBsDkAVUCWRjQGLIDIWhMghDY4AHqEYIyoDAEBkSQ2YoVMEQlAHC0AigIViIRwjsKFF8ywwoDJUBmUPja1yI+GIZEBnwHHiAcciAwvB4TsUCEgJdpwGuxsbVqOyBsgfKHmAcMiAzcENSbkjKHuh6aEAIbL+F6gGJITMUBmQuALoi9TdGQKDrhMAQ+28iIDFkhtIhASobEIbGwB5E9iCyB+uGrAckhsxQGNiDyA/tSlEPFGKKDIkBmauAwlAZhKF1EIAS9KHHhMAADxoAz0Fl5cogDP05AfnpgjKgC8qEwBAZEkNm6B4EtJAuKBOEoTEoQT0YAkNkgGk0lwoDKHg5GAJDZEgMmQFZQJVIZRCGxqAE7WAIDJEBHqAaW2YoDJVBGBqDUgXrwRAYIgPaaAEIlag2Bl2AENgJyFwDUCEi0HVCZcBzFNAYlKALSu1zaQGBrsNAiAyJgT0I7EFgD4IwNAZqSIiHncAeRH5oV4ra14wCQmBrX/IJCIGdoATpYAgMkSExQJVR8LhLb0BlEIbGoAS4S29AYDifE9FEe9DrTFdKI5soAKjJACWAmgwIDJEhMWSGwlAZ2IPCHhT2oLIHlT2o7EFlDyp7UNmDyh7gau/6hMagBLiQcwA8KIBeofUJhaEyIKcoeIjOACWA6PRFs4CY2WEA1/ENSAzsQWMPGnuAz6IBjUEJcB3fAPZA+aGKQoRmQHQGNIaeub7qFhAmOyEwRIZejX0FLSBMdkJhqAzdg9T7GE6BrX3xJ+AY2AmRAc/JgMxQGCqDMDQGJYDopAIIDJEhMWSGwlAZhACi09fWAoJha1/mCgiGnVAZhKExKAHGKhlVgrHKgMiQGDJDYagMwtA9yKhG6M4ToDsDAkNkSAyZKhi6M6AyCAM6YH9hIUx2lCgEZUBmKAzIHBpf5ULEKGZAYEAW4AFGMQMyAwoRrUq4GoWrUbgahT1o7EFjDzCKGZAYuCE1bkiNPWj80OfF3yiD58XfT0gMmQGZQ1N+Xu+NbD+v9+6Qntd7PwHtoAIiQ2JAIQqgsIHKIAyNgT0I7AE+iwZEhsSQGdiDwA+FUvQFvYD41wmRoWeur7oFxL9OKAyVobeQvoIWEP86QQkwihnQPUD94KzY+nQUgjKgMuA5GdAYlACCMiAwRIbEAA8KoDBUBmFoDEoAQRkQGGAazQXjkIKChzg8AeOQAYEhMiSGnoWKKoFsDKgMwtAYlACCMiAwdA8qqhGCMiAzFIbKIAyNKhiC8gQIyoDAgA6ogEoliu+dAY1BCfC9U9H4lAsRnzgDCgOyAA8wDhnQGFCIvVUhlvVpALGsEyJDYsgMhaEyCENjoIaEM2In8EMx9MAgC7GstS9zBcSyTmgMSgBBGRAYIkPXqvyEzFAYKoMwNAYlwBXjA/pzMLJDLOuEwlAZkNPeKBCxGjDMQ8TqhMiAFo9ChGwMKAwoUQUIG2gMSlDYg8IeFPagJIbMUBgqA3tQ+KEQFEGBQFAGZIaeub4tNSCWdYIwNIbeXPCdiFjWCYEhMsAD9B/IhqCNQjYGNAY8B+0AsjEgMESGxJAZCgM8QAuBugxoDEoAdRkQGCJDYoDp3lwQsVoxf4iI1QmRITFkhsLQs9CXnwICWyc0BiWAbAwIDJEhMcCDBCgMlUEYGoMSQF1QwQh5nRAZEgNqLgAalSjGIU/AOGRAYEDmMoALEeOQAcKALMADjEOegHHIABRiBXA1Zq7GzNWY2YPMHmT2AOOQAUpQuCEVbkiFPSj8UHyx9FW3gFjWCUqAEcoAmG6AyJAYMsMjcwc+YxHLOkEYGoMSdEGZEBgiAwoRFQxBGSAMjaHnVFEgEJQBgSEypMclZc+28xCUBYWhMghDY1CCfq/4hF6iikaO4cqAwlAZhKEtQJRr7Uu+AbGsta95BcSyViz+4DjXCcIAawWgBNCQvggYEOU6ITIgPwLIDIWhMghDY1ACaEhftguIcp0QGRJDZigMvebqE5TKDYIygEsUgtKX+gJCXidkhsJQGR45lb48GBAMO0EJutRMCB3gQZeaCYkhd0A1dqmZUBngAeo0NwYlKPAArarAA1RwgQeokgIPUIglMxQGPAdlUJSgHgyBoT8H60qIfx1NGcOVAcLQCDBCGdC7Mz5SesjrgsKARoESFWFoDErQDobAEBkSQ2boVYKVLQS2TlCCPg6Z0IsqwIBGhsSQGXpO8c3Uj4BdIAyNQRf0yNgFgSEyJIb+HMyy9fjXBchpAihBOBgCA3KaAYkhMxSGyiAMPaeYf+vxrxP69cATAkNkSAyZoTBUBiFIyGkBBIbIkBiQ0wooDJVBGHpO+96DIM87QAHPS0CfEBgiQ2LIDIUBdYqqh6A8AYIyIDBEhsRwPgfjrR4xO5J1JWUl20rqTD7kBYO0Hj87knEl00rmlSwriRx1HUMErGCJEhGwExIDygcuQF8GVAZhaAxKAH0ZEBgiQ2JgDxp70NiDxh409qCxB8oeKHsAfcEyLU6EnVAZhKGXKFZMESj7BATKTggMkSExZIbCAA8iQBgagxJAefo2vYBA2QmRITHkVfXtqTxPqAzC0BiUIB4MgSEyIKcZUBmEATktAOS0t2vE004IDJEBORVAZigMlQEewFEMcjA5gXjaARjkDAgMkSExZIbCUBmEgT14aFJD8qFIIxlW8qENaAwPLRrJvJIPbTiQrCspK9lWUmeyK9EzGVYyrmRaybyS62l1Pa2iHOEQdAifRwicFfROHCQ7oTBUBlhD5TVYa4DEkBkKQ2UQhl72WLFDFO0AjGYGBIbIkBgyQ2GAB2izUJsBjUEXIIpWMBhBFO0EeJAA8KAAMkNhqAzC0BiUAGozIDBEBvbgoTb4HuqhtiNZV/J8Nj5xepDtSOpMPhQGH2s98HYk40qmlcwrWVayrqSsZFtJncm0npbW06Ak+QkoLXgHvcBiAI6PHQC9GBAYujWsRCF2VrAShdjZCUqA8ciAwBAZetljVQmxsxMKQ2UQhsagBPj0GQAPDkBkSAyZAR6gXdTKAA9QohjBDFACORgCQ2RIDJmhe4BvJ4TYThCGxqAEfTJmQmCIDKcH4XimM6ULpSulhdJtpaEz+OxCCK1gnQchtBMwRnqCMDQGnfA4+JUhMESGxJAZUGIZgBIrACWAZgwIDJEhMWQG5LQCKoMwNAZ4IB0wQhkQGCJDYsgMhQEeNAA8UEBjUAKMXQYEhsiQZp1GBOROKAyVQRgagxJAiwYEhqVFEQG5EyqDMPTn9JWZeJAWxYO0KB5PLXpCf47AALRoQGXoz5HnbxobUIJ6MLAHlT2o7MFTi55QGCqDMLAHwg+FyAgKESIzoDAgc2jKEJkBjUEJIDKCpgyRGRAZEgM8QBvFkEbQRjGkGaAEGNIIGh+kZkBkSAyZoTBUhu5BQwvBkGaALkB07oTAEBkSQ2aA6V4lCLuVvoATEXY7ITFkhsJQGZCFAmgMSgB1GRAYIkNiyAzwoAIqgzA0BiWAugwIq4IRnTshMWQG1FwGKJUoZGNAYIgMyJwAuBAhGwMaA54DDzC4GRAY8BwFcDUWrsbC1VjYg8IeFPYAgvIECMoAbkiVG1JlDyo/FEqRUAZVCSAbAwJDN61oyrK+UGKQyiAM/Tl9+SQipHYAZGNAf46ifugbKQb6RoqBvpFiaOxBYw8aewBBGaAEEJQBgYE9UH4olEJRiFCKAboAIbXSl3YiQmonRIbE0J/TR/ARIbUTKoMwwINePwiplf4ZEhFSOyEx4DkKKAyVQRgagxJAUAY8PGh9YSUipHZCYsgMhaEyCEMjSDAdATCAgk+VQRgagxJ02ZiALKBKcmRIDJmhMFQGYWgM8ADVWA6GwBAZEkNmKFTBEJQBwtAIoCF9YTIipHaUaM0MhaEyIHNofMKFKIEhMuA58EAyQ2HAc9CqhKtRuBqFq7GxB409aOxBSwyZgRtS44bU2IPGD+1K0QKaZR96tL6EFBFSO6EwVAZdgMDZ1teTIgJnJ8BaAnR3+ipLRKhr64sXEaGuEzIDPKiAyiAMjZ4TlP7SO/qEwBAZ+hfYgMxQGCoDl0E6KNspMHDpJFg7AMiPAJCfBmgMSoBePyAwRIbEgBJVQGGoDN2DCN/Q6yMyh14fkQX0+oiyLv2b9lkGJTIkhke5SXsCnoN2UPAc1HZRgnowBIbIkBgyQ89pRGVBAgYIAzxALVR4gHKDOESUDsQhoXQe4hCfA7MeHrsgMzxmCZ6fcD0IdoESQAISfgMJGNBzmlBUkIABmaHnNCHbkIABwtBzimERYmUH6MEQGCJD9yDDayjFgMJQGYShMegCRNFOwHMCoLcdeQJ+00sHca8TAkP3us/VRhz1OgFeZ0BhqAzwugAagxJAXQYEhsiQGOBBBRSGyiAMjUEJHrozSyfhOQLIDIWhMuA5DdAYlAC6M+DR65/TQD1wdkFiyAyFoTIIQyPAmKLP50aEx05IDJmh57SgIfUxxQRhaAy9NxbUTz0YAkNkSAyZoTBUhl6imN9BrOyEwNBziikQxMpOyAzIKdo1hh4DkFM0ZQw9BigBdOfpG3RnQGRIDJmhMFQGeIBqhO4MUALozoDAEBl6WT/7dp+HfX7c9ZDaKM++3edhJ+iCHmy7IDBEhsTQ6xTS2YNtF1QGYege4KOrB9tOCAdDYIgMiSEzFIbK0J+DFxhCahFmExFSOyEyJIbMUBgqA+oUD4UiDVACjIQG9JzGJ0SGxJAZCkNlEIbGoAQYCfWz4CIibydkhp7TvuElIvJ2gjD0nPY1h4jI2wEYCfWFg4jI2wmRoXuAmWCE4U4oDJVBGBqDEmCMhOUBBOhOiAyJITMUBrQqeF25VQm3KuFWJdyqhFuVcKsSblXCrUq4VQm3KuFW1bhVNW5VjVtV41bVuFU1blWNW1XjVtW4VbVnq/rP//yHv/393/7pH//jX/7tX//bf/z7P//z3/7L/57/4X/+7b/8H//7b//jH//9n//1P/72X/71f/397//wt//nH//+v/o/+p//4x//tf////jHfz//eraof/7X/+v8/6fB//4vf//nR+o//2H9+nj/08fe1vHzx87UNE2c87N/GAnvjbTHXFU3cS62LgNS/zAQDS+Ox4geTpwz+m9NWBl57JcYNh7h628zkt8b6TdAdhOZvJD0x+/L+9+nR5Pvvz9HuMuBou5c4Gxs5OL8RHtfHfLeSOyX83QbjxfJMhEOrwnsVUZOaqOshD/LQg0TbVqgbLxUqPH7fsxL/31NZf4+HX+WZTCaZeiXJaIsS2jvbUSrIB7fc8+CkPTWhlWWffQCE63p27IMRsN8vA1HlaZErSLJnzasxpmmG7oK9Jzv9mdEl4Wjvc+IYaP0AxS6jTO5bNT4p4lmVetjgvVZrSW+NWG0rb7y1i00Fqwibgv9mxIWanhrIRqt87FSN6r0FL1pI/+ZjWg0zr6jAE6ovHciGVXat0CiSs/CXM271mv1Ie/rw2oVPfofrUIOfWfi0RXfi95jMecpejm8NSG367Tdr1O9W6fJeIecXXPUh57rxKtOU/RnJDy+hJ4ZKeFdRpLROOPS/+OtAVsqtM5GEdK7Gk35vnpbNs45l5GRcyrl/aswVfNNFGcXodI4l5/+tGEVRxs1Uo9CFpK/YaQwG0aS8rZhJKN5am6jfWo5WDD+9CMbfsS+jQiNSyIJxhd1IqOzn0M2eVsn2Rpz9vkK1IkGGnOGl+GiIZ+PraJL+87Zn2Ul/jnWyvl+68jlbuuw89LPBny6UYu+z4s19gyyFJAGO+dy6p822u32ofcl0C4PzWv4qDxkeimPEqwXrBzzBStUHq82LCXtwR7P8mirtZ+Tk3/aSFaPmS/6c3a4vbdhqWmcDeRx9cR7G8UayKahpo+54Pc2qvnNOnvuH4rc/A3EKYWl3ZfConebul2xOgojJ5Kx1wKtViPtByQ9X5P5feOo8X7F1nS7Ys3i0PmhdA5L37fRWjYUR91QHHK/OMxB2Oz257q94YbRRs/p5/HZd843h/dd1vJDa5qjweO9H2K00lqnH1XCexk0Rf0cEA4jj33Q8lbUxbBS4+y19Vy8f2/DGsKEY/bbQD3/KxuyhkGNRuk/bFTrU3i+5eT8v1Wq4WVewGiokucLSs6Z/vc2DDVNq9+Sip296E8LlpYGXV2OPiJfbTRjaNqv80JTT8c1CzoHYqG8z4fVulIatXrOwr1voS1Z3055ZqTWizb6+u/z+0viNRttfdi3470Nu8/2rf3PPntO3bz35Pbnk+mHhDmR99iO/X5A2NSap+7Lqc956ibHm3e+3v6AMpVjTdmfi53H25xovK8cmu4rh+a7yqHlvnJovascpgWXctgttK3FHNHyvr+p3u0pVus6F5/THDHEfK3XnyOXOfpp5yL8WyvhsAYeaX078bT3+Z36YiTd7W+2H3kuZzyiXt76Yc5YyGzpj92Gb2cswmENTPutkM95Ulb1H0bEko85r5bbH0bUb+RcbJxdJvNK1w8jen/uJITjbov/UKxtNpEaw8W66YdDP41YdROsL6CjzboJPIvzo8WbnrQ1Xidd/ulJsRYzdb638x/t9cWTUK1Vq6klKTW5ZsRdJvY6h7ep6a82tXSstdmjXZSBcwZc57xUlvdGrPWnxz7sOWWoUfWtMlqehDK/tpPVc6K1PnrIWq/gkdn5Jv3TiNFepc7ciPBc7jdGWp3LBa3yN9kPI7KhqVlrOM6mZvbgTCPeYHQ+a9nhEXu/VuaqYSSY776pJSJcwS8lYi5JOd/jphzNhbEzJRc7X5ozh+mcv3tvJJWb8RW2G3kO4B/nzBtumJNUa0IlJW7v9Qsjmmf3PdphGLHmdGXOdanQN83rt0Sw1qZUyrRBk6mpfOOHLD9oCeSnH6a0yuw0B0+6/fDECjEIU9AiT9j/6DTm6lSVRJ/ftbzrNtby1CPUdWpAyYYn1WwlulqJGAUr979ag7VC5f1sDVnvfreGctz/cA3WEpXvy9U24fp0td/gZc4UncNg471prVCdLWQK/EHvq9dQFGuFKq2ZkeN9AEYo5uR/mLEoUTJ13pd3b7E08XE95eh3j9sp3y4wmdL62JU3PzyDoc9lx1dWvf+VZcpImwGa52dJei8j1krVubqT1/zqavGqX9iQWcNVimHDmrc6wlxOPWi4ea7PvhgxSkSXxJ9rmtkwYq0B1Nl/z4ne+l7OrNWqUubKfymN3lhfjBTrHNOcQzVjpGgtVz2OOc5r3Z4K9qXBiznDmqihxfeeWAtWOYYVOcTxwK9BmxLvS5q1ouCUNMkbJE3KFkmzVCCFNW49B0fvVcBas4p1DbBEjdGitWjlHkxY61buwYS17OQcTLSwYTDR4u3BhGnCN5ioGxY1Qys76qXerxfZUS/tfr202/ViDkZymLPxRY3vPLUGmznKfNFQefyQVd0gq3pfVnWHrOr/D7Ia57pz+uN19Sqrag43V9xL4kCP106jO2RVN8hqPG7Lajw2yGo8bsuqbcIpq3YA4Jz8irm+HWzGo5jjM1rOP5IYZjZIfDxkRxtp99vIhtCVGG7HrtgmnG3EigrIaU6ic1Tky5dRtJaw0lwGS5mjLF4sWCvQMhePz28RmsrPr25YgnjI+gjQ+taIXR5hjjOl0mviR3lYUwGy9F0aOVJei8R6fR9zTZ7Wn3+a0PtfrDEe979Yo7V5yvvFGq3lK98Xq+2HV4WsqS+3ClnrTk4VMrdQeVXIWrpyqpBpwqVCdkv1vqms6Ygv3lRpRxtJcUMbSel2G7F23rjbiLV05WwjpglnGzEEsc0lCY6M/iGIqd2fRIhJN7QPa93K3T5yuN0+rHUrd/uwYr+c7cM04Wwf1lu3prX4rUYLyWacRVr7f8iTn0Y2zFXF3HY0sx0fVeX+R1XZ8VFV7n9UlQ0fVZay95uFx1AmvR0gWmtW+ZhTIvkoxpjK3FaVZ5zG487W5cirDaul6tyNdA4WqVA1vxixVDXN3XuPQ9tWI3vdRm3urKozxuJM6tuZFfsVMaPgHieUvO+81uYq74xIrBtirWPdEGwd6+1o61g3hFvHejve2jbhe0eY8t7fIM9xplgtRDe0EGvFyt1CrBUrdwuxVqycLcRasHK3EDMK3ddCTBO+FmKL2dqBlymm94eYmRusvJ+71mKV83NXNgTPxLZjqNruD1XbjqFquz9UbfeHqtZrl0OCI22z+vHabTtmVNuOGdV2f0a17ZhR1fszqnr8buX+sS5T31eutVZVjjyn/w5aaHpZePswytS53TRQmf4YZVqLVW2uuzU6uOOHGpobpWYwUlFeMnstjh3NVO83U93QTNNxu5naJpzN1GodYW1GTkbrSNZOK68GpWPDfGo6bs+npqPuqFy5X7m351Pto5jKPIqp1reHa1k7xta5b5ljiH+comQd6JeOubcihcTB9+ULIzw1nKJhxNqd6DuDLllrVL5D6EwTvhPLkrU1ynlkWbKah/PMMutL23sQnb9WxKgVb/Pg41C/amNhntyRorEJKJm7q5zHVybzgD/vCWhmdkqdm8WqmR0rnErmZMqZpAb/ErZjG+kXPMBIy2oYkfudN7bbndcy4ey8ZsCss/Nay1POzmstTrk7r7tWjM5rNg+dkQOifC7ca/OwlpacJ0km68A/b93Khrpt9+t2w1FqacdxW8lanfKet5Xy7S2AHzRonmUkTS8KWQu6BETex4anbIZS5bUpkiYOX8/0tcV9nZiVVIxBVd4gqfm+pOb7klo2SGq5L6llh6TmDZJqN4+5JyMff+zJeGkepdxvHqXebh7lviqXtqF53D/i19pL5W4e7lq53DzWd/JxtGvD5bziyvKRjTZmLUw5TxZPdUM7rffbab3fTuuGdlrvt1PZ0U7rhnZqt467MxjlmKeflqO8P/0+WQtKNc7o2JqT8doXc8/fjEvhEdnrW9+89SPM6eDwuMHtXdRBslaDvCcoJ2tVynuokW2k9JDTZxOJ6f2RU8ncRBV1HUVCoan1CxNpfSrzcTWvJqI1kTq9yDG8NfGhPJznUve9sO8Hy+tUlfOb/W1mNpxtnayVKefR55aJOk8RqlEvmpiqXOkd9dOEVRorCPvRZI3SMIs0KrX190asTVTeo3s+NDPvkeFJzdV+35nhydxJ5Tw03PIjznDfP47L+OmHZaTMZhL5FqIfRuyCFVl7mBs1+p8F227rmWnCpWfZWlvaomd/lAddBvGjPGwz3iPd82FfmrLOzqJou3jdSNtgpKarRnxH1Gdrjcl7Rn22dlJ5D6nPhx367zqlPgf7YJV1cs5RLxpxngGerQuonIeAf3Bk7oZ6XFR+NTcztPNxi/LVykkrUCXVq0bWmkZMssFIjoYRM9zVd6x5tvaq1GP2v3pouNh1nOfe57jhHoAc44auEzfcJpCtfVXermM74uw6thFn17Erp9JKXthhpFw10uhyQLloZJ3Wdn7sxotGms5Xl8arZbJeXYkXJm8YaVezM+8ESC1cbSdtHqv7uBz8qpG5spB4nfVbT2Y7afVyFc+wojOpVzvgGp1Es4rNo6TXF0YK6bKRYxnJG4zEdFmUdBm5KvZrq3ZMRTd4Yo4szLGj7x6cnGXDC9C8vsr7AjSNeF+A5bj/ArQdcb4AbSPOF6BdOc4XoN9IuWrE+QI0jXhfgFk2vADNUazzkqBcnLcE8WEJXw2FS5oRk4Uv5/luPO29J8ibHevSI/+XdTM+z2u+vZKTzRut0jxcM/GFRT8dsRa2yrwPRjjw+lVNrEMC09ral/64fenlFgRzaUvpZlG+U+bVhnkLyzHj0M80B6S2b4p1Lir9cRj0z2I1jeiqG33fSOyZrRpmKwk1GhOG2dp3JSuyRd6vGX5wZNp4OGLciGkuccmc4j4CTStL/sYV711f2Vrl8l72lS1fvLd92Uac133ltmGfYG4b9gnmdnufYG4b9gnmdnufoG3Cd3WPWbnOG5lykx2V23ZU7u3DrbNuONw66+3DrW0T9yvXfSGS2ULy3Gt8Jts1IyVNTSx/3F/wlSQ6b6jLau4p8V1RZxtx3lFnG/FeUmdnZw0Ya6sXjaxTKYuWcnGVq+Z5R8WZztfNrBiCs67kqhnv7X3luH2/tWnCFwJgm/CFANjxLt5bBMux4RrBEm7fI/jJj3XlXFD6Unr1wxgJaFg3ZoS3i8y2iTVK0xjbpUVmSXPrz5kWvdjghcLVpIT3Zop575Vr7d424Vq7L6H97tr9n+URbxTrCnYv6aqqyYrPONP1/UCrWFOWztoxTfhqJ+Zfrp0/ysMYeH6sHSEz4aoZ7wWW5f7NV6YJ58vCNLHhZdHCnAY+08Y7uNj3Xnni+EwTp0KvQYXUclwzIvTukxouGqE2wmtt3zT7FtcMQ0uX1cR9SWlJv2/mnGWnc4RoOuplZsxvJMSLRpy3rpb7W7VsP5y3rtpGSl53V9VwzchZH3OX1cFTweE18Ns8B9gXK13MwwSdF8AWa0HHu63YNOK9RdY0UvoFWfhkii1cNJLmBpRTe+S9kXJ/TFDujwnK7THBh9KYyxYl85mVP0rDipY+5i0850tYDSPm5/18C1M4xGtDtd2YK481/LF97Zu8hLm16JzeDleNzKmoen68XTbSphHjzmS7fp0XLxfrMMEtRry7A0q9PzVQ708N1NtTA3ZpOHcHfChS3+6AYm3b8u4O+PCi8V2JbRtxXkRdrGUt70XUxdq65b2I2jSSjxmRkQ/jIuoi96cG5P7UgLT7LxrnsXXWTda2EeeNvLYR51W4thFZq+xytcGntVExSTQ8+bDrynV0TLHuv/KP8ewF/9lWrauOSzOjXBxXHZsW6vwOqPSt97M4dEOZWmta7jK1Fk5D0BXWlXnc/FIi1gVYzjI1dyb4bn62jVSdRlo9LhpxXh9dtG5451lGtM4JDv0jRu11VGQbmfV7rgTrZSNpGonpohHnldrVugDLd6W2aSKs0yvPQfz727A/ZMZ3L3c9zBuGffdym0bOtYp5wtDBwZ1fZafNjxJtvIHlqwpuq6kpBev8LJP2y0ZiWFcDhmS1E2/UbDneG7FOowhhvrJOpY0XjayornAO+i4ayfMEhvOVUwwj1pAz13mAyx9Ti99UTqpTYFN7X66mSntvoq7BvAxzjvZioBiolxg104b3q7Oaoaqur07ThO+r0zbh+uq0S8P51fmhSH1fndXcr+V9A5utzHnFaLVuwvJeMVrNA+1kft08lsdWZl6aqrWG5DyQpkbzfiHPgTSmCd+BNNU6ZtAZxlytpR/fgTQ12TumXQfS+GtFjFqxWseKYg5KI/BXG8m8wGLOsZ5veb3oh+si3Goubrguwq1pw3UttpEV/ngmwzUj4Zj3gsVsXMlre1LSOkOyXjXivBy4ZktU3ZcDfzKjdOoQb/D4ykzI68jCsyvKZTPrrqLAIW4/zJgFnHRVNe8Z+6qW8lpc5yi5n0bMybThSK7J0Gj7vNBjCWy7JAZ/DMJpn+SrjXL7VuxazIFAmY1E+Sv6VaQtP5xFalft3Mtw1nK62AHDkVak3h+fe981+bAK5ZwuvtwBwzopK/z5Bvxm3DmDDysfO/Ld0HUuh5FA/jRhfmStGEg+RPXLj6wVn5pj2PC5F69OULT5laXNiN6v9fbigG3CtThQa/tVE871BbtAZ/s4y/b9tUnVuhMr1+WHhPC+v1hGQp+uR/uoh9FSTSN1Rik89jNdNNLKiigrVz3xzoJJuD8LZnuytqwFaVZ22oYZH9OId8bHNOKd8bF2Z3lnfOxyXUumLYSrReLUZ7tInPrsrhxLn+3lSl2nbeX3K421yf1Jjnp/OavuWM6qW5azzGJdA5tzjf39smm1lrPisUbhgcM5X44QrtbZfVLm94DUUC8aqbN+RUq7ZqSFuaLVEm8Y+8pImT2nlZgMI3J7PGH7UenOLzH80Pt+6N1BiVgLUb5BiV0adV5i1KzLVOT4bSPeeXC5vzFL7m/Mkvsbs+zScM6DfyhS3zy4hA3RV7YglhmMEmsyWoh5+KBvCls2XJUl96/KkvtXZcmGq7Lk/lVZsuOqLNlwVZbdOnxT2BLD7SnsD364prAl3p61Emv5yjuFbRtxTmGbRrxT2LYnzils24hzClui7pjC/mTGOYVtm3FPYX8y45zCtgvYOYVtG3FOYZs9yDffanZk5xS2bcM3hS3317PEXEVyTmHL/VWBD1Xrm8L+0Fa9U9gfzHinsD+ZcU5h20NG1xT2h1GnZwr7Q3z7OkCxGruxxNxIdczx4tlk3keVm0Z8cwpinjfonFOQEjbMKZjB+nEWazpfZG9LxDYi6xZP5SO1vov4d9aNdVOTM+pJ7NuenF975oYs39dekdtfe6YJ39eeWRrerz27SJ1fezXe/9qzd7hk2lgd3m9OkZp/2UhMc1gTyx93eb0asWKxZb0oRLjnvRaseSWBZ/+w7YeuE0H0j8zkb4xkGgqki0akra2//OX4akTCBn2WeF+fzeycQ7N1Rm48jOxY7bXKsU4okvCu53wykuh8IjoJ8tVINSdb1hbxko3s2JFYc2P20d4v/4q10OE9AU7Eihh0ngAn5k1YrhPgxFrI8p4AJ1ZAqO8EONuE6wQ4u4W0eYhAOqIhAtaOrJrmKnLNtCFa9QsbMr/IqxTDhrkQNheiE1+Fl+PL3KJ1zKAuCVCe0P9pxGqpdVbNKVrvV/jFWsUqZZ7NUAodIZD81XtmYO4fPFfE31evOWVb16q66GFkJm0QAOsyLbcAaLktAFo3CIB5qJ5PAOxz+VwCYLZUZ7006yotb700aw3LVy/tiPfrpVlrJb56sU3cF+bzS3Fu644a3/bcdljtlPYdpSMZ9SI7Wkjb0UJuH97awobDW1u4fXirbcLZc80V8PkRcC7F17cvqhbMmx+VjsE86Naqn2bKhjZirWO524i1kOVtI21HG9H7bUTvtxGrXvK81/ccVJV3o6pmHwg4p6z+OLP1xYIlhzKPETvHMRR6kl/dsGa9DlkjVVokeTVil0eYQxmpNIf+ozzMT9616iN8om55LRLz1uZ58DKd//XTRLs/2m3WpLV3tNs39d4d7TZrI5ZvtGv74VUhayeWW4VSvq1CqWxQIXMnlk+F7M1cHhWyW6r3TWWuXPnfVHlHG8kb7hlo+fY9Ay1vuGeg5dv3DNgmnG3ECkCZM1V81c8PQbTXrHzfqS23He1jw0RVK7cnqlrZMFHVyu2JKtuEs31Yb92a1iKAGi3EWhg5v4HWxUd8guAPI3VDMys7PqrKjo+qcv+jqu74qKr3P6rqho8qa4BYCw1l0tsBYjWXVucu/XwUY0xVzTW8FYaTafZfX21YLVXnASjnYJEKVV/mEMzlqnU1Vsw8h/CyyNvMu7GcMWj2K6Ktw3b4nI7XzivOu6/NGRFrvcrdea31KnfntdZXnZ3XWmhyd17rXixn5zVN+N4RprzHsMaZYrWQtqOF7JhVbTtmVdv9WdW2Y1a13Z9VbbdnVT+I2bpSMvPOr1cxa3XD5641e+f83DX9cDeyHUNVvT9U1R1DVb0/VNX7Q1VznzIdHxppU+2P167umFHVHTOqen9GVXfMqOr9GVXV363cP9Zl6tvKVWudqqxzA8tB4ecvZ0F9GGXOgxTPNXd9O8rUw9x9Qjvg3qqhmhut6roajAPpX4tjQzPV43Yz1WNDM9XjdjO1TTibqXnc/rqTM1mtw4pZ92qQhg3zqRpuz6dq2DCfquH2fKptwveRamlQXlfXZUn6dm3YNrLi5bLk95F7GjdEVmvcEFltx3eu+aFYqxXfae4tmsH3j1met0Y05h1lUn69TOZGuChHNbIj9rz7nHkrGt4FIn4yMvfTnenS3hoxj1FLFKsW32fHWiPKMcxDKP6Iq0ivRsxzRlw7+9Q6NNC3mUetpSrvLjZNWw5is824t599bCiVGsq7DfWadrQ2y4hvS73dTHzblDWbCuvapqzmcpVrm7JpwrdNWc3FKt82ZbUWmnzblDVbyurcpuyvlffblD+IiGubsppX5vi2Kdsq4pybtY049webRrz7g21PnPuDP4mic0/uJ1F0bqa1s+TcTGsbcW6mNV9avp2f+uHAXc9mWtuGbzOtWotWzvdvNXuwbzOt6Ye3SM2q9W2m/dBWvZtpP5jxbqb9ZMa7mfbDLpp1Q0N9f7OnWotX3q04ev/YQDMk2PvFZu7mOcera+iaru7mcc6Aq7V2Veq6qa3yiX8vq7XBt1bDN858t5tHZhzd+YVhfNWb+2h2GAl1fTlWug/3OyMi6+RBjYYRc1VgNBLJ9ZoJnRuLeAD+lYlw0JdJfT9ZotbqlfPUQbtMdW3o02i1M/NEqlkipbVru6SCBAo+DfyxlqLfTK1rs1Wt7Z0rap715zpk4IMbR11u6Hs3rDZSlwacaS1vS0StFazQ11GeNRz43ffN1rE4pwfPGaL3AYpqLkD5ZNHeODbL9fxkrJdMrO3wZzJfM+HJiL2fx6nvthGvNJsrWDuMuPXdNOLU9/NjKtwVeNuGT+FtG16JP63cv0vILlenxtv7YJwDozM7crvnhLah54QNjT4c5parLVa8feeDFXfnsZe0fJ3HsuHtPOZhee7OYy1IOTvPh4L19h5zM4rz/Xm6ord7j70XxfMCtU24XqAfTPgyUjbIgGnE3YHjr1vxy4BpxS0Dsd2XAcuGVwbMa5/cMpDCBhkwC9YrA3nDdrIzP/l27zFXLLy9xzTibvdJftuKv/eYVty9x6xlZ++xbHh7j7mU4+49Vi27e49ZsO6XqDl4XCtC5MdLCPSZG2tIsMJk8x93l+dvdlK5u7G5wuXrxmXDLKFtxN0Bf9+KvxubVtzduOT73diy4e3G5t1c7m5sbctyd2OzYHd0Y50H6WspRje2lpZKWDHmkY5W/NGNzc0u7m5cb89q2RtVvN3YNOLugLX8thV/N65bxrJ1w1i2bhjL1i1jWdkxlq07xrLmCam6ohGU7oH62ZHtw1p1HdZKTf9HRza3nLo7srUU4uzI9djQkeuWWSXR37bi78imFXdHbvF+R7ZseDuyZcPfka0VIndHNgt2R0dOYRbs2WGC0ZGtFaLc5mbafCqD8UbWHR15w/JM27E80+KOLqjpt634O7Jpxd2R7b1bvo5sXjTp7MiWDX9HtnZeuTuyWbDejmy+1tOMoglJaBn+ZY45HGZQwcwNx5BX+cJGmUFbHEH6pY0Z01f4JKqvbNR5IVOlMwKu2yhXbdR1AOzV8qizPOrl8pCZF7lcHmzjanmsG0TlcnnILA+5XB5t5qVdLg+2cbU82lSQJpf9mGfItXbVDz3GO0IvlwfbuOzHPHldDQ2yj+VwRm3bRpy7UEKwThkMVddLs5hWrGnYeVN1/uO+3PxFdpzB1s3+jPVFstueOCPZP5wz4FrKNE34ljLb/YgG3TGLqzvmX0OKv23FPdi0rXgHmyGV24NN04ZzsGnacA82g3k/lXOwaResd7CpO+KBQr4fCKA74oF2BME9trr8thV/7zGtuHuPdfCgt/dYNry9x7Lh7z3WuYPu3mMWrPtTzTxro6yDVCiy9/WsjTM/1hlZYZ0+GvgE4/pqxGwotJWTija8jtiKeS/bvCaD7/76ysTcM1hbu2piHupwvPXiw/ElcUayH398V7y6Yc0IlHk4Xebrsm4Y0XdG3Ce6pOMwWpl5XVZeVzLl1N5npybrM3ru1K2Bb7r6YcTedLjuyzp7ettihg/cq9/MtugqlvfHGNonzKxJDg1vB/VnbtrdDwP7dBjnK9Q24n75SfhtK/5XqOwIIwhyP4zAtOF9hcqOMIIgG8II7IJ1v0LNc4DmBvHzY3bJ/Y+Q2mDemZXXgabx/YypeQ5hndtc+V61152y5nFE7sF0u73t0D5KyKsEYUcMQWj1t634laDVHUrQ9L4SNL2vBE13KIHGDUrQdmw/dN/0lt/f9Hbmx3qft3WySst86cSfnphXgbn7sd6eUrKv8XL2Y9uItwfG4/htK+5+bFvx9uN43N8kY9pw9mPThrsfx2PDJhm7YL1v9GNHGE887m+SCTvCeLZsDosh/rYVf+8JOyZkY7g/IWva8PaesGNCNoYNE7J2we54C55f+PP0p0Q3lv88Q8MSg3XAbz7q+7v5zgWv+NtWaitzUqnJu/NNPthYJ/xVjXLRxprc0vLehtlg5xSKxsuNfh5Hq1LudxzDhq1raV7wdf4uXDQS19UL6bCkZMfGLtPIuVayjuPJ7aIrmEJ7WmnlqhWaU0p62ZeyDhgqtNn0Wyt1HQTX9HKOlrSlaObofgy3acP7zkg7Yrhj/vVmm6YqneuOcrVQnLpk2nDqkrNyTBvmkNqZF9OGMy/Oob1hw/7ycmrsh29Ar8aWHY21bNHYskVjyxaNLVs0tmzR2LJFY8sGjS0bNLZs0dj6683WrbFlg8aWDRpb7musPf3oy4ttw5cX7zSoYcOepXZq7If5cq/G7tjUZRrxa6xs0VjZorGyRWNli8bKFo2VDRorGzRWtmhs+/Vm69ZY2aCxskFjZYPGmou9To01bTg11rnobGmsGRPg1Vg7OsGrsbqjseoWjdUtGqtbNFa3aKxu0VjdorG6QWN1g8bqDo1Nx683W7fG6gaN1Q0aqxs01oxJdWqsacOpsc7YWGs+Vjdo7IcgaqfGprChsZpG3Br7wYpTY20rXo21rXg19oMVp8Z+yJFTY1O4r7GmDafGmjb8Ght/vdl6NdYuFJ8u2TZ8uuStHFPb0v01L9uGU2PT/TUvc3OVW2PDDo3dseaVtqx5pS1rXmnLmlfasuaVtqx5pS1rXmnDmlfasOaVtqx5pfzrzdatsRvWvNKGNa90f83rw+bTeZphqeX9VdumibkXovB1B9/s5nVe0vPBiO8Spw/Hgvjq1rbhq1vv8SRm3cYN7xz7HBvvO6dsOKvINOJ/59hWvO+cUna8c0wr7neObcX7zrFz5H3n1PtHbJk2vO+cuuOIrVR/vdm63zlmoTjfOaYN5zvHWTmmtrX7ebFtODW23c6LfdSeV2Prjli2JDsaq2zRWNmisbJFY2WLxsoWjZUtGrvhGMO04RjDtOUYw9R+vdm6NXaDLqUNupTaBo2t979RbBtOja33v1HMc4m9GmufkOzVWN3RWHWLxuoWjdUtGqtbNFa3aKzu0Nh83NdY04ZTY00bbo3Nx683W6/G2oXi0yXbhk+XvJVjalu5H2dh23BqbLkdZ2Ff4eDV2LJjfjqHDY3VNOLW2A9WnBprW/FqrG3Fq7EfrDg19kOOvBobN2hs3KCxcYvGxl9vtm6NjRs0Nm7Q2LhBY81rjJwaa9pwaqzzOiVLY83brrwaa9+75dXYtKOxpi0am7ZobNqisWmLxqYtGpu2aGzeoLF5g8bmLRqbf73ZujU2b9DYvEFj8waNjRvmCuKGuYJ4f64gbdiT8eFmUK/G7ljzylvWvPKWNa+8Zc0rb1nzylvWvPKWNa+8Yc0rb1jzylvWvHL99Wbr1tgNa155w5pXvr/m9eG+YlechW3CFWcRjYmC1M/j6iZS4sMv82vlinV60WzudA31a4xFuL/P2rbhfN+E2/us7Wvg3WdZ7IidzrLhGhnTiP99Y1vxvm9MK+73jWnF/b6xrXjfN3aOvO+bdv/2I9OG933Tdtx+lNuvN1v3+6bdj/2ybTjfN+127Fc4rG0/Xo01bTg11rTh09hjRxzbsSOOLe+4qss04tdY3aKxukVjdYvG6haN1R0aW477GmvacGqsacOtseX49Wbr1Vi7UHy6ZNvw6ZK3cswzdo67Y/oPJjxjepXbB2rYJlzlaZvwFWfbsARpG/HKfNmxn8s04pb5D1acMm9b8cq8bcUr8x+sOGX+Q468Mh/vb5Ep8f4WGdOGX+bTrzdbt8xvmFIuG6aUy/0pZbHuBq9l3r1JlwTEkL4wkXWayG9NFGtazueFbcLnRTKv3Xvc4Ax5/aPvvlyRYxupOg9HrpouGlm3RUc9yjUj5xtiXn90RCM72To295gTYuecWrpmxHdUrW3CdVLtBxOeg2rtepF5CP7jBs2LlfuHkXzVSFxG0vt6CcWKaUr9JInnlGnIb4rkg40033gpNXlvI/2ujRxmXnIMF6t3XhYUhc8B/65m5k1dUfSqirAnl420Of4+k5eNzFGEbcR6UTn13TTh03frHHHtZz8/39vvNcQ2MY++P5P6zsRx/1133H7XZfMSDQnzGgChM/xDPL4w0uI0cq7uXDUyX5hnsl41UpYntHLzpZH1ydvKVU90NrJyNrjLZaLLiFE71mFruayblwrtO75hpF00UueA+VydzVeNzGuvzwU8o2Ct+6ykzpeESDDu0Ch2ocwme2aNJjZq+soV33UepZlzLJ7rPHIzg+5813nYRrwXcZTft+K+zsO24r3Oo2xYzioblrPKluWssmM5yy5Y53UeucmOjmxe0uXuyDvu5elXlt7syLrhXh7biLsLWi+wPVb8Hdm04u3I1brCydmRTRvOjmzacHfkah3C7+7IZsF6O7L1Li3HNFKO+H7QdebHkLfz02G0lBJ5ENlejVgTWTKLtgrNab8Y+ZCdOseQPF/yF9nRDdmxLpHZkp0wL+I+kxfHkOe07pirKCnKRSPrSvAzucNIDVeNtFnFfG30l0ZkfibEdrlg55LFmaxXjaRlJGerxd7fyWLb8E2JeyXWsGG/AZ1LdR/exc6lumqFNHpl2jTiXqr7YMW5VGdb8S7V2Va8S3UfrDiX6j7kyLlUV63FLe/oIoX7owvzCDn36CL9erP1LtXZheLUpXQ/UsxbOeZy34YIvrIhgq/cj+Czpwu8Gtt27BaseUdjzVs0Nm/R2LxFY/MWjc1bNDZv0diyQWPLBo0tWzS2/HqzdWts2aCxZYPGltsam60D55PIXBCVRhNCLV810i4aaceomtTCcdXInFQ6f1euGsltGdHLnoRphO68/dLInMk5k5Yn5n6UWTvnCyRfNJKOuN5f6bKRYxnJG4zEq55EXW/S2K56klaZFN3gSTWavX19rrOKP1zk66viD0Z8Vew2Eq964q1i2xNnFbs9Mao4qTn2y3MAGQuvo7/EjNR2P/7FtuGLXakt/a4NX/yLXahpvkFjksMqVGsudop0pffWy6yj7UdeITQ8tvkLP9qGSVRrxcs5iWpnp8TZVs8ZyLfZ+WBkTl3GUpthxFqWKXkqSSnHNSO+aD7bhCua74MJTzRfshqqLxLHNuGKxEnVXPiTtdGirZHROUjy25BjzmvLoe9sBLGmTmM+5ppdZjH8YcT6uMm6PvhKNIxYZw7MEmmJJqSLfGGjzZbeeKL/pw3rWM1j7iiP56fatJJ/ZMYI1urH+sMROrf/LxyxonDDjExKZ7HSOnW9WjcSL7aSNF8zZyupF430IP2nDlH06g8j1jii6NpepFWvGpnBuLYRu+e0JfA5GJ6k+43esuFt9OadvSHN0NNAG79+NPpgXa4+X+DpsEyUDZ3POnzA2/mCNQQIc9BbA9Xuz87nt1KvWsnHyFDNtOT+04p1dJ23dszstPkGD+1yduJsa5VH8d9amV2nRr1cQWm9yxOFkP5F0Vo3FjYdvmj7456W+I2VY85s66HHVSthhs8oTyd/aSXOUB49vxyvWkkz3liTWL4k86yauUNHy8HvwfRqxYwyXF/2Qp2ofuOJzNBnFZ7P+umJ24petqJr8lTLRSvhOGao75lulh27pufyg+bULre6vFodxWJ/ayWtiP9i9Ub/6729f72bZxXOS6DOF/07zf3woTClpUgwBk3matcxe3M+6DUUQvnGypqRyjyZ9BdWrEGCzNqJkq0MyYYPDmvW0Tv2smx4x17l2DDmsZZBvGOeEnd8cLjrxvrgsFtJXWrd8jUjKcicYAtUKt8aOe4bSWvwlejV/qWRuuYtm2Gk6IbvJ9uI8/vJzE5erS3XtsHI1cZ2TgjPPbO5GVVsCXWo60Uq0eqCpisyJ/ySVEMda91Qx7aRHXUsIfzVyupPT6xTWo65sBMe75qrJatradVqbmJN+0+lzodVxWINubTM7KhYHy6WJ3luOMvUTP6iSMwX+lyAyEmz8UK3LipyzyBK3fBCF7n/QrdseF/o1skx7he6tcfL+0I3V6ncL3R33Vgaa7YS7wyiacQ7g2jdzuUWNrvROyf/2ob22ja017ajveqG9mrdBu6fL9At8wW6Yb7ALFjvrKp1SZFz3s4sV/f8lGnF/V1t17F3psC04p4rM62458rscvHOlemWuSXdMrekW+aWdNPckl2+3lkhv2K/H/+1o92cz/kw6Mp5jdxoQufLuZgcViCoNRfTrHWwc3iwwn0D9cVDX61Y0wY1zlFG5avOX63YOdI0VLsEiuv+ixzlLTkqv52jEqaVErKZI/nVJlfyHOeXotVyxNoGHua3zx/nSr1sGGvxuP1Stf1I9S++fP7CD1OatK3Q/YPGPPUrKy3NTcanvh0Xrej85j/TNVwrlXliV1azdurv2jg/1nWJfgtGydYtJVt3lOwHK762YvfBSl8dtCfiZx80l2tkzR0IDZBDyK9W7g9tbU9W/H/QP5YU8ldWMs2FpKtWZB4SE5Q/Pn5akR2vDvP8Pe+rw8xRDHO3cYzxMHJkXfAWqqwtNPVcB39b0x+szDfzmaa9Kz+sWDkqM/gvFj4N6GeOzFNE5nJ9PGim9sepG83qiyLzo/mcCzKtGIMEyXNaUjjA8y+sWNOSZWpuMLbRNGvFJYZ1+mQ81LJiRs7OQYJ1dodtY37b1VAsG2acyhwgpyNammCth9XUZqRopohk1W+M9LgrGJFiGbHCvNfiazpo/1iOr8pvXoi7FEE5aP0vrFht1ntqTSvW0kCZA4VS2rtTwu1aPvMwl9XiYSlcMc9dlXUgJk8D/MyP7tCDeuzQgxru60GNO/Sgpvt6YNpw6oHZZv21U7fUjmyonbaldnRD7ejvqnWKc6B+LqNGox+LeZXJOsQqHcmoHfMWL3dLkbyjpVjTTd6WYi28+FuKtaLlbSmmDW8/tt6DcX4xpJir8QazlsVC0WONRo8klp2wo620uKOtmBvBnG2l5R1txVwbc7YVe33N2VbMXftzkkd4CefHwMvaCra2LSbaBR1e53utBZzSQz5QIC0Ytws2a2ksHbJGtDz/lr8ZjEqYYx2pFH3wo0zMOfm1s+38aiZXymuxWGtjZZ7jUeg89L+wkXcMi63FMf+wWOuOYbF5fq9zWGx64pYl614jtyypFQHrlCW1dh+5ZUmtbV1OWbJtOGXJbLPeV5geZcsrTI8dbUWt8w+/aCttQ1vRHW3F3NvlbCv2/jBnW7F2Zc35rsYTm68aqdbOLvfnrYYd010adkx3abg/3aVBtrSTtqGdbJjuMt/INa24UbVainXF0fnRtKKU/4iR/GEl7mhvccdnmMYdn2Ea73+GadzxGabx/meYbWPH0LoWGuukt8NITYZA5nXLUD6KMexS89zBPI+IfVzgvlz5YcRqs7rieg+a6I2aX62Yh2CsU+UyT0C8LrSrdQRirOsuqUqLfCmlb94cbS19hmB05VQ3zKhokh1dObUdXTnp/a5srWX5u3IO97uyacPXlW3Rj2ENR8VqKdZqmL+l5B2ztJp3zNJqlg0tpW1pKbqhpdyfpf0gb3nF6FMI9095K3HDZ7Ja84DOz2TbE3drK1uGtGXDkLZsGdKWDUPa0ja0NmtN4Mhhre1F45Vcd8zQat0xQ6v1/gyt1h0ztFrvz9DaNnbU8R/rPtWqY/PihHmgWzmEokLqV4NRTbN2qGB/DkbF2r8wD4ptHNv+QyCtTVllblottJ0qpdcikS0NVjY0WNnSYGVDg5UdDdZqJWGeUJeT3UraDlGSLfOzbcP8bNsyP9s2zM+2DfOzlihlmROrWZIai9GmlRXClyUb4YRq3r3lDSdUa3vXnkj0ui50qUHMkxtMK6uK/rgz5Dsrq+3XcuhVK2mdN1n40+fVippzb+46sr7XN9VRmStZtQYzRx/WFuZ04uNWymmnfmdlRiufaVqd+2HFOqyxzuBeOWq0cmRduxjXTpc/AkySvFqx9pDrutD2CG+3+MfDXBBz7f4+bViCG8M6wlby2ymi04q9Z4COk1c+Hrh+ZSfkFYB99gZ5a8duvJJmriTl94339MbaouU7GuY0cn8n+Wnk9s5c24ZvZ248jvs7c88mfXtn7mljw07yL+pGrLoxW4nraBjbiPNomI9GjvtGfCd+PFTLGjzR7pJysWCdh9R8MuI6pOacFrh/yOcnI659/h+yk+cOivNTMBiepF/3xHVczhdGrnZA53E58Yj2LZ+u43I+tXtnQ3F3nsvV4zvpJh72RVy+k24+ueI66eZ0Jd0f61jLYd6TbmxPnCfdfBzQVhrQvjv0//RE7g+LbSu+I/s/DGdlzrCeSaPJmhu7vCOlHO6PlCwb3pGStTPMPVKyhrHekVIuO0ZK7roxztz58NEzX+iPL1ijgtsOdQz3F8Y/WFmTb2cyXLQSjrUTMdtfYJYvJa3jJOqN7zjaLa1ar3/HrVCK85uuWHasXCVdZcMXrH9XNlnmsTf5j+Nm0hdf227dt7+fjqUK7Vo3OicgZuMN1qu9bpg7sFbE/O/TertcP9XwPJXirOx0tfWHY+3yD0e+PosRCo2b5HovCuv6w/CneL+uTlvx/nN9mxYI8o/NkfaW67ku9thyHd4ONMxzE50bt20rzuGKuUnMPaPe7Fd8WHN46fLmb2cQQzzEPs5hLnlUGjv9qGVr0Z8Cb2I2bjK1rcjcR3HOn71ffTnz8+tWzo+6YzW4dtWKzLn9xwFThpVmbsf1XPxp2/Bd/Gnb8F78eVqxPoJ8F39+KFhdx0FotBqcFUBa1v780trFnfVBAm1ECjyB/Xqql71Dv64d+pW+dfW1XKyNYr77nD45cqzlGxom/3BETd1fknCm9f2JdKcdq3TXeX+PDQb0GvvqyIG4zpKL+f0ulXiYe8WcSmkfODAL9/xQrdds1Hkf25nMF2348mJu/3arvmnFrdfmyHaLFb/q21MaTtUP5iViPtU3bThVP9gfdk7VD9ZMnlv17VkAr+qb+6W9w6ZgbRPzdqCWd3Qg04q36YcQftuKuwPZVtwdyNws5uxAlg1vBzIPcnR3IGtq39uB7IJ1dyBzp7L3bRrMRS1nB7L3KfvepqYN59vUtuHKi72/2CsGthV3Nzb3iW2x4hcD04pbDKLeFwPLhlcMou4QAzOuzysGZsF6xcDeuu1+m6ayoQPplg60YyAZUvttK/4OZFpxdyBzdczZgSwb3g6Uw44OZB867exAZsH636bmVyWdpkqT2PE1O9bgYG2Kynz3449jWezd9e6ubG7ycnblsGM+0bbi7oTWBq09Vvxd2bTi7sr2ZjFfV7ZseLuyZcPfla1tXu6uXOJvd2Wdd7poKUZXtlbGSlh7CiPdkvGzK5u7nd1dud6f8LL3Kbu7smnF3Qlr/W0r/q5ctwxr64Zhbd0wrK1bhrWyY1hbtwxrrQ3pUVdQhLZodGZrt1c+5ux1/uPehPzVKSTuziwbvlFj3dGZ93xdtuO3rfg7s2nF3ZmtlTFvZ7ZseDuzZcPfma1dY+7ObBbsls6cwizZs88EozNbJyjmNg9WyUpXtv3szLns6MwaNryZ25Y385YvXc2/bcXfmU0r7s6scr8zWza8ndmy4e7M0Yxg83Zms2DdndmMLE8zAickoUX78pofMwhhZoc34lX5wkaZgWMc1vqljRleWPgI069s1GPtiD022ChXbdR1w8DV8qizPOrl8pCZF7lcHmzjannwdVdXy0Nmecjl8mgzL+1yebCNq+XRpoQ0uezHPH64tat+9JNioaqXy4NtXPZjXvWjhgZ9OKbNGUf+wYp3J2+0PlPOD8T13iymFWtmtspfKPPPg0fM/Dhjv20r3uj6D744o+s/nTTlWui0bfgWOj/Y8I07y5bJ3bJjcjfa94ftsOIed9pWvOPOmMxz51zjTtOGc9xp2vCPO62TEr3jTrtg3ePOuiNsKFrx494OVHeEDdlW3E0/l9+24u9AphV3B8rtfgeybHg7kGXD34GsYF53BzIL1v/hZp6zto4H4IDg13PWzgxZB9eHdXB94Msw6qsRs6XQplMq2/A6frNCaGue17KVdNHE3NVYW7tqYp7idbz14tPRdXGGwR9/fGa8+GHuxSpzq3aueYsRfWfEf55fOg6jnVlrXyGvW0H5cvef+bFOQjrmnuIaaMfRTyNWYz2b+dxZGcrRtpjhc5nqV9MvusrFOunaPF1wTXtoeDvIP/Oj9z8UZMubVLa8SSX+thX/m1R2xBlEuR9nYNrwvkllR5xBlA1xBnbB+t+k5r7XuZH9/Lxdqv8jADdacfApr4Pv4/tpVOukwzRPPsl8tW99FRTzHEr3uLrd38VonyDpVoO2IwI3NvltK341aDt2MUa9v4vRtOFVA92xizHqhl2MdsG6o47ctwzn97cMnxmyvtfbOhCmZb7E7MUV8/pZd1/WDVtratzQl20r3l6YtsTkm1bcfdm24u3LZ1O63ZdNG86+bNpw9+V0bNhaYxesuy/LjlCfFDZsrZEdoT62FXfTD+m3rfg7UNgxS5vC/Vla04a3A4Uds7RnA9zQgUL67Zfh+cU/z6xKJbx9GX445WNd+5D/PO/35ZWarAWxPVZq39n+nCSSt+en2DbWUcpVo1y0sea7tLy3YTbZOaei8XKzn2emqpT7XUfKVWlL8+rY84fhqpW4butKhyUnO/aDmUZCSOvIoNwuuhLCrJ8QWrlqhWaZkl72paxDkAptVP3WSl0H2DW9nKMlbymaObof723a8L430o5475R/vdmmqUshFblaKE5lMm04lclZOaYNc2TtzItpw5kX5wjfVFnzC8ytsvbXoFdly47mWraobNmismWLypYtKlu2qGzZorJlg8qWDSpbtqhs/fVm61bZskFlywaVLfdV1p6L9OXFtuHLi3dO1FJZe87aq7If5s+9KrtjE5hpxK+yskVlZYvKyhaVlS0qK1tUVjaorGxQWdmisu3Xm61bZWWDysoGlZUNKmuu/zpV1rThVFnnOrSpsmacgFtl7ZgFr8rqjuaqW1RWt6isblFZ3aKyukVldYvK6gaV1Q0qqztUNh+/3mzdKqsbVFY3qKxuUFkzXtWpsqYNp8o642ZNla1bVLbuUNkcNjRX04hbZT9YcaqsbcWrsrYVr8p+sOJU2Q85cqpsDvdV1rThVFnThl9l4683W6/K2oXiUybbhk+ZvJVjqlu6v/pl23CqbLq/+mVvv3KrrL0VzKuyO1a/8pbVr7xl9StvWf3KW1a/8pbVr7xl9StvWP3KG1a/8pbVr5x/vdm6VXbD6lfesPqV769+fdqiOs9CLJUiQL7b5rouY+SLFL7a+Ou8WOiTFecFVPZBIr76tW346td7oIlZv+aBM+43j334jffNUzaccWQa8b95bCveN49pxf3mMa243zy2Fe+bx86R981T7x/NZdrwvnnqjqO5cv31Zut+85iF4nzzmDacbx5n5Zjq1u7nxbbhVNmW7qts3BHd9uG8QK/Kyo7mKltUVraorGxRWdmisrJFZWWLym44ADFvOAAxbzkAMbdfb7Zuld2gTHmDMuW2QWXr/W8V24ZTZeuGbxXzWGP/WPbYobK6o7nqFpXVLSqrW1RWt6isblFZ3aGy5bivsqYNp8qaNtwqW45fb7ZelbULxadMtg2fMnkrx1S3cj/uwrbhVNmyIe4ibJmrDjvmqkvY0FxNI26V/WDFqbK2Fa/K2la8KvvBilNlP+TIq7Jxg8rGDSobt6hs/PVm61bZuEFl4waVjRtU1rwQyamypg2nyjovZjJV1rw4y62y9iVeXpVNO5pr2qKyaYvKpi0qm7aobNqismmLyuYNKps3qGzeorL515utW2XzBpXNG1Q2b1DZuGHGIG6YMYgbZgyOLTs1jh07NcqO1a+yZfWrbFn9KltWv8qW1a+yZfWrbFn9KhtWv8qG1a+yZfWr1F9vtm6V3bD6VTasfpX7q1+f7kB2xV18sOGKu2jWfrgUdBRISnxYZn6tX2uXxbyEj27TzK8hF+H+JmzbhvOlEzZswm47Qqo/3Hbvfem0DTfRmEb8Lx3bivelY1pxv3RMK+6Xjm3F+9Kxc+R96bT7FyiZNrwvnbbjAqWiv95s3S+ddj8YzLbhfOm028FgMVj7gbwqa9pwqqxpw3vUxY7ANtuKV2Xrjvu+TCNulf1gxamythWvytpWvCr7wYpTZT/kyKmy9bivsqYNp8qaNtwqW8OvN1uvytqF4lMm24ZPmbyVYyqT9bHjHdrbNjxD+3i0+0du2DZ8ZWrbcJZp3rEoaVtxq/2O/V6mEb/axx0baGwrbrWPOzbQfLDiVfu4YwNNjfc30FTnLGa56odf7dOvN1u32m+YYq4bppjrhinmFs0zYXVd5Pe4BG/aqd9YOX+pywqVSn2tYiM/Kc3Ok1KTSzZyeBw2jmYSg7zPTdxSJnFHmdhrTdoO8uWaFWepiHWQgmqZTVYbjQtq+srKarTa4nsr7TBb7TEvozjT9Or4zo7vuN0PNlzH7X6y4TluN0jaUj9pR/1Ialvqx7TjrB/bhq9+Ptjw1Y+1qbymde1yon6c6ldW4rw067Qib62kZN3jl+e52TGHNTyv8UVTrOu7zin2NdShc+d/GrHuWZxXZrW0/AhFvrDR5q24rQbLhnXo/DHXEc65n1U5+UdmjDnvPlUDR2jz5l84UqwFjfn1lc5ifVu/X9SNvK0bu5Gk+c74417dr2yUOO8VKCkZbcRo8kXXx6RWvWpk3nhiGUnmbauuxmqf+Nt02ND2xw7f+IWRmKZGx3LVyPpqUr7y7jsjoa6rsVnlv8vOvPDhzFl8b8QMapOoczBc37+3vjCiV43oGtrr+zffhzLJq0xKNQrWlPm2bqOmj/QfHcc66pAvtn+riylaN8OpzFsrlYUxvQqjtaD4xy2e2VCBVja8s1q9/86ybHjfWa1teGc1vf/Oshfhve8sd92IVTdWK9F5yWo4P+LeG7Gu+3K+Kz55Mqdf4sGfXD88sUYDs4bzYdaO/a3kutne9iSHefkf3UH4Fw02mw32WA22XSvXeM4UTiPt/dhVrFl/Z7mKfQdUabOpSXjf6k1PfOVq6msL89SQFlp6q6/2W8v59fjBiO/j0TTi/3Y8S1Z+347zSh7bhu9Kng82fN+g1qqMrJWdZijs/S9HMS9/cr6FxQp1cr6FTRvOt7BY+1y8b2Gxasb5FpbQNryF/XUj19qI78PRNOH8bhRrAtb73fjBiG8sILc/G48NX43Hhk+1Y8OXmm74UHPb0Is2nJ9puuMVY5aq90t8x7zCjmkF/eW8eFvqhjmF0u63VL8NvWjD11LLlgn5HbMS9gjCNykhOd+dlDAM5GO29XNEwzdHvg4NrS1cKc43XUo8GvrGhm/RU6zz7XzLe1Z5JF2r6wcV6c/yKOa087p0tQTq/Ye+WrGuqq9xDmQqn6X4YsXcF+ecALfG23G0sXPNZa2uvxSIaWEOLysHYLxaMPcFzbihUPia1JdLRe2iiKsoYnpr46wU8/by2Or83I2qbxqZuZYt8xvzcV4jNbLmt3EWw0HZoQFVPF7yY62QeLuuacPZdc37ulxd19LCKOvQUKGbjl8slLst3bTgaulWLrwt3bThbulWTLW7pZuResf8BDrT5MkXNsos1FiKYcPsLSIz4Kk0imT52Vusq4q8vcW04ewt1kYtZ2/xl0hIb0vEfEWd75f1rb3KI1620e7boPnDHzasVaIwPx3On9GgrmW/jVjztFHloo0Z2RBTPd7bsIYxcd5jfybrRRtr+BGT3LeR41sbYtRtPeayWT00vLVh7X711q1pw1m3tg1f3ZqREbXSsDBssFEu2phLTGdSrtmQNVcnJV6z0eZqyrmccbE8zgHD9IMWU67baBfzcoz2kVq42D5amlrY8sW6bbktG3rVj9k+Wr1at5KmDdGLfU7WGMSqW/tg4Dm5nehd+aWNY9nI923EdFWD1u6J2C76kVZ5FL3vh6WFcYOuxw26Hjfoetig62GDrocNuh426HrYoOtWtNvR5tLHofXS+KMkHeVxJo1xkDk+nWOYxEvTr+PT2KyYV+8SW4vmx/oMvz07cTVciVa8apFhRYrS5EN7NWJ+CbX1JcTrffJqxIpYXZEupzhGw4j1xRyOvHZg8eacnxkyy7bMZp/oDI2/KFvTiq4a0veNxfy8q+tAkFCj9cHbYrs5wfzBkWni4UgzHDEXh2ROaRxBqZZfOrL10ZzDmCA6k+8dsWyUNJcPCtfwq41m3rOzRKm2es3Giqp6LO++tWFXTU5zw2DN+bKV2YvPtBplcnuSud2eZLZCAM/pV9pipMfbEJeWzfXlucx9rtrJNRtxDjc1xnZpijnNzXlnmobOX9Wt0PLBuVahRufN+fa0mW3DN23WzKMG70+b/Vki8Xq5tmUlXex5smZGzzQNO3/WTrm/BGDbcNZOib9bO3+UiByXa0fISnhrRfWuopkWfIsJVk7Oed0ZBnwOLcVqIe3u0opt45TF9baRShP531mRGcx0pmu4amUpvfBkzRdtrcU1JGnJ6MPmGTrhFKw5D9/+2ND9jZnzA3QGivF2uPgyDPYbCfGikTJjX2Oh+vnKyJmFeZzdwd9LP4zI/fVz00gJZbSUEhsHSHxjJM0onJIo7PXVSGzWh6hXp00bTp2W+5uo7QKZ38Mlh2IViLXaesyYxHrQLNRfWLHOaJlTjJVmXH9899mOrM2o/GH+ZXbWWSLnR1O4bGUu/laOGvvaSptW6Bv0Z7O3Zl/ynIku2TJinW7ke4/aJlwvUjMr3mV524h3Xb5ZW6a86/LBvJHjmEH0+c+u8zptYu288iqSacOpSOY5g05FssLPZE2LSeTO174wUtf8j8T01siZGzP03Bk91jRvePslUwZmz6EBzl84UrdkZ8fL3ApEO4VnjrV4OTqEH63NOp5lTTiSqEn9wo++xew55uPvtvBqRDfogH1/9RxO6x+LDq8SbRuZxapy6GUjaRrhpa1XI9bEyTmNO2Waw1kfw/M/jVgj2GO+cuJp770ROxB9vsy1ceTDV2XSVsEqTZ2+Gonm7SJ7rPyx35BDSl5K5YOVFZgSI30D/rQSoj1Ttybq4lUra579bFT5qpU89yyd8lYsK9a2UuepXh8uo6nzMz2194UbilnP8zM9Bjr28GXOP9T7Y7Z6f8xWdozZyo4xm5pnYHm12joyyrvzX82VLueeQzVPMvDtOTRtOPccqrWjzLsgqtYSl3PPoVon0Ln3HPrr5n2wvt1InBv/Nd3f7Bes8SfObEDdVDoB8nW7vW1EVuzv2fqvGfFu/Lc9KWlt16mWEetoh0PXwO9M8+FX35gJOa/3X+aYlS/NhLzMZONwMrNkkq7iDfVi8eY1w5z/2Lf3asScmPKcIWB2H+fRDLYN58kMmu+feKHZnClwnsxgeuItVbN2ZwzAWdHpYucJR6LTKHlg/l2rD6tUzumOy30wrP034U/N/2aYU+ZIicPWvxspzfk+0qVXE5+GwtOPc/h3eUCd526Pc9gUdgzLDSsfvpzmUFgbxWn8/OYp9+e3bBu++S3dsMHKtOGcI7MLdbaSs3yrUajWEYO5LkckvD9hxbZyduL57qqH1WLrh+ikaSXpVSutrFXWctkXnRty4nGEi1a8kxcffFlxX0GalSM5dnymy7HjM12OHZ/p5tKX9zPdLtwV/NFCuFwsXsm2i8Ur2e4qsiTb+kZ2zjX3QMDbc81q3XTgnms2v5HLHBZLDbwmWPxGWsjzSKsU80UjZdZxK3+sSrzWcbsdw/XBkXnYeyscPPnTkfuHDdg2nC/UdvuwgRDN447m8T6Nrxj5Wb3t9mSbacI32WZlxT3ZZhpxT7aZ3/veybay4ZhNVe/pC9Zkm94+Nsm24Z1s0/u7D9JhHfPnm2w7bYQdk23uujEm28r9UzbP7OT7k23WPUPuyTbTiHeyrWw4ZdP2xDvZZp7U4Z9sM834J9s+mPFOtpW6YbLNNOKdbCv3p4XK/XNQbRu+ybZ0WMcO+ibbThvt/mSb7Ym3VOuGyTa7ubon22wz7sm2D2a8k23mMMc32WaPlDyTbcE6WdL3nZMOe6Dk+845rbQN3znBHI7PrcDp1G0aw8oXRmSGoyXlzWo/jLT7K9fhdtS+bcI3mDa1xDuYNo04B9PpSDuiDZM5y0BB+0HeV28yz5leO5o08wd1/sZIJpVOF41IW+d38TD2R8ma5zu7+7AVrOTuw+aBUVXWFV1VwvtKNvKT5VjzukmvFW1e2TlHj2bR1i1FuyXk8LBG5vOAxVhrNZq+ZaTMN1eskt8aSceOUwlPKxtOJQzVDM1ZB4Gf6fD2ZjnZsgxunoCZ69oVLHwY3+vJteahTbKqWbLxJVjuTxecRjacslxuTxecNnZMF9QN0wV1w3TBF3UjVt2YrWROgEaxPlaKeTOWrLPOVC4bOe4bkbJi5qvR6Ks4pz/KxYJNFJN9DiCvGqlrYrkZRqylEOdh65+M+C7psrOT5zs98aLMT0/Sr3uyeuC5DLfByNUOeK4dyDTSjGYvZvT+OkJaoilLsqGhuDvP5eo5V+FnN7ZUqZm3lQh96BfrpWG6ouv8M6ulWGdjeGdz7FuLvLM57X5A2oeRUqprpFTerXedjohtJZOVdsmK9/bc+zHM6dD7N26eRm7fuGnb8I6T9P6Nm+nQ2zdunjY23Lj5Rd0YyypyP4b5dKTdX1aRHTHMsiOGWXbEMMuOGGbZE8Mse4KPZUfwsewIPpb7Wi8bgo/lfvBxMjdMO9+gIWy4Fs72xFuqO4KPZU/wsewJPpY9wccfpv3Wdsn6/jCVZM8z135l+LRSLllxji3MQHXn3GHI5jVmYV1Xmd4HDgdr5lDq/MwQie8DZVOI5jlx6/iEymGlLwtn1sQhb7ekXajnf/7CiMwg2XOa63hr5MxN/W0roa45zEqzdV9aEVnhrRotK8bQXOYRfMILPV/ZoIsiS7toIxxxLkfw0ZU/rVh7vpyhrR8KVtc6gkajvVmH6ZY2C6U0modR9ds4l5lWoZxplv3oN1NrWEvG9D2qr4ViX3/jWjO2/ZjXTZ5+qOGH1U7qUoMzrcaNYvYm+3XHWlA+DLu+RC1aJ3ufrWNeCBZJrHMsr67E2xJpTqGUWbTnt2S9ZGKtGp/JfM2EKyNNNmi9acSt0rn9thW/1ue2Q+utVS+v1ls2vFpfwg6tL3mD1psF69T6aJ2Y4x8pldu9J7oPpshWbnRHu6/Hb1vx9x7Tirv3WDtevL3HsuHtPebOG3fvsS4ucPces2C9vSceO16i5iH5vt5j3g7seonaJlwv0Q8mfBmpG2Rgz6eOlN+24pcB04pbBqTdlwHLhlcGpO2QAWvFyy0DZsF6ZcAKmvK/RK0lL2fvsWJp3L3HNOJu93sGsk129B7Tirv3WCsr3t5j2fD2HnOFx917NG3oPWbBenuPNfNY6lonIj/K6yextZkop7l2lv+4FiK/7Du1vs/93dhc9/J1Y/MAPG83No14O2C09nrtseLuxrYVbzeO1nYvZzc2bTi7sWnD3Y2jdZCztxvbBbujG+vcSvvHfSiv3Thaq00lzGPHS6QjGH50Y2uuzt2NY7g/lq1lQzeuO0ahMfy6FX83DjvGsmZz83bjcH8sa9rwd+O4YSxrF6y3G5vrb7piFJROHvnZka2T9PIxp6hz4IN+Xztybjs6svUx6OzI1qSfuyOXLW/SqL9txd+RTSvujmyte3k7smXD25EtG/6OnMqGjmwW7I6OjIWbbuTsMMHoyMkKC2jzcrF8KsP7jmyFU/s7srXs5ezIVoyQuyObRtxdMP+6FX9Hti9c8nZkq8F5O7Jlw9uRzc1n7o6cdUNHNgvW25HNnS9phtWcy9y0HP8yxxzNu71m2G+mCj7bzBc2yozj4sDSL23MSL/CNy9+ZaPOmyL+uDDmso1y1cYsj3q5POosj3q5PNbNGXK5PNjG1fLgu0qvlse66Ewul0ebeWmXy4NtXC2PNhWkyWU/ZAhia1f90HlnuV4uD7Zx2Y+5a1sNDYrmpkZnLLdtJM6gohiNWO4UzSD5dV/G49pDy4p5GKf8hS6nlL/IjjME2zTijW+3PXHGt0drcci5lGma8C1lyv1Z3LZjFrdtmcX9fSv+waZpxT3YbOX+YNOy4R1strJjsGkeZegdbJoF6x1sth3xQNHal+XtPTvigdqW2RLNv23F33tMK+7eYx5p6Ow9lg1v71HZ0HuSdaahu/fYh1Z6P9WsE0vi2pDP8b3nk1/zY+2fDfOgnXMSh0dbr0a852dS0b6eWJIO6/q5eSpU5ZOlvjIxtxJWuub3SxOj48jx1otoLXaXI86I9uOP74pXN6wZgTL3Rmc+WeqGEX1n5EMrm8OsR8cwWtmHywLmcU45tffZMc9SO+Yu3hr4YKkfRqymysdThXK0LWboYO8fhWvOtqy7xzP1G/1xfLtrkkPD20H9mZt2+8NAd7xCdccrNMXw21bcr1DbivcVmuL9MALThvMVatrwv0LjhjACu2Ddr1DzWNO5bfz8mF1y/yOkNlkHdqV5bHumuyn0hwnznK258zXyrMnrZvy0YTCd0u1tiOnYEFVrG3H34fTrVvxKkHZsQ0zp/jZE04ZXCdKObYgpb9iGaBesdxuitZ04rm2IiTd8/ziKMFlWQlsHr7TcSE/+9ER2BCKkvGGL2YZABNuIuwdu2ZRsWvH347Jjk0y/suVuPy73N8mYNvz9uGzYJGMXrLcf65beU+5vkjl2hPFsCYhNNf62FX/vqTsmZFO9PyFr2vD2nrpjQrYfNni799T4y2/BlOZyyNlBwtu3oH0yx7GW/48ajVepteK1x0ptZU4qNXl75IltY51eWzXKRRtrckvLextmg51TKBovN/p5JKlKud9xDBu2rqV55Pn5u3DRSJzRYqc9S0p2bOwyjYR+oPNzMii3i66EMGsnhFauWqE5paSXfSnrzKFCm02/tVLX+XB0pNq3OVrSdq5KWVbux3CbNrzvjLYjhjvprzfbNFUppCJXC8WpS6YNpy45K8e0YQ6pnXkxbTjz4hzaGzbsLy+nxn74BnRqbD42NFbTiFtjP1hxaqxtxauxthWvxn6w4tTYDzlyamy/QvSmxpo2nBpr2nBrbA6/3my9GmsXik+XbBs+XfJWjqlt5vSjU2NNG06NdU6DWjbMWWqnxn6YL/dq7I5NXaYRv8bGLRobt2hs3KKxcYvGxi0aGzdobNygsXGLxqZfb7ZujY0bNDZu0Ni4QWPNxV6nxpo2nBrrXHS25grMmADvXIEdneDV2LyjseYtGpu3aGzeorF5i8bmLRqbt2hs3qCxeYPG5i0aW3692bo1Nm/Q2LxBY/N9jbVjUn15sW348uKNjbU0tu3Q2LZFY+uOxlq3aGzdorF1i8bWLRpbt2hs3aKxdYPG1g0aW7dorPx6s3VrbN2gsXWDxtYNGtvur3nZNpwa2+6veZnbotwaG3do7I41r7xlzStvWfPKW9a88pY1r7xlzStvWfPKG9a88oY1r7xlzSvrrzdbt8ZuWPPKG9a88v01rw+bT+dphqVSzMdX+1fX7YZ868E3u3md9/Z8MOK72unDsSDOd45pw/nOcR5PYtZt2vDOsc+xcb5zyrHhrCLTiPud88GK851jW/G+c2wr3nfOByvOd86HHDnfOSXcP2LLtOF855g23O+cEn692XrfOXah+HTJtuHTJW/lmNqW7ufFtuHU2HQ7L/ZRe16NLTviLErc0VjjFo2NWzQ2btHYuEVj4xaNjVs0dsMxhmXDMYZlyzGGJf16s3Vr7AZdKht0qaQNGhvuf6PYNpwaG+5/o5jnEns11j4h2auxeUdjzVs0Nm/R2LxFY/MWjc1bNDZv0diyQWPLBo0tWzS2/HqzdWts2aCxZYPGlg0ae9yPs7BtODX2uB9nkXfMT+cd89Ol7misdYvG1i0aW7dobN2isXWLxtYtGisbNFY2aKxs0Vj59Wbr1ljZoLGyQWPlvsba1xj58mLb8OXFe52SpbHmbVdejbXv3fJqbNvRWNsWjW1bNLZt0di2RWPbFo1tWzRWN2isbtBY3aKx+uvN1q2xukFjdYPG6gaNlftzBbYNp8bK/bmCuGFPxoebQZ0aW3esedUta151y5pX3bLmVbesedUta151y5pX3bDmVTesedUta141/Hqz9Wps3bDmVTesedX7a14f7it2xVnYJlxxFlbdnkPcURop8eGX+bVyo3V60WzudA31S4yFfb+3831T7++z9t4zbp5lsSN2+tgRO13jhmtkTCP+941txfu+Ma243zemFff7xrbifd/YOfK+b9L9249MG973Tdpx+1FNv95s3e+bdD/2y7bhfN+k27FfKVgxBV6NNW04Nda04TzLQu5rrG3ErbE7ruoyjfg1Nm/R2LxFY/MWjc1bNDZv0diyQWPLBo0tWzS2/HqzdWts2aCxZYPGltsaG6rcHdN/MOEZ06cQ75+oYdtwKn28faJGME969Sq9acSt9Du2dJlG/EovO3bJ2FbcSi87dsl8sOJVetmxS6bK/V0yVe7vkjFt+JW+/XqzdSv9hlnlumFWud6fVQ7BkLZa5vWbdE9ADOkLE1mniWyYOO57cdz24rCCPMpjSxLk9Y+++3JLjm2k6jwfuWq6aGRdGB31KNeMnG+IeQPSEd9nJzZrt2s65qTYOa+WLlrxnVf7wYbrvNpPNjzn1dp1I/Ms/MdFmhcr+A8j+aqRuIyk91WTxDrILUVtc+Y05DdF8sFGmm+9lJq8t5F+10YOMy85hovVO+8MisLHgX9XM/PCrih6VUnYk8tG2hyGn8nLRuZIwjSit180evs9c/pqxbr0RYTnq9vQENvGPAH/TOobG9aMja8sTAuusmjWhTgS5lUAQuf4h3j4bbQ4bbQULtqY78szWS/aKMsPWrr5zsb65G3loh86W1c5W9rV8tBl4329iBFJlcu6dqnQpuPrNto1G3UOlHOl252/szEvvM5itDGx72Ntc2EvGJdniHV+XS6zpZ4ZoxmNmr7xxHeNh1gXc/mu8ZANt9rJjkvtxLqYa48V9yUethXvJR6yYRFLNixiyZZFLNmxiGUXrPMSDzPez92JzZu5nJ34gyfOTpzz3U6s5X4nNm24u591K9ceK/5ObFpxd2JrqtXbictxvxObl0e5O7F17L67E5sF6+zE1tu8HNNGOeL7UdaZHetq2DgvMy6Rx4zt1Yg1hJZZslVoBvvFiJ2bOseMPDfyF7nRDbmpx+/mJsx7t8/ktVFj6ZcLw0aKcs3Guv/7TG6wUcNFG23WLt8Q/Z0NmV8EsV0t07kwcSbrRRtp2cjZaqn3d6zYNnzz3l5hNWzoho3XumPftZjfN15plrxhNe6DFedqnG3FuxpnW/Guxn2w4lyN+5Aj52qcWOtX3hFFC/dHFOZBce4RRfv1ZutdjbMLxalK7X48mLdyTBsb4vRkQ5ye3I/Tkw3hw7Ijelh0R1PVLQqrWxRWtyisblFY3aKwukNh23FfYU0bToU1bbgVth2/3my9CmsXik+VbBs+VfJWjmHDOon6fB/Nxc7z/bYmXVq+aKNds9GrHjZaOC7amBNI58/KRRu5LRt61Y8wbdCNtt/ZmJM2Z9LwwzyjY9bL+eLI12ykI663Vrpq41g28n0b8aIfUdfbM7aLfqRVHkXv+1Hft/VS7tdtKffr9oMNV926bcSLfjjr1vbDV7duP4y6NSePY54jxVh4Pfwl9KOl+2Estg1fCEpL6Xdt+MJYzDJN81UZkxxWmVrzrFOUK72jXqYUTTfyioPhMcxfuNHuT5A2ax3LOUFq5qbE2VDPCca3ubFtzInJWOr7EolihbHGkqeElHJctOIMyrNt+ILyPtjwBOVZB7j5AmpMC66AmnQ7qCfdDuopVkCwljnK1hberm7aNtYoW1t8ayOa66zhOGb8yJmmb93v7HjbqGnD2UZtG542msywsRlgpJECjM638Bc20gpfK/Leht5vI7YNbxtJm9pI2tBG0oY2kq61kf96wj/+07/8+3/7+7/90z/+x7/827/+z/N3//kw9e//8o//59//+Yn//X/96z/RX//j//0f4y//57//y9///i//93/7H//+b//0z//X//r3f35Yevztb8fzf/6PeC506T+c/5v0v/7D39L5X84GXeKZDvjz47Sdx//K4z8F/OIcej3+t/zX/3w4+f8B"},{"name":"public_dispatch","is_unconstrained":true,"custom_attributes":["external","public"],"abi":{"parameters":[{"name":"selector","type":{"kind":"field"},"visibility":"private"}],"return_type":null,"error_types":{"361444214588792908":{"error_kind":"string","string":"attempt to multiply with overflow"},"459713770342432051":{"error_kind":"string","string":"Not initialized"},"1998584279744703196":{"error_kind":"string","string":"attempt to subtract with overflow"},"2360858009427093503":{"error_kind":"string","string":"InvalidTimelock"},"2369193878689457446":{"error_kind":"string","string":"HTLCNotExists"},"2718955667607728260":{"error_kind":"string","string":"Function get_htlc can only be called statically"},"3380315280177356474":{"error_kind":"string","string":"FundsNotSent"},"3781809441605198943":{"error_kind":"string","string":"Function get_user_swaps_count can only be called statically"},"4493654309393309420":{"error_kind":"string","string":"AlreadyClaimed"},"4736483829072576196":{"error_kind":"string","string":"HTLCAlreadyExists"},"5029608433027800177":{"error_kind":"string","string":"NotPassedTimelock"},"7413154743021792023":{"error_kind":"string","string":"InvalidRewardAmount"},"9967937311635654895":{"error_kind":"string","string":"Initialization hash does not match"},"13455385521185560676":{"error_kind":"string","string":"Storage slot 0 not allowed. Storage slots must start from 1."},"14415304921900233953":{"error_kind":"string","string":"Initializer address is not the contract deployer"},"14576755381182599325":{"error_kind":"fmtstring","length":24,"item_types":[]},"14924807131364042204":{"error_kind":"string","string":"HashlockNotMatch"},"14990209321349310352":{"error_kind":"string","string":"attempt to add with overflow"},"15764276373176857197":{"error_kind":"string","string":"Stack too deep"},"16190783185788596410":{"error_kind":"string","string":"Function has_htlc can only be called statically"},"16431471497789672479":{"error_kind":"string","string":"Index out of bounds"},"16810041750452690220":{"error_kind":"fmtstring","length":27,"item_types":[{"kind":"field"}]},"16884080922827299127":{"error_kind":"string","string":"InvalidRewardTimelock"},"17552554873437466887":{"error_kind":"string","string":"SwapAlreadyInitialized"}}},"bytecode":"JwACBAEoAAABBIBqJwAABGonAgIEAScCAwQAHwoAAgADAGktCGkBJQAAAEElAAABqCcCAQRqJwICBAA7DgACAAEsAABDADBkTnLhMaApuFBFtoGBWF0oM+hIeblwkUPh9ZPwAAAAKQAARARqCeZnKQAARQS7Z66FKQAARgQ8bvNyKQAARwSlT/U6KQAASARRDlJ/KQAASQSbBWiMKQAASgQfg9mrKQAASwRb4M0ZLQABTCcATQQJAAABTQEnAUwEAQAATAJNLQBNTi0ERE4AAE4CTi0ERU4AAE4CTi0ERk4AAE4CTi0ER04AAE4CTi0ESE4AAE4CTi0ESU4AAE4CTi0ESk4AAE4CTi0ES04nAE0EDSkAAE4E/////ycATwQQJwBQBAQoAABRBAEAJwBSBA4nAFMEAScAVAQDJwBVAQAnAFYCACcAVwQAJwBYBgAnAFkAACcAWgEBJwBbAAEnAFwEAicAXQYIJwBeBAwnAF8EDycAYAQeJwBhBCAnAGIEWicAYwS7JwBkBL4oAABlAAEcKAAAZgABICgAAGcAASUoAABoAAEpJiUAAEVyKQIAAgAX8SiICioBAgMnAgQEACcCBgQDACoEBgUtCAECAAgBBQEnAwIEAQAiAgIFLQ4EBQAiBQIFLQ4EBScCBQQDACoCBQQkAgADAAACASMAAAJDJwIDBAQtCAAEAAgAAwAlAABFmC0CAAAtCwIDACIDAgMtDgMCACICAgUtCwUEJwIGBAIAKgUGAzsOAAQAAyMAAAJDKQIAAwD8WpQ3CioBAwQnAgMCUycCBQJlJwIGAm4nAgcCZCcCCAJyJwIJAiAnAgoCbScCCwJ1JwIMAnMnAg0CdCcCDgJvJwIPAmInAhACIS0IAREnAhIEGQAIARIBJwMRBAEAIhECEi0KEhMtDgMTACITAhMtDgUTACITAhMtDgYTACITAhMtDgcTACITAhMtDgUTACITAhMtDggTACITAhMtDgkTACITAhMtDgoTACITAhMtDgsTACITAhMtDgwTACITAhMtDg0TACITAhMtDgkTACITAhMtDgYTACITAhMtDg4TACITAhMtDg0TACITAhMtDgkTACITAhMtDg8TACITAhMtDgUTACITAhMtDgkTACITAhMtDgYTACITAhMtDg4TACITAhMtDgYTACITAhMtDgUTACITAhMtDhATJwID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LS0KFy4ACAAkACUAAFK/LQIAAC0KLh4tCi8iHAoeFwAcCiIeACkCACIAKzxNXi0IASQnAiUEEAAIASUBJwMkBAEAIiQCJS0KJSctDiInACInAictDhonACInAictDhsnACInAictDhcnACInAictDh4nACInAictDhwnACInAictDiYnACInAictDiAnACInAictDh8nACInAictDiEnACInAictDiMnACInAictDFknACInAictDFknACInAictDFknACInAictDFknLQ4kGS0LKhcAIhcCFy0OFyotCAEXJwIaBB8ACAEaAScDFwQBACIXAhonAhsEHgAqGxobLQoaHA4qGxweJAIAHgAAJEYtDFYcACIcAhwjAAAkKy0IARoAAAECAS0OFxotCFcTIwAAJFwMIhNgFyQCABcAAEJWIwAAJG4tCxoXJwIaBC0tCAAtLQoXLgAIABoAJQAAU6ctAgAALQouGC0LGRctAhcDJwAEBBAlAABUWy0IBRoAIhpeGy0OGBstDhoZLQsrFwAiFwIXLQ4XKy0IARcnAhgEHwAIARgBJwMXBAEAIhcCGCcCGgQeACoaGBotChgbDioaGxwkAgAcAAAlAi0MVhsAIhsCGyMAACTnLQgBGAAAAQIBLQ4XGC0IVxMjAAAlGAwiE2AXJAIAFwAAQhIjAAAlKi0LGBcnAhoELS0IAC0tChcuAAgAGgAlAABTpy0CAAAtCi4YLQsZFy0CFwMnAAQEECUAAFRbLQgFGgAiGk0bLQ4YGy0OGhktCAEXJwIYBB8ACAEYAScDFwQBACIXAhgnAhoEHgAqGhgaLQoYGw4qGhscJAIAHAAAJbEtDFYbACIbAhsjAAAlli0IARgAAAECAS0OFxgtCFcTIwAAJccMIhNgFyQCABcAAEHOIwAAJdktCxgXJwIaBBstCAAbLQoXHAAIABoAJQAAU6ctAgAALQocGC0LGRctAhcDJwAEBBAlAABUWy0IBRoAIhpSGy0OGBstAhoDJwAEBBAlAABUWy0IBRcAIhdfGC0MWRgtDhcZLQgBGCcCGQQQAAgBGQEnAxgEAQAiGAIZJwIaBA8AKhoZGi0KGRsOKhobHCQCABwAACZ7LQxZGwAiGwIbIwAAJmAtCAEZAAABAgEtDhgZLQhXEyMAACaRDCITXxgkAgAYAABBiiMAACajLQsZEycCGQQP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","debug_symbols":"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"},{"name":"redeem","is_unconstrained":true,"custom_attributes":["external","public"],"abi":{"parameters":[{"name":"swap_id","type":{"kind":"field"},"visibility":"private"},{"name":"htlc_id","type":{"kind":"field"},"visibility":"private"},{"name":"secret_high","type":{"kind":"integer","sign":"unsigned","width":128},"visibility":"private"},{"name":"secret_low","type":{"kind":"integer","sign":"unsigned","width":128},"visibility":"private"}],"return_type":null,"error_types":{"361444214588792908":{"error_kind":"string","string":"attempt to multiply with overflow"},"459713770342432051":{"error_kind":"string","string":"Not initialized"},"1998584279744703196":{"error_kind":"string","string":"attempt to subtract with overflow"},"2369193878689457446":{"error_kind":"string","string":"HTLCNotExists"},"4493654309393309420":{"error_kind":"string","string":"AlreadyClaimed"},"13455385521185560676":{"error_kind":"string","string":"Storage slot 0 not allowed. Storage slots must start from 1."},"14576755381182599325":{"error_kind":"fmtstring","length":24,"item_types":[]},"14924807131364042204":{"error_kind":"string","string":"HashlockNotMatch"},"14990209321349310352":{"error_kind":"string","string":"attempt to add with overflow"},"15764276373176857197":{"error_kind":"string","string":"Stack too deep"},"16431471497789672479":{"error_kind":"string","string":"Index out of bounds"}}},"bytecode":"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","debug_symbols":"tZ3Zjh7HkYXfhde6yH3xqxiGINu0QYCQBI40wEDQu0/Gia1IobKL9Vf7wvp4uity3yKX/uPDvz/+8/f//vjp5//88j8f/vb3Pz7888unz58//ffHz7/866ffPv3y81L/+BDo/3IeH/5WfviQS/7wt07/Xf+OYUFtC+KCFhWmQC8LMsEUGFlhCExVpiglZAVVoiqxC6QkkINCUZCwSlGlqJ2qdqraQZwBTWDS5yuhFWHVBbkuaAvweSdYP0or7bWtaKRE0AV6lB/1JjAoiEHQBKYqU5QWooIqUZWoSlIlqZJVyaoUVYoqNShUgaZKU6WrgvICDAGUF6ALzKQgQXSNfA9isMegUBSmQMoKEkTPSUGC6JqKrqnomoquqehVDTYNoqnBrkF0NTg0CC2CrkXQpxgcISgUBQlixKwgQYyUFCSIoWUxtCxGUYNFgyhqsGoQVQ02DaKpwa5BdDWoFWmMZTCtKjpmUBBlhqAwBCjyDF2AIs+gCkUeQE2GYQpUVaoqTQ02/bzr56jzBEOVoYpGdVpUqaHl1UvEQA1eaChF06JpyTSKORNFXagpUc4LVSMKLRFRbRcqRvbTYdowbZpGfRRoRcGoK1GbFWpKKRhVI7IciHI2GkolGTWlGo2qkVmhJiBkVrpZoVbAhBxfWb8ilY2GUjQtmpZMQ46DkONMTQk5zlSNKLRKRP2mUFeijpcJed+JJv10VfCYqUsRqkZTCTFlGkpUqUsANSWKqZBpxbRiWjWtmkY9e4mgpkT1XMi0EYyq0YppoZLG4CbUhQqljYm6yZJBxWgoIUUF1JVoKGKiHGeimGYmLY/So5FpIxhVIy2jMrORllENWkY1ahnVrGVUSzSqRlpGGCuFtIwwWiJ3a9N8xngpZNowbZg2TZuqtaBlhGGTKUYj01IwqkZaRi1nIy0jjKNMNPKUBqIy6qCpRF0gE7U3JtSDuahTK6sB1JUofkLVaCqlYrRyrVIMMD4KdaViWjGtmlZNa6ZRz1CoFDpiytSUUIuZKAYZNJWobtQGGkIjqDaQIqZlr9EXg3JcqCpl07JpxTQaeYSGEtUhoa5EKRKi0KgWD+rRharSMG2YNk2jHl1oCE1KkVBXislIQ5s0DxMiywk0lWgaKjSUqLSEuhL1OUJmhWZmQmalmRWa1jAhHQ1UjCZTCqEYmRZNo/6FifoXoa5EPaZQU0IZdVAxGkpU65hQCpOI5vY9ENFkUagJRZqiCBWjqUR9e0+grkQxFTItm5ZNK6YV06gO9QzqSlSHhEyjfkioKVEd6gVUjIYS0kaUqJ/sFVSNphJS1EBDicYoJspxpqIlk2oy0pJJzbSmJZN6NKpSChhNmWjqLtSFMJqijDKN7MjxjDwFIS5M1UhLJpdiNCR3c01GmuMYOYVM66Z104ZpyFPK8TyTkZZMCclIS6bEaFSlFAr1okxIG1NXovrcBxHV5z5BVQm1hGkoUe6OSEQ94aCYYpQU6kIYJYWqEo3sQivXRgENJYqfkGnZtGxaMa2YRqPQCKChRDku1JSoNY4KqkaUDsqDSvVZyDSkiAjj6kygpkQ5LmRaMi2Zlk3LplGOC1UlynGhrtQs3GZaN3vd7FGvN6n0O/XPs4Dop9QWOmLFRKFRijqNPUKmIVb4PcSKaSpRPgsN/YJWPkKmUa/Mv0drZiaq2fxTanlM0zTKZ/zeQD4zmRajkaZoWIowmjLlYOQaxZ7qLkZTIdMsRaNqKkczDavnQFVnYP0s6OrQhI6hCR3TtKkJnSEZmRY1oViEMiFRE9SUsmlUeQaIikmoGk0lqkZCQwnNgcmsoDEzmZVuVtAcmMzKNCtoGItyCNGoKsVgVIyGUspGZiWbFU1lDsWsFLOiqVy9tlmpZkVTuYgcBIH8bYGSqegqJU9xGsLxJjgUsa5dAzOwGcIbJUjejNCB0zAVRxijmGGQVuyGxdXianW1utpc5WQCOZmM0xC+KkGPw3R1mt0UzG5CguDJTNQJR3guE+IbEyHcUYLNEC4pOC4TfFGM8OMIDsPuKnxSjPBKCcIu5W+asFuBxXEqZrhHBbthTI4wRmWRU3BEMgdwGsJrKuhqyY7DECXECNdhpOxjjy45OhdSdBJlX4Z/TbApYumrWA3hLRSk6JAfNWMhLAifoaCrqFyC3RCFJYgg4LOG540RvrdUgcMQ5Sboane1uzpcHa7CLyrYFSsnk3EaxuLoasqOZrfm5NgMOZmMCKIBpyEnk9HV5mpztbvaXeXSJGzwjaYOHz9iRpWgsQ8+AJshHKGCFLOMHQF2ygPZLQ9kNzwVVkMflbFXgLZJ/omFzZBryQTidytwGsIVy4g8E4QFSgW7lQWnITJKEPsElEwM9Yquok9lhDM2IzqjGqLxCpJd8lNkrJoZsWwWRDMlZ0QeaG/kb8gDGxIFOyRoZIKIL+U6j86C3ZCjw1gd/bPpn6F6ku8oTzRIQfqsRuA0RFYLuppcTa6i9xTshujtBZshLX8VEXACTkPUVEFXu6vdVTRIwW6IBinYBAuGcMVqiMoliCACcBiibQp2Q9R1wWYIx7+gG0OVY6xurLoxDHWMnLaCLbDsOAynq9PUGLJjN8TYLdgMMTIIVkcEXLHllh27IdoQIxdWx64cfmEQoiIKVsdpyFFnHIo8HrcAbIaIuqCrydXkanY1u4ra1yKwGaL2CbqKjTHB6khRJ79L4WFcsBsixYxo/g37k2j+gkMxczILsBtiBsKIYmHMVoS5REcrwlxdrVaEuQXHooWV0YkxYmNJsBkivijNgqkEiqVwhQFyhWEsjlaEJWfHrgXA47GgFUuprlZXm6vN1e4q53rElm50tCIs09VpRVhDcCxaWBW7y4xIsWAzRLsg/8pCVIKOLeRiyJWLsRtyNZrYZaYgyGeyphrJsRmiwggWx6nY0KTJS7KwGyK+gq4mV5Or2dXsKkacNoDdkIuFsToiOrxJXhyRNsqdhnYh6ConE8i7rfiM91sJO++4MroaXY0HdRryDjLjMORdZMZuyDvJBVgNeTeZ0dXmajuo05D3lRmHIe8tM3bD6QHzPjmh7DEnYHGchrzTzNgNebeZsRlmN4aJlqAbK24Ms3hGTlsDTkPe+Wd0dbg6XEUPLtgVse5XbIZ8jIERAXfgNOTSZOyGXFjUhrDdvFzywG6ITkGwOk5DRF2QEk+eo8JzAsEuuLqH5OhqdDW6mlxF7SM/VA2ofYLdsLiKvo8RjUwQUS/AacgpZuyG6KsnnUcJ5JdWLI6IDp1T4ekBMGK+I9gMkxZhjakb5uToaomOzZDbUAcWx2GI6Qwj4kulWXnIp2KpPOQLNkM0f8HiOA0RdRQA9qQFc3J0tbhaXK2uVlc51zPQijD15OjqiI5WsDz6o7B49Bccijz6M6JdkHOs8uhPXq/Ko7/gMMTAylhwqCgSUle88hA4DCm+is2QCkCxOtKJjoDoUIVRHIo4iKXoanQ1uppcTbBLhYU5gWI3LNER0aH6W2pwRNoGcBo2VzmZjGSXvCjLSZ4cXZ2uTlNrgFqArkZXcVwG578qDswINkMcmhF0tbhaXEXaBIvjNMShGsFh2D3g7tEZHsTwIKYHgSM2ghZEC8XRgmgxO1oQzVPcPMXNU4ylvWAJjh5E8YBxSA7n5hpXxAnE71IRwnefyJu0Eky/wAfpaPq1Wjthhkr9TqeRLJEromLDOyV8RrsdKePYHY1kKeMzGg4SeRrWRIySmWGB+smU8RmqvaCpWKMrdkNUDUFXk6vIKEZklGA1REYJHtRpWD3g6tFpHkTzgLsH0T3g4UEMDwINnTwNFRvfikMRW9+KriYc4spAHNqqQBijAsCCX3EYluTYDauraMeCbqy72l0drg5Xpwc8NeCGYVyxGSZYaMBhyFFnRCQnIUedsRnW6OgqzaMSeTAadr4VhyGqnCAFQWuyhh3xVBEz9EZAeN0VXaVBQrEZJleTq2gigtVxGqJtCrqKKifoATePTvMgugfcPYjhAQ8PYngQKKw6gUMxcYoZu2F0FVWOFm0LyRgtoBs89Gt1DuyGKDfBZohyE3QV3Stjd2Pd1eHqcHW6Oi1gjOiKFkSmOYwgqhyt51vOybEbYryghWPjwZ0R44VgNWyuouHQIrPhkLUgBkDBbkgLkJRwKhjHQ2kF2OCAT7TIXEjGaFXX4IBXdBUHRRmRClrVNR7RO+yiAARdra6iABhpla/oancVlYsRlUuwOE7D6SoqF5AHd0GLTo3R0QKuKThWRwsCC35FCoL21xv25hW7IVIs6Cr6B1p9NbjaEy0GG5wDiSbTDc4BxW5Ia0jFpoij4oIYuwXNWEuuJlezq9nVkhwtYLgBFKshWgsdJFjYDTnqjIgkZVTjqDNWRSz4FV1FlaO5fcMqXxBVjhFVjhGtheYEDev5NIFoLTMCiyMlk5Y7Dd78RDPoBm++YHe1u4oECXbD6eo0daAsBJshmr9gNUyuYkgStIBHzo4eREmOHkT1gKsH0TwIPhIcgdOwZ8dhOFydOHFMmYqT5Jmm4wthrAOHIU7hCnZDmhApupqnYXFjxdXqanW1udo84O4Bdw9iREOccw6NbiTgoLPgMIyI5AR2wxQdm2F2lc+VR2A1xElXwWGIU7m0kuhYxGfaNO7Yn88RccDBXMbh6nB1BseqiNNzigd1GlJzUhyGfHSe0dWcHC1gLPgVPYjqAVcPonrAzYNoHgTOofMVEBQWI6eYsRlOUxOqHO0qdz6hTkuCjulBpm3cnviEPRDlJlgNc3B0lXo5werGqqvN1eZqd7V7wMMDHh4E3xsgzHw1IBPy3QDGZsi3AxqwOk7DXBxdLcgSyqiM2seII/WCzRCjqdyvIQu0HuqZrzlM4DCkXi5nRB2nwGnB1HEAT9HV6CoSxIiyEHQ1u4qyYERzEiyO07C6ipbF2Dzg5tHpHkT3gIcHMTzg4UFMDwJ3O2iHdI0n2bEbcooZXUU9ox3djplCpm3cjplCpo3Vjl0CxW6IGx2CzbC5il5O0I0NV4er09VpKo7xKVrAOMinWA1xEYXWeh27BIIcdUZEkjKqcdQZq2ELjq7iig2dLF84DUc3RJUD4h5Zot2oztMDQVxRoPztGHEEh2FyNbmaXc2uFldRFozoCRiRCsHi6HHorna3O9zucLvozwSb4uAEUSvE7bFM284dzoFMx+071v6ZVosda/9Mh+s7jrsLoq7T4qpjwa9YHKfhdHWayiO64DBEBRfshik6NsMcHKujB1E8iOJB8FUgRg+iecDNg/BkwseviCCou5qc64zDEDWK9gs79v2BA/v+ghghaWW5NmGgJkKMZLTIHHDAK1IkaaW2XEHJEXYrIQpAsBpOV1EAglMRW/WZ9hYXUtRpVTciCkCwGyZXUQCM6FMFqyMu6lAyI+q64DCsrlZXm6tIMSMKQLAZIsWC1dEDRooFLQi+ciZoQfCILmhB8IguaEHwiC5YHD0ITzEW/LlH3NDE7yYgfpcKFqt8RVenq9NUrPIVu2F0NbrKUWdshhx1xmpYXC0HdRrW7OhBoLXQ3YKRubCAXFiMzXC4ysmkKpc5mYym8jjfO7BpnuF0nmI1TK6m4jgNs6tcQkAMKIwoITS9gk6344Yshg46fz8K7mkKHlTcMKMyhkeAmymP6IzTVLgBFLshBkBGVC70BFjw5wFE1Gm5vnAaFlfRnAYs8DW3AhyGzVUUi2AzRBtiRHxpAT3grGfEvn+mdfeAs16QLz524DBE/yDYDVHPGFHPBm4XcyoYp2F1lVMB5FQwuopuUBB9NaWioZ4JVkNOEJVbx4gj6CoaDiOngpHs0oJ/LVijI1QqIbgBFKshViiCwxCpoC2+hd0QqRB0FakQbIbTVSzEBDEOEQ4eTRmHIRJEDorB4zxt/K21NtQK7IbFVUy0JpXbwLyEPBgDoz82/gZuuykWx2E48BmVEF8Hp92+gfN9gtFVjIXkMhjYlBdMrtKUqtBe3WB3P3/Gm3nAkhxdhYNCsBk2V5tHB75Mxu5BdDc21MJKj24lz8AnKBiHIXbtBRtFPRJm3UpeOA2LqwXJRBDUpBVd5burGdjtMzuGMGV/HjhcHdVwBseDatHh43uCFgQf32NMZiFmSzxujguW5NgMcYUV+YCFuVjoHlp3dSRNcaSJrOB0lW/fUj6kYDHDvTdB28CffLJe0JKZUnF0NWdHSzwfvRd0Y9UtIEHk5p68VS/YDEdwLBT1Qu8dBD2NNfkcHmN0letOJaQRXdHVjExtwGqf5WlYiqOr/IQI4zBsrjaPDiqXoAfR3dgwCxi7cXxvYuwW5GOtjMURtRqY9Xzf5IN6gq5y3WGshs3VhkydwGmf9ew4DIeroxvO5GhqDdGxOloQNZox7M8LZkt8LcGxOA7DmjQf4KEXC91DG65y3WGchtPVOTQf+MwePuMze4x2qnLymT3GFB0t1/kMvWB1tMTz8T1BN1bdAhJEroiJJXih+y0TS/BC/smJ7XdFV/FeQcRnfGidGnrnQ+uMrvL5dWCKjtUQ8aWt5Il1d4lQ0dOSY3Qt6rKjq/zyQgVSF0R+xMm31gVd5TcXgDM4FsXBTwhRwNjAL3QMYWIDv5BPbGKUVnQVL0fQiYTJ77mQT2ztRUdHV/kCAeM05AsEQD6mT5mKY/qF3JoLqS+hWy9rYzs6moqxu5Dfc2LsLuQxnBi7FV0lH4jiMKS5hiDiS8cm5kSTlqdYqmFzFU2a7pZMDM2F/IgT+/OKw3BkR1enq1PV5bkO2RkdLHkd6fkXChtPlAQMxFF+BzVBHoZBVRDuBx0vFyhTcvihFoy2xkd9GmPANR7OiJswqjbHhw/KC+P0pfJRn87odpQPOgYB5e6MtzCoshJXZ06j8HBGNuMhj4C7bcLYWzc+6HgbQ7k5p4OOFzKUpzNaMB4DCXCiK6MTVYbNBm7xwAe9H3R0R8Kclv4DnvTB7wzmeuDpTLMIZdRzZcrPyA8C8cU94eZcDzqOYArjBLDyUZ/OfJWPGTOkjDoM17mx69hmV0bbxdMlAZvnpfDTRDS1UUbrxNMjgUdc4XbQKQ4Fj8QEHH8reAgm4PxbKZW5W56UmQ7seg2et5XfohH2vMVNtIIHUALuqBc8chLg4C545iRgeC2Ff5/a70R0ML4qdsPmKtULQVzzFnSVKr5iMaQuZSC34OJWbIa4kitIUcOLKgEn4Udi7IbFVbwIVPlDvAmkfNBRDpV/n+qIfEpVRJA6SkVXqaNUHIbT1WlR6vqiAGF1NGPwfgtSotpkbIZ4s0OwOFKZ4UmXtVpp/JrDQjx9IegqOp1amKvzPOgYaGtlnvopDtApDsPoKp72YMTbHoKu5uhYHT2I4saqW2iWA6MHx+I4DNFYODOmPklCaMFhqFUslmisk5XTQUdL4czAUlk+zZYqLJUVXa3R0bIfS2VFj1KzHMBSWdGNDbUQsVRGA41YKisOQ0yIBFHDG5iWlpVNUIYLFle5GnUwpnDKBx1DN01Fibt9SlVNsRkOV6mmCVJFUzyoFqVozyvxG2yC9sASv70myO5IxmHI7kjGZoguuCJjeCcbycCCWdFVVKPGgaDPFZ4HHZM6cjNSlKJ+muxps4hFs+JBnYbwyAi6mrNjNyweRHFj1S00ywHe2Ba0HEjs4mcslhnsBx+MFhz7wQWbJZqXzcoHHZM9zgz2hfOn2VKVS3F01R4Ui9leFIu5udo8Sj06ehDdjQ2zgJVzwbtKEdvbypiE4KWpWDhdzJyuwtycOV3C1RkTJ2VqIbQBtBgTJ+Xu3A46Jk7CmDgpH3T008rwOTBOQ9wGAVZOINo5trONDzpmgMKcKGGqCY3tUGkpY/Rvg3k6o2tQHs6cKGZO1GSuzpwo4aM+nTH4KLuO5bcxFsdAXn8zYp38558/fNB3bn/87cvHj/TM7eHh27//8eHXn758/Pm3D3/7+ffPn3/48L8/ff4dv/Q/v/70M/77209f1k9Xvf7487/Xf5fB/3z6/JHozx/863D+KU3Qh3xOk+BhJlZX+JWRuDGCk85sI7V+MFG/MpE2JtaeZlQbtKlpRnr8ykY+t5HXhv0UG5meHTqzsUsKDs5wNFY/cJqU+kBS2jsnJdEOkSQlnJfKODexdvrVxNp7n2eRmJuErHVM0oSsdczLCSnnCdlU87WJpY2EtqDMRP0mEpsaiq03TsfIbiBcNoAFPQysJe0tA1PTUEO4Y6AWrZe13EpCnVopW5hnBrbF0LoVw6inxbCpkvT8oXU2y4F/XqF2tZIeDLPm1Uo8NbKPSQkek5nOjKRN3c60WuZKsbpOz5BbOTpPK3bKu/4qW5e3NrLNREmXI9Gr5ubyNbbTSGw6zYZ9f65aJR3a+Pi6cqVNpxktFssBZRaox/jKQt/0d6XrYNjroWotx8/XNjbVIlt/t2ZtZiHlb/JiUzvXtFvbKT3jeGojb4qkJm2pawp1z8K0Aon1XjrS0EikfCiRv8RiVzlrsjZWD33/99lo02yMec8GTmDLGJTGuY22q11aM3pptyxM6y3WLtAtC+RUteleOy/XvCnXgtUTV/FynDHO78jO4tOserNYs9XQheOWjSeSgremOBqxjHstpUfruvqmvZb6vjZia5aW1sc9G93mjLHP81ZfxqstZWfhWkvZWbjaUmp8uXpts3N6x7OmO+fVaze41qBJaWtdcTq4kh/x1EbPGo8eDwPb8i59bWMTj7VXYNnRxziNx9WpxsHEN1ON2l+fatTx6lSjztenGi28OtVo8fWpRkuvTjW2Fi5NNbbpuDjVaPX1qcbexrWpxtbGxalGe7kDbS93oO2BDrS/3oHus/PaVGNv49pUY2fjiaRcnGpsW8rFaULv72vj6lRja+PiVGOEV1vKzsK1ljLC6y1lvD6T3WbnxanGdnC9ONUY7dpUI4d4OtUYuyo6og0IIx+mK/PWVGMcxpRvphpj6/0053pe/zuNxdwN8msH14ysjchzL+zOzRSiVTHifNNImW6khntGkrmbFpdzI/s8SYc86eXUyHaxg/dfpQuKzTM25/QdVvDAj1hJBwf3X6zsmt6YzZpe9NJZ3vPrNpo1m7ja3i0bo2tfNmY4tbBrNCNFazRHJ3O8bsGmpGPV/FMfcdhMKKf5qdcevaejhPKNjfy+NnKznYvcD+7dvxrZ7if55GONNRsj7Z2NJJzl5E51baBujOymprEXW0j2etPItGGmzxjvGRm+1zdybjfzpNm+0MJ8zwj1rNadbSvbzgjuBclgM+/GpNgiKJe7eZJ9LkKPyp8bidtZgI1YrZejs+C6DdqX91lmOAzi3xWVNTrM6n38YS/1O83gdJb20Ifl4feaSd7Rl3o7UdXHHHq052ZZV1uT5No2VXe3BfWIEfpDcDaNXpxvm5m+H5by7djgdSE1syvsNzbnDrEp8Tw2uyF1WpdLV9XOd7/nbmZgw/r5zvHcrV0tGQcfz3dZyH4K4J6FFLWWpZjuWbCWl1q4sQG+hi1bLIZeb0yPJv5gC1tYfdEdC8nOQtBduFsWbN098/Eowjf1KY/X6tPu+2v1aWvhUn3aWbhWn7YWXq1P3Vt2H/FOWc6gY/Wc6dRCLA9s3sfy8u59LA9s38fy8v49VsKvetXxxzZec6vvTVzyq++TctGxHusDm/hvGLnmWt8buehbR2V8zWW4NXHNZ7g1cdVpGOvrW/lv5Ok1B/sbRq552LdGHknNRR/7vtVcdJDHVt/ZyFU3+97IRT97fH1LKr6+JxWf2JSKD+xK7fP0orN9P/Be9LbD5fLqzn7s77u1/9VMJJ+6DmN/YG8/9pc392N/YHc/jpe39+N4YH8ff5rlxZnIeHmHf5+UqzOR8cAe/xtGLs5ExgO7/HG83qeO1/vU8USfOh/oU8cDW/1vGLk4Exn1nVNzdSYyHtjuj7O/s5HLM5H5wI4/XByvtZqtiWutZmviaqtJ4YEZ73xg238/8F6ciaTwwMZ/Cu+78//VTKSc+kvxd2ROB+8xzKU9w3k04EM6NZLwmiRbSfn8KlmKu/tTpdjFH7oCOk63qNPu8s9qcLZ7MQ5e5G93h/dGqh1miLXGjZFtgppN0RYftv//mqB97poLcHGt57m72wChswNqZXE/s7LtC4JfJQqh3dk3p6dfmu9Y53nLBl5WExtrK/C06qeNlUR/H8fdmuH0dEba3oxKs/odrc0Zj216cj+mJ93Kk17dxgibPCm72au57VP6qsLmb4zsPALNjs6kdpi95tbupWbWcCdH6NUam5mENs9zZOdnffHmGz2ZYL3acrLXWympdn2OLnf305TkXXd09cJvyrv7pVev/G7TU+bw9JR6np4n6mp+57r6VWr6+eZEyn3bB/i4tfoA71vbt8nZrXFS9+3cNEI+L+OtlXFYoYR4epYPN0vPW45fiM7leCP6u+KS8YqUxCWeX6RNZVdry7DZ9OKW78bF++kc53kLKmUXlxmrxWXmeTcutRziEs/jsj0WEexwUaY/o3ozLsn7pzUIbvJlu6NVQ7e41Hx+UXnfjnr3OUof7bQd7bakYm++gDusAst39ArDF05x1b7TXqE+8d5Eqvm9++zDiByPy8m/pKc+0ctt95Qu93J7K1d7uTqe6OW2cbncy20vWl3u5d6Iy8VerqUnerk34nKxl2vliV5uH5ervVxrT/Ry+3Z0tZfb7jI90Mv54RJ6XOt81dHDE71cj+/dy+Xg6bm5Ov1qxh/Pb3+m/sTstj8wu005PNFnb2/tXO6z91au9tm7ba/rffY2Lpf77BGf6LPfiMvFPnt3Oet6n/1GXC722btthet99j4uV/vs3S2t75iZhif67N1drQf67FDtVCO9B3vuTZiPeBPme3sTQj1sUdSNn2c+0d/O9/Z8HVPT07lvZD7iTZiPeBPmE96EHB7xJswnvAk5POJNmE94E3J4xJswn/Am5PCIN2E+4U3I4RFvwnzCm5Dj+3oTwoj+/uU4v2+Y4yOvV8YnvAkpPdFD5Vgf6KHesHK1h4r9gR5qH5fLPdT25cCrPdRbcbnYQ+3fDrzYQ70Vl4s91P4G18Ue6o24XO2hUn2ih0qP9FBbKw/0UMlOI+BPZZz2UNvLU5d7qBzee1Z53KeO43SvO+92y67OKvPu6bbLq/hdj3C9v82P9Lf5kf42P9Lf5kf62/xIf5sf6W/LI/1tfqS/LY/0t/mR/rY80t/u29HV/ra8b3+bkvdPy+9wPiMs2+NfF16L3lq49Fz03sKV96K3Fi49GL238OKL0asEvLUk6pjPSmPn1e8+5PR4OPNZ03fYyHZEa+FNG/66Qi+1nNt47eLs9vtLF2f3Fq5cnN1auHRxdm/hysXZN8rC37Yvh2d7vq88m71lUnq4Z6NagayN4JvxqKGajcNzKDV9Rzvz0+arzZ3Pynb7XgV/QI07rdJOx4Hcdr1WtzeISp/5dFK2NzJspF7YbhqZVtHLbGNj5GqW9PPBfm8j+Snv84OQebftlfModpwyj97vFc6owfK19rv56nfF5tgUzrYDsOqa8r2OMBVbQRwOIt+1MO91pT64tXzPQrNlw/Hl/XsWRrmZChsQRr03TbC7IbW1exasTtWRblqwOIx5z4KVZj1MyL9rymYv0pV600KzaWO/OfH0KyXj3rSx+NHeeto23zhU71dBFpdz5/sbVnyR9IoVK5XFLdy1YpMesnI+EsztRkCP/rRWr+dLre3tJVuuzXT3ApRVs9nrTRN+h6rv7oSOVxOyN3EpIVevUO5MtNcT0l5PSHs9IduHLa4lZGviWkIuPq+xM5FfnV/sLVyZX1y2MG9ZuDS/2Fu4Mr+4auF8fvFGKi7ML/bvdl0qza2FS6V51cK8ZeFaaW4tXCrNixY2pblPxaXS3D+K53+lb+S8eQHxO8yUeN+Mpygf3Drfmim7v15Vk10YrWkeLoyOb2zsbuFefDNzn5ziJzUX19u50r2m5H77/cOvY3PfTPQyKnffJKXHns3M4nLbjB86aNsnJveP4NqKfmG/Z2QEu6s5Yqh3jdiYvfYZbyZnJFvCjRzKE8mZN434OePlR2p3jfRpRma6baS6kXw3Y+2F8oXpdulYEadxt574Gy7bIn7jAXm/WR82e1ZvGGn1ASP+t02XkdMlXdnfzmr2dMLifLpPOl5e0Y2XF3Tj5fXc66ug1xdBr6+BysupKC+norycivzyQi6/vI7Lry/j0ot+xa2BK27FvYELXsWtgStOxe2fDb7iU9wauOJS3Bu44FHcGjh1KP5j/eunf3368uPh76b/8SdZ+vLpp39+/ij//M/vP//r8NPf/u9X/ck/v3z6/PnTf3/89csv//r479+/fCRL9LMPQf7v72vhVn5Ia7/2Hz98yPj3mmouMa9/R/6FSL8QJwkRQqff6PUff1IU/x8="},{"name":"refund","is_unconstrained":true,"custom_attributes":["external","public"],"abi":{"parameters":[{"name":"swap_id","type":{"kind":"field"},"visibility":"private"},{"name":"htlc_id","type":{"kind":"field"},"visibility":"private"}],"return_type":null,"error_types":{"459713770342432051":{"error_kind":"string","string":"Not initialized"},"4493654309393309420":{"error_kind":"string","string":"AlreadyClaimed"},"5029608433027800177":{"error_kind":"string","string":"NotPassedTimelock"},"13455385521185560676":{"error_kind":"string","string":"Storage slot 0 not allowed. Storage slots must start from 1."},"14990209321349310352":{"error_kind":"string","string":"attempt to add with overflow"},"15764276373176857197":{"error_kind":"string","string":"Stack too deep"}}},"bytecode":"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","debug_symbols":"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"},{"name":"sync_private_state","is_unconstrained":true,"custom_attributes":["external","utility"],"abi":{"parameters":[],"return_type":null,"error_types":{"344423948968719440":{"error_kind":"fmtstring","length":98,"item_types":[{"kind":"integer","sign":"unsigned","width":32},{"kind":"integer","sign":"unsigned","width":32},{"kind":"field"}]},"361444214588792908":{"error_kind":"string","string":"attempt to multiply with overflow"},"992401946138144806":{"error_kind":"string","string":"Attempted to read past end of BoundedVec"},"1998584279744703196":{"error_kind":"string","string":"attempt to subtract with overflow"},"3080037330898348111":{"error_kind":"fmtstring","length":132,"item_types":[{"kind":"integer","sign":"unsigned","width":32}]},"4261968856572588300":{"error_kind":"string","string":"Value does not fit in field"},"4440399188109668273":{"error_kind":"string","string":"Input length must be a multiple of 32"},"7564993426627941149":{"error_kind":"fmtstring","length":48,"item_types":[{"kind":"field"},{"kind":"field"}]},"7995966536718645961":{"error_kind":"fmtstring","length":61,"item_types":[{"kind":"field"},{"kind":"field"}]},"8992688621799713766":{"error_kind":"string","string":"Invalid public keys hint for address"},"9791669845391776238":{"error_kind":"string","string":"0 has a square root; you cannot claim it is not square"},"9885968605480832328":{"error_kind":"string","string":"Attempted to read past the length of a CapsuleArray"},"9921926525851912681":{"error_kind":"fmtstring","length":98,"item_types":[]},"10791800398362570014":{"error_kind":"string","string":"extend_from_bounded_vec out of bounds"},"11021520179822076911":{"error_kind":"string","string":"Attempted to delete past the length of a CapsuleArray"},"12469291177396340830":{"error_kind":"string","string":"call to assert_max_bit_size"},"12913276134398371456":{"error_kind":"string","string":"push out of bounds"},"13450089406971132036":{"error_kind":"fmtstring","length":144,"item_types":[{"kind":"integer","sign":"unsigned","width":32}]},"14067204867181196045":{"error_kind":"fmtstring","length":75,"item_types":[]},"14990209321349310352":{"error_kind":"string","string":"attempt to add with overflow"},"15764276373176857197":{"error_kind":"string","string":"Stack too deep"},"16431471497789672479":{"error_kind":"string","string":"Index out of bounds"},"16792019527863081935":{"error_kind":"fmtstring","length":77,"item_types":[{"kind":"integer","sign":"unsigned","width":32}]},"17154023812102399658":{"error_kind":"fmtstring","length":128,"item_types":[{"kind":"integer","sign":"unsigned","width":32}]},"17803644318014042523":{"error_kind":"fmtstring","length":58,"item_types":[{"kind":"field"}]}}},"bytecode":"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","debug_symbols":"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4iYa0YmHGES6DboNug26MUuSWZLMkmSWJLMkmSXJLElmSTJLklmSzJJkliSzJJklySxJZkkyS5JZksySZJYksySZJcksSWZJMkuSWZLMkmSWJLMkmSXJLElmSTJLklmSzJJkliSzJJklySxJZkkyS5JZksySZJYksySZJcksSWZJMkuSWZLMkmSWJLMkmSXJLElmSTJLklmSzJJkliSzJJklySxJZkkyS5JZksySahEcYxQO4iQu4iYa0YmHGMR8mHRLuiXdKkvGLNxEIzrxEIOYF2d1EjYO4iQu4iYa0YmHGES6DboNug26DboNug26DboNug26DbpNuk26TbpNuk26TbpNuk26TbpNui26Lbotui26Lbotui26Lbotui26bbptum26bbptum26bbptum26bboZ3YxulSVjFy7iJpbbKXTiIQYxH1aWXBzESVzETaSb083p5nRzuh26Hboduh26Hboduh26Hboduh26Bd2CbkG3oFvQLegWdAu6Bd2Cbkm3pFvSLemWdEu6Jd2Sbkm3fG7j9yMO4iQu4iYa0YmHGES6DboNug26DboNug26DboNug26DbpNuk26TbpNuk26TbpNuk26TbpNui26Lbotui26Lbotui26Lbotui26bbptum26bbptum26bbptum26bboZ3YxuRjejm9GNWTKYJYNZMpglg1kymCWDWTKYJYNZMpglg1kymCWDWTKYJYNZMpglg1kymCWDWTKYJYNZMpglg1kymCWDWTKYJYNZMpglg1kymCWDWTKYJYNZMpglg1kymCWDWTKYJYNZMpglg1kymCWDWTKYJYNZMpklk1kymSWTWTKZJZNZMpklk1kymSWTWTKZJZNZMpklk1kymSWTWTKZJZNZMpklk1kymSWTWTKZJZNZMpklk1kymSWTWTKZJZNZMpklk1kymSWTWTKZJZNZMpklk1kymSWTWTKZJZNZMpklk1kymSWTWTKZJZNZMpklk1kymSWTWTKZJZNZMpklk1kymSWTWTKZJZNZMpklk1kymSWTWTKZJZNZMpklk1kymSWTWTKZJZNZMpklk1kymSWTWTKZJZNZMpklk1kymSWTWTKZJZNZMpklk1kymSWTWTKZJZNZMpklk1kymSWTWTKZJZNZMpklk1kymSWTWbKYJYtZspgli1mymCWLWbKYJYtZspgli1mymCWL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26DboNug26TbpNuk26TbpNuk26TbpNuk26Tbotui26Lbotui26Lbotui26Lbotum26bbptumW2XJ960xu/peG534uc0oDGI+rCz5fqNyV99r4yR+bqvcKksuGvFz+z7h39X32hjEz+37XG9X32vjIH5u2woXcRM/N6sLqiy5eIifm2GwfFhZcvFz81/hJC7i5+Y138qSi0783LzWrLLkYj6sLDk138qSi5P4uZ1as8qSi0b83E6temXJxSDmw8qSi4M4iYu4iUakW9It6ZbPrfpeGwdxEhdxE43oxEMMIt0G3QbdBt0G3QbdBt0G3QbdKku+++pdfa8XK0sufm7fX1Da1ffauIibaEQnHmIQ82FlyUW6Lbotui26VZZ8f4FpV99r4yF+bjkL82FlycXPLesyK0suLuImGtGJhxjEfFhZcpFuRrcvS9av5vtlSaMR/cOa75cljUHMD796q77XxkGcH9Z2+yLuRnRKRtE37Piqv1oi1/eOYFdLZOMibqIRnXiIQcyH3zFrpNuk26TbpNuk26TbpNuk26Tbotui26Lbotui26Lbotui26Lbotum26bbptum26bbptum26bbptumm9HN6GZ0M7oZ3YxuRjejm9HN6OZ0c7o53ZxudcyGFRrRiYcYxHx4yq0O6hnESVzEz23W+f1esho/t++b5na1RDYGMR9+L1mNgziJn9vchZtoxHLzwkMMYrnVfPNHHMRJXMRN/Ny+r0jY1RLZeIhB/Ny+34Tb1RLZOIif2/4VLuImfm5f2+uulsjG83DUVZzCb9y6hak2x7W9sEbIQiceYhDzYeXDxW/curGpNsfGRdzEz63ucarNsfFzs5pk5cPFfFj5cHEQJ/Fz+zosdrU5NhrRiZ/b98RrV5tj4+fmNcnKh4uDOInlVsaVDxeN6MRDDOLndmo6lQ8XB3ESP7dTk6x8uGjEcrPCQ4yHVfMXa4S6iqruupWrzsS/J+AfVklfHMRJXMRvsKhJVklfdOIhBjEfVknXPUN1JjZO4iKWW823SvqiE8utZlYlfTEfVklHHdoq6awaqpKuu47qTGzcRCM68TRWD+LfvyocxElcxE20h1WF35+d3NUg2FgW33yrFXDXXUe1AjZO4iJuoj1c9f+t+S4jOvEQg5gP9484iJO4iHTbdNt023TbdNt0sxp3FdYIu7BG8MJDDGKN8G13teE1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"}],"outputs":{"globals":{"storage":[{"fields":[{"name":"contract_name","value":{"kind":"string","value":"Token"}},{"name":"fields","value":{"fields":[{"name":"admin","value":{"fields":[{"name":"slot","value":{"kind":"integer","sign":false,"value":"0000000000000000000000000000000000000000000000000000000000000001"}}],"kind":"struct"}},{"name":"minters","value":{"fields":[{"name":"slot","value":{"kind":"integer","sign":false,"value":"0000000000000000000000000000000000000000000000000000000000000002"}}],"kind":"struct"}},{"name":"balances","value":{"fields":[{"name":"slot","value":{"kind":"integer","sign":false,"value":"0000000000000000000000000000000000000000000000000000000000000003"}}],"kind":"struct"}},{"name":"total_supply","value":{"fields":[{"name":"slot","value":{"kind":"integer","sign":false,"value":"0000000000000000000000000000000000000000000000000000000000000004"}}],"kind":"struct"}},{"name":"public_balances","value":{"fields":[{"name":"slot","value":{"kind":"integer","sign":false,"value":"0000000000000000000000000000000000000000000000000000000000000005"}}],"kind":"struct"}},{"name":"symbol","value":{"fields":[{"name":"slot","value":{"kind":"integer","sign":false,"value":"0000000000000000000000000000000000000000000000000000000000000006"}}],"kind":"struct"}},{"name":"name","value":{"fields":[{"name":"slot","value":{"kind":"integer","sign":false,"value":"0000000000000000000000000000000000000000000000000000000000000008"}}],"kind":"struct"}},{"name":"decimals","value":{"fields":[{"name":"slot","value":{"kind":"integer","sign":false,"value":"000000000000000000000000000000000000000000000000000000000000000a"}}],"kind":"struct"}}],"kind":"struct"}}],"kind":"struct"},{"fields":[{"name":"contract_name","value":{"kind":"string","value":"Train"}},{"name":"fields","value":{"fields":[{"name":"contracts","value":{"fields":[{"name":"slot","value":{"kind":"integer","sign":false,"value":"0000000000000000000000000000000000000000000000000000000000000001"}}],"kind":"struct"}},{"name":"user_swaps_count","value":{"fields":[{"name":"slot","value":{"kind":"integer","sign":false,"value":"0000000000000000000000000000000000000000000000000000000000000002"}}],"kind":"struct"}},{"name":"user_swaps","value":{"fields":[{"name":"slot","value":{"kind":"integer","sign":false,"value":"0000000000000000000000000000000000000000000000000000000000000003"}}],"kind":"struct"}}],"kind":"struct"}}],"kind":"struct"}]},"structs":{"functions":[{"fields":[{"name":"parameters","type":{"fields":[],"kind":"struct","path":"Train::constructor_parameters"}}],"kind":"struct","path":"Train::constructor_abi"},{"fields":[{"name":"parameters","type":{"fields":[{"name":"swap_id","type":{"kind":"field"}},{"name":"htlc_id","type":{"kind":"field"}}],"kind":"struct","path":"Train::get_htlc_parameters"}},{"name":"return_type","type":{"fields":[{"name":"amount","type":{"kind":"integer","sign":"unsigned","width":128}},{"name":"token","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"hashlock_high","type":{"kind":"integer","sign":"unsigned","width":128}},{"name":"hashlock_low","type":{"kind":"integer","sign":"unsigned","width":128}},{"name":"secret_high","type":{"kind":"integer","sign":"unsigned","width":128}},{"name":"secret_low","type":{"kind":"integer","sign":"unsigned","width":128}},{"name":"sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"src_receiver","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"timelock","type":{"kind":"integer","sign":"unsigned","width":64}},{"name":"claimed","type":{"kind":"integer","sign":"unsigned","width":8}},{"name":"reward","type":{"kind":"integer","sign":"unsigned","width":128}},{"name":"reward_timelock","type":{"kind":"integer","sign":"unsigned","width":64}}],"kind":"struct","path":"Train::HTLC_Public"}}],"kind":"struct","path":"Train::get_htlc_abi"},{"fields":[{"name":"parameters","type":{"fields":[{"name":"user","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress"}}],"kind":"struct","path":"Train::get_user_swaps_count_parameters"}},{"name":"return_type","type":{"kind":"field"}}],"kind":"struct","path":"Train::get_user_swaps_count_abi"},{"fields":[{"name":"parameters","type":{"fields":[{"name":"swap_id","type":{"kind":"field"}},{"name":"htlc_id","type":{"kind":"field"}}],"kind":"struct","path":"Train::has_htlc_parameters"}},{"name":"return_type","type":{"kind":"boolean"}}],"kind":"struct","path":"Train::has_htlc_abi"},{"fields":[{"name":"parameters","type":{"fields":[{"name":"swap_id","type":{"kind":"field"}},{"name":"htlc_id","type":{"kind":"field"}},{"name":"hashlock_high","type":{"kind":"integer","sign":"unsigned","width":128}},{"name":"hashlock_low","type":{"kind":"integer","sign":"unsigned","width":128}},{"name":"reward","type":{"kind":"integer","sign":"unsigned","width":128}},{"name":"reward_timelock","type":{"kind":"integer","sign":"unsigned","width":64}},{"name":"timelock","type":{"kind":"integer","sign":"unsigned","width":64}},{"name":"src_receiver","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"token","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"total_amount","type":{"kind":"integer","sign":"unsigned","width":128}},{"name":"src_asset","type":{"kind":"string","length":30}},{"name":"dst_chain","type":{"kind":"string","length":30}},{"name":"dst_asset","type":{"kind":"string","length":30}},{"name":"dst_address","type":{"kind":"string","length":90}}],"kind":"struct","path":"Train::lock_dst_parameters"}}],"kind":"struct","path":"Train::lock_dst_abi"},{"fields":[{"name":"parameters","type":{"fields":[{"name":"swap_id","type":{"kind":"field"}},{"name":"hashlock_high","type":{"kind":"integer","sign":"unsigned","width":128}},{"name":"hashlock_low","type":{"kind":"integer","sign":"unsigned","width":128}},{"name":"timelock","type":{"kind":"integer","sign":"unsigned","width":64}},{"name":"src_receiver","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"token","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"amount","type":{"kind":"integer","sign":"unsigned","width":128}},{"name":"src_asset","type":{"kind":"string","length":30}},{"name":"dst_chain","type":{"kind":"string","length":30}},{"name":"dst_asset","type":{"kind":"string","length":30}},{"name":"dst_address","type":{"kind":"string","length":90}}],"kind":"struct","path":"Train::lock_src_parameters"}}],"kind":"struct","path":"Train::lock_src_abi"},{"fields":[{"name":"parameters","type":{"fields":[{"name":"message_ciphertext","type":{"fields":[{"name":"storage","type":{"kind":"array","length":17,"type":{"kind":"field"}}},{"name":"len","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"std::collections::bounded_vec::BoundedVec"}},{"name":"message_context","type":{"fields":[{"name":"tx_hash","type":{"kind":"field"}},{"name":"unique_note_hashes_in_tx","type":{"fields":[{"name":"storage","type":{"kind":"array","length":64,"type":{"kind":"field"}}},{"name":"len","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"std::collections::bounded_vec::BoundedVec"}},{"name":"first_nullifier_in_tx","type":{"kind":"field"}},{"name":"recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress"}}],"kind":"struct","path":"aztec::messages::processing::message_context::MessageContext"}}],"kind":"struct","path":"Train::process_message_parameters"}}],"kind":"struct","path":"Train::process_message_abi"},{"fields":[{"name":"parameters","type":{"fields":[{"name":"swap_id","type":{"kind":"field"}},{"name":"htlc_id","type":{"kind":"field"}},{"name":"secret_high","type":{"kind":"integer","sign":"unsigned","width":128}},{"name":"secret_low","type":{"kind":"integer","sign":"unsigned","width":128}}],"kind":"struct","path":"Train::redeem_parameters"}}],"kind":"struct","path":"Train::redeem_abi"},{"fields":[{"name":"parameters","type":{"fields":[{"name":"swap_id","type":{"kind":"field"}},{"name":"htlc_id","type":{"kind":"field"}}],"kind":"struct","path":"Train::refund_parameters"}}],"kind":"struct","path":"Train::refund_abi"},{"fields":[{"name":"parameters","type":{"fields":[],"kind":"struct","path":"Train::sync_private_state_parameters"}}],"kind":"struct","path":"Train::sync_private_state_abi"}]}},"file_map":{"100":{"path":"/home/nerses/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.2/noir-projects/aztec-nr/aztec/src/macros/dispatch.nr","source":"use super::utils::compute_fn_selector;\nuse poseidon::poseidon2::Poseidon2Hasher;\nuse protocol_types::meta::utils::get_params_len_quote;\nuse std::{collections::umap::UHashMap, hash::BuildHasherDefault, panic};\n\n/// Returns an `fn public_dispatch(...)` function for the given module that's assumed to be an Aztec contract.\npub comptime fn generate_public_dispatch(m: Module) -> Quoted {\n let functions = m.functions();\n let functions =\n functions.filter(|function: FunctionDefinition| function.has_named_attribute(\"public\"));\n\n let unit = get_type::<()>();\n\n let seen_selectors =\n &mut UHashMap::>::default();\n\n let ifs = functions.map(|function: FunctionDefinition| {\n let parameters = function.parameters();\n let return_type = function.return_type();\n\n let selector: Field = compute_fn_selector(function);\n let fn_name = function.name();\n\n // Since function selectors are computed as the first 4 bytes of the hash of the function signature,\n // it's possible to have collisions. With the following check, we ensure it doesn't happen within\n // the same contract.\n if seen_selectors.contains_key(selector) {\n let existing_fn = seen_selectors.get(selector).unwrap();\n panic(\n f\"Public function selector collision detected between functions '{fn_name}' and '{existing_fn}'\",\n );\n }\n seen_selectors.insert(selector, fn_name);\n\n let params_len_quote = get_params_len_quote(parameters);\n\n let initial_read = if parameters.len() == 0 {\n quote {}\n } else {\n // The initial calldata_copy offset is 1 to skip the Field selector\n // The expected calldata is the serialization of\n // - FunctionSelector: the selector of the function intended to dispatch\n // - Parameters: the parameters of the function intended to dispatch\n // That is, exactly what is expected for a call to the target function,\n // but with a selector added at the beginning.\n quote {\n let input_calldata: [Field; $params_len_quote] = dep::aztec::context::public_context::calldata_copy(1, $params_len_quote);\n let mut reader = dep::aztec::protocol_types::utils::reader::Reader::new(input_calldata);\n }\n };\n\n let parameter_index: &mut u32 = &mut 0;\n let reads = parameters.map(|param: (Quoted, Type)| {\n let parameter_index_value = *parameter_index;\n let param_name = f\"arg{parameter_index_value}\".quoted_contents();\n let param_type = param.1;\n let read = quote {\n let $param_name: $param_type = reader.read_struct(dep::aztec::protocol_types::traits::Deserialize::deserialize);\n };\n *parameter_index += 1;\n quote { $read }\n });\n let read = reads.join(quote { });\n\n let mut args = &[];\n for parameter_index in 0..parameters.len() {\n let param_name = f\"arg{parameter_index}\".quoted_contents();\n args = args.push_back(quote { $param_name });\n }\n\n let args = args.join(quote { , });\n // name of the function is assigned just before the call so debug metadata doesn't span most of this macro when figuring out where the call comes from.\n let name = function.name();\n let call = quote { $name($args) };\n\n let return_code = if return_type == unit {\n quote {\n $call;\n // Force early return.\n dep::aztec::context::public_context::avm_return([]);\n }\n } else {\n quote {\n let return_value = dep::aztec::protocol_types::traits::Serialize::serialize($call);\n dep::aztec::context::public_context::avm_return(return_value.as_slice());\n }\n };\n\n let if_ = quote {\n if selector == $selector {\n $initial_read\n $read\n $return_code\n }\n };\n if_\n });\n\n if ifs.len() == 0 {\n // No dispatch function if there are no public functions\n quote {}\n } else {\n let ifs = ifs.push_back(quote { panic(f\"Unknown selector {selector}\") });\n let dispatch = ifs.join(quote { });\n\n let body = quote {\n // We mark this as public because our whole system depends on public\n // functions having this attribute. However, the public MACRO will\n // handle the public_dispatch function specially and do nothing.\n #[external(\"public\")]\n pub unconstrained fn public_dispatch(selector: Field) {\n $dispatch\n }\n };\n\n body\n }\n}\n\ncomptime fn get_type() -> Type {\n let t: T = std::mem::zeroed();\n std::meta::type_of(t)\n}\n"},"105":{"path":"/home/nerses/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.2/noir-projects/aztec-nr/aztec/src/macros/functions/initialization_utils.nr","source":"use dep::protocol_types::{\n abis::function_selector::FunctionSelector, address::AztecAddress,\n constants::GENERATOR_INDEX__CONSTRUCTOR, hash::poseidon2_hash_with_separator, traits::ToField,\n};\n\nuse crate::{\n context::{PrivateContext, PublicContext},\n oracle::get_contract_instance::{\n get_contract_instance, get_contract_instance_deployer_avm,\n get_contract_instance_initialization_hash_avm,\n },\n};\n\n// Used by `create_mark_as_initialized` (you won't find it through searching)\npub fn mark_as_initialized_public(context: &mut PublicContext) {\n let init_nullifier =\n compute_unsiloed_contract_initialization_nullifier((*context).this_address());\n context.push_nullifier(init_nullifier);\n}\n\n// Used by `create_mark_as_initialized` (you won't find it through searching)\npub fn mark_as_initialized_private(context: &mut PrivateContext) {\n let init_nullifier =\n compute_unsiloed_contract_initialization_nullifier((*context).this_address());\n context.push_nullifier(init_nullifier);\n}\n\n// Used by `create_init_check` (you won't find it through searching)\npub fn assert_is_initialized_public(context: &mut PublicContext) {\n let init_nullifier = compute_unsiloed_contract_initialization_nullifier(context.this_address());\n assert(context.nullifier_exists(init_nullifier, context.this_address()), \"Not initialized\");\n}\n\n// Used by `create_init_check` (you won't find it through searching)\npub fn assert_is_initialized_private(context: &mut PrivateContext) {\n let init_nullifier = compute_unsiloed_contract_initialization_nullifier(context.this_address());\n context.push_nullifier_read_request(init_nullifier);\n}\n\nfn compute_unsiloed_contract_initialization_nullifier(address: AztecAddress) -> Field {\n address.to_field()\n}\n\n// Used by `create_assert_correct_initializer_args` (you won't find it through searching)\npub fn assert_initialization_matches_address_preimage_public(context: PublicContext) {\n let address = context.this_address();\n let deployer = get_contract_instance_deployer_avm(address).unwrap();\n let initialization_hash = get_contract_instance_initialization_hash_avm(address).unwrap();\n let expected_init = compute_initialization_hash(context.selector(), context.get_args_hash());\n assert(initialization_hash == expected_init, \"Initialization hash does not match\");\n assert(\n (deployer.is_zero()) | (deployer == context.msg_sender().unwrap()),\n \"Initializer address is not the contract deployer\",\n );\n}\n\n// Used by `create_assert_correct_initializer_args` (you won't find it through searching)\npub fn assert_initialization_matches_address_preimage_private(context: PrivateContext) {\n let address = context.this_address();\n let instance = get_contract_instance(address);\n let expected_init = compute_initialization_hash(context.selector(), context.get_args_hash());\n assert(instance.initialization_hash == expected_init, \"Initialization hash does not match\");\n assert(\n (instance.deployer.is_zero()) | (instance.deployer == context.msg_sender().unwrap()),\n \"Initializer address is not the contract deployer\",\n );\n}\n\n/// This function is not only used in macros but it's also used by external people to check that an instance has been\n/// initialized with the correct constructor arguments. Don't hide this unless you implement factory functionality.\npub fn compute_initialization_hash(\n init_selector: FunctionSelector,\n init_args_hash: Field,\n) -> Field {\n poseidon2_hash_with_separator(\n [init_selector.to_field(), init_args_hash],\n GENERATOR_INDEX__CONSTRUCTOR,\n )\n}\n"},"108":{"path":"/home/nerses/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.2/noir-projects/aztec-nr/aztec/src/macros/functions/utils.nr","source":"use crate::macros::{\n functions::{\n auth_registry::AUTHORIZE_ONCE_REGISTRY,\n call_interface_stubs::{\n register_private_fn_stub, register_public_fn_stub, register_utility_fn_stub,\n },\n },\n notes::NOTES,\n utils::{\n fn_has_authorize_once, fn_has_noinitcheck, is_fn_contract_library_method, is_fn_external,\n is_fn_initializer, is_fn_internal, is_fn_test, is_fn_view, modify_fn_body,\n module_has_initializer, module_has_storage,\n },\n};\nuse dep::protocol_types::meta::utils::derive_serialization_quotes;\nuse std::meta::{ctstring::AsCtString, type_of};\n\npub(crate) comptime fn transform_private(f: FunctionDefinition) {\n register_private_fn_stub(f);\n\n let module_has_initializer = module_has_initializer(f.module());\n let module_has_storage = module_has_storage(f.module());\n\n // Private functions undergo a lot of transformations from their Aztec.nr form into a circuit that can be fed to the\n // Private Kernel Circuit.\n // First we change the function signature so that it also receives `PrivateContextInputs`, which contain information\n // about the execution context (e.g. the caller).\n let original_params = f.parameters();\n f.set_parameters(&[(\n quote { inputs },\n quote { crate::context::inputs::private_context_inputs::PrivateContextInputs }.as_type(),\n )]\n .append(original_params));\n\n let mut body = f.body().as_block().unwrap();\n\n // The original params are hashed and passed to the `context` object, so that the kernel can verify we've received\n // the correct values.\n let (args_serialization, _, serialized_args_name) =\n derive_serialization_quotes(original_params, false);\n\n let context_creation = quote {\n $args_serialization\n let args_hash = dep::aztec::hash::hash_args_array($serialized_args_name);\n let mut context = dep::aztec::context::private_context::PrivateContext::new(inputs, args_hash);\n };\n\n let function_name = f.name();\n\n // Modifications introduced by the different marker attributes.\n let internal_check = if is_fn_internal(f) {\n let assertion_message = f\"Function {function_name} can only be called internally\";\n quote { assert(context.msg_sender().unwrap() == context.this_address(), $assertion_message); }\n } else {\n quote {}\n };\n\n let view_check = if is_fn_view(f) {\n let assertion_message =\n f\"Function {function_name} can only be called statically\".as_ctstring().as_quoted_str();\n quote { assert(context.inputs.call_context.is_static_call, $assertion_message); }\n } else {\n quote {}\n };\n\n let (assert_initializer, mark_as_initialized) = if is_fn_initializer(f) {\n (\n quote { aztec::macros::functions::initialization_utils::assert_initialization_matches_address_preimage_private(context); },\n quote { aztec::macros::functions::initialization_utils::mark_as_initialized_private(&mut context); },\n )\n } else {\n (quote {}, quote {})\n };\n\n let storage_init = if module_has_storage {\n quote {\n // Some functions don't access storage, but it'd be quite difficult to only inject this variable if it is\n // referenced. We instead ignore 'unused variable' warnings for it.\n #[allow(unused_variables)]\n let storage = Storage::init(&mut context);\n }\n } else {\n quote {}\n };\n\n // Initialization checks are not included in contracts that don't have initializers.\n let init_check = if module_has_initializer & !is_fn_initializer(f) & !fn_has_noinitcheck(f) {\n quote { aztec::macros::functions::initialization_utils::assert_is_initialized_private(&mut context); }\n } else {\n quote {}\n };\n\n // All private functions perform message discovery, since they may need to access notes. This is slightly\n // inefficient and could be improved by only doing it once we actually attempt to read any. Note that the message\n // discovery call syncs private events as well. We do not sync those here if there are no notes because we don't\n // have an API that would access events from private functions.\n let message_discovery_call = if NOTES.len() > 0 {\n create_message_discovery_call()\n } else {\n quote {}\n };\n\n // Inject the authwit check if the function is marked with #[authorize_once].\n let authorize_once_check = if fn_has_authorize_once(f) {\n create_authorize_once_check(f, true)\n } else {\n quote {}\n };\n\n // Finally, we need to change the return type to be `PrivateCircuitPublicInputs`, which is what the Private Kernel\n // circuit expects.\n let return_value_var_name = quote { macro__returned__values };\n\n let return_value_type = f.return_type();\n let return_value = if body.len() == 0 {\n quote {}\n } else if return_value_type != type_of(()) {\n // The original return value is serialized and hashed before being passed to the context.\n let (body_without_return, last_body_expr) = body.pop_back();\n let return_value = last_body_expr.quoted();\n let return_value_assignment =\n quote { let $return_value_var_name: $return_value_type = $return_value; };\n\n let (return_serialization, _, serialized_return_name) =\n derive_serialization_quotes([(return_value_var_name, return_value_type)], false);\n\n body = body_without_return;\n\n quote {\n $return_value_assignment\n $return_serialization\n context.set_return_hash($serialized_return_name);\n }\n } else {\n let (body_without_return, last_body_expr) = body.pop_back();\n if !last_body_expr.has_semicolon()\n & last_body_expr.as_for().is_none()\n & last_body_expr.as_assert().is_none()\n & last_body_expr.as_for_range().is_none()\n & last_body_expr.as_assert_eq().is_none()\n & last_body_expr.as_let().is_none() {\n let unused_return_value_name = f\"_{return_value_var_name}\".quoted_contents();\n body = body_without_return.push_back(\n quote { let $unused_return_value_name = $last_body_expr; }.as_expr().unwrap(),\n );\n }\n quote {}\n };\n\n let context_finish = quote { context.finish() };\n\n // A quote to be injected at the beginning of the function body.\n let to_prepend = quote {\n dep::aztec::oracle::version::assert_compatible_oracle_version();\n $context_creation\n $assert_initializer\n $init_check\n $internal_check\n $view_check\n $storage_init\n $message_discovery_call\n $authorize_once_check\n };\n\n let to_append = quote {\n $return_value\n $mark_as_initialized\n $context_finish\n };\n let modified_body = modify_fn_body(body, to_prepend, to_append);\n f.set_body(modified_body);\n f.set_return_type(\n quote { dep::protocol_types::abis::private_circuit_public_inputs::PrivateCircuitPublicInputs }\n .as_type(),\n );\n f.set_return_data();\n}\n\npub(crate) comptime fn transform_public(f: FunctionDefinition) {\n register_public_fn_stub(f);\n\n let module_has_initializer = module_has_initializer(f.module());\n let module_has_storage = module_has_storage(f.module());\n\n // Public functions undergo a lot of transformations from their Aztec.nr form.\n let original_params = f.parameters();\n\n let args_len_quote = if original_params.len() == 0 {\n // If the function has no parameters, we set the args_len to 0.\n quote { 0 }\n } else {\n // The following will give us ::N + ::N + ...\n original_params\n .map(|(_, param_type): (Quoted, Type)| {\n quote {\n <$param_type as $crate::protocol_types::traits::Serialize>::N\n }\n })\n .join(quote {+})\n };\n\n // Unlike in the private case, in public the `context` does not need to receive the hash of the original params.\n let context_creation = quote {\n let mut context = dep::aztec::context::public_context::PublicContext::new(|| {\n // We start from 1 because we skip the selector for the dispatch function.\n let serialized_args : [Field; $args_len_quote] = dep::aztec::context::public_context::calldata_copy(1, $args_len_quote);\n dep::aztec::hash::hash_args_array(serialized_args)\n });\n };\n\n let name = f.name();\n // Modifications introduced by the different marker attributes.\n let internal_check = if is_fn_internal(f) {\n let assertion_message = f\"Function {name} can only be called internally\";\n quote { assert(context.msg_sender().unwrap() == context.this_address(), $assertion_message); }\n } else {\n quote {}\n };\n\n let view_check = if is_fn_view(f) {\n let name = f.name();\n let assertion_message =\n f\"Function {name} can only be called statically\".as_ctstring().as_quoted_str();\n quote { assert(context.is_static_call(), $assertion_message); }\n } else {\n quote {}\n };\n\n let (assert_initializer, mark_as_initialized) = if is_fn_initializer(f) {\n (\n quote { aztec::macros::functions::initialization_utils::assert_initialization_matches_address_preimage_public(context); },\n quote { aztec::macros::functions::initialization_utils::mark_as_initialized_public(&mut context); },\n )\n } else {\n (quote {}, quote {})\n };\n\n let storage_init = if module_has_storage {\n // Some functions don't access storage, but it'd be quite difficult to only inject this variable if it is\n // referenced. We instead ignore 'unused variable' warnings for it.\n quote {\n #[allow(unused_variables)]\n let storage = Storage::init(&mut context);\n }\n } else {\n quote {}\n };\n\n // Initialization checks are not included in contracts that don't have initializers.\n let init_check = if module_has_initializer & !fn_has_noinitcheck(f) & !is_fn_initializer(f) {\n quote { aztec::macros::functions::initialization_utils::assert_is_initialized_public(&mut context); }\n } else {\n quote {}\n };\n\n // Inject the authwit check if the function is marked with #[authorize_once].\n let authorize_once_check = if fn_has_authorize_once(f) {\n create_authorize_once_check(f, false)\n } else {\n quote {}\n };\n\n let to_prepend = quote {\n $context_creation\n $assert_initializer\n $init_check\n $internal_check\n $view_check\n $storage_init\n $authorize_once_check\n };\n\n let to_append = quote {\n $mark_as_initialized\n };\n\n let body = f.body().as_block().unwrap();\n let modified_body = modify_fn_body(body, to_prepend, to_append);\n f.set_body(modified_body);\n\n // All public functions are automatically made unconstrained, even if they were not marked as such. This is because\n // instead of compiling into a circuit, they will compile to bytecode that will be later transpiled into AVM\n // bytecode.\n f.set_unconstrained(true);\n f.set_return_public(true);\n}\n\npub(crate) comptime fn transform_utility(f: FunctionDefinition) {\n register_utility_fn_stub(f);\n\n // Create utility context\n let context_creation =\n quote { let mut context = dep::aztec::context::utility_context::UtilityContext::new(); };\n\n // Initialize Storage if module has storage\n let storage_init = if module_has_storage(f.module()) {\n quote {\n // Some functions don't access storage, but it'd be quite difficult to only inject this variable if it is\n // referenced. We instead ignore 'unused variable' warnings for it.\n #[allow(unused_variables)]\n let storage = Storage::init(context);\n }\n } else {\n quote {}\n };\n\n // All utility functions perform message discovery, since they may need to access private notes that would be\n // found during this process or they may be used to sync private events from TypeScript\n // (`sync_private_state` function gets invoked by PXE::getPrivateEvents function).\n let message_discovery_call = create_message_discovery_call();\n\n // A quote to be injected at the beginning of the function body.\n let to_prepend = quote {\n dep::aztec::oracle::version::assert_compatible_oracle_version();\n $context_creation\n $storage_init\n $message_discovery_call\n };\n let body = f.body().as_block().unwrap();\n let modified_body = modify_fn_body(body, to_prepend, quote {});\n f.set_body(modified_body);\n\n f.set_return_public(true);\n}\n\n/// Injects a call to `aztec::messages::discovery::discover_new_messages`, causing for new notes to be added to PXE and made\n/// available for the current execution.\npub(crate) comptime fn create_message_discovery_call() -> Quoted {\n quote {\n /// Safety: message discovery returns nothing and is performed solely for its side-effects. It is therefore\n /// always safe to call.\n unsafe {\n dep::aztec::messages::discovery::discover_new_messages(\n context.this_address(),\n _compute_note_hash_and_nullifier,\n );\n };\n }\n}\n\n/// Injects an authwit verification check of the form:\n/// ```\n/// if (!from.eq(context.msg_sender().unwrap())) {\n/// assert_current_call_valid_authwit::(&mut context, from);\n/// } else {\n/// assert(authwit_nonce, \"Invalid authwit nonce. When 'from' and 'msg_sender' are the same, authwit_nonce must be zero\");\n/// }\n/// ```\n/// where `from` and `authwit_nonce` are the names of the parameters that are expected to be present in the function definition.\n/// This check is injected by the `#[authorize_once(\"from_arg_name\", \"nonce_arg_name\")]`, which allows the user to define\n/// which parameters to use.\n///\n/// # Arguments\n/// * `f` - The function definition to inject the authwit verification check into. The function must have parameters\n/// matching the names specified in the `#[authorize_once]` attribute.\n/// * `is_private` - Whether the function is a private function (`true`) or a public function (`false`). This determines\n/// which authwit verification method to use: `assert_current_call_valid_authwit` for private functions\n/// or `assert_current_call_valid_authwit_public` for public functions.\npub(crate) comptime fn create_authorize_once_check(\n f: FunctionDefinition,\n is_private: bool,\n) -> Quoted {\n let maybe_authorize_once_args = AUTHORIZE_ONCE_REGISTRY.get(f);\n let authorize_once_args = if maybe_authorize_once_args.is_some() {\n maybe_authorize_once_args.unwrap()\n } else {\n // We need to for authorize_once to have already executed so that we can retrieve its params - this depends on\n // the order in which the attributes are applied.\n panic(\n f\"Functions marked with #[authorize_once] must have the #[external(\\\"private\\\")] or #[external(\\\"public\\\")] attribute placed last\",\n )\n };\n\n let (from_arg_name, nonce_arg_name) = authorize_once_args;\n let name: Quoted = f.name();\n\n let from_arg_candidates =\n f.parameters().filter(|(name, _)| name == f\"{from_arg_name}\".quoted_contents());\n let (from_arg_name_quoted, from_arg_type) = if from_arg_candidates.len() == 1 {\n from_arg_candidates[0]\n } else {\n panic(\n f\"Function {name} does not have a {from_arg_name} parameter. Please specify which one to use in #[authorize_once(\\\"...\\\", \\\"authwit_nonce\\\")]\",\n )\n };\n if from_arg_type\n != quote { dep::protocol_types::address::aztec_address::AztecAddress }.as_type() {\n panic(\n f\"Argument {from_arg_name_quoted} in function {name} must be of type AztecAddress, but is of type {from_arg_type}\",\n )\n }\n\n let nonce_arg_candidates =\n f.parameters().filter(|(name, _)| name == f\"{nonce_arg_name}\".quoted_contents());\n let (nonce_arg_name_quoted, nonce_arg_type) = if nonce_arg_candidates.len() == 1 {\n nonce_arg_candidates[0]\n } else {\n panic(\n f\"Function {name} does not have a {nonce_arg_name}. Please specify which one to use in #[authorize_once(\\\"from\\\", \\\"...\\\")]\",\n )\n };\n if nonce_arg_type != quote { Field }.as_type() {\n panic(\n f\"Argument {nonce_arg_name_quoted} in function {name} must be of type Field, but is of type {nonce_arg_type}\",\n );\n }\n\n let nonce_check_quote = f\"{nonce_arg_name_quoted} == 0\".quoted_contents();\n\n let fn_call = if is_private {\n // At this point, the original args of the fn have already been altered by the macro\n // to include PrivateContextInputs, so we need to adjust the args_len accordingly.\n let args_len = f.parameters().len() - 1;\n quote { dep::aztec::authwit::auth::assert_current_call_valid_authwit::<$args_len> }\n } else {\n quote { dep::aztec::authwit::auth::assert_current_call_valid_authwit_public }\n };\n let invalid_nonce_message = f\"Invalid authwit nonce. When '{from_arg_name}' and 'msg_sender' are the same, '{nonce_arg_name}' must be zero\"\n .as_ctstring()\n .as_quoted_str();\n quote { \n if (!$from_arg_name_quoted.eq(context.msg_sender().unwrap())) {\n $fn_call(&mut context, $from_arg_name_quoted);\n } else {\n assert($nonce_check_quote, $invalid_nonce_message);\n }\n }\n}\n\n/// Checks if each function in the module is marked with either #[external(...)], #[contract_library_method], or #[test].\n/// Non-macroified functions are not allowed in contracts.\npub(crate) comptime fn check_each_fn_macroified(m: Module) {\n for f in m.functions() {\n let name = f.name();\n if !is_fn_external(f) & !is_fn_contract_library_method(f) & !is_fn_test(f) {\n panic(\n f\"Function {name} must be marked as either #[external(...)], #[contract_library_method], or #[test]\",\n );\n }\n }\n}\n"},"110":{"path":"/home/nerses/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.2/noir-projects/aztec-nr/aztec/src/macros/notes.nr","source":"use crate::note::note_getter_options::PropertySelector;\nuse std::{collections::bounded_vec::BoundedVec, meta::{ctstring::AsCtString, type_of}};\n\n/// Maximum number of note types within 1 contract.\ncomptime global MAX_NOTE_TYPES: u32 = 128;\n\n/// A BoundedVec containing all the note types within this contract.\npub comptime mut global NOTES: BoundedVec = BoundedVec::new();\n\ncomptime mut global NOTE_TYPE_ID_COUNTER: u32 = 0;\n\n/// The note type id is set by enumerating the note types.\ncomptime fn get_next_note_type_id() -> Field {\n // We assert that the note type id fits within 7 bits\n assert(\n NOTE_TYPE_ID_COUNTER < MAX_NOTE_TYPES,\n f\"A contract can contain at most {MAX_NOTE_TYPES} different note types\",\n );\n\n let note_type_id = NOTE_TYPE_ID_COUNTER as Field;\n NOTE_TYPE_ID_COUNTER += 1;\n note_type_id\n}\n\n/// Generates default `NoteType` implementation for a given note struct `s` and returns it as a quote.\n///\n/// impl NoteType for NoteStruct {\n/// fn get_id() -> Field {\n/// ...\n/// }\n/// }\ncomptime fn generate_note_type_impl(s: TypeDefinition, note_type_id: Field) -> Quoted {\n let name = s.name();\n let typ = s.as_type();\n let note_type_name: str<_> = f\"{name}\".as_ctstring().as_quoted_str!();\n let max_note_packed_len = crate::messages::discovery::private_notes::MAX_NOTE_PACKED_LEN;\n\n quote {\n impl aztec::note::note_interface::NoteType for $name {\n fn get_id() -> Field {\n // This static assertion ensures the note's packed length doesn't exceed the maximum allowed size.\n // While this check would ideally live in the Packable trait implementation, we place it here since\n // this function is always generated by our macros and the Packable trait implementation is not.\n // Note: We set the note type name and max packed length as local variables because injecting them\n // directly into the error message doesn't work.\n let note_type_name = $note_type_name;\n let max_note_packed_len: u32 = $max_note_packed_len; // Casting to u32 to avoid the value to be printed in hex.\n let note_packed_len = <$typ as Packable>::N;\n std::static_assert(note_packed_len <= $max_note_packed_len, f\"{note_type_name} has a packed length of {note_packed_len} fields, which exceeds the maximum allowed length of {max_note_packed_len} fields\");\n\n $note_type_id\n }\n }\n }\n}\n\n/// Generates default `NoteHash` trait implementation for a given note struct `s` and returns it as a quote.\n///\n/// # Generated Implementation\n/// ```\n/// impl NoteHash for NoteStruct {\n/// fn compute_note_hash(self, storage_slot: Field) -> Field { ... }\n///\n/// fn compute_nullifier(self, context: &mut PrivateContext, note_hash_for_nullification: Field) -> Field { ... }\n///\n/// unconstrained fn compute_nullifier_unconstrained(note_hash_for_nullification: Field) -> Field { ... }\n/// }\n/// ```\ncomptime fn generate_note_hash_trait_impl(s: TypeDefinition) -> Quoted {\n let name = s.name();\n\n quote {\n impl aztec::note::note_interface::NoteHash for $name {\n fn compute_note_hash(self, storage_slot: Field) -> Field {\n let inputs = aztec::protocol_types::traits::Packable::pack(self).concat( [storage_slot]);\n aztec::protocol_types::hash::poseidon2_hash_with_separator(inputs, aztec::protocol_types::constants::GENERATOR_INDEX__NOTE_HASH)\n }\n\n fn compute_nullifier(\n self,\n context: &mut aztec::context::PrivateContext,\n note_hash_for_nullification: Field,\n ) -> Field {\n let owner_npk_m = aztec::keys::getters::get_public_keys(self.owner).npk_m;\n // We invoke hash as a static trait function rather than calling owner_npk_m.hash() directly\n // in the quote to avoid \"trait not in scope\" compiler warnings.\n let owner_npk_m_hash = aztec::protocol_types::traits::Hash::hash(owner_npk_m);\n let secret = context.request_nsk_app(owner_npk_m_hash);\n aztec::protocol_types::hash::poseidon2_hash_with_separator(\n [note_hash_for_nullification, secret],\n aztec::protocol_types::constants::GENERATOR_INDEX__NOTE_NULLIFIER as Field,\n )\n }\n\n unconstrained fn compute_nullifier_unconstrained(\n self,\n note_hash_for_nullification: Field,\n ) -> Field {\n let owner_npk_m = aztec::keys::getters::get_public_keys(self.owner).npk_m;\n // We invoke hash as a static trait function rather than calling owner_npk_m.hash() directly\n // in the quote to avoid \"trait not in scope\" compiler warnings.\n let owner_npk_m_hash = aztec::protocol_types::traits::Hash::hash(owner_npk_m);\n let secret = aztec::keys::getters::get_nsk_app(owner_npk_m_hash);\n aztec::protocol_types::hash::poseidon2_hash_with_separator(\n [note_hash_for_nullification, secret],\n aztec::protocol_types::constants::GENERATOR_INDEX__NOTE_NULLIFIER as Field,\n )\n }\n }\n }\n}\n\n/// Generates note properties struct for a given note struct `s`.\n///\n/// Example:\n/// ```\n/// struct TokenNoteProperties {\n/// amount: aztec::note::note_getter_options::PropertySelector,\n/// npk_m_hash: aztec::note::note_getter_options::PropertySelector\n/// randomness: aztec::note::note_getter_options::PropertySelector\n/// }\n///\n/// impl aztec::note::note_interface::NoteProperties for TokenNote {\n/// fn properties() -> TokenNoteProperties {\n/// Self {\n/// amount: aztec::note::note_getter_options::PropertySelector { index: 0, offset: 0, length: 32 },\n/// npk_m_hash: aztec::note::note_getter_options::PropertySelector { index: 1, offset: 0, length: 32 },\n/// randomness: aztec::note::note_getter_options::PropertySelector { index: 2, offset: 0, length: 32 }\n/// }\n/// }\n/// }\n/// ```\ncomptime fn generate_note_properties(s: TypeDefinition) -> Quoted {\n let name = s.name();\n\n let struct_name = f\"{name}Properties\".quoted_contents();\n\n let property_selector_type = type_of(PropertySelector { index: 0, offset: 0, length: 0 });\n\n let note_fields = s.fields_as_written();\n\n let properties_types = note_fields\n .map(|(name, _, _)| quote { pub $name: $property_selector_type })\n .join(quote {,});\n\n // TODO #8694: Properly handle non-field types https://github.com/AztecProtocol/aztec-packages/issues/8694\n let mut properties_list = &[];\n for i in 0..note_fields.len() {\n let (name, _, _) = note_fields[i];\n properties_list = properties_list.push_back(\n quote { $name: aztec::note::note_getter_options::PropertySelector { index: $i, offset: 0, length: 32 } },\n );\n }\n\n let properties = properties_list.join(quote {,});\n\n quote {\n pub struct $struct_name {\n $properties_types\n }\n\n impl aztec::note::note_interface::NoteProperties<$struct_name> for $name {\n fn properties() -> $struct_name {\n $struct_name {\n $properties\n }\n }\n }\n }\n}\n\n/// Generates the core note functionality for a struct:\n///\n/// - NoteTypeProperties: Defines the structure and properties of note fields\n/// - NoteType trait implementation: Provides the note type ID\n/// - NoteHash trait implementation: Handles note hash and nullifier computation\n///\n/// # Requirements\n///\n/// The note struct must:\n/// - Have an `owner` field\n/// - Implement the `Packable` trait\n/// - Not exceed `MAX_NOTE_PACKED_LEN` when packed\n///\n/// # Registration\n///\n/// Registers the note in the global `NOTES` BoundedVec to enable note processing functionality.\n///\n/// # Generated Code\n///\n/// For detailed documentation on the generated implementations, see:\n/// - `generate_note_properties()`\n/// - `generate_note_type_impl()`\n/// - `generate_note_hash_trait_impl()`\npub comptime fn note(s: TypeDefinition) -> Quoted {\n assert_has_owner(s);\n assert_has_packable(s);\n\n // We register the note in the global `NOTES` BoundedVec because we need that information inside the #[aztec] macro\n // to generate note processing functionality.\n NOTES.push(s.as_type());\n\n let note_properties = generate_note_properties(s);\n let note_type_id = get_next_note_type_id();\n let note_type_impl = generate_note_type_impl(s, note_type_id);\n let note_hash_impl = generate_note_hash_trait_impl(s);\n\n quote {\n $note_properties\n $note_type_impl\n $note_hash_impl\n }\n}\n\n/// Generates code for a custom note implementation that requires specialized note hash or nullifier computation.\n///\n/// # Generated Code\n/// - NoteTypeProperties: Defines the structure and properties of note fields\n/// - NoteType trait implementation: Provides the note type ID\n///\n/// # Requirements\n///\n/// The note struct must:\n/// - Implement the `Packable` trait\n/// - Not exceed `MAX_NOTE_PACKED_LEN` when packed\n///\n/// Unlike the `#[note]` macro, there is no requirement for an `owner` field.\n///\n/// # Registration\n///\n/// Registers the note in the global `NOTES` BoundedVec to enable note processing functionality.\n///\n/// # Use Cases\n/// Use this macro when implementing a note that needs custom:\n/// - Note hash computation logic\n/// - Nullifier computation logic\n///\n/// The macro omits generating default NoteHash trait implementation, allowing you to provide your own.\n///\n/// # Example\n/// ```\n/// #[custom_note]\n/// struct CustomNote {\n/// value: Field,\n/// metadata: Field\n/// }\n///\n/// impl NoteHash for CustomNote {\n/// // Custom note hash computation...\n/// fn compute_note_hash(...) -> Field { ... }\n///\n/// // Custom nullifier computation...\n/// fn compute_nullifier(...) -> Field { ... }\n/// fn compute_nullifier_unconstrained(...) -> Field { ... }\n/// }\n/// ```\npub comptime fn custom_note(s: TypeDefinition) -> Quoted {\n assert_has_packable(s);\n\n // We register the note in the global `NOTES` BoundedVec because we need that information inside the #[aztec] macro\n // to generate note processing functionality.\n NOTES.push(s.as_type());\n\n let note_type_id = get_next_note_type_id();\n let note_properties = generate_note_properties(s);\n let note_type_impl = generate_note_type_impl(s, note_type_id);\n\n quote {\n $note_properties\n $note_type_impl\n }\n}\n\n/// Asserts that the given note implements the `Packable` trait.\n///\n/// We require that notes have the `Packable` trait implemented because it is used when emitting a note in a log or as\n/// an offchain message.\ncomptime fn assert_has_packable(note: TypeDefinition) {\n let packable_constraint =\n quote { crate::protocol_types::traits::Packable }.as_trait_constraint();\n let note_name = note.name();\n\n assert(\n note.as_type().implements(packable_constraint),\n f\"{note_name} does not implement Packable trait. Either implement it manually or place #[derive(Packable)] on the note struct before #[note] macro invocation.\",\n );\n}\n\n/// Asserts that the note has an 'owner' field.\n///\n/// We require notes implemented with #[note] macro macro to have an 'owner' field because our\n/// auto-generated nullifier functions expect it. This requirement is most likely only temporary.\ncomptime fn assert_has_owner(note: TypeDefinition) {\n let fields = note.fields_as_written();\n let mut has_owner = false;\n for i in 0..fields.len() {\n let (field_name, _, _) = fields[i];\n if field_name == quote { owner } {\n has_owner = true;\n break;\n }\n }\n let note_name = note.name();\n\n assert(\n has_owner,\n f\"{note_name} does not have an 'owner' field. If your notes have no owner, use #[custom_note] insteadof #[note] and implement the NoteHashing trait manually.\",\n );\n}\n"},"111":{"path":"/home/nerses/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.2/noir-projects/aztec-nr/aztec/src/macros/storage.nr","source":"use poseidon::poseidon2::Poseidon2Hasher;\nuse std::{collections::umap::UHashMap, hash::BuildHasherDefault};\n\nuse super::utils::AsStrQuote;\nuse super::utils::get_storage_size;\n\n/// Stores a map from a module to the name of the struct that describes its storage layout.\n/// This is then used when generating a `storage_layout()` getter on the contract struct.\npub comptime mut global STORAGE_LAYOUT_NAME: UHashMap> =\n UHashMap::default();\n\n/// Marks a struct as the one describing the storage layout of a contract.\n///\n/// The contract's storage is accessed via the `storage` variable, which will will automatically be made available in\n/// all functions as an instance of the struct this macro was applied to.\n///\n/// Only a single struct in the entire contract should have this macro (or `storage_no_init`) applied to it, and the\n/// struct has to be called 'Storage'.\npub comptime fn storage(s: TypeDefinition) -> Quoted {\n let struct_name = s.name();\n if struct_name != quote { Storage } {\n panic(\n f\"The #[storage] macro can only be applied to a struct with name 'Storage', got '{struct_name}' instead.\",\n )\n }\n\n assert(\n !s.has_named_attribute(\"storage_no_init\"),\n f\"Only one of #[storage] and #[storage_no_init] can be applied to the Storage struct.\",\n );\n\n // This macro performs three things:\n // - it marks the contract as having storage, so that `macros::utils::module_has_storage` will return true and\n // functions will have the storage variable injected and initialized via the `init` function.\n // - it implements said `init` function by allocating appropriate storage slots to each state variable.\n // - it exposes the storage layout by creating a `StorageLayout` struct that is exposed via the `abi(storage)`\n // macro.\n let mut slot: u32 = 1;\n let mut storage_vars_constructors = &[];\n let mut storage_layout_fields = &[];\n let mut storage_layout_constructors = &[];\n\n // TODO(#8658): uncomment the code below to inject the Context type parameter.\n //let mut new_storage_fields = &[];\n //let context_generic = s.add_generic(\"Context\");\n for field in s.fields_as_written() {\n // FIXME: This doesn't handle field types with generics\n let (name, typ, _) = field;\n let (storage_field_constructor, storage_size) =\n generate_storage_field_constructor(typ, quote { $slot });\n storage_vars_constructors =\n storage_vars_constructors.push_back(quote { $name: $storage_field_constructor });\n // We have `Storable` in a separate `.nr` file instead of defining it in the last quote of this function\n // because that way a dev gets a more reasonable error if he defines a struct with the same name in\n // a contract.\n storage_layout_fields = storage_layout_fields.push_back(\n quote { pub $name: dep::aztec::state_vars::storage::Storable },\n );\n storage_layout_constructors = storage_layout_constructors.push_back(\n quote { $name: dep::aztec::state_vars::storage::Storable { slot: $slot } },\n );\n //let with_context_generic = add_context_generic(typ, context_generic);\n //println(with_context_generic);\n //new_storage_fields = new_storage_fields.push_back((name, with_context_generic ));\n slot += storage_size;\n }\n\n //s.set_fields(new_storage_fields);\n let storage_vars_constructors = storage_vars_constructors.join(quote {,});\n let storage_impl = quote {\n impl Storage {\n fn init(context: Context) -> Self {\n Self {\n $storage_vars_constructors\n }\n }\n }\n };\n\n let storage_layout_fields = storage_layout_fields.join(quote {,});\n let storage_layout_constructors = storage_layout_constructors.join(quote {,});\n\n let module = s.module();\n let module_name = module.name();\n let storage_layout_name = f\"STORAGE_LAYOUT_{module_name}\".quoted_contents();\n let (module_name_str, module_name_len) = module_name.as_str_quote();\n STORAGE_LAYOUT_NAME.insert(module, storage_layout_name);\n\n quote {\n $storage_impl\n\n pub struct StorageLayoutFields {\n $storage_layout_fields\n }\n\n pub struct StorageLayout {\n pub contract_name: str,\n pub fields: StorageLayoutFields\n }\n\n #[abi(storage)]\n pub global $storage_layout_name: StorageLayout<$module_name_len> = StorageLayout {\n contract_name: $module_name_str,\n fields: StorageLayoutFields { $storage_layout_constructors }\n };\n }\n}\n\n/// Same as `storage`, except the user is in charge of providing an implementation of the `init` constructor function\n/// with signature `fn init(context: Context) -> Self`, which allows for manual control of storage slot\n/// allocation. Similarly, no `StorageLayout` struct will be created.\n///\n/// The contract's storage is accessed via the `storage` variable, which will will automatically be made available in\n/// all functions as an instance of the struct this macro was applied to.\n///\n/// Only a single struct in the entire contract can have this macro (or storage_no_init) applied to it, and the struct\n/// has to be called 'Storage'.\npub comptime fn storage_no_init(s: TypeDefinition) {\n // All `storage` does is provide the `init` implementation, so we don't need to do anything here. Applying this\n // macro however will cause for `macros::utils::module_has_storage` to return true, resulting in the injection of\n // the `storage` variable.\n\n // We do need to make sure that the type is called Storage, since we'll do `Storage::init` later on.\n\n if s.name() != quote { Storage } {\n let name = s.name();\n panic(\n f\"The #[storage_no_init] macro can only be applied to a struct with name 'Storage', got '{name}' instead.\",\n )\n }\n\n assert(\n !s.has_named_attribute(\"storage\"),\n f\"Only one of #[storage] and #[storage_no_init] can be applied to the Storage struct.\",\n );\n}\n\n/// Returns the expression required to initialize a state variable with a given slot, along with its serialization size,\n/// i.e. how many contiguous storage slots the variable requires.\ncomptime fn generate_storage_field_constructor(typ: Type, slot: Quoted) -> (Quoted, u32) {\n assert(\n typ.as_data_type().is_some(),\n \"Storage containers must be generic structs of the form `Container<_, Context>`, or Map\",\n );\n let (container_struct, generics) = typ.as_data_type().unwrap();\n let struct_name = container_struct.name();\n\n let constructor = if is_storage_map(typ) {\n // Map state variables recursively initialize their contents - this includes nested maps.\n let (value_constructor, _) =\n generate_storage_field_constructor(generics[1], quote { slot });\n\n quote { $struct_name::new(context, $slot, | context, slot | { $value_constructor }) }\n } else {\n // We assume below that all state variables implement `fn new(context: Context, slot: Field) -> Self`.\n quote { $struct_name::new(context, $slot)}\n };\n\n (constructor, get_storage_size(typ))\n}\n\n/// Returns true if `typ` is `state_vars::map::Map`.\ncomptime fn is_storage_map(typ: Type) -> bool {\n if typ.as_data_type().is_some() {\n let (def, generics) = typ.as_data_type().unwrap();\n let maybe_map = if (def.name() == quote { Map }) & (generics.len() == 3) {\n let maybe_key = generics[0];\n let maybe_value = generics[1];\n let maybe_context = generics[2];\n quote { crate::state_vars::map::Map<$maybe_key, $maybe_value, $maybe_context> }.as_type()\n } else {\n quote {()}.as_type()\n };\n typ == maybe_map\n } else {\n false\n }\n}\n\ncomptime fn add_context_generic(typ: Type, context_generic: Type) -> Type {\n let (def, mut generics) = typ.as_data_type().expect(\n f\"Storage containers must be generic structs of the form `Container<..., Context>`\",\n );\n let name = def.name();\n\n if is_storage_map(typ) {\n generics[generics.len() - 2] = add_context_generic(generics[1], context_generic);\n generics[generics.len() - 1] = context_generic;\n } else {\n generics[generics.len() - 1] = context_generic;\n }\n\n let generics = generics.map(|typ: Type| quote {$typ}).join(quote {,});\n quote { $name<$generics> }.as_type()\n}\n"},"113":{"path":"/home/nerses/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.2/noir-projects/aztec-nr/aztec/src/messages/discovery/mod.nr","source":"use protocol_types::{address::AztecAddress, debug_log::{debug_log, debug_log_format}};\n\npub mod nonce_discovery;\npub mod partial_notes;\npub mod private_events;\npub mod private_notes;\npub mod process_message;\n\nuse crate::{\n messages::{\n discovery::{\n private_notes::MAX_NOTE_PACKED_LEN, process_message::process_message_ciphertext,\n },\n processing::{\n get_private_logs, pending_tagged_log::PendingTaggedLog,\n validate_enqueued_notes_and_events,\n },\n },\n utils::array,\n};\n\npub struct NoteHashAndNullifier {\n /// The result of NoteHash::compute_note_hash\n pub note_hash: Field,\n /// The result of NoteHash::compute_nullifier_unconstrained (since all of message discovery is unconstrained)\n pub inner_nullifier: Field,\n}\n\n/// A function which takes a note's packed content, address of the emitting contract, note nonce, storage slot and note\n/// type ID and attempts to compute its note hash (not hashed by note nonce nor siloed by address) and inner nullifier\n/// (not siloed by address).\n///\n/// This function must be user-provided as its implementation requires knowledge of how note type IDs are allocated in a\n/// contract. The `#[aztec]` macro automatically creates such a contract library method called\n/// `_compute_note_hash_and_nullifier`, which looks something like this:\n///\n/// ```\n/// |packed_note, contract_address, note_nonce, storage_slot, note_type_id| {\n/// if note_type_id == MyNoteType::get_id() {\n/// assert(packed_note.len() == MY_NOTE_TYPE_SERIALIZATION_LENGTH);\n///\n/// let note = MyNoteType::unpack(aztec::utils::array::subarray(packed_note.storage(), 0));\n///\n/// let note_hash = note.compute_note_hash(storage_slot);\n/// let note_hash_for_nullification = aztec::note::utils::compute_note_hash_for_nullification(\n/// RetrievedNote{ note, contract_address, metadata: SettledNoteMetadata::new(note_nonce).into() },\n/// storage_slot\n/// );\n///\n/// let inner_nullifier = note.compute_nullifier_unconstrained(note_hash_for_nullification);\n///\n/// Option::some(\n/// aztec::messages::discovery::NoteHashAndNullifier {\n/// note_hash, inner_nullifier\n/// }\n/// )\n/// } else if note_type_id == MyOtherNoteType::get_id() {\n/// ... // Similar to above but calling MyOtherNoteType::unpack_content\n/// } else {\n/// Option::none() // Unknown note type ID\n/// };\n/// }\n/// ```\npub type ComputeNoteHashAndNullifier = unconstrained fn[Env](/* packed_note */BoundedVec, /* storage_slot */ Field, /* note_type_id */ Field, /* contract_address */ AztecAddress, /* note nonce */ Field) -> Option;\n\n/// Performs the message discovery process, in which private logs are downloaded and inspected to find new private\n/// notes, partial notes and events, etc., and pending partial notes are processed to search for their completion logs.\n/// This is the mechanism via which a contract updates its knowledge of its private state.\n///\n/// Note that the state is synchronized up to the latest block synchronized by PXE. That should be close to the chain\n/// tip as block synchronization is performed before contract function simulation is done.\n///\n/// Receives the address of the contract on which discovery is performed along with its\n/// `compute_note_hash_and_nullifier` function.\npub unconstrained fn discover_new_messages(\n contract_address: AztecAddress,\n compute_note_hash_and_nullifier: ComputeNoteHashAndNullifier,\n) {\n debug_log(\"Performing message discovery\");\n\n // First we process all private logs, which can contain different kinds of messages e.g. private notes, partial\n // notes, private events, etc.\n let mut logs = get_private_logs(contract_address);\n logs.for_each(|i, pending_tagged_log: PendingTaggedLog| {\n debug_log_format(\n \"Processing log with tag {0}\",\n [pending_tagged_log.log.get(0)],\n );\n\n // We remove the tag from the pending tagged log and process the message ciphertext contained in it.\n let message_ciphertext = array::subbvec(pending_tagged_log.log, 1);\n\n process_message_ciphertext(\n contract_address,\n compute_note_hash_and_nullifier,\n message_ciphertext,\n pending_tagged_log.context,\n );\n logs.remove(i);\n });\n\n // Then we process all pending partial notes, regardless of whether they were found in the current or previous\n // executions.\n partial_notes::fetch_and_process_partial_note_completion_logs(\n contract_address,\n compute_note_hash_and_nullifier,\n );\n\n // Finally we validate all notes and events that were found as part of the previous processes, resulting in them\n // being added to PXE's database and retrievable via oracles (get_notes) and our TS API (PXE::getPrivateEvents).\n validate_enqueued_notes_and_events(contract_address);\n}\n"},"114":{"path":"/home/nerses/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.2/noir-projects/aztec-nr/aztec/src/messages/discovery/nonce_discovery.nr","source":"use crate::messages::discovery::{ComputeNoteHashAndNullifier, private_notes::MAX_NOTE_PACKED_LEN};\n\nuse dep::protocol_types::{\n address::AztecAddress,\n constants::MAX_NOTE_HASHES_PER_TX,\n debug_log::debug_log_format,\n hash::{compute_note_hash_nonce, compute_siloed_note_hash, compute_unique_note_hash},\n traits::ToField,\n};\n\n/// A struct with the discovered information of a complete note, required for delivery to PXE. Note that this is *not*\n/// the complete note information, since it does not include content, storage slot, etc.\npub struct DiscoveredNoteInfo {\n pub note_nonce: Field,\n pub note_hash: Field,\n pub inner_nullifier: Field,\n}\n\n/// Searches for note nonces that will result in a note that was emitted in a transaction. While rare, it is possible\n/// for multiple notes to have the exact same packed content and storage slot but different nonces, resulting in\n/// different unique note hashes. Because of this this function returns a *vector* of discovered notes, though in most\n/// cases it will contain a single element.\n///\n/// Due to how nonces are computed, this function requires knowledge of the transaction in which the note was created,\n/// more specifically the list of all unique note hashes in it plus the value of its first nullifier.\npub unconstrained fn attempt_note_nonce_discovery(\n unique_note_hashes_in_tx: BoundedVec,\n first_nullifier_in_tx: Field,\n compute_note_hash_and_nullifier: ComputeNoteHashAndNullifier,\n contract_address: AztecAddress,\n storage_slot: Field,\n note_type_id: Field,\n packed_note: BoundedVec,\n) -> BoundedVec {\n let discovered_notes = &mut BoundedVec::new();\n\n debug_log_format(\n \"Attempting nonce discovery on {0} potential notes on contract {1} for storage slot {2}\",\n [unique_note_hashes_in_tx.len() as Field, contract_address.to_field(), storage_slot],\n );\n\n // We need to find nonces (typically just one) that result in a note hash that, once siloed into a unique note hash,\n // is one of the note hashes created by the transaction.\n unique_note_hashes_in_tx.for_eachi(|i, expected_unique_note_hash| {\n // Nonces are computed by hashing the first nullifier in the transaction with the index of the note in the\n // new note hashes array. We therefore know for each note in every transaction what its nonce is.\n let candidate_nonce = compute_note_hash_nonce(first_nullifier_in_tx, i);\n\n // Given note nonce, note content and metadata, we can compute the note hash and silo it to check if it matches\n // the note hash at the array index we're currently processing.\n // TODO(#11157): handle failed note_hash_and_nullifier computation\n let hashes = compute_note_hash_and_nullifier(\n packed_note,\n storage_slot,\n note_type_id,\n contract_address,\n candidate_nonce,\n )\n .expect(f\"Failed to compute a note hash for note type {note_type_id}\");\n\n let siloed_note_hash = compute_siloed_note_hash(contract_address, hashes.note_hash);\n let unique_note_hash = compute_unique_note_hash(candidate_nonce, siloed_note_hash);\n\n if unique_note_hash == expected_unique_note_hash {\n // Note that while we did check that the note hash is the preimage of the expected unique note hash, we\n // perform no validations on the nullifier - we fundamentally cannot, since only the application knows\n // how to compute nullifiers. We simply trust it to have provided the correct one: if it hasn't, then\n // PXE may fail to realize that a given note has been nullified already, and calls to the application\n // could result in invalid transactions (with duplicate nullifiers). This is not a concern because an\n // application already has more direct means of making a call to it fail the transaction.\n discovered_notes.push(\n DiscoveredNoteInfo {\n note_nonce: candidate_nonce,\n note_hash: hashes.note_hash,\n inner_nullifier: hashes.inner_nullifier,\n },\n );\n\n // We don't exit the loop - it is possible (though rare) for the exact same note content to be present\n // multiple times in the same transaction with different nonces. This typically doesn't happen due to\n // notes containing random values in order to hide their contents.\n }\n });\n\n debug_log_format(\n \"Found valid nonces for a total of {0} notes\",\n [discovered_notes.len() as Field],\n );\n\n *discovered_notes\n}\n\nmod test {\n use crate::{\n messages::discovery::{NoteHashAndNullifier, private_notes::MAX_NOTE_PACKED_LEN},\n note::{\n note_interface::{NoteHash, NoteType},\n note_metadata::SettledNoteMetadata,\n retrieved_note::RetrievedNote,\n utils::compute_note_hash_for_nullification,\n },\n oracle::random::random,\n test::mocks::mock_note::MockNote,\n utils::array,\n };\n\n use dep::protocol_types::{\n address::AztecAddress,\n hash::{compute_note_hash_nonce, compute_siloed_note_hash, compute_unique_note_hash},\n traits::{FromField, Packable},\n };\n\n use super::attempt_note_nonce_discovery;\n\n // This implementation could be simpler, but this serves as a nice example of the expected flow in a real\n // implementation, and as a sanity check that the interface is sufficient.\n unconstrained fn compute_note_hash_and_nullifier(\n packed_note: BoundedVec,\n storage_slot: Field,\n note_type_id: Field,\n contract_address: AztecAddress,\n note_nonce: Field,\n ) -> Option {\n if note_type_id == MockNote::get_id() {\n let note = MockNote::unpack(array::subarray(packed_note.storage(), 0));\n let note_hash = note.compute_note_hash(storage_slot);\n\n let note_hash_for_nullification = compute_note_hash_for_nullification(\n RetrievedNote {\n note,\n contract_address,\n metadata: SettledNoteMetadata::new(note_nonce).into(),\n },\n storage_slot,\n );\n\n let inner_nullifier = note.compute_nullifier_unconstrained(note_hash_for_nullification);\n\n Option::some(NoteHashAndNullifier { note_hash, inner_nullifier })\n } else {\n Option::none()\n }\n }\n\n global VALUE: Field = 7;\n global FIRST_NULLIFIER_IN_TX: Field = 47;\n global CONTRACT_ADDRESS: AztecAddress = AztecAddress::from_field(13);\n global STORAGE_SLOT: Field = 99;\n\n #[test]\n unconstrained fn no_note_hashes() {\n let unique_note_hashes_in_tx = BoundedVec::new();\n let packed_note = BoundedVec::new();\n\n let discovered_notes = attempt_note_nonce_discovery(\n unique_note_hashes_in_tx,\n FIRST_NULLIFIER_IN_TX,\n compute_note_hash_and_nullifier,\n CONTRACT_ADDRESS,\n STORAGE_SLOT,\n MockNote::get_id(),\n packed_note,\n );\n\n assert_eq(discovered_notes.len(), 0);\n }\n\n #[test(should_fail_with = \"Failed to compute a note hash\")]\n unconstrained fn failed_hash_computation() {\n let unique_note_hashes_in_tx = BoundedVec::from_array([random()]);\n let packed_note = BoundedVec::new();\n let note_type_id = 0; // This note type id is unknown to compute_note_hash_and_nullifier\n\n let discovered_notes = attempt_note_nonce_discovery(\n unique_note_hashes_in_tx,\n FIRST_NULLIFIER_IN_TX,\n compute_note_hash_and_nullifier,\n CONTRACT_ADDRESS,\n STORAGE_SLOT,\n note_type_id,\n packed_note,\n );\n\n assert_eq(discovered_notes.len(), 0);\n }\n\n struct NoteAndData {\n note: MockNote,\n note_nonce: Field,\n note_hash: Field,\n unique_note_hash: Field,\n inner_nullifier: Field,\n }\n\n unconstrained fn construct_note(value: Field, note_index_in_tx: u32) -> NoteAndData {\n let note_nonce = compute_note_hash_nonce(FIRST_NULLIFIER_IN_TX, note_index_in_tx);\n\n let retrieved_note = MockNote::new(value)\n .contract_address(CONTRACT_ADDRESS)\n .note_metadata(SettledNoteMetadata::new(note_nonce).into())\n .build_retrieved_note();\n let note = retrieved_note.note;\n\n let note_hash = note.compute_note_hash(STORAGE_SLOT);\n let unique_note_hash = compute_unique_note_hash(\n note_nonce,\n compute_siloed_note_hash(CONTRACT_ADDRESS, note_hash),\n );\n let inner_nullifier = note.compute_nullifier_unconstrained(\n compute_note_hash_for_nullification(retrieved_note, STORAGE_SLOT),\n );\n\n NoteAndData { note, note_nonce, note_hash, unique_note_hash, inner_nullifier }\n }\n\n #[test]\n unconstrained fn single_note() {\n let note_index_in_tx = 2;\n let note_and_data = construct_note(VALUE, note_index_in_tx);\n\n let mut unique_note_hashes_in_tx = BoundedVec::from_array([\n random(), random(), random(), random(), random(), random(), random(),\n ]);\n unique_note_hashes_in_tx.set(note_index_in_tx, note_and_data.unique_note_hash);\n\n let discovered_notes = attempt_note_nonce_discovery(\n unique_note_hashes_in_tx,\n FIRST_NULLIFIER_IN_TX,\n compute_note_hash_and_nullifier,\n CONTRACT_ADDRESS,\n STORAGE_SLOT,\n MockNote::get_id(),\n BoundedVec::from_array(note_and_data.note.pack()),\n );\n\n assert_eq(discovered_notes.len(), 1);\n let discovered_note = discovered_notes.get(0);\n\n assert_eq(discovered_note.note_nonce, note_and_data.note_nonce);\n assert_eq(discovered_note.note_hash, note_and_data.note_hash);\n assert_eq(discovered_note.inner_nullifier, note_and_data.inner_nullifier);\n }\n\n #[test]\n unconstrained fn multiple_notes_same_preimage() {\n let first_note_index_in_tx = 3;\n let first_note_and_data = construct_note(VALUE, first_note_index_in_tx);\n\n let second_note_index_in_tx = 5;\n let second_note_and_data = construct_note(VALUE, second_note_index_in_tx);\n\n // Both notes have the same preimage (and therefore packed representation), so both should be found in the same\n // call.\n assert_eq(first_note_and_data.note, second_note_and_data.note);\n let packed_note = first_note_and_data.note.pack();\n\n let mut unique_note_hashes_in_tx = BoundedVec::from_array([\n random(), random(), random(), random(), random(), random(), random(),\n ]);\n unique_note_hashes_in_tx.set(first_note_index_in_tx, first_note_and_data.unique_note_hash);\n unique_note_hashes_in_tx.set(second_note_index_in_tx, second_note_and_data.unique_note_hash);\n\n let discovered_notes = attempt_note_nonce_discovery(\n unique_note_hashes_in_tx,\n FIRST_NULLIFIER_IN_TX,\n compute_note_hash_and_nullifier,\n CONTRACT_ADDRESS,\n STORAGE_SLOT,\n MockNote::get_id(),\n BoundedVec::from_array(packed_note),\n );\n\n assert_eq(discovered_notes.len(), 2);\n\n assert(discovered_notes.any(|discovered_note| {\n (discovered_note.note_nonce == first_note_and_data.note_nonce)\n & (discovered_note.note_hash == first_note_and_data.note_hash)\n & (discovered_note.inner_nullifier == first_note_and_data.inner_nullifier)\n }));\n\n assert(discovered_notes.any(|discovered_note| {\n (discovered_note.note_nonce == second_note_and_data.note_nonce)\n & (discovered_note.note_hash == second_note_and_data.note_hash)\n & (discovered_note.inner_nullifier == second_note_and_data.inner_nullifier)\n }));\n }\n}\n"},"115":{"path":"/home/nerses/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.2/noir-projects/aztec-nr/aztec/src/messages/discovery/partial_notes.nr","source":"use crate::{\n capsules::CapsuleArray,\n messages::{\n discovery::{ComputeNoteHashAndNullifier, nonce_discovery::attempt_note_nonce_discovery},\n encoding::MAX_MESSAGE_CONTENT_LEN,\n processing::{\n enqueue_note_for_validation, get_pending_partial_notes_completion_logs,\n log_retrieval_response::LogRetrievalResponse,\n },\n },\n utils::array,\n};\n\nuse protocol_types::{\n address::AztecAddress,\n debug_log::debug_log_format,\n hash::sha256_to_field,\n traits::{Deserialize, Serialize},\n};\n\nglobal PARTIAL_NOTE_PRIVATE_MSG_CONTENT_NON_NOTE_FIELDS_LEN: u32 = 2;\n\n/// Partial notes have a maximum packed length of their private fields bound by extra content in their private message\n/// (e.g. the storage slot, note completion log tag, etc.).\npub global MAX_PARTIAL_NOTE_PRIVATE_PACKED_LEN: u32 =\n MAX_MESSAGE_CONTENT_LEN - PARTIAL_NOTE_PRIVATE_MSG_CONTENT_NON_NOTE_FIELDS_LEN;\n\n/// The slot in the PXE capsules where we store a `CapsuleArray` of `DeliveredPendingPartialNote`.\npub global DELIVERED_PENDING_PARTIAL_NOTE_ARRAY_LENGTH_CAPSULES_SLOT: Field = sha256_to_field(\n \"AZTEC_NR::DELIVERED_PENDING_PARTIAL_NOTE_ARRAY_LENGTH_CAPSULES_SLOT\".as_bytes(),\n);\n\n/// A partial note that was delivered but is still pending completion. Contains the information necessary to find the\n/// log that will complete it and lead to a note being discovered and delivered.\n#[derive(Serialize, Deserialize)]\npub(crate) struct DeliveredPendingPartialNote {\n pub(crate) note_completion_log_tag: Field,\n pub(crate) storage_slot: Field,\n pub(crate) note_type_id: Field,\n pub(crate) packed_private_note_content: BoundedVec,\n pub(crate) recipient: AztecAddress,\n}\n\npub unconstrained fn process_partial_note_private_msg(\n contract_address: AztecAddress,\n recipient: AztecAddress,\n msg_metadata: u64,\n msg_content: BoundedVec,\n) {\n let (note_type_id, storage_slot, note_completion_log_tag, packed_private_note_content) =\n decode_partial_note_private_msg(msg_metadata, msg_content);\n\n // We store the information of the partial note we found in a persistent capsule in PXE, so that we can later search\n // for the public log that will complete it.\n let pending = DeliveredPendingPartialNote {\n note_completion_log_tag,\n storage_slot,\n note_type_id,\n packed_private_note_content,\n recipient,\n };\n\n CapsuleArray::at(\n contract_address,\n DELIVERED_PENDING_PARTIAL_NOTE_ARRAY_LENGTH_CAPSULES_SLOT,\n )\n .push(pending);\n}\n\n/// Searches for logs that would result in the completion of pending partial notes, ultimately resulting in the notes\n/// being delivered to PXE if completed.\npub unconstrained fn fetch_and_process_partial_note_completion_logs(\n contract_address: AztecAddress,\n compute_note_hash_and_nullifier: ComputeNoteHashAndNullifier,\n) {\n let pending_partial_notes = CapsuleArray::at(\n contract_address,\n DELIVERED_PENDING_PARTIAL_NOTE_ARRAY_LENGTH_CAPSULES_SLOT,\n );\n\n debug_log_format(\n \"{} pending partial notes\",\n [pending_partial_notes.len() as Field],\n );\n\n // Each of the pending partial notes might get completed by a log containing its public values. For performance\n // reasons, we fetch all of these logs concurrently and then process them one by one, minimizing the amount of time\n // waiting for the node roundtrip.\n let maybe_completion_logs =\n get_pending_partial_notes_completion_logs(contract_address, pending_partial_notes);\n\n // Each entry in the maybe completion logs array corresponds to the entry in the pending partial notes array at the\n // same index. This means we can use the same index as we iterate through the responses to get both the partial note\n // and the log that might complete it.\n assert_eq(maybe_completion_logs.len(), pending_partial_notes.len());\n\n maybe_completion_logs.for_each(|i, maybe_log: Option| {\n // We clear the completion logs as we read them so that the array is empty by the time we next query it.\n // TODO(#14943): use volatile arrays to avoid having to manually clear this.\n maybe_completion_logs.remove(i);\n\n let pending_partial_note = pending_partial_notes.get(i);\n\n if maybe_log.is_none() {\n debug_log_format(\n \"Found no completion logs for partial note with tag {}\",\n [pending_partial_note.note_completion_log_tag],\n );\n\n // Note that we're not removing the pending partial note from the capsule array, so we will continue\n // searching for this tagged log when performing message discovery in the future until we either find it or\n // the entry is somehow removed from the array.\n } else {\n debug_log_format(\n \"Completion log found for partial note with tag {}\",\n [pending_partial_note.note_completion_log_tag],\n );\n let log = maybe_log.unwrap();\n\n // Public fields are assumed to all be placed at the end of the packed representation, so we combine the\n // private and public packed fields (i.e. the contents of the private message and public log plaintext to get\n // the complete packed content.\n let complete_packed_note = array::append(\n pending_partial_note.packed_private_note_content,\n log.log_payload,\n );\n\n let discovered_notes = attempt_note_nonce_discovery(\n log.unique_note_hashes_in_tx,\n log.first_nullifier_in_tx,\n compute_note_hash_and_nullifier,\n contract_address,\n pending_partial_note.storage_slot,\n pending_partial_note.note_type_id,\n complete_packed_note,\n );\n\n // TODO(#11627): is there anything reasonable we can do if we get a log but it doesn't result in a note\n // being found?\n if discovered_notes.len() == 0 {\n panic(\n f\"A partial note's completion log did not result in any notes being found - this should never happen\",\n );\n }\n\n debug_log_format(\n \"Discovered {0} notes for partial note with tag {1}\",\n [discovered_notes.len() as Field, pending_partial_note.note_completion_log_tag],\n );\n\n discovered_notes.for_each(|discovered_note| {\n enqueue_note_for_validation(\n contract_address,\n pending_partial_note.storage_slot,\n discovered_note.note_nonce,\n complete_packed_note,\n discovered_note.note_hash,\n discovered_note.inner_nullifier,\n log.tx_hash,\n pending_partial_note.recipient,\n );\n });\n\n // Because there is only a single log for a given tag, once we've processed the tagged log then we\n // simply delete the pending work entry, regardless of whether it was actually completed or not.\n pending_partial_notes.remove(i);\n }\n });\n}\n\nfn decode_partial_note_private_msg(\n msg_metadata: u64,\n msg_content: BoundedVec,\n) -> (Field, Field, Field, BoundedVec) {\n let note_type_id = msg_metadata as Field; // TODO: make note type id not be a full field\n\n assert(\n msg_content.len() > PARTIAL_NOTE_PRIVATE_MSG_CONTENT_NON_NOTE_FIELDS_LEN,\n f\"Invalid private note message: all partial note private messages must have at least {PARTIAL_NOTE_PRIVATE_MSG_CONTENT_NON_NOTE_FIELDS_LEN} fields\",\n );\n\n // If PARTIAL_NOTE_PRIVATE_MSG_CONTENT_NON_NOTE_FIELDS_LEN is changed, causing the assertion below to fail, then the\n // destructuring of the partial note private message encoding below must be updated as well.\n std::static_assert(\n PARTIAL_NOTE_PRIVATE_MSG_CONTENT_NON_NOTE_FIELDS_LEN == 2,\n \"unexpected value for PARTIAL_NOTE_PRIVATE_MSG_CONTENT_NON_NOTE_FIELDS_LEN\",\n );\n\n // We currently have two fields that are not the partial note's packed representation, which are the storage slot\n // and the note completion log tag.\n let storage_slot = msg_content.get(0);\n let note_completion_log_tag = msg_content.get(1);\n\n let packed_private_note_content = array::subbvec(msg_content, 2);\n\n (note_type_id, storage_slot, note_completion_log_tag, packed_private_note_content)\n}\n"},"116":{"path":"/home/nerses/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.2/noir-projects/aztec-nr/aztec/src/messages/discovery/private_events.nr","source":"use crate::{\n event::event_selector::EventSelector,\n messages::{encoding::MAX_MESSAGE_CONTENT_LEN, processing::enqueue_event_for_validation},\n utils::array,\n};\nuse protocol_types::{\n address::AztecAddress, constants::GENERATOR_INDEX__EVENT_COMMITMENT,\n hash::poseidon2_hash_with_separator_bounded_vec, traits::FromField,\n};\n\n/// The number of fields in a private event message content that are not the event's serialized representation\n/// (1 field for randomness).\nglobal PRIVATE_EVENT_MSG_CONTENT_NON_EVENT_FIELDS_LEN: u32 = 1;\n\n/// The maximum length of the packed representation of an event's contents. This is limited by private log size,\n/// encryption overhead and extra fields in the message (e.g. message type id, randomness, etc.).\npub global MAX_EVENT_SERIALIZED_LEN: u32 =\n MAX_MESSAGE_CONTENT_LEN - PRIVATE_EVENT_MSG_CONTENT_NON_EVENT_FIELDS_LEN;\n\npub unconstrained fn process_private_event_msg(\n contract_address: AztecAddress,\n recipient: AztecAddress,\n msg_metadata: u64,\n msg_content: BoundedVec,\n tx_hash: Field,\n) {\n // In the case of events, the msg metadata is the event selector.\n let event_type_id = EventSelector::from_field(msg_metadata as Field);\n\n assert(\n msg_content.len() > PRIVATE_EVENT_MSG_CONTENT_NON_EVENT_FIELDS_LEN,\n f\"Invalid private event message: all private event messages must have at least {PRIVATE_EVENT_MSG_CONTENT_NON_EVENT_FIELDS_LEN} fields\",\n );\n\n // If PRIVATE_EVENT_MSG_CONTENT_NON_EVENT_FIELDS_LEN is changed, causing the assertion below to fail, then the\n // destructuring of the private event message encoding below must be updated as well.\n std::static_assert(\n PRIVATE_EVENT_MSG_CONTENT_NON_EVENT_FIELDS_LEN == 1,\n \"unexpected value for PRIVATE_EVENT_MSG_CONTENT_NON_EVENT_FIELDS_LEN\",\n );\n\n let serialized_event_with_randomness = msg_content;\n\n let event_commitment = poseidon2_hash_with_separator_bounded_vec(\n serialized_event_with_randomness,\n GENERATOR_INDEX__EVENT_COMMITMENT,\n );\n\n // Randomness was injected into the event payload in `emit_event_in_private` but we have already used it\n // to compute the event commitment, so we can safely discard it now.\n let serialized_event = array::subbvec(\n serialized_event_with_randomness,\n PRIVATE_EVENT_MSG_CONTENT_NON_EVENT_FIELDS_LEN,\n );\n\n enqueue_event_for_validation(\n contract_address,\n event_type_id,\n serialized_event,\n event_commitment,\n tx_hash,\n recipient,\n );\n}\n"},"117":{"path":"/home/nerses/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.2/noir-projects/aztec-nr/aztec/src/messages/discovery/private_notes.nr","source":"use crate::{\n messages::{\n discovery::{ComputeNoteHashAndNullifier, nonce_discovery::attempt_note_nonce_discovery},\n encoding::MAX_MESSAGE_CONTENT_LEN,\n processing::enqueue_note_for_validation,\n },\n utils::array,\n};\nuse protocol_types::{\n address::AztecAddress, constants::MAX_NOTE_HASHES_PER_TX, debug_log::debug_log_format,\n};\n\n/// The number of fields in a private note message content that are not the note's packed representation.\n// See the call to `std::static_assert` below to see what's in these fields.\nglobal PRIVATE_NOTE_MSG_CONTENT_NON_NOTE_FIELDS_LEN: u32 = 1;\n\n/// The maximum length of the packed representation of a note's contents. This is limited by private log size,\n/// encryption overhead and extra fields in the message (e.g. message type id, storage slot, etc.).\npub global MAX_NOTE_PACKED_LEN: u32 =\n MAX_MESSAGE_CONTENT_LEN - PRIVATE_NOTE_MSG_CONTENT_NON_NOTE_FIELDS_LEN;\n\npub unconstrained fn process_private_note_msg(\n contract_address: AztecAddress,\n tx_hash: Field,\n unique_note_hashes_in_tx: BoundedVec,\n first_nullifier_in_tx: Field,\n recipient: AztecAddress,\n compute_note_hash_and_nullifier: ComputeNoteHashAndNullifier,\n msg_metadata: u64,\n msg_content: BoundedVec,\n) {\n let (note_type_id, storage_slot, packed_note) =\n decode_private_note_msg(msg_metadata, msg_content);\n\n attempt_note_discovery(\n contract_address,\n tx_hash,\n unique_note_hashes_in_tx,\n first_nullifier_in_tx,\n recipient,\n compute_note_hash_and_nullifier,\n storage_slot,\n note_type_id,\n packed_note,\n );\n}\n\n/// Attempts discovery of a note given information about its contents and the transaction in which it is\n/// suspected the note was created.\npub unconstrained fn attempt_note_discovery(\n contract_address: AztecAddress,\n tx_hash: Field,\n unique_note_hashes_in_tx: BoundedVec,\n first_nullifier_in_tx: Field,\n recipient: AztecAddress,\n compute_note_hash_and_nullifier: ComputeNoteHashAndNullifier,\n storage_slot: Field,\n note_type_id: Field,\n packed_note: BoundedVec,\n) {\n let discovered_notes = attempt_note_nonce_discovery(\n unique_note_hashes_in_tx,\n first_nullifier_in_tx,\n compute_note_hash_and_nullifier,\n contract_address,\n storage_slot,\n note_type_id,\n packed_note,\n );\n\n debug_log_format(\n \"Discovered {0} notes from a private message\",\n [discovered_notes.len() as Field],\n );\n\n discovered_notes.for_each(|discovered_note| {\n enqueue_note_for_validation(\n contract_address,\n storage_slot,\n discovered_note.note_nonce,\n packed_note,\n discovered_note.note_hash,\n discovered_note.inner_nullifier,\n tx_hash,\n recipient,\n );\n });\n}\n\nfn decode_private_note_msg(\n msg_metadata: u64,\n msg_content: BoundedVec,\n) -> (Field, Field, BoundedVec) {\n let note_type_id = msg_metadata as Field; // TODO: make note type id not be a full field\n\n assert(\n msg_content.len() > PRIVATE_NOTE_MSG_CONTENT_NON_NOTE_FIELDS_LEN,\n f\"Invalid private note message: all private note messages must have at least {PRIVATE_NOTE_MSG_CONTENT_NON_NOTE_FIELDS_LEN} fields\",\n );\n\n // If PRIVATE_NOTE_MSG_CONTENT_NON_NOTE_FIELDS_LEN is changed, causing the assertion below to fail, then the\n // destructuring of the private note message encoding below must be updated as well.\n std::static_assert(\n PRIVATE_NOTE_MSG_CONTENT_NON_NOTE_FIELDS_LEN == 1,\n \"unexpected value for PRIVATE_NOTE_MSG_CONTENT_NON_NOTE_FIELDS_LEN\",\n );\n\n // We currently have a single field that is not the note's packed representation, which is the storage slot.\n let storage_slot = msg_content.get(0);\n let packed_note = array::subbvec(msg_content, PRIVATE_NOTE_MSG_CONTENT_NON_NOTE_FIELDS_LEN);\n\n (note_type_id, storage_slot, packed_note)\n}\n"},"118":{"path":"/home/nerses/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.2/noir-projects/aztec-nr/aztec/src/messages/discovery/process_message.nr","source":"use crate::messages::{\n discovery::{\n ComputeNoteHashAndNullifier, partial_notes::process_partial_note_private_msg,\n private_events::process_private_event_msg, private_notes::process_private_note_msg,\n },\n encoding::{decode_message, MESSAGE_CIPHERTEXT_LEN, MESSAGE_PLAINTEXT_LEN},\n encryption::{aes128::AES128, message_encryption::MessageEncryption},\n msg_type::{\n PARTIAL_NOTE_PRIVATE_MSG_TYPE_ID, PRIVATE_EVENT_MSG_TYPE_ID, PRIVATE_NOTE_MSG_TYPE_ID,\n },\n processing::message_context::MessageContext,\n};\n\nuse protocol_types::{address::AztecAddress, debug_log::{debug_log, debug_log_format}};\n\n/// Processes a message that can contain notes, partial notes, or events.\n///\n/// Notes result in nonce discovery being performed prior to delivery, which requires knowledge of the transaction hash\n/// in which the notes would've been created (typically the same transaction in which the log was emitted), along with\n/// the list of unique note hashes in said transaction and the `compute_note_hash_and_nullifier` function. Once\n/// discovered, the notes are enqueued for validation.\n///\n/// Partial notes result in a pending partial note entry being stored in a PXE capsule, which will later be retrieved to\n/// search for the note's completion public log.\n///\n/// Events are processed by computing an event commitment from the serialized event data and its randomness field, then\n/// enqueueing the event data and commitment for validation.\npub unconstrained fn process_message_ciphertext(\n contract_address: AztecAddress,\n compute_note_hash_and_nullifier: ComputeNoteHashAndNullifier,\n message_ciphertext: BoundedVec,\n message_context: MessageContext,\n) {\n process_message_plaintext(\n contract_address,\n compute_note_hash_and_nullifier,\n AES128::decrypt(message_ciphertext, message_context.recipient),\n message_context,\n );\n}\n\npub unconstrained fn process_message_plaintext(\n contract_address: AztecAddress,\n compute_note_hash_and_nullifier: ComputeNoteHashAndNullifier,\n message_plaintext: BoundedVec,\n message_context: MessageContext,\n) {\n // The first thing to do after decrypting the message is to determine what type of message we're processing. We\n // have 3 message types: private notes, partial notes and events.\n\n // We decode the message to obtain the message type id, metadata and content.\n let (msg_type_id, msg_metadata, msg_content) = decode_message(message_plaintext);\n\n if msg_type_id == PRIVATE_NOTE_MSG_TYPE_ID {\n debug_log(\"Processing private note msg\");\n\n process_private_note_msg(\n contract_address,\n message_context.tx_hash,\n message_context.unique_note_hashes_in_tx,\n message_context.first_nullifier_in_tx,\n message_context.recipient,\n compute_note_hash_and_nullifier,\n msg_metadata,\n msg_content,\n );\n } else if msg_type_id == PARTIAL_NOTE_PRIVATE_MSG_TYPE_ID {\n debug_log(\"Processing partial note private msg\");\n\n process_partial_note_private_msg(\n contract_address,\n message_context.recipient,\n msg_metadata,\n msg_content,\n );\n } else if msg_type_id == PRIVATE_EVENT_MSG_TYPE_ID {\n debug_log(\"Processing private event msg\");\n\n process_private_event_msg(\n contract_address,\n message_context.recipient,\n msg_metadata,\n msg_content,\n message_context.tx_hash,\n );\n } else {\n debug_log_format(\"Unknown msg type id {0}\", [msg_type_id as Field]);\n }\n}\n"},"119":{"path":"/home/nerses/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.2/noir-projects/aztec-nr/aztec/src/messages/encoding.nr","source":"// TODO(#12750): don't make these values assume we're using AES.\nuse crate::utils::array;\nuse protocol_types::constants::PRIVATE_LOG_CIPHERTEXT_LEN;\n\n// We reassign to the constant here to communicate the distinction between a log and a message. In Aztec.nr, unlike in\n// protocol circuits, we have a concept of a message that can be emitted either as a private log or as an offchain\n// message. Message is a piece of data that is to be eventually delivered to a contract via the `process_message(...)`\n// utility function function that is injected by the #[aztec] macro.\npub global MESSAGE_CIPHERTEXT_LEN: u32 = PRIVATE_LOG_CIPHERTEXT_LEN;\n\n// TODO(#12750): The global variables below should not be here as they are AES128 specific.\n// ciphertext_length (2) + 14 bytes pkcs#7 AES padding.\npub(crate) global HEADER_CIPHERTEXT_SIZE_IN_BYTES: u32 = 16;\n\npub global EPH_PK_X_SIZE_IN_FIELDS: u32 = 1;\npub global EPH_PK_SIGN_BYTE_SIZE_IN_BYTES: u32 = 1;\n\n// (17 - 1) * 31 - 16 - 1 = 479\nglobal MESSAGE_PLAINTEXT_SIZE_IN_BYTES: u32 = (MESSAGE_CIPHERTEXT_LEN - EPH_PK_X_SIZE_IN_FIELDS)\n * 31\n - HEADER_CIPHERTEXT_SIZE_IN_BYTES\n - EPH_PK_SIGN_BYTE_SIZE_IN_BYTES;\n// Each field of the original note log was serialized to 32 bytes. Below we convert the bytes back to fields.\n// 479 / 32 = 15\npub global MESSAGE_PLAINTEXT_LEN: u32 = MESSAGE_PLAINTEXT_SIZE_IN_BYTES / 32;\n\nglobal MESSAGE_EXPANDED_METADATA_LEN: u32 = 1;\n\n// The standard message layout is composed of:\n// - an initial field called the 'expanded metadata'\n// - an arbitrary number of fields following that called the 'message content'\n//\n// ```\n// message: [ msg_expanded_metadata, ...msg_content ]\n// ```\n//\n// The expanded metadata itself is interpreted as a u128, of which:\n// - the upper 64 bits are the message type id\n// - the lower 64 bits are called the 'message metadata'\n//\n// ```\n// msg_expanded_metadata: [ msg_type_id | msg_metadata ]\n// <--- 64 bits --->|<--- 64 bits --->\n// ```\n//\n// The meaning of the message metadata and message content depend on the value of the message type id. Note that there\n// is nothing special about the message metadata, it _can_ be considered part of the content. It just has a different\n// name to make it distinct from the message content given that it is not a full field.\n\n/// The maximum length of a message's content, i.e. not including the expanded message metadata.\npub global MAX_MESSAGE_CONTENT_LEN: u32 = MESSAGE_PLAINTEXT_LEN - MESSAGE_EXPANDED_METADATA_LEN;\n\n/// Encodes a message following aztec-nr's standard message encoding. This message can later be decoded with\n/// `decode_message` to retrieve the original values.\n///\n/// - The `msg_type` is an identifier that groups types of messages that are all processed the same way, e.g. private\n/// notes or events. Possible values are defined in `aztec::messages::msg_type`.\n/// - The `msg_metadata` and `msg_content` are the values stored in the message, whose meaning depends on the\n/// `msg_type`. The only special thing about `msg_metadata` that separates it from `msg_content` is that it is a u64\n/// instead of a full Field (due to details of how messages are encoded), allowing applications that can fit values into\n/// this smaller variable to achieve higher data efficiency.\npub fn encode_message(\n msg_type: u64,\n msg_metadata: u64,\n msg_content: [Field; N],\n) -> [Field; (N + MESSAGE_EXPANDED_METADATA_LEN)] {\n std::static_assert(\n msg_content.len() <= MAX_MESSAGE_CONTENT_LEN,\n \"Invalid message content: it must have a length of at most MAX_MESSAGE_CONTENT_LEN\",\n );\n\n // If MESSAGE_EXPANDED_METADATA_LEN is changed, causing the assertion below to fail, then the destructuring of\n // the message encoding below must be updated as well.\n std::static_assert(\n MESSAGE_EXPANDED_METADATA_LEN == 1,\n \"unexpected value for MESSAGE_EXPANDED_METADATA_LEN\",\n );\n let mut message: [Field; (N + MESSAGE_EXPANDED_METADATA_LEN)] = std::mem::zeroed();\n\n message[0] = to_expanded_metadata(msg_type, msg_metadata);\n for i in 0..msg_content.len() {\n message[MESSAGE_EXPANDED_METADATA_LEN + i] = msg_content[i];\n }\n\n message\n}\n\n/// Decodes a standard aztec-nr message, i.e. one created via `encode_message`, returning the original encoded values.\n///\n/// Note that `encode_message` returns a fixed size array while this function takes a `BoundedVec`: this is because\n/// prior to decoding the message type is unknown, and consequentially not known at compile time. If working with\n/// fixed-size messages, consider using `BoundedVec::from_array` to convert them.\npub unconstrained fn decode_message(\n message: BoundedVec,\n) -> (u64, u64, BoundedVec) {\n assert(\n message.len() >= MESSAGE_EXPANDED_METADATA_LEN,\n f\"Invalid message: it must have at least {MESSAGE_EXPANDED_METADATA_LEN} fields\",\n );\n\n // If MESSAGE_EXPANDED_METADATA_LEN is changed, causing the assertion below to fail, then the destructuring of\n // the message encoding below must be updated as well.\n std::static_assert(\n MESSAGE_EXPANDED_METADATA_LEN == 1,\n \"unexpected value for MESSAGE_EXPANDED_METADATA_LEN\",\n );\n\n let msg_expanded_metadata = message.get(0);\n let (msg_type_id, msg_metadata) = from_expanded_metadata(msg_expanded_metadata);\n let msg_content = array::subbvec(message, MESSAGE_EXPANDED_METADATA_LEN);\n\n (msg_type_id, msg_metadata, msg_content)\n}\n\nglobal U64_SHIFT_MULTIPLIER: Field = 2.pow_32(64);\n\nfn to_expanded_metadata(msg_type: u64, msg_metadata: u64) -> Field {\n // We use multiplication instead of bit shifting operations to shift the type bits as bit shift operations are\n // expensive in circuits.\n let type_field: Field = (msg_type as Field) * U64_SHIFT_MULTIPLIER;\n let msg_metadata_field = msg_metadata as Field;\n\n type_field + msg_metadata_field\n}\n\nfn from_expanded_metadata(input: Field) -> (u64, u64) {\n input.assert_max_bit_size::<128>();\n let msg_metadata = (input as u64);\n let msg_type = ((input - (msg_metadata as Field)) / U64_SHIFT_MULTIPLIER) as u64;\n // Use division instead of bit shift since bit shifts are expensive in circuits\n (msg_type, msg_metadata)\n}\n\nmod tests {\n use crate::utils::array::subarray::subarray;\n use super::{\n decode_message, encode_message, from_expanded_metadata, MAX_MESSAGE_CONTENT_LEN,\n to_expanded_metadata,\n };\n\n global U64_MAX: u64 = (2.pow_32(64) - 1) as u64;\n global U128_MAX: Field = (2.pow_32(128) - 1);\n\n #[test]\n unconstrained fn encode_decode_empty_message(msg_type: u64, msg_metadata: u64) {\n let encoded = encode_message(msg_type, msg_metadata, []);\n let (decoded_msg_type, decoded_msg_metadata, decoded_msg_content) =\n decode_message(BoundedVec::from_array(encoded));\n\n assert_eq(decoded_msg_type, msg_type);\n assert_eq(decoded_msg_metadata, msg_metadata);\n assert_eq(decoded_msg_content.len(), 0);\n }\n\n #[test]\n unconstrained fn encode_decode_short_message(\n msg_type: u64,\n msg_metadata: u64,\n msg_content: [Field; MAX_MESSAGE_CONTENT_LEN / 2],\n ) {\n let encoded = encode_message(msg_type, msg_metadata, msg_content);\n let (decoded_msg_type, decoded_msg_metadata, decoded_msg_content) =\n decode_message(BoundedVec::from_array(encoded));\n\n assert_eq(decoded_msg_type, msg_type);\n assert_eq(decoded_msg_metadata, msg_metadata);\n assert_eq(decoded_msg_content.len(), msg_content.len());\n assert_eq(subarray(decoded_msg_content.storage(), 0), msg_content);\n }\n\n #[test]\n unconstrained fn encode_decode_full_message(\n msg_type: u64,\n msg_metadata: u64,\n msg_content: [Field; MAX_MESSAGE_CONTENT_LEN],\n ) {\n let encoded = encode_message(msg_type, msg_metadata, msg_content);\n let (decoded_msg_type, decoded_msg_metadata, decoded_msg_content) =\n decode_message(BoundedVec::from_array(encoded));\n\n assert_eq(decoded_msg_type, msg_type);\n assert_eq(decoded_msg_metadata, msg_metadata);\n assert_eq(decoded_msg_content.len(), msg_content.len());\n assert_eq(subarray(decoded_msg_content.storage(), 0), msg_content);\n }\n\n #[test]\n unconstrained fn to_expanded_metadata_packing() {\n // Test case 1: All bits set\n let packed = to_expanded_metadata(U64_MAX, U64_MAX);\n let (msg_type, msg_metadata) = from_expanded_metadata(packed);\n assert_eq(msg_type, U64_MAX);\n assert_eq(msg_metadata, U64_MAX);\n\n // Test case 2: Only log type bits set\n let packed = to_expanded_metadata(U64_MAX, 0);\n let (msg_type, msg_metadata) = from_expanded_metadata(packed);\n assert_eq(msg_type, U64_MAX);\n assert_eq(msg_metadata, 0);\n\n // Test case 3: Only msg_metadata bits set\n let packed = to_expanded_metadata(0, U64_MAX);\n let (msg_type, msg_metadata) = from_expanded_metadata(packed);\n assert_eq(msg_type, 0);\n assert_eq(msg_metadata, U64_MAX);\n\n // Test case 4: No bits set\n let packed = to_expanded_metadata(0, 0);\n let (msg_type, msg_metadata) = from_expanded_metadata(packed);\n assert_eq(msg_type, 0);\n assert_eq(msg_metadata, 0);\n }\n\n #[test]\n unconstrained fn from_expanded_metadata_packing() {\n // Test case 1: All bits set\n let input = U128_MAX as Field;\n let (msg_type, msg_metadata) = from_expanded_metadata(input);\n assert_eq(msg_type, U64_MAX);\n assert_eq(msg_metadata, U64_MAX);\n\n // Test case 2: Only log type bits set\n let input = (U128_MAX - U64_MAX as Field);\n let (msg_type, msg_metadata) = from_expanded_metadata(input);\n assert_eq(msg_type, U64_MAX);\n assert_eq(msg_metadata, 0);\n\n // Test case 3: Only msg_metadata bits set\n let input = U64_MAX as Field;\n let (msg_type, msg_metadata) = from_expanded_metadata(input);\n assert_eq(msg_type, 0);\n assert_eq(msg_metadata, U64_MAX);\n\n // Test case 4: No bits set\n let input = 0;\n let (msg_type, msg_metadata) = from_expanded_metadata(input);\n assert_eq(msg_type, 0);\n assert_eq(msg_metadata, 0);\n }\n\n #[test]\n unconstrained fn to_from_expanded_metadata(original_msg_type: u64, original_msg_metadata: u64) {\n let packed = to_expanded_metadata(original_msg_type, original_msg_metadata);\n let (unpacked_msg_type, unpacked_msg_metadata) = from_expanded_metadata(packed);\n\n assert_eq(original_msg_type, unpacked_msg_type);\n assert_eq(original_msg_metadata, unpacked_msg_metadata);\n }\n}\n"},"12":{"path":"std/convert.nr","source":"// docs:start:from-trait\npub trait From {\n fn from(input: T) -> Self;\n}\n// docs:end:from-trait\n\nimpl From for T {\n fn from(input: T) -> T {\n input\n }\n}\n\n// docs:start:into-trait\npub trait Into {\n fn into(self) -> T;\n}\n\nimpl Into for U\nwhere\n T: From,\n{\n fn into(self) -> T {\n T::from(self)\n }\n}\n// docs:end:into-trait\n\n// docs:start:from-impls\n// Unsigned integers\n\nimpl From for u16 {\n fn from(value: u8) -> u16 {\n value as u16\n }\n}\n\nimpl From for u32 {\n fn from(value: u8) -> u32 {\n value as u32\n }\n}\n\nimpl From for u32 {\n fn from(value: u16) -> u32 {\n value as u32\n }\n}\n\nimpl From for u64 {\n fn from(value: u8) -> u64 {\n value as u64\n }\n}\n\nimpl From for u64 {\n fn from(value: u16) -> u64 {\n value as u64\n }\n}\n\nimpl From for u64 {\n fn from(value: u32) -> u64 {\n value as u64\n }\n}\n\nimpl From for u128 {\n fn from(value: u8) -> u128 {\n value as u128\n }\n}\n\nimpl From for u128 {\n fn from(value: u16) -> u128 {\n value as u128\n }\n}\n\nimpl From for u128 {\n fn from(value: u32) -> u128 {\n value as u128\n }\n}\nimpl From for u128 {\n fn from(value: u64) -> u128 {\n value as u128\n }\n}\n\nimpl From for Field {\n fn from(value: u8) -> Field {\n value as Field\n }\n}\n\nimpl From for Field {\n fn from(value: u16) -> Field {\n value as Field\n }\n}\n\nimpl From for Field {\n fn from(value: u32) -> Field {\n value as Field\n }\n}\nimpl From for Field {\n fn from(value: u64) -> Field {\n value as Field\n }\n}\n\nimpl From for Field {\n fn from(value: u128) -> Field {\n value as Field\n }\n}\n\n// Signed integers\n\nimpl From for i16 {\n fn from(value: i8) -> i16 {\n value as i16\n }\n}\n\nimpl From for i32 {\n fn from(value: i8) -> i32 {\n value as i32\n }\n}\n\nimpl From for i32 {\n fn from(value: i16) -> i32 {\n value as i32\n }\n}\n\nimpl From for i64 {\n fn from(value: i8) -> i64 {\n value as i64\n }\n}\n\nimpl From for i64 {\n fn from(value: i16) -> i64 {\n value as i64\n }\n}\n\nimpl From for i64 {\n fn from(value: i32) -> i64 {\n value as i64\n }\n}\n\n// Booleans\nimpl From for u8 {\n fn from(value: bool) -> u8 {\n value as u8\n }\n}\nimpl From for u16 {\n fn from(value: bool) -> u16 {\n value as u16\n }\n}\nimpl From for u32 {\n fn from(value: bool) -> u32 {\n value as u32\n }\n}\nimpl From for u64 {\n fn from(value: bool) -> u64 {\n value as u64\n }\n}\nimpl From for u128 {\n fn from(value: bool) -> u128 {\n value as u128\n }\n}\nimpl From for i8 {\n fn from(value: bool) -> i8 {\n value as i8\n }\n}\nimpl From for i16 {\n fn from(value: bool) -> i16 {\n value as i16\n }\n}\nimpl From for i32 {\n fn from(value: bool) -> i32 {\n value as i32\n }\n}\nimpl From for i64 {\n fn from(value: bool) -> i64 {\n value as i64\n }\n}\nimpl From for Field {\n fn from(value: bool) -> Field {\n value as Field\n }\n}\n// docs:end:from-impls\n\n/// A generic interface for casting between primitive types,\n/// equivalent of using the `as` keyword between values.\n///\n/// # Example\n///\n/// ```\n/// let x: Field = 1234567890;\n/// let y: u8 = x as u8;\n/// let z: u8 = x.as_();\n/// assert_eq(y, z);\n/// ```\npub trait AsPrimitive {\n /// The equivalent of doing `self as T`.\n fn as_(self) -> T;\n}\n\n#[generate_as_primitive_impls]\ncomptime fn generate_as_primitive_impls(_: FunctionDefinition) -> Quoted {\n let types = [\n quote { bool },\n quote { u8 },\n quote { u16 },\n quote { u32 },\n quote { u64 },\n quote { u128 },\n quote { i8 },\n quote { i16 },\n quote { i32 },\n quote { i64 },\n ];\n\n let mut impls = &[];\n for type1 in types {\n for type2 in types {\n let body = if type1 == type2 {\n quote { self }\n } else if type1 == quote { bool } {\n quote { self != 0 }\n } else {\n quote { self as $type1 }\n };\n\n impls = impls.push_back(\n quote {\n impl AsPrimitive<$type1> for $type2 {\n fn as_(self) -> $type1 {\n $body\n }\n }\n },\n );\n }\n }\n\n let u_types =\n [quote { bool }, quote { u8 }, quote { u16 }, quote { u32 }, quote { u64 }, quote { u128 }];\n\n for type2 in u_types {\n let body = quote { self as Field };\n\n impls = impls.push_back(\n quote {\n impl AsPrimitive for $type2 {\n fn as_(self) -> Field {\n $body\n }\n }\n },\n );\n }\n\n for type1 in u_types {\n let body = if type1 == quote { bool } {\n quote { self != 0 }\n } else {\n quote { self as $type1 }\n };\n\n impls = impls.push_back(\n quote {\n impl AsPrimitive<$type1> for Field {\n fn as_(self) -> $type1 {\n $body\n }\n }\n },\n );\n }\n\n impls.join(quote {})\n}\n"},"120":{"path":"/home/nerses/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.2/noir-projects/aztec-nr/aztec/src/messages/encryption/aes128.nr","source":"use dep::protocol_types::{\n address::AztecAddress,\n constants::{GENERATOR_INDEX__SYMMETRIC_KEY, GENERATOR_INDEX__SYMMETRIC_KEY_2},\n hash::poseidon2_hash_with_separator,\n point::Point,\n};\n\nuse crate::{\n keys::{\n ecdh_shared_secret::derive_ecdh_shared_secret_using_aztec_address,\n ephemeral::generate_ephemeral_key_pair,\n },\n messages::{\n encoding::{\n EPH_PK_SIGN_BYTE_SIZE_IN_BYTES, EPH_PK_X_SIZE_IN_FIELDS,\n HEADER_CIPHERTEXT_SIZE_IN_BYTES, MESSAGE_CIPHERTEXT_LEN, MESSAGE_PLAINTEXT_LEN,\n },\n encryption::message_encryption::MessageEncryption,\n logs::arithmetic_generics_utils::{\n get_arr_of_size__message_bytes__from_PT,\n get_arr_of_size__message_bytes_padding__from_PT,\n },\n },\n oracle::{aes128_decrypt::aes128_decrypt_oracle, shared_secret::get_shared_secret},\n utils::{\n array,\n conversion::{\n bytes_to_fields::{bytes_from_fields, bytes_to_fields},\n fields_to_bytes::{fields_from_bytes, fields_to_bytes},\n },\n point::{get_sign_of_point, point_from_x_coord_and_sign},\n random::get_random_bytes,\n },\n};\n\nuse std::aes128::aes128_encrypt;\n\n/**\n * Computes N close-to-uniformly-random 256 bits from a given ECDH shared_secret.\n *\n * NEVER re-use the same iv and sym_key.\n * DO NOT call this function more than once with the same shared_secret.\n *\n * This function is only known to be safe if shared_secret is computed by combining a \n * random ephemeral key with an address point. See big comment within the body of the function.\n * See big comment within the body of the function.\n */\nfn extract_many_close_to_uniformly_random_256_bits_from_ecdh_shared_secret_using_poseidon2_unsafe(\n shared_secret: Point,\n) -> [[u8; 32]; N] {\n /*\n * Unsafe because of https://eprint.iacr.org/2010/264.pdf Page 13, Lemma 2 (and the * two paragraphs below it).\n *\n * If you call this function, you need to be careful and aware of how the arg\n * `shared_secret` has been derived.\n *\n * The paper says that the way you derive aes keys and IVs should be fine with poseidon2\n * (modelled as a RO), as long as you _don't_ use Poseidon2 as a PRG to generate the * two exponents x & y which multiply to the shared secret S:\n *\n * S = [x*y]*G.\n *\n * (Otherwise, you would have to \"key\" poseidon2, i.e. generate a uniformly string K\n * which can be public and compute Hash(x) as poseidon(K,x)).\n * In that lemma, k would be 2*254=508, and m would be the number of points on the * grumpkin curve (which is close to r according to the Hasse bound).\n *\n * Our shared secret S is [esk * address_sk] * G, and the question is: * Can we compute hash(S) using poseidon2 instead of sha256?\n *\n * Well, esk is random and not generated with poseidon2, so that's good.\n * What about address_sk?\n * Well, address_sk = poseidon2(stuff) + ivsk, so there was some\n * discussion about whether address_sk is independent of poseidon2.\n * Given that ivsk is random and independent of poseidon2, the address_sk is also\n * independent of poseidon2.\n *\n * Tl;dr: we believe it's safe to hash S = [esk * address_sk] * G using poseidon2,\n * in order to derive a symmetric key.\n *\n * If you're calling this function for a differently-derived `shared_secret`, be\n * careful.\n *\n */\n\n /* The output of this function needs to be 32 random bytes.\n * A single field won't give us 32 bytes of entropy.\n * So we compute two \"random\" fields, by poseidon-hashing with two different\n * generators.\n * We then extract the last 16 (big endian) bytes of each \"random\" field.\n * Note: we use to_be_bytes because it's slightly more efficient. But we have to\n * be careful not to take bytes from the \"big end\", because the \"big\" byte is\n * not uniformly random over the byte: it only has < 6 bits of randomness, because\n * it's the big end of a 254-bit field element.\n */\n\n let mut all_bytes: [[u8; 32]; N] = std::mem::zeroed();\n // We restrict N to be < 2^8, because of how we compute the domain separator\n // from k below (where k <= N must be 8 bits). In practice, it's extremely\n // unlikely that an app will want to compute >= 256 ciphertexts.\n std::static_assert(N < 256, \"N too large\");\n for k in 0..N {\n // We augment the domain separator with the loop index, so that we can\n // generate N lots of randomness.\n let k_shift = (k as u16 << 8);\n let separator_1 = k_shift + GENERATOR_INDEX__SYMMETRIC_KEY as u16;\n let separator_2 = k_shift + GENERATOR_INDEX__SYMMETRIC_KEY_2 as u16;\n\n let rand1: Field =\n poseidon2_hash_with_separator([shared_secret.x, shared_secret.y], separator_1);\n let rand2: Field =\n poseidon2_hash_with_separator([shared_secret.x, shared_secret.y], separator_2);\n\n let rand1_bytes: [u8; 32] = rand1.to_be_bytes();\n let rand2_bytes: [u8; 32] = rand2.to_be_bytes();\n\n let mut bytes: [u8; 32] = [0; 32];\n for i in 0..16 {\n // We take bytes from the \"little end\" of the be-bytes arrays:\n let j = 32 - i - 1;\n bytes[i] = rand1_bytes[j];\n bytes[16 + i] = rand2_bytes[j];\n }\n\n all_bytes[k] = bytes;\n }\n\n all_bytes\n}\n\nfn derive_aes_symmetric_key_and_iv_from_uniformly_random_256_bits(\n many_random_256_bits: [[u8; 32]; N],\n) -> [([u8; 16], [u8; 16]); N] {\n // Many (sym_key, iv) pairs:\n let mut many_pairs: [([u8; 16], [u8; 16]); N] = std::mem::zeroed();\n for k in 0..N {\n let random_256_bits = many_random_256_bits[k];\n let mut sym_key = [0; 16];\n let mut iv = [0; 16];\n for i in 0..16 {\n sym_key[i] = random_256_bits[i];\n iv[i] = random_256_bits[i + 16];\n }\n many_pairs[k] = (sym_key, iv);\n }\n\n many_pairs\n}\n\npub fn derive_aes_symmetric_key_and_iv_from_ecdh_shared_secret_using_poseidon2_unsafe(\n shared_secret: Point,\n) -> [([u8; 16], [u8; 16]); N] {\n let many_random_256_bits: [[u8; 32]; N] = extract_many_close_to_uniformly_random_256_bits_from_ecdh_shared_secret_using_poseidon2_unsafe(\n shared_secret,\n );\n\n derive_aes_symmetric_key_and_iv_from_uniformly_random_256_bits(many_random_256_bits)\n}\n\npub struct AES128 {}\n\nimpl MessageEncryption for AES128 {\n fn encrypt(\n plaintext: [Field; PlaintextLen],\n recipient: AztecAddress,\n ) -> [Field; MESSAGE_CIPHERTEXT_LEN] {\n // AES 128 operates on bytes, not fields, so we need to convert the fields to bytes.\n // (This process is then reversed when processing the message in `do_process_message`)\n let plaintext_bytes = fields_to_bytes(plaintext);\n\n // *****************************************************************************\n // Compute the shared secret\n // *****************************************************************************\n\n let (eph_sk, eph_pk) = generate_ephemeral_key_pair();\n\n let eph_pk_sign_byte: u8 = get_sign_of_point(eph_pk) as u8;\n\n // (not to be confused with the tagging shared secret)\n // TODO (#17158): Currently we unwrap the Option returned by derive_ecdh_shared_secret_using_aztec_address.\n // We need to handle the case where the ephemeral public key is invalid to prevent potential DoS vectors.\n let ciphertext_shared_secret =\n derive_ecdh_shared_secret_using_aztec_address(eph_sk, recipient).unwrap();\n // TODO: also use this shared secret for deriving note randomness.\n\n // *****************************************************************************\n // Convert the plaintext into whatever format the encryption function expects\n // *****************************************************************************\n\n // Already done for this strategy: AES expects bytes.\n\n // *****************************************************************************\n // Encrypt the plaintext\n // *****************************************************************************\n\n // It is safe to call the `unsafe` function here, because we know the `shared_secret`\n // was derived using an AztecAddress (the recipient). See the block comment\n // at the start of this unsafe target function for more info.\n let pairs = derive_aes_symmetric_key_and_iv_from_ecdh_shared_secret_using_poseidon2_unsafe::<2>(\n ciphertext_shared_secret,\n );\n let (body_sym_key, body_iv) = pairs[0];\n let (header_sym_key, header_iv) = pairs[1];\n\n let ciphertext_bytes = aes128_encrypt(plaintext_bytes, body_iv, body_sym_key);\n\n // |full_pt| = |pt_length| + |pt|\n // |pt_aes_padding| = 16 - (|full_pt| % 16)\n // or... since a % b is the same as a - b * (a // b) (integer division), so:\n // |pt_aes_padding| = 16 - (|full_pt| - 16 * (|full_pt| // 16))\n // |ct| = |full_pt| + |pt_aes_padding|\n // = |full_pt| + 16 - (|full_pt| - 16 * (|full_pt| // 16))\n // = 16 + 16 * (|full_pt| // 16)\n // = 16 * (1 + |full_pt| // 16)\n std::static_assert(\n ciphertext_bytes.len() == 16 * (1 + (PlaintextLen * 32) / 16),\n \"unexpected ciphertext length\",\n );\n\n // *****************************************************************************\n // Compute the header ciphertext\n // *****************************************************************************\n\n // Header contains only the length of the ciphertext stored in 2 bytes.\n let mut header_plaintext: [u8; 2] = [0 as u8; 2];\n let ciphertext_bytes_length = ciphertext_bytes.len();\n header_plaintext[0] = (ciphertext_bytes_length >> 8) as u8;\n header_plaintext[1] = ciphertext_bytes_length as u8;\n\n // Note: the aes128_encrypt builtin fn automatically appends bytes to the\n // input, according to pkcs#7; hence why the output `header_ciphertext_bytes` is 16\n // bytes larger than the input in this case.\n let header_ciphertext_bytes = aes128_encrypt(header_plaintext, header_iv, header_sym_key);\n // I recall that converting a slice to an array incurs constraints, so I'll check the length this way instead:\n std::static_assert(\n header_ciphertext_bytes.len() == HEADER_CIPHERTEXT_SIZE_IN_BYTES,\n \"unexpected ciphertext header length\",\n );\n\n // *****************************************************************************\n // Prepend / append more bytes of data to the ciphertext, before converting back\n // to fields.\n // *****************************************************************************\n\n let mut message_bytes_padding_to_mult_31 =\n get_arr_of_size__message_bytes_padding__from_PT::();\n // Safety: this randomness won't be constrained to be random. It's in the\n // interest of the executor of this fn to encrypt with random bytes.\n message_bytes_padding_to_mult_31 = unsafe { get_random_bytes() };\n\n let mut message_bytes = get_arr_of_size__message_bytes__from_PT::();\n\n std::static_assert(\n message_bytes.len() % 31 == 0,\n \"Unexpected error: message_bytes.len() should be divisible by 31, by construction.\",\n );\n\n message_bytes[0] = eph_pk_sign_byte;\n let mut offset = 1;\n for i in 0..header_ciphertext_bytes.len() {\n message_bytes[offset + i] = header_ciphertext_bytes[i];\n }\n offset += header_ciphertext_bytes.len();\n\n for i in 0..ciphertext_bytes.len() {\n message_bytes[offset + i] = ciphertext_bytes[i];\n }\n offset += ciphertext_bytes.len();\n\n for i in 0..message_bytes_padding_to_mult_31.len() {\n message_bytes[offset + i] = message_bytes_padding_to_mult_31[i];\n }\n offset += message_bytes_padding_to_mult_31.len();\n\n // Ideally we would be able to have a static assert where we check that the offset would be such that we've\n // written to the entire log_bytes array, but we cannot since Noir does not treat the offset as a comptime\n // value (despite the values that it goes through being known at each stage). We instead check that the\n // computation used to obtain the offset computes the expected value (which we _can_ do in a static check), and\n // then add a cheap runtime check to also validate that the offset matches this.\n std::static_assert(\n 1\n + header_ciphertext_bytes.len()\n + ciphertext_bytes.len()\n + message_bytes_padding_to_mult_31.len()\n == message_bytes.len(),\n \"unexpected message length\",\n );\n assert(offset == message_bytes.len(), \"unexpected encrypted message length\");\n\n // *****************************************************************************\n // Convert bytes back to fields\n // *****************************************************************************\n\n // TODO(#12749): As Mike pointed out, we need to make messages produced by different encryption schemes\n // indistinguishable from each other and for this reason the output here and in the last for-loop of this function\n // should cover a full field.\n let message_bytes_as_fields = bytes_to_fields(message_bytes);\n\n // *****************************************************************************\n // Prepend / append fields, to create the final message\n // *****************************************************************************\n\n let mut ciphertext: [Field; MESSAGE_CIPHERTEXT_LEN] = [0; MESSAGE_CIPHERTEXT_LEN];\n\n ciphertext[0] = eph_pk.x;\n\n let mut offset = 1;\n for i in 0..message_bytes_as_fields.len() {\n ciphertext[offset + i] = message_bytes_as_fields[i];\n }\n offset += message_bytes_as_fields.len();\n\n for i in offset..MESSAGE_CIPHERTEXT_LEN {\n // We need to get a random value that fits in 31 bytes to not leak information about the size of the message\n // (all the \"real\" message fields contain at most 31 bytes because of the way we convert the bytes to fields).\n // TODO(#12749): Long term, this is not a good solution.\n\n // Safety: we assume that the sender wants for the message to be private - a malicious one could simply reveal its\n // contents publicly. It is therefore fine to trust the sender to provide random padding.\n let field_bytes = unsafe { get_random_bytes::<31>() };\n ciphertext[i] = Field::from_be_bytes::<31>(field_bytes);\n }\n\n ciphertext\n }\n\n unconstrained fn decrypt(\n ciphertext: BoundedVec,\n recipient: AztecAddress,\n ) -> BoundedVec {\n let eph_pk_x = ciphertext.get(0);\n\n let ciphertext_without_eph_pk_x_fields = array::subbvec::(\n ciphertext,\n EPH_PK_X_SIZE_IN_FIELDS,\n );\n\n // Convert the ciphertext represented as fields to a byte representation (its original format)\n let ciphertext_without_eph_pk_x = bytes_from_fields(ciphertext_without_eph_pk_x_fields);\n\n // First byte of the ciphertext represents the ephemeral public key sign\n let eph_pk_sign_bool = ciphertext_without_eph_pk_x.get(0) != 0;\n // With the sign and the x-coordinate of the ephemeral public key, we can reconstruct the point\n let eph_pk = point_from_x_coord_and_sign(eph_pk_x, eph_pk_sign_bool);\n\n // Derive shared secret\n // TODO(#17158): handle invalid ephemeral keys when decrypting to prevent DoS vectors\n let ciphertext_shared_secret = get_shared_secret(recipient, eph_pk.unwrap());\n\n // Derive symmetric keys:\n let pairs = derive_aes_symmetric_key_and_iv_from_ecdh_shared_secret_using_poseidon2_unsafe::<2>(\n ciphertext_shared_secret,\n );\n let (body_sym_key, body_iv) = pairs[0];\n let (header_sym_key, header_iv) = pairs[1];\n\n // Extract the header ciphertext\n let header_start = EPH_PK_SIGN_BYTE_SIZE_IN_BYTES; // Skip eph_pk_sign byte\n let header_ciphertext: [u8; HEADER_CIPHERTEXT_SIZE_IN_BYTES] =\n array::subarray(ciphertext_without_eph_pk_x.storage(), header_start);\n // We need to convert the array to a BoundedVec because the oracle expects a BoundedVec as it's designed to work\n // with messages with unknown length at compile time. This would not be necessary here as the header ciphertext length\n // is fixed. But we do it anyway to not have to have duplicate oracles.\n let header_ciphertext_bvec =\n BoundedVec::::from_array(header_ciphertext);\n\n // Decrypt header\n let header_plaintext =\n aes128_decrypt_oracle(header_ciphertext_bvec, header_iv, header_sym_key);\n\n // Extract ciphertext length from header (2 bytes, big-endian)\n let ciphertext_length =\n ((header_plaintext.get(0) as u32) << 8) | (header_plaintext.get(1) as u32);\n\n // Extract and decrypt main ciphertext\n let ciphertext_start = header_start + HEADER_CIPHERTEXT_SIZE_IN_BYTES;\n let ciphertext_with_padding: [u8; (MESSAGE_CIPHERTEXT_LEN - EPH_PK_X_SIZE_IN_FIELDS) * 31 - HEADER_CIPHERTEXT_SIZE_IN_BYTES - EPH_PK_SIGN_BYTE_SIZE_IN_BYTES] =\n array::subarray(ciphertext_without_eph_pk_x.storage(), ciphertext_start);\n let ciphertext: BoundedVec =\n BoundedVec::from_parts(ciphertext_with_padding, ciphertext_length);\n\n // Decrypt main ciphertext and return it\n let plaintext_bytes = aes128_decrypt_oracle(ciphertext, body_iv, body_sym_key);\n\n // Each field of the original note message was serialized to 32 bytes so we convert the bytes back to fields.\n fields_from_bytes(plaintext_bytes)\n }\n}\n\nmod test {\n use crate::{\n keys::ecdh_shared_secret::derive_ecdh_shared_secret_using_aztec_address,\n messages::{\n encoding::MESSAGE_PLAINTEXT_LEN, encryption::message_encryption::MessageEncryption,\n },\n test::helpers::test_environment::TestEnvironment,\n };\n use super::AES128;\n use protocol_types::{address::AztecAddress, traits::FromField};\n use std::{embedded_curve_ops::EmbeddedCurveScalar, test::OracleMock};\n\n #[test]\n unconstrained fn encrypt_decrypt() {\n let env = TestEnvironment::new();\n\n // Message decryption requires oracles that are only available during private execution\n env.private_context(|_| {\n let plaintext = [1, 2, 3];\n\n let recipient = AztecAddress::from_field(\n 0x25afb798ea6d0b8c1618e50fdeafa463059415013d3b7c75d46abf5e242be70c,\n );\n\n // Mock random values for deterministic test\n let eph_sk = 0x1358d15019d4639393d62b97e1588c095957ce74a1c32d6ec7d62fe6705d9538;\n let _ = OracleMock::mock(\"utilityGetRandomField\").returns(eph_sk).times(1);\n\n let randomness = 0x0101010101010101010101010101010101010101010101010101010101010101;\n let _ = OracleMock::mock(\"utilityGetRandomField\").returns(randomness).times(1000000);\n\n let _ = OracleMock::mock(\"privateGetNextAppTagAsSender\").returns(42);\n\n // Encrypt the message\n let encrypted_message = BoundedVec::from_array(AES128::encrypt(plaintext, recipient));\n\n // Mock shared secret for deterministic test\n let shared_secret = derive_ecdh_shared_secret_using_aztec_address(\n EmbeddedCurveScalar::from_field(eph_sk),\n recipient,\n );\n\n let _ = OracleMock::mock(\"utilityGetSharedSecret\").returns(shared_secret.unwrap());\n\n // Decrypt the message\n let decrypted = AES128::decrypt(encrypted_message, recipient);\n\n // The decryption function spits out a BoundedVec because it's designed to work with messages with unknown length\n // at compile time. For this reason we need to convert the original input to a BoundedVec.\n let plaintext_bvec = BoundedVec::::from_array(plaintext);\n\n // Verify decryption matches original plaintext\n assert_eq(\n decrypted,\n plaintext_bvec,\n \"Decrypted bytes should match original plaintext\",\n );\n\n // The following is a workaround of \"struct is never constructed\" Noir compilation error (we only ever use\n // static methods of the struct).\n let _ = AES128 {};\n });\n }\n}\n"},"137":{"path":"/home/nerses/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.2/noir-projects/aztec-nr/aztec/src/messages/processing/mod.nr","source":"pub(crate) mod event_validation_request;\npub mod message_context;\npub(crate) mod note_validation_request;\npub(crate) mod log_retrieval_request;\npub(crate) mod log_retrieval_response;\npub(crate) mod pending_tagged_log;\n\nuse crate::{\n capsules::CapsuleArray,\n event::event_selector::EventSelector,\n messages::{\n discovery::{\n partial_notes::DeliveredPendingPartialNote, private_events::MAX_EVENT_SERIALIZED_LEN,\n private_notes::MAX_NOTE_PACKED_LEN,\n },\n processing::{\n log_retrieval_request::LogRetrievalRequest,\n log_retrieval_response::LogRetrievalResponse,\n note_validation_request::NoteValidationRequest, pending_tagged_log::PendingTaggedLog,\n },\n },\n oracle,\n};\nuse event_validation_request::EventValidationRequest;\nuse protocol_types::{address::AztecAddress, hash::sha256_to_field};\n\n// Base slot for the pending tagged log array to which the fetch_tagged_logs oracle inserts found private logs.\nglobal PENDING_TAGGED_LOG_ARRAY_BASE_SLOT: Field =\n sha256_to_field(\"AZTEC_NR::PENDING_TAGGED_LOG_ARRAY_BASE_SLOT\".as_bytes());\n\nglobal NOTE_VALIDATION_REQUESTS_ARRAY_BASE_SLOT: Field = sha256_to_field(\n \"AZTEC_NR::NOTE_VALIDATION_REQUESTS_ARRAY_BASE_SLOT\".as_bytes(),\n);\n\nglobal EVENT_VALIDATION_REQUESTS_ARRAY_BASE_SLOT: Field = sha256_to_field(\n \"AZTEC_NR::EVENT_VALIDATION_REQUESTS_ARRAY_BASE_SLOT\".as_bytes(),\n);\n\nglobal LOG_RETRIEVAL_REQUESTS_ARRAY_BASE_SLOT: Field = sha256_to_field(\n \"AZTEC_NR::LOG_RETRIEVAL_REQUESTS_ARRAY_BASE_SLOT\".as_bytes(),\n);\n\nglobal LOG_RETRIEVAL_RESPONSES_ARRAY_BASE_SLOT: Field = sha256_to_field(\n \"AZTEC_NR::LOG_RETRIEVAL_RESPONSES_ARRAY_BASE_SLOT\".as_bytes(),\n);\n\n/// Searches for private logs emitted by `contract_address` that might contain messages for one of the local accounts,\n/// and stores them in a `CapsuleArray` which is then returned.\npub(crate) unconstrained fn get_private_logs(\n contract_address: AztecAddress,\n) -> CapsuleArray {\n // We will eventually perform log discovery via tagging here, but for now we simply call the `fetchTaggedLogs`\n // oracle. This makes PXE synchronize tags, download logs and store the pending tagged logs in a capsule array.\n oracle::message_processing::fetch_tagged_logs(PENDING_TAGGED_LOG_ARRAY_BASE_SLOT);\n\n CapsuleArray::at(contract_address, PENDING_TAGGED_LOG_ARRAY_BASE_SLOT)\n}\n\n/// Enqueues a note for validation by PXE, so that it becomes aware of a note's existence allowing for later retrieval\n/// via `get_notes` oracle. The note will be scoped to `contract_address`, meaning other contracts will not be able to\n/// access it unless authorized.\n///\n/// In order for the note validation and insertion to occur, `validate_enqueued_notes_and_events` must be later called.\n/// For optimal performance, accumulate as many note validation requests as possible and then validate them all at the\n/// end (which results in PXE minimizing the number of network round-trips).\n///\n/// The `packed_note` is what `getNotes` will later return. PXE indexes notes by `storage_slot`, so this value\n/// is typically used to filter notes that correspond to different state variables. `note_hash` and `nullifier` are\n/// the inner hashes, i.e. the raw hashes returned by `NoteHash::compute_note_hash` and\n/// `NoteHash::compute_nullifier`. PXE will verify that the siloed unique note hash was inserted into the tree\n/// at `tx_hash`, and will store the nullifier to later check for nullification.\n///\n/// `recipient` is the account to which the note was sent to. Other accounts will not be able to access this note (e.g.\n/// other accounts will not be able to see one another's token balance notes, even in the same PXE) unless authorized.\npub(crate) unconstrained fn enqueue_note_for_validation(\n contract_address: AztecAddress,\n storage_slot: Field,\n note_nonce: Field,\n packed_note: BoundedVec,\n note_hash: Field,\n nullifier: Field,\n tx_hash: Field,\n recipient: AztecAddress,\n) {\n // We store requests in a `CapsuleArray`, which PXE will later read from and deserialize into its version of the\n // Noir `NoteValidationRequest`\n CapsuleArray::at(contract_address, NOTE_VALIDATION_REQUESTS_ARRAY_BASE_SLOT).push(\n NoteValidationRequest {\n contract_address,\n storage_slot,\n note_nonce,\n packed_note,\n note_hash,\n nullifier,\n tx_hash,\n recipient,\n },\n )\n}\n\n/// Enqueues an event for validation by PXE, so that it can be efficiently validated and then inserted into the event\n/// store.\n///\n/// In order for the event validation and insertion to occur, `validate_enqueued_notes_and_events` must be later\n/// called. For optimal performance, accumulate as many event validation requests as possible and then validate them\n/// all at the end (which results in PXE minimizing the number of network round-trips).\npub(crate) unconstrained fn enqueue_event_for_validation(\n contract_address: AztecAddress,\n event_type_id: EventSelector,\n serialized_event: BoundedVec,\n event_commitment: Field,\n tx_hash: Field,\n recipient: AztecAddress,\n) {\n // We store requests in a `CapsuleArray`, which PXE will later read from and deserialize into its version of the\n // Noir `EventValidationRequest`\n CapsuleArray::at(contract_address, EVENT_VALIDATION_REQUESTS_ARRAY_BASE_SLOT).push(\n EventValidationRequest {\n contract_address,\n event_type_id,\n serialized_event,\n event_commitment,\n tx_hash,\n recipient,\n },\n )\n}\n\n/// Validates all note and event validation requests enqueued via `enqueue_note_for_validation` and\n/// `enqueue_event_for_validation`, inserting them into the note database and event store respectively, making them\n/// queryable via `get_notes` oracle and our TS API (PXE::getPrivateEvents).\n///\n/// This automatically clears both validation request queues, so no further work needs to be done by the caller.\npub(crate) unconstrained fn validate_enqueued_notes_and_events(contract_address: AztecAddress) {\n oracle::message_processing::validate_enqueued_notes_and_events(\n contract_address,\n NOTE_VALIDATION_REQUESTS_ARRAY_BASE_SLOT,\n EVENT_VALIDATION_REQUESTS_ARRAY_BASE_SLOT,\n );\n}\n\n/// Efficiently queries the node for logs that result in the completion of all `DeliveredPendingPartialNote`s stored in\n/// a `CapsuleArray` by performing all node communication concurrently. Returns a second `CapsuleArray` with Options for\n/// the responses that correspond to the pending partial notes at the same index.\n///\n/// For example, given an array with pending partial notes `[ p1, p2, p3 ]`, where `p1` and `p3` have corresponding\n/// completion logs but `p2` does not, the returned `CapsuleArray` will have contents\n/// `[some(p1_log), none(), some(p3_log)]`.\npub(crate) unconstrained fn get_pending_partial_notes_completion_logs(\n contract_address: AztecAddress,\n pending_partial_notes: CapsuleArray,\n) -> CapsuleArray> {\n let log_retrieval_requests =\n CapsuleArray::at(contract_address, LOG_RETRIEVAL_REQUESTS_ARRAY_BASE_SLOT);\n\n // We create a LogRetrievalRequest for each PendingPartialNote in the CapsuleArray. Because we need the indices in\n // the request array to match the indices in the partial note array, we can't use CapsuleArray::for_each, as that\n // function has arbitrary iteration order. Instead, we manually iterate the array from the beginning and push into\n // the requests array, which we expect to be empty.\n let mut i = 0;\n let pending_partial_notes_count = pending_partial_notes.len();\n while i < pending_partial_notes_count {\n let pending_partial_note = pending_partial_notes.get(i);\n log_retrieval_requests.push(\n LogRetrievalRequest {\n contract_address,\n unsiloed_tag: pending_partial_note.note_completion_log_tag,\n },\n );\n i += 1;\n }\n\n oracle::message_processing::bulk_retrieve_logs(\n contract_address,\n LOG_RETRIEVAL_REQUESTS_ARRAY_BASE_SLOT,\n LOG_RETRIEVAL_RESPONSES_ARRAY_BASE_SLOT,\n );\n\n CapsuleArray::at(contract_address, LOG_RETRIEVAL_RESPONSES_ARRAY_BASE_SLOT)\n}\n"},"149":{"path":"/home/nerses/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.2/noir-projects/aztec-nr/aztec/src/note/note_metadata.nr","source":"use protocol_types::traits::{Deserialize, Packable, Serialize};\n\n// There's temporarily quite a bit of boilerplate here because Noir does not yet support enums. This file will\n// eventually be simplified into something closer to:\n//\n// pub enum NoteMetadata {\n// PendingSamePhase{ note_hash_counter: u32 },\n// PendingOtherPhase{ note_hash_counter: u32, note_nonce: Field },\n// Settled{ note_nonce: Field },\n// }\n//\n// For now, we have `NoteMetadata` acting as a sort of tagged union.\n\nstruct NoteStageEnum {\n /// A note that was created in the transaction that is currently being executed, during the current execution phase,\n /// i.e. non-revertible or revertible.\n ///\n /// These notes are not yet in the note hash tree, though they will be inserted unless nullified in this transaction\n /// (becoming a transient note).\n PENDING_SAME_PHASE: u8,\n /// A note that was created in the transaction that is currently being executed, during the previous execution\n /// phase. Because there are only two phases and their order is always the same (first non-revertible and then\n /// revertible) this implies that the note was created in the non-revertible phase, and that the current phase is\n /// the revertible phase.\n ///\n /// These notes are not yet in the note hash tree, though they will be inserted **even if nullified in this\n /// transaction**. This means that they must be nullified as if they were settled (i.e. using the unique note hash)\n /// in order to avoid double spends once they become settled.\n PENDING_PREVIOUS_PHASE: u8,\n /// A note that was created in a prior transaction and is therefore already in the note hash tree.\n SETTLED: u8,\n}\n\nglobal NoteStage: NoteStageEnum =\n NoteStageEnum { PENDING_SAME_PHASE: 1, PENDING_PREVIOUS_PHASE: 2, SETTLED: 3 };\n\n/// The metadata required to both prove a note's existence and destroy it, by computing the correct note hash for kernel\n/// read requests, as well as the correct nullifier to avoid double-spends.\n///\n/// This represents a note in any of the three valid stages (pending same phase, pending previous phase, or settled). In\n/// order to access the underlying fields callers must first find the appropriate stage (e.g. via `is_settled()`) and\n/// then convert this into the appropriate type (e.g. via `to_settled()`).\n#[derive(Deserialize, Eq, Serialize, Packable)]\npub struct NoteMetadata {\n stage: u8,\n maybe_note_nonce: Field,\n}\n\nimpl NoteMetadata {\n /// Constructs a `NoteMetadata` object from optional note hash counter and nonce. Both a zero note hash counter and\n /// a zero nonce are invalid, so those are used to signal non-existent values.\n pub fn from_raw_data(nonzero_note_hash_counter: bool, maybe_note_nonce: Field) -> Self {\n if nonzero_note_hash_counter {\n if maybe_note_nonce == 0 {\n Self { stage: NoteStage.PENDING_SAME_PHASE, maybe_note_nonce }\n } else {\n Self { stage: NoteStage.PENDING_PREVIOUS_PHASE, maybe_note_nonce }\n }\n } else if maybe_note_nonce != 0 {\n Self { stage: NoteStage.SETTLED, maybe_note_nonce }\n } else {\n panic(\n f\"Note has a zero note hash counter and no nonce - existence cannot be proven\",\n )\n }\n }\n\n /// Returns true if the note is pending **and** from the same phase, i.e. if it's been created in the current\n /// transaction during the current execution phase (either non-revertible or revertible).\n pub fn is_pending_same_phase(self) -> bool {\n self.stage == NoteStage.PENDING_SAME_PHASE\n }\n\n /// Returns true if the note is pending **and** from the previous phase, i.e. if it's been created in the current\n /// transaction during an execution phase prior to the current one. Because private execution only has two phases\n /// with strict ordering, this implies that the note was created in the non-revertible phase, and that the current\n /// phase is the revertible phase.\n pub fn is_pending_previous_phase(self) -> bool {\n self.stage == NoteStage.PENDING_PREVIOUS_PHASE\n }\n\n /// Returns true if the note is settled, i.e. if it's been created in a prior transaction and is therefore already\n /// in the note hash tree.\n pub fn is_settled(self) -> bool {\n self.stage == NoteStage.SETTLED\n }\n\n /// Asserts that the metadata is that of a pending note from the same phase and converts it accordingly.\n pub fn to_pending_same_phase(self) -> PendingSamePhaseNoteMetadata {\n assert_eq(self.stage, NoteStage.PENDING_SAME_PHASE);\n PendingSamePhaseNoteMetadata::new()\n }\n\n /// Asserts that the metadata is that of a pending note from a previous phase and converts it accordingly.\n pub fn to_pending_previous_phase(self) -> PendingPreviousPhaseNoteMetadata {\n assert_eq(self.stage, NoteStage.PENDING_PREVIOUS_PHASE);\n PendingPreviousPhaseNoteMetadata::new(self.maybe_note_nonce)\n }\n\n /// Asserts that the metadata is that of a settled note and converts it accordingly.\n pub fn to_settled(self) -> SettledNoteMetadata {\n assert_eq(self.stage, NoteStage.SETTLED);\n SettledNoteMetadata::new(self.maybe_note_nonce)\n }\n}\n\nimpl From for NoteMetadata {\n fn from(_value: PendingSamePhaseNoteMetadata) -> Self {\n NoteMetadata::from_raw_data(true, std::mem::zeroed())\n }\n}\n\nimpl From for NoteMetadata {\n fn from(value: PendingPreviousPhaseNoteMetadata) -> Self {\n NoteMetadata::from_raw_data(true, value.note_nonce())\n }\n}\n\nimpl From for NoteMetadata {\n fn from(value: SettledNoteMetadata) -> Self {\n NoteMetadata::from_raw_data(false, value.note_nonce())\n }\n}\n\n/// The metadata required to both prove a note's existence and destroy it, by computing the correct note hash for kernel\n/// read requests, as well as the correct nullifier to avoid double-spends.\n///\n/// This represents a pending same phase note, i.e. a note that was created in the transaction that is currently being\n/// executed during the current execution phase (either non-revertible or revertible).\npub struct PendingSamePhaseNoteMetadata {\n // This struct contains no fields since there is no metadata associated with a pending same phase note: it has no\n // nonce (since it may get squashed by a nullifier emitted in the same phase), and while it does have a note hash\n // counter we cannot constrain its value (and don't need to - only that it is non-zero).\n}\n\nimpl PendingSamePhaseNoteMetadata {\n pub fn new() -> Self {\n Self {}\n }\n}\n\n/// The metadata required to both prove a note's existence and destroy it, by computing the correct note hash for kernel\n/// read requests, as well as the correct nullifier to avoid double-spends.\n///\n/// This represents a pending previous phase note, i.e. a note that was created in the transaction that is currently\n/// being executed, during the previous execution phase. Because there are only two phases and their order is always the\n/// same (first non-revertible and then revertible) this implies that the note was created in the non-revertible phase,\n/// and that the current phase is the revertible phase.\npub struct PendingPreviousPhaseNoteMetadata {\n note_nonce: Field,\n // This struct does not contain a note hash counter, even though one exists for this note, because we cannot\n // constrain its value (and don't need to - only that it is non-zero).\n}\n\nimpl PendingPreviousPhaseNoteMetadata {\n pub fn new(note_nonce: Field) -> Self {\n Self { note_nonce }\n }\n\n pub fn note_nonce(self) -> Field {\n self.note_nonce\n }\n}\n\n/// The metadata required to both prove a note's existence and destroy it, by computing the correct note hash for kernel\n/// read requests, as well as the correct nullifier to avoid double-spends.\n///\n/// This represents a settled note, i.e. a note that was created in a prior transaction and is therefore already in the\n/// note hash tree.\npub struct SettledNoteMetadata {\n note_nonce: Field,\n}\n\nimpl SettledNoteMetadata {\n pub fn new(note_nonce: Field) -> Self {\n Self { note_nonce }\n }\n\n pub fn note_nonce(self) -> Field {\n self.note_nonce\n }\n}\n"},"152":{"path":"/home/nerses/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.2/noir-projects/aztec-nr/aztec/src/note/utils.nr","source":"use crate::{\n context::PrivateContext,\n note::{note_interface::NoteHash, retrieved_note::RetrievedNote},\n};\n\nuse dep::protocol_types::hash::{\n compute_siloed_note_hash, compute_siloed_nullifier, compute_unique_note_hash,\n};\n\n/// Returns the note hash that must be used to issue a private kernel read request for a note.\npub fn compute_note_hash_for_read_request(\n retrieved_note: RetrievedNote,\n storage_slot: Field,\n) -> Field\nwhere\n Note: NoteHash,\n{\n let note_hash = retrieved_note.note.compute_note_hash(storage_slot);\n\n if retrieved_note.metadata.is_settled() {\n // Settled notes are read by siloing with contract address and nonce (resulting in the final unique note hash,\n // which is already in the note hash tree).\n let siloed_note_hash = compute_siloed_note_hash(retrieved_note.contract_address, note_hash);\n compute_unique_note_hash(\n retrieved_note.metadata.to_settled().note_nonce(),\n siloed_note_hash,\n )\n } else {\n // Pending notes (both same phase and previous phase ones) re read by their non-siloed hash (not even by\n // contract address), which is what is stored in the new note hashes array (at the position hinted by note hash\n // counter).\n note_hash\n }\n}\n\n/// Returns the note hash that must be used to compute a note's nullifier when calling `NoteHash::compute_nullifier` or\n/// `NoteHash::compute_nullifier_unconstrained`.\npub fn compute_note_hash_for_nullification(\n retrieved_note: RetrievedNote,\n storage_slot: Field,\n) -> Field\nwhere\n Note: NoteHash,\n{\n compute_note_hash_for_nullification_from_read_request(\n retrieved_note,\n compute_note_hash_for_read_request(retrieved_note, storage_slot),\n )\n}\n\n/// Same as `compute_note_hash_for_nullification`, except it takes the note hash used in a read request (i.e. what\n/// `compute_note_hash_for_read_request` would return). This is useful in scenarios where that hash has already been\n/// computed to reduce constraints by reusing this value.\npub fn compute_note_hash_for_nullification_from_read_request(\n retrieved_note: RetrievedNote,\n note_hash_for_read_request: Field,\n) -> Field {\n // There is just one instance in which the note hash for nullification does not match the note hash used for a read\n // request, which is when dealing with pending previous phase notes. These had their existence proven using their\n // non-siloed note hash along with the note hash counter (like all pending notes), but since they will be\n // unconditionally inserted in the note hash tree (since they cannot be squashed) they must be nullified using the\n // *unique* note hash.\n // If we didn't, it'd be possible to emit a second different nullifier for the same note in a follow up transaction,\n // once the note is settled, resulting in a double spend.\n\n if retrieved_note.metadata.is_pending_previous_phase() {\n let siloed_note_hash =\n compute_siloed_note_hash(retrieved_note.contract_address, note_hash_for_read_request);\n let note_nonce = retrieved_note.metadata.to_pending_previous_phase().note_nonce();\n\n compute_unique_note_hash(note_nonce, siloed_note_hash)\n } else {\n note_hash_for_read_request\n }\n}\n\n/// Computes a note's siloed nullifier, i.e. the one that will be inserted into the nullifier tree.\npub fn compute_siloed_note_nullifier(\n retrieved_note: RetrievedNote,\n storage_slot: Field,\n context: &mut PrivateContext,\n) -> Field\nwhere\n Note: NoteHash,\n{\n let note_hash_for_nullification =\n compute_note_hash_for_nullification(retrieved_note, storage_slot);\n let inner_nullifier =\n retrieved_note.note.compute_nullifier(context, note_hash_for_nullification);\n\n compute_siloed_nullifier(retrieved_note.contract_address, inner_nullifier)\n}\n"},"157":{"path":"/home/nerses/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.2/noir-projects/aztec-nr/aztec/src/oracle/capsules.nr","source":"use protocol_types::{address::AztecAddress, traits::{Deserialize, Serialize}};\n\n/// Stores arbitrary information in a per-contract non-volatile database, which can later be retrieved with `load`. If\n/// data was already stored at this slot, it is overwritten.\npub unconstrained fn store(contract_address: AztecAddress, slot: Field, value: T)\nwhere\n T: Serialize,\n{\n let serialized = value.serialize();\n store_oracle(contract_address, slot, serialized);\n}\n\n/// Returns data previously stored via `storeCapsule` in the per-contract non-volatile database. Returns Option::none() if\n/// nothing was stored at the given slot.\npub unconstrained fn load(contract_address: AztecAddress, slot: Field) -> Option\nwhere\n T: Deserialize,\n{\n let serialized_option = load_oracle(contract_address, slot, ::N);\n serialized_option.map(|arr| Deserialize::deserialize(arr))\n}\n\n/// Deletes data in the per-contract non-volatile database. Does nothing if no data was present.\npub unconstrained fn delete(contract_address: AztecAddress, slot: Field) {\n delete_oracle(contract_address, slot);\n}\n\n/// Copies a number of contiguous entries in the per-contract non-volatile database. This allows for efficient data\n/// structures by avoiding repeated calls to `loadCapsule` and `storeCapsule`.\n/// Supports overlapping source and destination regions (which will result in the overlapped source values being\n/// overwritten). All copied slots must exist in the database (i.e. have been stored and not deleted)\npub unconstrained fn copy(\n contract_address: AztecAddress,\n src_slot: Field,\n dst_slot: Field,\n num_entries: u32,\n) {\n copy_oracle(contract_address, src_slot, dst_slot, num_entries);\n}\n\n#[oracle(utilityStoreCapsule)]\nunconstrained fn store_oracle(\n contract_address: AztecAddress,\n slot: Field,\n values: [Field; N],\n) {}\n\n/// We need to pass in `array_len` (the value of N) as a parameter to tell the oracle how many fields the response must\n/// have.\n///\n/// Note that the oracle returns an Option<[Field; N]> because we cannot return an Option directly. That would\n/// require for the oracle resolver to know the shape of T (e.g. if T were a struct of 3 u32 values then the expected\n/// response shape would be 3 single items, whereas it were a struct containing `u32, [Field;10], u32` then the expected\n/// shape would be single, array, single.). Instead, we return the serialization and deserialize in Noir.\n#[oracle(utilityLoadCapsule)]\nunconstrained fn load_oracle(\n contract_address: AztecAddress,\n slot: Field,\n array_len: u32,\n) -> Option<[Field; N]> {}\n\n#[oracle(utilityDeleteCapsule)]\nunconstrained fn delete_oracle(contract_address: AztecAddress, slot: Field) {}\n\n#[oracle(utilityCopyCapsule)]\nunconstrained fn copy_oracle(\n contract_address: AztecAddress,\n src_slot: Field,\n dst_slot: Field,\n num_entries: u32,\n) {}\n\nmod test {\n // These tests are sort of redundant since we already test the oracle implementation directly in TypeScript, but\n // they are cheap regardless and help ensure both that the TXE implementation works accordingly and that the Noir\n // oracles are hooked up correctly.\n\n use crate::{\n oracle::capsules::{copy, delete, load, store},\n test::{helpers::test_environment::TestEnvironment, mocks::mock_struct::MockStruct},\n };\n use protocol_types::{address::AztecAddress, traits::{FromField, ToField}};\n\n global SLOT: Field = 1;\n\n #[test]\n unconstrained fn stores_and_loads() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n\n let value = MockStruct::new(5, 6);\n store(contract_address, SLOT, value);\n\n assert_eq(load(contract_address, SLOT).unwrap(), value);\n });\n }\n\n #[test]\n unconstrained fn store_overwrites() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n\n let value = MockStruct::new(5, 6);\n store(contract_address, SLOT, value);\n\n let new_value = MockStruct::new(7, 8);\n store(contract_address, SLOT, new_value);\n\n assert_eq(load(contract_address, SLOT).unwrap(), new_value);\n });\n }\n\n #[test]\n unconstrained fn loads_empty_slot() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n\n let loaded_value: Option = load(contract_address, SLOT);\n assert_eq(loaded_value, Option::none());\n });\n }\n\n #[test]\n unconstrained fn deletes_stored_value() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n\n let value = MockStruct::new(5, 6);\n store(contract_address, SLOT, value);\n delete(contract_address, SLOT);\n\n let loaded_value: Option = load(contract_address, SLOT);\n assert_eq(loaded_value, Option::none());\n });\n }\n\n #[test]\n unconstrained fn deletes_empty_slot() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n\n delete(contract_address, SLOT);\n let loaded_value: Option = load(contract_address, SLOT);\n assert_eq(loaded_value, Option::none());\n });\n }\n\n #[test]\n unconstrained fn copies_non_overlapping_values() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n\n let src = 5;\n\n let values = [MockStruct::new(5, 6), MockStruct::new(7, 8), MockStruct::new(9, 10)];\n store(contract_address, src, values[0]);\n store(contract_address, src + 1, values[1]);\n store(contract_address, src + 2, values[2]);\n\n let dst = 10;\n copy(contract_address, src, dst, 3);\n\n assert_eq(load(contract_address, dst).unwrap(), values[0]);\n assert_eq(load(contract_address, dst + 1).unwrap(), values[1]);\n assert_eq(load(contract_address, dst + 2).unwrap(), values[2]);\n });\n }\n\n #[test]\n unconstrained fn copies_overlapping_values_with_src_ahead() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n\n let src = 1;\n\n let values = [MockStruct::new(5, 6), MockStruct::new(7, 8), MockStruct::new(9, 10)];\n store(contract_address, src, values[0]);\n store(contract_address, src + 1, values[1]);\n store(contract_address, src + 2, values[2]);\n\n let dst = 2;\n copy(contract_address, src, dst, 3);\n\n assert_eq(load(contract_address, dst).unwrap(), values[0]);\n assert_eq(load(contract_address, dst + 1).unwrap(), values[1]);\n assert_eq(load(contract_address, dst + 2).unwrap(), values[2]);\n\n // src[1] and src[2] should have been overwritten since they are also dst[0] and dst[1]\n assert_eq(load(contract_address, src).unwrap(), values[0]); // src[0] (unchanged)\n assert_eq(load(contract_address, src + 1).unwrap(), values[0]); // dst[0]\n assert_eq(load(contract_address, src + 2).unwrap(), values[1]); // dst[1]\n });\n }\n\n #[test]\n unconstrained fn copies_overlapping_values_with_dst_ahead() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n\n let src = 2;\n\n let values = [MockStruct::new(5, 6), MockStruct::new(7, 8), MockStruct::new(9, 10)];\n store(contract_address, src, values[0]);\n store(contract_address, src + 1, values[1]);\n store(contract_address, src + 2, values[2]);\n\n let dst = 1;\n copy(contract_address, src, dst, 3);\n\n assert_eq(load(contract_address, dst).unwrap(), values[0]);\n assert_eq(load(contract_address, dst + 1).unwrap(), values[1]);\n assert_eq(load(contract_address, dst + 2).unwrap(), values[2]);\n\n // src[0] and src[1] should have been overwritten since they are also dst[1] and dst[2]\n assert_eq(load(contract_address, src).unwrap(), values[1]); // dst[1]\n assert_eq(load(contract_address, src + 1).unwrap(), values[2]); // dst[2]\n assert_eq(load(contract_address, src + 2).unwrap(), values[2]); // src[2] (unchanged)\n });\n }\n\n #[test(should_fail_with = \"copy empty slot\")]\n unconstrained fn cannot_copy_empty_values() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n\n copy(contract_address, SLOT, SLOT, 1);\n });\n }\n\n #[test(should_fail_with = \"not allowed to access\")]\n unconstrained fn cannot_store_other_contract() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n let other_contract_address = AztecAddress::from_field(contract_address.to_field() + 1);\n\n let value = MockStruct::new(5, 6);\n store(other_contract_address, SLOT, value);\n });\n }\n\n #[test(should_fail_with = \"not allowed to access\")]\n unconstrained fn cannot_load_other_contract() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n let other_contract_address = AztecAddress::from_field(contract_address.to_field() + 1);\n\n let _: Option = load(other_contract_address, SLOT);\n });\n }\n\n #[test(should_fail_with = \"not allowed to access\")]\n unconstrained fn cannot_delete_other_contract() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n let other_contract_address = AztecAddress::from_field(contract_address.to_field() + 1);\n\n delete(other_contract_address, SLOT);\n });\n }\n\n #[test(should_fail_with = \"not allowed to access\")]\n unconstrained fn cannot_copy_other_contract() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n let other_contract_address = AztecAddress::from_field(contract_address.to_field() + 1);\n\n copy(other_contract_address, SLOT, SLOT, 0);\n });\n }\n}\n"},"159":{"path":"/home/nerses/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.2/noir-projects/aztec-nr/aztec/src/oracle/execution.nr","source":"use crate::context::utility_context::UtilityContext;\n\n#[oracle(utilityGetUtilityContext)]\nunconstrained fn get_utility_context_oracle() -> UtilityContext {}\n\n/// Returns a utility context built from the global variables of anchor block and the contract address of the function\n/// being executed.\npub unconstrained fn get_utility_context() -> UtilityContext {\n get_utility_context_oracle()\n}\n"},"16":{"path":"std/embedded_curve_ops.nr","source":"use crate::cmp::Eq;\nuse crate::hash::Hash;\nuse crate::ops::arith::{Add, Neg, Sub};\n\n/// A point on the embedded elliptic curve\n/// By definition, the base field of the embedded curve is the scalar field of the proof system curve, i.e the Noir Field.\n/// x and y denotes the Weierstrass coordinates of the point, if is_infinite is false.\npub struct EmbeddedCurvePoint {\n pub x: Field,\n pub y: Field,\n pub is_infinite: bool,\n}\n\nimpl EmbeddedCurvePoint {\n /// Elliptic curve point doubling operation\n /// returns the doubled point of a point P, i.e P+P\n pub fn double(self) -> EmbeddedCurvePoint {\n embedded_curve_add(self, self)\n }\n\n /// Returns the null element of the curve; 'the point at infinity'\n pub fn point_at_infinity() -> EmbeddedCurvePoint {\n EmbeddedCurvePoint { x: 0, y: 0, is_infinite: true }\n }\n\n /// Returns the curve's generator point.\n pub fn generator() -> EmbeddedCurvePoint {\n // Generator point for the grumpkin curve (y^2 = x^3 - 17)\n EmbeddedCurvePoint {\n x: 1,\n y: 17631683881184975370165255887551781615748388533673675138860, // sqrt(-16)\n is_infinite: false,\n }\n }\n}\n\nimpl Add for EmbeddedCurvePoint {\n /// Adds two points P+Q, using the curve addition formula, and also handles point at infinity\n fn add(self, other: EmbeddedCurvePoint) -> EmbeddedCurvePoint {\n embedded_curve_add(self, other)\n }\n}\n\nimpl Sub for EmbeddedCurvePoint {\n /// Points subtraction operation, using addition and negation\n fn sub(self, other: EmbeddedCurvePoint) -> EmbeddedCurvePoint {\n self + other.neg()\n }\n}\n\nimpl Neg for EmbeddedCurvePoint {\n /// Negates a point P, i.e returns -P, by negating the y coordinate.\n /// If the point is at infinity, then the result is also at infinity.\n fn neg(self) -> EmbeddedCurvePoint {\n EmbeddedCurvePoint { x: self.x, y: -self.y, is_infinite: self.is_infinite }\n }\n}\n\nimpl Eq for EmbeddedCurvePoint {\n /// Checks whether two points are equal\n fn eq(self: Self, b: EmbeddedCurvePoint) -> bool {\n (self.is_infinite & b.is_infinite)\n | ((self.is_infinite == b.is_infinite) & (self.x == b.x) & (self.y == b.y))\n }\n}\n\nimpl Hash for EmbeddedCurvePoint {\n fn hash(self, state: &mut H)\n where\n H: crate::hash::Hasher,\n {\n if self.is_infinite {\n self.is_infinite.hash(state);\n } else {\n self.x.hash(state);\n self.y.hash(state);\n }\n }\n}\n\n/// Scalar for the embedded curve represented as low and high limbs\n/// By definition, the scalar field of the embedded curve is base field of the proving system curve.\n/// It may not fit into a Field element, so it is represented with two Field elements; its low and high limbs.\npub struct EmbeddedCurveScalar {\n pub lo: Field,\n pub hi: Field,\n}\n\nimpl EmbeddedCurveScalar {\n pub fn new(lo: Field, hi: Field) -> Self {\n EmbeddedCurveScalar { lo, hi }\n }\n\n #[field(bn254)]\n pub fn from_field(scalar: Field) -> EmbeddedCurveScalar {\n let (a, b) = crate::field::bn254::decompose(scalar);\n EmbeddedCurveScalar { lo: a, hi: b }\n }\n\n //Bytes to scalar: take the first (after the specified offset) 16 bytes of the input as the lo value, and the next 16 bytes as the hi value\n #[field(bn254)]\n pub(crate) fn from_bytes(bytes: [u8; 64], offset: u32) -> EmbeddedCurveScalar {\n let mut v = 1;\n let mut lo = 0 as Field;\n let mut hi = 0 as Field;\n for i in 0..16 {\n lo = lo + (bytes[offset + 31 - i] as Field) * v;\n hi = hi + (bytes[offset + 15 - i] as Field) * v;\n v = v * 256;\n }\n let sig_s = crate::embedded_curve_ops::EmbeddedCurveScalar { lo, hi };\n sig_s\n }\n}\n\nimpl Eq for EmbeddedCurveScalar {\n fn eq(self, other: Self) -> bool {\n (other.hi == self.hi) & (other.lo == self.lo)\n }\n}\n\nimpl Hash for EmbeddedCurveScalar {\n fn hash(self, state: &mut H)\n where\n H: crate::hash::Hasher,\n {\n self.hi.hash(state);\n self.lo.hash(state);\n }\n}\n\n// Computes a multi scalar multiplication over the embedded curve.\n// For bn254, We have Grumpkin and Baby JubJub.\n// For bls12-381, we have JubJub and Bandersnatch.\n//\n// The embedded curve being used is decided by the\n// underlying proof system.\n// docs:start:multi_scalar_mul\npub fn multi_scalar_mul(\n points: [EmbeddedCurvePoint; N],\n scalars: [EmbeddedCurveScalar; N],\n) -> EmbeddedCurvePoint\n// docs:end:multi_scalar_mul\n{\n multi_scalar_mul_array_return(points, scalars, true)[0]\n}\n\n#[foreign(multi_scalar_mul)]\npub(crate) fn multi_scalar_mul_array_return(\n points: [EmbeddedCurvePoint; N],\n scalars: [EmbeddedCurveScalar; N],\n predicate: bool,\n) -> [EmbeddedCurvePoint; 1] {}\n\n// docs:start:fixed_base_scalar_mul\npub fn fixed_base_scalar_mul(scalar: EmbeddedCurveScalar) -> EmbeddedCurvePoint\n// docs:end:fixed_base_scalar_mul\n{\n multi_scalar_mul([EmbeddedCurvePoint::generator()], [scalar])\n}\n\n/// This function only assumes that the points are on the curve\n/// It handles corner cases around the infinity point causing some overhead compared to embedded_curve_add_not_nul and embedded_curve_add_unsafe\n// docs:start:embedded_curve_add\npub fn embedded_curve_add(\n point1: EmbeddedCurvePoint,\n point2: EmbeddedCurvePoint,\n) -> EmbeddedCurvePoint {\n // docs:end:embedded_curve_add\n if crate::runtime::is_unconstrained() {\n // `embedded_curve_add_unsafe` requires the inputs not to be the infinity point, so we check it here.\n // This is because `embedded_curve_add_unsafe` uses the `embedded_curve_add` opcode.\n // For efficiency, the backend does not check the inputs for the infinity point, but it assumes that they are not the infinity point\n // so that it can apply the ec addition formula directly.\n if point1.is_infinite {\n point2\n } else if point2.is_infinite {\n point1\n } else {\n embedded_curve_add_unsafe(point1, point2)\n }\n } else {\n // In a constrained context, we also need to check the inputs are not the infinity point because we also use `embedded_curve_add_unsafe`\n // However we also need to identify the case where the two inputs are the same, because then\n // the addition formula does not work and we need to use the doubling formula instead.\n // In unconstrained context, we can check directly if the input values are the same when solving the opcode, so it is not an issue.\n\n // x_coordinates_match is true if both abscissae are the same\n let x_coordinates_match = point1.x == point2.x;\n // y_coordinates_match is true if both ordinates are the same\n let y_coordinates_match = point1.y == point2.y;\n // double_predicate is true if both abscissae and ordinates are the same\n let double_predicate = (x_coordinates_match & y_coordinates_match);\n // If the abscissae are the same, but not the ordinates, then one point is the opposite of the other\n let infinity_predicate = (x_coordinates_match & !y_coordinates_match);\n\n // `embedded_curve_add_unsafe` would not perform doubling, even if the inputs point1 and point2 are the same, because it cannot know this without adding some logic (and some constraints)\n // However we did this logic when we computed `double_predicate`, so we set the result to 2*point1 if point1 and point2 are the same\n let mut result = if double_predicate {\n // `embedded_curve_add_unsafe` is doing a doubling if the input is the same variable, because in this case it is guaranteed (at 'compile time') that the input is the same.\n embedded_curve_add_unsafe(point1, point1)\n } else {\n let point1_1 = EmbeddedCurvePoint {\n x: point1.x + (x_coordinates_match as Field),\n y: point1.y,\n is_infinite: false,\n };\n let point2_1 = EmbeddedCurvePoint { x: point2.x, y: point2.y, is_infinite: false };\n // point1_1 is guaranteed to have a different abscissa than point2:\n // - if x_coordinates_match is 0, that means point1.x != point2.x, and point1_1.x = point1.x + 0\n // - if x_coordinates_match is 1, that means point1.x = point2.x, but point1_1.x = point1.x + 1 in this case\n // Because the abscissa is different, the addition formula is guaranteed to succeed, so we can safely use `embedded_curve_add_unsafe`\n // Note that this computation may be garbage: if x_coordinates_match is 1, or if one of the input is the point at infinity.\n // therefore we only want to do this if we need the result, otherwise it needs to be eliminated as a dead instruction, lest we want the circuit to fail.\n embedded_curve_add_unsafe(point1_1, point2_1)\n };\n\n // Same logic as above for unconstrained context, we set the proper result when one of the inputs is the infinity point\n if point1.is_infinite {\n result = point2;\n }\n if point2.is_infinite {\n result = point1;\n }\n\n // Finally, we set the is_infinity flag of the result:\n // Opposite points should sum into the infinity point, however, if one of them is point at infinity, their coordinates are not meaningful\n // so we should not use the fact that the inputs are opposite in this case:\n let mut result_is_infinity =\n infinity_predicate & (!point1.is_infinite & !point2.is_infinite);\n // However, if both of them are at infinity, then the result is also at infinity\n result.is_infinite = result_is_infinity | (point1.is_infinite & point2.is_infinite);\n result\n }\n}\n\n#[foreign(embedded_curve_add)]\nfn embedded_curve_add_array_return(\n _point1: EmbeddedCurvePoint,\n _point2: EmbeddedCurvePoint,\n _predicate: bool,\n) -> [EmbeddedCurvePoint; 1] {}\n\n/// This function assumes that:\n/// The points are on the curve, and\n/// The points don't share an x-coordinate, and\n/// Neither point is the infinity point.\n/// If it is used with correct input, the function ensures the correct non-zero result is returned.\n/// Except for points on the curve, the other assumptions are checked by the function. It will cause assertion failure if they are not respected.\npub fn embedded_curve_add_not_nul(\n point1: EmbeddedCurvePoint,\n point2: EmbeddedCurvePoint,\n) -> EmbeddedCurvePoint {\n assert(point1.x != point2.x);\n assert(!point1.is_infinite);\n assert(!point2.is_infinite);\n // Ensure is_infinite is comptime\n let point1_1 = EmbeddedCurvePoint { x: point1.x, y: point1.y, is_infinite: false };\n let point2_1 = EmbeddedCurvePoint { x: point2.x, y: point2.y, is_infinite: false };\n embedded_curve_add_unsafe(point1_1, point2_1)\n}\n\n/// Unsafe ec addition\n/// If the inputs are the same, it will perform a doubling, but only if point1 and point2 are the same variable.\n/// If they have the same value but are different variables, the result will be incorrect because in this case\n/// it assumes (but does not check) that the points' x-coordinates are not equal.\n/// It also assumes neither point is the infinity point.\npub fn embedded_curve_add_unsafe(\n point1: EmbeddedCurvePoint,\n point2: EmbeddedCurvePoint,\n) -> EmbeddedCurvePoint {\n embedded_curve_add_array_return(point1, point2, true)[0]\n}\n"},"161":{"path":"/home/nerses/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.2/noir-projects/aztec-nr/aztec/src/oracle/get_contract_instance.nr","source":"use protocol_types::{\n address::AztecAddress, contract_class_id::ContractClassId, contract_instance::ContractInstance,\n traits::FromField,\n};\n\n// NOTE: this is for use in private only\n#[oracle(utilityGetContractInstance)]\nunconstrained fn get_contract_instance_oracle(_address: AztecAddress) -> ContractInstance {}\n\n// NOTE: this is for use in private only\nunconstrained fn get_contract_instance_internal(address: AztecAddress) -> ContractInstance {\n get_contract_instance_oracle(address)\n}\n\n// NOTE: this is for use in private only\npub fn get_contract_instance(address: AztecAddress) -> ContractInstance {\n // Safety: The to_address function combines all values in the instance object to produce an address,\n // so by checking that we get the expected address we validate the entire struct.\n let instance = unsafe { get_contract_instance_internal(address) };\n assert_eq(instance.to_address(), address);\n\n instance\n}\n\nstruct GetContractInstanceResult {\n exists: bool,\n member: Field,\n}\n\n// These oracles each return a ContractInstance member\n// plus a boolean indicating whether the instance was found.\n#[oracle(avmOpcodeGetContractInstanceDeployer)]\nunconstrained fn get_contract_instance_deployer_oracle_avm(\n _address: AztecAddress,\n) -> [GetContractInstanceResult; 1] {}\n#[oracle(avmOpcodeGetContractInstanceClassId)]\nunconstrained fn get_contract_instance_class_id_oracle_avm(\n _address: AztecAddress,\n) -> [GetContractInstanceResult; 1] {}\n#[oracle(avmOpcodeGetContractInstanceInitializationHash)]\nunconstrained fn get_contract_instance_initialization_hash_oracle_avm(\n _address: AztecAddress,\n) -> [GetContractInstanceResult; 1] {}\n\nunconstrained fn get_contract_instance_deployer_internal_avm(\n address: AztecAddress,\n) -> [GetContractInstanceResult; 1] {\n get_contract_instance_deployer_oracle_avm(address)\n}\nunconstrained fn get_contract_instance_class_id_internal_avm(\n address: AztecAddress,\n) -> [GetContractInstanceResult; 1] {\n get_contract_instance_class_id_oracle_avm(address)\n}\nunconstrained fn get_contract_instance_initialization_hash_internal_avm(\n address: AztecAddress,\n) -> [GetContractInstanceResult; 1] {\n get_contract_instance_initialization_hash_oracle_avm(address)\n}\n\npub fn get_contract_instance_deployer_avm(address: AztecAddress) -> Option {\n // Safety: AVM opcodes are constrained by the AVM itself\n let GetContractInstanceResult { exists, member } =\n unsafe { get_contract_instance_deployer_internal_avm(address)[0] };\n if exists {\n Option::some(AztecAddress::from_field(member))\n } else {\n Option::none()\n }\n}\npub fn get_contract_instance_class_id_avm(address: AztecAddress) -> Option {\n // Safety: AVM opcodes are constrained by the AVM itself\n let GetContractInstanceResult { exists, member } =\n unsafe { get_contract_instance_class_id_internal_avm(address)[0] };\n if exists {\n Option::some(ContractClassId::from_field(member))\n } else {\n Option::none()\n }\n}\npub fn get_contract_instance_initialization_hash_avm(address: AztecAddress) -> Option {\n // Safety: AVM opcodes are constrained by the AVM itself\n let GetContractInstanceResult { exists, member } =\n unsafe { get_contract_instance_initialization_hash_internal_avm(address)[0] };\n if exists {\n Option::some(member)\n } else {\n Option::none()\n }\n}\n"},"166":{"path":"/home/nerses/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.2/noir-projects/aztec-nr/aztec/src/oracle/key_validation_request.nr","source":"use protocol_types::abis::validation_requests::KeyValidationRequest;\n\n#[oracle(utilityGetKeyValidationRequest)]\nunconstrained fn get_key_validation_request_oracle(\n _pk_m_hash: Field,\n _key_index: Field,\n) -> KeyValidationRequest {}\n\npub unconstrained fn get_key_validation_request(\n pk_m_hash: Field,\n key_index: Field,\n) -> KeyValidationRequest {\n get_key_validation_request_oracle(pk_m_hash, key_index)\n}\n"},"167":{"path":"/home/nerses/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.2/noir-projects/aztec-nr/aztec/src/oracle/keys.nr","source":"use dep::protocol_types::{\n address::{AztecAddress, PartialAddress},\n point::Point,\n public_keys::{IvpkM, NpkM, OvpkM, PublicKeys, TpkM},\n};\n\n#[oracle(utilityGetPublicKeysAndPartialAddress)]\nunconstrained fn get_public_keys_and_partial_address_oracle(_address: AztecAddress) -> [Field; 13] {}\n\npub unconstrained fn get_public_keys_and_partial_address(\n address: AztecAddress,\n) -> (PublicKeys, PartialAddress) {\n let result = get_public_keys_and_partial_address_oracle(address);\n\n let keys = PublicKeys {\n npk_m: NpkM { inner: Point { x: result[0], y: result[1], is_infinite: result[2] != 0 } },\n ivpk_m: IvpkM { inner: Point { x: result[3], y: result[4], is_infinite: result[5] != 0 } },\n ovpk_m: OvpkM { inner: Point { x: result[6], y: result[7], is_infinite: result[8] != 0 } },\n tpk_m: TpkM { inner: Point { x: result[9], y: result[10], is_infinite: result[11] != 0 } },\n };\n\n let partial_address = PartialAddress::from_field(result[12]);\n\n (keys, partial_address)\n}\n"},"169":{"path":"/home/nerses/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.2/noir-projects/aztec-nr/aztec/src/oracle/message_processing.nr","source":"use protocol_types::address::AztecAddress;\n\n/// Finds new private logs that may have been sent to all registered accounts in PXE in the current contract and makes\n/// them available for later processing in Noir by storing them in a capsule array.\npub unconstrained fn fetch_tagged_logs(pending_tagged_log_array_base_slot: Field) {\n fetch_tagged_logs_oracle(pending_tagged_log_array_base_slot);\n}\n\n#[oracle(utilityFetchTaggedLogs)]\nunconstrained fn fetch_tagged_logs_oracle(pending_tagged_log_array_base_slot: Field) {}\n\n// This must be a single oracle and not one for notes and one for events because the entire point is to validate\n// all notes and events in one go, minimizing node round-trips.\npub(crate) unconstrained fn validate_enqueued_notes_and_events(\n contract_address: AztecAddress,\n note_validation_requests_array_base_slot: Field,\n event_validation_requests_array_base_slot: Field,\n) {\n validate_enqueued_notes_and_events_oracle(\n contract_address,\n note_validation_requests_array_base_slot,\n event_validation_requests_array_base_slot,\n );\n}\n\n#[oracle(utilityValidateEnqueuedNotesAndEvents)]\nunconstrained fn validate_enqueued_notes_and_events_oracle(\n contract_address: AztecAddress,\n note_validation_requests_array_base_slot: Field,\n event_validation_requests_array_base_slot: Field,\n) {}\n\npub(crate) unconstrained fn bulk_retrieve_logs(\n contract_address: AztecAddress,\n log_retrieval_requests_array_base_slot: Field,\n log_retrieval_responses_array_base_slot: Field,\n) {\n bulk_retrieve_logs_oracle(\n contract_address,\n log_retrieval_requests_array_base_slot,\n log_retrieval_responses_array_base_slot,\n );\n}\n\n#[oracle(utilityBulkRetrieveLogs)]\nunconstrained fn bulk_retrieve_logs_oracle(\n contract_address: AztecAddress,\n log_retrieval_requests_array_base_slot: Field,\n log_retrieval_responses_array_base_slot: Field,\n) {}\n"},"17":{"path":"std/field/bn254.nr","source":"use crate::field::field_less_than;\nuse crate::runtime::is_unconstrained;\n\n// The low and high decomposition of the field modulus\nglobal PLO: Field = 53438638232309528389504892708671455233;\nglobal PHI: Field = 64323764613183177041862057485226039389;\n\npub(crate) global TWO_POW_128: Field = 0x100000000000000000000000000000000;\n\n// Decomposes a single field into two 16 byte fields.\nfn compute_decomposition(x: Field) -> (Field, Field) {\n // Here's we're taking advantage of truncating 128 bit limbs from the input field\n // and then subtracting them from the input such the field division is equivalent to integer division.\n let low = (x as u128) as Field;\n let high = (x - low) / TWO_POW_128;\n\n (low, high)\n}\n\npub(crate) unconstrained fn decompose_hint(x: Field) -> (Field, Field) {\n compute_decomposition(x)\n}\n\nunconstrained fn lte_hint(x: Field, y: Field) -> bool {\n if x == y {\n true\n } else {\n field_less_than(x, y)\n }\n}\n\n// Assert that (alo > blo && ahi >= bhi) || (alo <= blo && ahi > bhi)\nfn assert_gt_limbs(a: (Field, Field), b: (Field, Field)) {\n let (alo, ahi) = a;\n let (blo, bhi) = b;\n // Safety: borrow is enforced to be boolean due to its type.\n // if borrow is 0, it asserts that (alo > blo && ahi >= bhi)\n // if borrow is 1, it asserts that (alo <= blo && ahi > bhi)\n unsafe {\n let borrow = lte_hint(alo, blo);\n\n let rlo = alo - blo - 1 + (borrow as Field) * TWO_POW_128;\n let rhi = ahi - bhi - (borrow as Field);\n\n rlo.assert_max_bit_size::<128>();\n rhi.assert_max_bit_size::<128>();\n }\n}\n\n/// Decompose a single field into two 16 byte fields.\npub fn decompose(x: Field) -> (Field, Field) {\n if is_unconstrained() {\n compute_decomposition(x)\n } else {\n // Safety: decomposition is properly checked below\n unsafe {\n // Take hints of the decomposition\n let (xlo, xhi) = decompose_hint(x);\n\n // Range check the limbs\n xlo.assert_max_bit_size::<128>();\n xhi.assert_max_bit_size::<128>();\n\n // Check that the decomposition is correct\n assert_eq(x, xlo + TWO_POW_128 * xhi);\n\n // Assert that the decomposition of P is greater than the decomposition of x\n assert_gt_limbs((PLO, PHI), (xlo, xhi));\n (xlo, xhi)\n }\n }\n}\n\npub fn assert_gt(a: Field, b: Field) {\n if is_unconstrained() {\n assert(\n // Safety: already unconstrained\n unsafe { field_less_than(b, a) },\n );\n } else {\n // Decompose a and b\n let a_limbs = decompose(a);\n let b_limbs = decompose(b);\n\n // Assert that a_limbs is greater than b_limbs\n assert_gt_limbs(a_limbs, b_limbs)\n }\n}\n\npub fn assert_lt(a: Field, b: Field) {\n assert_gt(b, a);\n}\n\npub fn gt(a: Field, b: Field) -> bool {\n if is_unconstrained() {\n // Safety: unsafe in unconstrained\n unsafe {\n field_less_than(b, a)\n }\n } else if a == b {\n false\n } else {\n // Safety: Take a hint of the comparison and verify it\n unsafe {\n if field_less_than(a, b) {\n assert_gt(b, a);\n false\n } else {\n assert_gt(a, b);\n true\n }\n }\n }\n}\n\npub fn lt(a: Field, b: Field) -> bool {\n gt(b, a)\n}\n\nmod tests {\n // TODO: Allow imports from \"super\"\n use crate::field::bn254::{assert_gt, decompose, gt, lt, lte_hint, PHI, PLO, TWO_POW_128};\n\n #[test]\n fn check_decompose() {\n assert_eq(decompose(TWO_POW_128), (0, 1));\n assert_eq(decompose(TWO_POW_128 + 0x1234567890), (0x1234567890, 1));\n assert_eq(decompose(0x1234567890), (0x1234567890, 0));\n }\n\n #[test]\n unconstrained fn check_lte_hint() {\n assert(lte_hint(0, 1));\n assert(lte_hint(0, 0x100));\n assert(lte_hint(0x100, TWO_POW_128 - 1));\n assert(!lte_hint(0 - 1, 0));\n\n assert(lte_hint(0, 0));\n assert(lte_hint(0x100, 0x100));\n assert(lte_hint(0 - 1, 0 - 1));\n }\n\n #[test]\n fn check_gt() {\n assert(gt(1, 0));\n assert(gt(0x100, 0));\n assert(gt((0 - 1), (0 - 2)));\n assert(gt(TWO_POW_128, 0));\n assert(!gt(0, 0));\n assert(!gt(0, 0x100));\n assert(gt(0 - 1, 0 - 2));\n assert(!gt(0 - 2, 0 - 1));\n assert_gt(0 - 1, 0);\n }\n\n #[test]\n fn check_plo_phi() {\n assert_eq(PLO + PHI * TWO_POW_128, 0);\n let p_bytes = crate::field::modulus_le_bytes();\n let mut p_low: Field = 0;\n let mut p_high: Field = 0;\n\n let mut offset = 1;\n for i in 0..16 {\n p_low += (p_bytes[i] as Field) * offset;\n p_high += (p_bytes[i + 16] as Field) * offset;\n offset *= 256;\n }\n assert_eq(p_low, PLO);\n assert_eq(p_high, PHI);\n }\n\n #[test]\n fn check_decompose_edge_cases() {\n assert_eq(decompose(0), (0, 0));\n assert_eq(decompose(TWO_POW_128 - 1), (TWO_POW_128 - 1, 0));\n assert_eq(decompose(TWO_POW_128 + 1), (1, 1));\n assert_eq(decompose(TWO_POW_128 * 2), (0, 2));\n assert_eq(decompose(TWO_POW_128 * 2 + 0x1234567890), (0x1234567890, 2));\n }\n\n #[test]\n fn check_decompose_large_values() {\n let large_field = 0xffffffffffffffff;\n let (lo, hi) = decompose(large_field);\n assert_eq(large_field, lo + TWO_POW_128 * hi);\n\n let large_value = large_field - TWO_POW_128;\n let (lo2, hi2) = decompose(large_value);\n assert_eq(large_value, lo2 + TWO_POW_128 * hi2);\n }\n\n #[test]\n fn check_lt_comprehensive() {\n assert(lt(0, 1));\n assert(!lt(1, 0));\n assert(!lt(0, 0));\n assert(!lt(42, 42));\n\n assert(lt(TWO_POW_128 - 1, TWO_POW_128));\n assert(!lt(TWO_POW_128, TWO_POW_128 - 1));\n }\n}\n"},"174":{"path":"/home/nerses/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.2/noir-projects/aztec-nr/aztec/src/oracle/shared_secret.nr","source":"use protocol_types::{address::aztec_address::AztecAddress, point::Point};\n\n// TODO(#12656): return an app-siloed secret + document this\n#[oracle(utilityGetSharedSecret)]\nunconstrained fn get_shared_secret_oracle(address: AztecAddress, ephPk: Point) -> Point {}\n\n/// Returns an app-siloed shared secret between `address` and someone who knows the secret key behind an\n/// ephemeral public key `ephPk`. The app-siloing means that contracts cannot retrieve secrets that belong to\n/// other contracts, and therefore cannot e.g. decrypt their messages. This is an important security consideration\n/// given that both the `address` and `ephPk` are public information.\n///\n/// The shared secret `S` is computed as:\n/// `let S = (ivsk + h) * ephPk`\n/// where `ivsk + h` is the 'preaddress' i.e. the preimage of the address, also called the address secret.\n/// TODO(#12656): app-silo this secret\npub unconstrained fn get_shared_secret(address: AztecAddress, ephPk: Point) -> Point {\n get_shared_secret_oracle(address, ephPk)\n}\n"},"176":{"path":"/home/nerses/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.2/noir-projects/aztec-nr/aztec/src/oracle/version.nr","source":"/// The ORACLE_VERSION constant is used to check that the oracle interface is in sync between PXE and Aztec.nr. We need\n/// to version the oracle interface to ensure that developers get a reasonable error message if they use incompatible\n/// versions of Aztec.nr and PXE. The TypeScript counterpart is in `oracle_version.ts`.\n///\n/// @dev Whenever a contract function or Noir test is run, the `utilityAssertCompatibleOracleVersion` oracle is called and\n/// if the oracle version is incompatible an error is thrown.\npub global ORACLE_VERSION: Field = 3;\n\n/// Asserts that the version of the oracle is compatible with the version expected by the contract.\npub fn assert_compatible_oracle_version() {\n // Safety: This oracle call returns nothing: we only call it to check Aztec.nr and Oracle interface versions are\n // compatible. It is therefore always safe to call.\n unsafe {\n assert_compatible_oracle_version_wrapper();\n }\n}\n\nunconstrained fn assert_compatible_oracle_version_wrapper() {\n assert_compatible_oracle_version_oracle(ORACLE_VERSION);\n}\n\n#[oracle(utilityAssertCompatibleOracleVersion)]\nunconstrained fn assert_compatible_oracle_version_oracle(version: Field) {}\n\nmod test {\n use super::{assert_compatible_oracle_version_oracle, ORACLE_VERSION};\n\n #[test]\n unconstrained fn compatible_oracle_version() {\n assert_compatible_oracle_version_oracle(ORACLE_VERSION);\n }\n\n #[test(should_fail_with = \"Incompatible oracle version. TXE is using version '3', but got a request for '318183437'.\")]\n unconstrained fn incompatible_oracle_version() {\n let arbitrary_incorrect_version = 318183437;\n assert_compatible_oracle_version_oracle(arbitrary_incorrect_version);\n }\n}\n"},"18":{"path":"std/field/mod.nr","source":"pub mod bn254;\nuse crate::{runtime::is_unconstrained, static_assert};\nuse bn254::lt as bn254_lt;\n\nimpl Field {\n /// Asserts that `self` can be represented in `bit_size` bits.\n ///\n /// # Failures\n /// Causes a constraint failure for `Field` values exceeding `2^{bit_size}`.\n // docs:start:assert_max_bit_size\n pub fn assert_max_bit_size(self) {\n // docs:end:assert_max_bit_size\n static_assert(\n BIT_SIZE < modulus_num_bits() as u32,\n \"BIT_SIZE must be less than modulus_num_bits\",\n );\n __assert_max_bit_size(self, BIT_SIZE);\n }\n\n /// Decomposes `self` into its little endian bit decomposition as a `[u1; N]` array.\n /// This slice will be zero padded should not all bits be necessary to represent `self`.\n ///\n /// # Failures\n /// Causes a constraint failure for `Field` values exceeding `2^N` as the resulting slice will not\n /// be able to represent the original `Field`.\n ///\n /// # Safety\n /// The bit decomposition returned is canonical and is guaranteed to not overflow the modulus.\n // docs:start:to_le_bits\n pub fn to_le_bits(self: Self) -> [u1; N] {\n // docs:end:to_le_bits\n let bits = __to_le_bits(self);\n\n if !is_unconstrained() {\n // Ensure that the byte decomposition does not overflow the modulus\n let p = modulus_le_bits();\n assert(bits.len() <= p.len());\n let mut ok = bits.len() != p.len();\n for i in 0..N {\n if !ok {\n if (bits[N - 1 - i] != p[N - 1 - i]) {\n assert(p[N - 1 - i] == 1);\n ok = true;\n }\n }\n }\n assert(ok);\n }\n bits\n }\n\n /// Decomposes `self` into its big endian bit decomposition as a `[u1; N]` array.\n /// This array will be zero padded should not all bits be necessary to represent `self`.\n ///\n /// # Failures\n /// Causes a constraint failure for `Field` values exceeding `2^N` as the resulting slice will not\n /// be able to represent the original `Field`.\n ///\n /// # Safety\n /// The bit decomposition returned is canonical and is guaranteed to not overflow the modulus.\n // docs:start:to_be_bits\n pub fn to_be_bits(self: Self) -> [u1; N] {\n // docs:end:to_be_bits\n let bits = __to_be_bits(self);\n\n if !is_unconstrained() {\n // Ensure that the decomposition does not overflow the modulus\n let p = modulus_be_bits();\n assert(bits.len() <= p.len());\n let mut ok = bits.len() != p.len();\n for i in 0..N {\n if !ok {\n if (bits[i] != p[i]) {\n assert(p[i] == 1);\n ok = true;\n }\n }\n }\n assert(ok);\n }\n bits\n }\n\n /// Decomposes `self` into its little endian byte decomposition as a `[u8;N]` array\n /// This array will be zero padded should not all bytes be necessary to represent `self`.\n ///\n /// # Failures\n /// The length N of the array must be big enough to contain all the bytes of the 'self',\n /// and no more than the number of bytes required to represent the field modulus\n ///\n /// # Safety\n /// The result is ensured to be the canonical decomposition of the field element\n // docs:start:to_le_bytes\n pub fn to_le_bytes(self: Self) -> [u8; N] {\n // docs:end:to_le_bytes\n static_assert(\n N <= modulus_le_bytes().len(),\n \"N must be less than or equal to modulus_le_bytes().len()\",\n );\n // Compute the byte decomposition\n let bytes = self.to_le_radix(256);\n\n if !is_unconstrained() {\n // Ensure that the byte decomposition does not overflow the modulus\n let p = modulus_le_bytes();\n assert(bytes.len() <= p.len());\n let mut ok = bytes.len() != p.len();\n for i in 0..N {\n if !ok {\n if (bytes[N - 1 - i] != p[N - 1 - i]) {\n assert(bytes[N - 1 - i] < p[N - 1 - i]);\n ok = true;\n }\n }\n }\n assert(ok);\n }\n bytes\n }\n\n /// Decomposes `self` into its big endian byte decomposition as a `[u8;N]` array of length required to represent the field modulus\n /// This array will be zero padded should not all bytes be necessary to represent `self`.\n ///\n /// # Failures\n /// The length N of the array must be big enough to contain all the bytes of the 'self',\n /// and no more than the number of bytes required to represent the field modulus\n ///\n /// # Safety\n /// The result is ensured to be the canonical decomposition of the field element\n // docs:start:to_be_bytes\n pub fn to_be_bytes(self: Self) -> [u8; N] {\n // docs:end:to_be_bytes\n static_assert(\n N <= modulus_le_bytes().len(),\n \"N must be less than or equal to modulus_le_bytes().len()\",\n );\n // Compute the byte decomposition\n let bytes = self.to_be_radix(256);\n\n if !is_unconstrained() {\n // Ensure that the byte decomposition does not overflow the modulus\n let p = modulus_be_bytes();\n assert(bytes.len() <= p.len());\n let mut ok = bytes.len() != p.len();\n for i in 0..N {\n if !ok {\n if (bytes[i] != p[i]) {\n assert(bytes[i] < p[i]);\n ok = true;\n }\n }\n }\n assert(ok);\n }\n bytes\n }\n\n fn to_le_radix(self: Self, radix: u32) -> [u8; N] {\n // Brillig does not need an immediate radix\n if !crate::runtime::is_unconstrained() {\n static_assert(1 < radix, \"radix must be greater than 1\");\n static_assert(radix <= 256, \"radix must be less than or equal to 256\");\n static_assert(radix & (radix - 1) == 0, \"radix must be a power of 2\");\n }\n __to_le_radix(self, radix)\n }\n\n fn to_be_radix(self: Self, radix: u32) -> [u8; N] {\n // Brillig does not need an immediate radix\n if !crate::runtime::is_unconstrained() {\n static_assert(1 < radix, \"radix must be greater than 1\");\n static_assert(radix <= 256, \"radix must be less than or equal to 256\");\n static_assert(radix & (radix - 1) == 0, \"radix must be a power of 2\");\n }\n __to_be_radix(self, radix)\n }\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: [u1; 32] = exponent.to_le_bits();\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 `elem` {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 /// Convert a little endian byte array to a field element.\n /// If the provided byte array overflows the field modulus then the Field will silently wrap around.\n pub fn from_le_bytes(bytes: [u8; N]) -> Field {\n static_assert(\n N <= modulus_le_bytes().len(),\n \"N must be less than or equal to modulus_le_bytes().len()\",\n );\n let mut v = 1;\n let mut result = 0;\n\n for i in 0..N {\n result += (bytes[i] as Field) * v;\n v = v * 256;\n }\n result\n }\n\n /// Convert a big endian byte array to a field element.\n /// If the provided byte array overflows the field modulus then the Field will silently wrap around.\n pub fn from_be_bytes(bytes: [u8; N]) -> Field {\n let mut v = 1;\n let mut result = 0;\n\n for i in 0..N {\n result += (bytes[N - 1 - i] as Field) * v;\n v = v * 256;\n }\n result\n }\n}\n\n#[builtin(apply_range_constraint)]\nfn __assert_max_bit_size(value: Field, bit_size: u32) {}\n\n// `_radix` must be less than 256\n#[builtin(to_le_radix)]\nfn __to_le_radix(value: Field, radix: u32) -> [u8; N] {}\n\n// `_radix` must be less than 256\n#[builtin(to_be_radix)]\nfn __to_be_radix(value: Field, radix: u32) -> [u8; N] {}\n\n/// Decomposes `self` into its little endian bit decomposition as a `[u1; N]` array.\n/// This slice will be zero padded should not all bits be necessary to represent `self`.\n///\n/// # Failures\n/// Causes a constraint failure for `Field` values exceeding `2^N` as the resulting slice will not\n/// be able to represent the original `Field`.\n///\n/// # Safety\n/// Values of `N` equal to or greater than the number of bits necessary to represent the `Field` modulus\n/// (e.g. 254 for the BN254 field) allow for multiple bit decompositions. This is due to how the `Field` will\n/// wrap around due to overflow when verifying the decomposition.\n#[builtin(to_le_bits)]\nfn __to_le_bits(value: Field) -> [u1; N] {}\n\n/// Decomposes `self` into its big endian bit decomposition as a `[u1; N]` array.\n/// This array will be zero padded should not all bits be necessary to represent `self`.\n///\n/// # Failures\n/// Causes a constraint failure for `Field` values exceeding `2^N` as the resulting slice will not\n/// be able to represent the original `Field`.\n///\n/// # Safety\n/// Values of `N` equal to or greater than the number of bits necessary to represent the `Field` modulus\n/// (e.g. 254 for the BN254 field) allow for multiple bit decompositions. This is due to how the `Field` will\n/// wrap around due to overflow when verifying the decomposition.\n#[builtin(to_be_bits)]\nfn __to_be_bits(value: Field) -> [u1; N] {}\n\n#[builtin(modulus_num_bits)]\npub comptime fn modulus_num_bits() -> u64 {}\n\n#[builtin(modulus_be_bits)]\npub comptime fn modulus_be_bits() -> [u1] {}\n\n#[builtin(modulus_le_bits)]\npub comptime fn modulus_le_bits() -> [u1] {}\n\n#[builtin(modulus_be_bytes)]\npub comptime fn modulus_be_bytes() -> [u8] {}\n\n#[builtin(modulus_le_bytes)]\npub comptime fn modulus_le_bytes() -> [u8] {}\n\n/// An unconstrained only built in to efficiently compare fields.\n#[builtin(field_less_than)]\nunconstrained fn __field_less_than(x: Field, y: Field) -> bool {}\n\npub(crate) unconstrained fn field_less_than(x: Field, y: Field) -> bool {\n __field_less_than(x, y)\n}\n\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 if is_unconstrained() {\n // Safety: unconstrained context\n unsafe {\n field_less_than(x, y)\n }\n } else {\n let x_bytes: [u8; 32] = x.to_le_bytes();\n let y_bytes: [u8; 32] = y.to_le_bytes();\n let mut x_is_lt = false;\n let mut done = false;\n for i in 0..32 {\n if (!done) {\n let x_byte = x_bytes[32 - 1 - i] as u8;\n let y_byte = y_bytes[32 - 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\nmod tests {\n use crate::{panic::panic, runtime, static_assert};\n use super::{\n field_less_than, modulus_be_bits, modulus_be_bytes, modulus_le_bits, modulus_le_bytes,\n };\n\n #[test]\n // docs:start:to_be_bits_example\n fn test_to_be_bits() {\n let field = 2;\n let bits: [u1; 8] = field.to_be_bits();\n assert_eq(bits, [0, 0, 0, 0, 0, 0, 1, 0]);\n }\n // docs:end:to_be_bits_example\n\n #[test]\n // docs:start:to_le_bits_example\n fn test_to_le_bits() {\n let field = 2;\n let bits: [u1; 8] = field.to_le_bits();\n assert_eq(bits, [0, 1, 0, 0, 0, 0, 0, 0]);\n }\n // docs:end:to_le_bits_example\n\n #[test]\n // docs:start:to_be_bytes_example\n fn test_to_be_bytes() {\n let field = 2;\n let bytes: [u8; 8] = field.to_be_bytes();\n assert_eq(bytes, [0, 0, 0, 0, 0, 0, 0, 2]);\n assert_eq(Field::from_be_bytes::<8>(bytes), field);\n }\n // docs:end:to_be_bytes_example\n\n #[test]\n // docs:start:to_le_bytes_example\n fn test_to_le_bytes() {\n let field = 2;\n let bytes: [u8; 8] = field.to_le_bytes();\n assert_eq(bytes, [2, 0, 0, 0, 0, 0, 0, 0]);\n assert_eq(Field::from_le_bytes::<8>(bytes), field);\n }\n // docs:end:to_le_bytes_example\n\n #[test]\n // docs:start:to_be_radix_example\n fn test_to_be_radix() {\n // 259, in base 256, big endian, is [1, 3].\n // i.e. 3 * 256^0 + 1 * 256^1\n let field = 259;\n\n // The radix (in this example, 256) must be a power of 2.\n // The length of the returned byte array can be specified to be\n // >= the amount of space needed.\n let bytes: [u8; 8] = field.to_be_radix(256);\n assert_eq(bytes, [0, 0, 0, 0, 0, 0, 1, 3]);\n assert_eq(Field::from_be_bytes::<8>(bytes), field);\n }\n // docs:end:to_be_radix_example\n\n #[test]\n // docs:start:to_le_radix_example\n fn test_to_le_radix() {\n // 259, in base 256, little endian, is [3, 1].\n // i.e. 3 * 256^0 + 1 * 256^1\n let field = 259;\n\n // The radix (in this example, 256) must be a power of 2.\n // The length of the returned byte array can be specified to be\n // >= the amount of space needed.\n let bytes: [u8; 8] = field.to_le_radix(256);\n assert_eq(bytes, [3, 1, 0, 0, 0, 0, 0, 0]);\n assert_eq(Field::from_le_bytes::<8>(bytes), field);\n }\n // docs:end:to_le_radix_example\n\n #[test(should_fail_with = \"radix must be greater than 1\")]\n fn test_to_le_radix_1() {\n // this test should only fail in constrained mode\n if !runtime::is_unconstrained() {\n let field = 2;\n let _: [u8; 8] = field.to_le_radix(1);\n } else {\n panic(f\"radix must be greater than 1\");\n }\n }\n\n // Updated test to account for Brillig restriction that radix must be greater than 2\n #[test(should_fail_with = \"radix must be greater than 1\")]\n fn test_to_le_radix_brillig_1() {\n // this test should only fail in constrained mode\n if !runtime::is_unconstrained() {\n let field = 1;\n let _: [u8; 8] = field.to_le_radix(1);\n } else {\n panic(f\"radix must be greater than 1\");\n }\n }\n\n #[test(should_fail_with = \"radix must be a power of 2\")]\n fn test_to_le_radix_3() {\n // this test should only fail in constrained mode\n if !runtime::is_unconstrained() {\n let field = 2;\n let _: [u8; 8] = field.to_le_radix(3);\n } else {\n panic(f\"radix must be a power of 2\");\n }\n }\n\n #[test]\n fn test_to_le_radix_brillig_3() {\n // this test should only fail in constrained mode\n if runtime::is_unconstrained() {\n let field = 1;\n let out: [u8; 8] = field.to_le_radix(3);\n let mut expected = [0; 8];\n expected[0] = 1;\n assert(out == expected, \"unexpected result\");\n }\n }\n\n #[test(should_fail_with = \"radix must be less than or equal to 256\")]\n fn test_to_le_radix_512() {\n // this test should only fail in constrained mode\n if !runtime::is_unconstrained() {\n let field = 2;\n let _: [u8; 8] = field.to_le_radix(512);\n } else {\n panic(f\"radix must be less than or equal to 256\")\n }\n }\n\n #[test(should_fail_with = \"Field failed to decompose into specified 16 limbs\")]\n unconstrained fn not_enough_limbs_brillig() {\n let _: [u8; 16] = 0x100000000000000000000000000000000.to_le_bytes();\n }\n\n #[test(should_fail_with = \"Field failed to decompose into specified 16 limbs\")]\n fn not_enough_limbs() {\n let _: [u8; 16] = 0x100000000000000000000000000000000.to_le_bytes();\n }\n\n #[test]\n unconstrained fn test_field_less_than() {\n assert(field_less_than(0, 1));\n assert(field_less_than(0, 0x100));\n assert(field_less_than(0x100, 0 - 1));\n assert(!field_less_than(0 - 1, 0));\n }\n\n #[test]\n unconstrained fn test_large_field_values_unconstrained() {\n let large_field = 0xffffffffffffffff;\n\n let bits: [u1; 64] = large_field.to_le_bits();\n assert_eq(bits[0], 1);\n\n let bytes: [u8; 8] = large_field.to_le_bytes();\n assert_eq(Field::from_le_bytes::<8>(bytes), large_field);\n\n let radix_bytes: [u8; 8] = large_field.to_le_radix(256);\n assert_eq(Field::from_le_bytes::<8>(radix_bytes), large_field);\n }\n\n #[test]\n fn test_large_field_values() {\n let large_val = 0xffffffffffffffff;\n\n let bits: [u1; 64] = large_val.to_le_bits();\n assert_eq(bits[0], 1);\n\n let bytes: [u8; 8] = large_val.to_le_bytes();\n assert_eq(Field::from_le_bytes::<8>(bytes), large_val);\n\n let radix_bytes: [u8; 8] = large_val.to_le_radix(256);\n assert_eq(Field::from_le_bytes::<8>(radix_bytes), large_val);\n }\n\n #[test]\n fn test_decomposition_edge_cases() {\n let zero_bits: [u1; 8] = 0.to_le_bits();\n assert_eq(zero_bits, [0; 8]);\n\n let zero_bytes: [u8; 8] = 0.to_le_bytes();\n assert_eq(zero_bytes, [0; 8]);\n\n let one_bits: [u1; 8] = 1.to_le_bits();\n let expected: [u1; 8] = [1, 0, 0, 0, 0, 0, 0, 0];\n assert_eq(one_bits, expected);\n\n let pow2_bits: [u1; 8] = 4.to_le_bits();\n let expected: [u1; 8] = [0, 0, 1, 0, 0, 0, 0, 0];\n assert_eq(pow2_bits, expected);\n }\n\n #[test]\n fn test_pow_32() {\n assert_eq(2.pow_32(3), 8);\n assert_eq(3.pow_32(2), 9);\n assert_eq(5.pow_32(0), 1);\n assert_eq(7.pow_32(1), 7);\n\n assert_eq(2.pow_32(10), 1024);\n\n assert_eq(0.pow_32(5), 0);\n assert_eq(0.pow_32(0), 1);\n\n assert_eq(1.pow_32(100), 1);\n }\n\n #[test]\n fn test_sgn0() {\n assert_eq(0.sgn0(), 0);\n assert_eq(2.sgn0(), 0);\n assert_eq(4.sgn0(), 0);\n assert_eq(100.sgn0(), 0);\n\n assert_eq(1.sgn0(), 1);\n assert_eq(3.sgn0(), 1);\n assert_eq(5.sgn0(), 1);\n assert_eq(101.sgn0(), 1);\n }\n\n #[test(should_fail_with = \"Field failed to decompose into specified 8 limbs\")]\n fn test_bit_decomposition_overflow() {\n // 8 bits can't represent large field values\n let large_val = 0x1000000000000000;\n let _: [u1; 8] = large_val.to_le_bits();\n }\n\n #[test(should_fail_with = \"Field failed to decompose into specified 4 limbs\")]\n fn test_byte_decomposition_overflow() {\n // 4 bytes can't represent large field values\n let large_val = 0x1000000000000000;\n let _: [u8; 4] = large_val.to_le_bytes();\n }\n\n #[test]\n fn test_to_from_be_bytes_bn254_edge_cases() {\n if crate::compat::is_bn254() {\n // checking that decrementing this byte produces the expected 32 BE bytes for (modulus - 1)\n let mut p_minus_1_bytes: [u8; 32] = modulus_be_bytes().as_array();\n assert(p_minus_1_bytes[32 - 1] > 0);\n p_minus_1_bytes[32 - 1] -= 1;\n\n let p_minus_1 = Field::from_be_bytes::<32>(p_minus_1_bytes);\n assert_eq(p_minus_1 + 1, 0);\n\n // checking that converting (modulus - 1) from and then to 32 BE bytes produces the same bytes\n let p_minus_1_converted_bytes: [u8; 32] = p_minus_1.to_be_bytes();\n assert_eq(p_minus_1_converted_bytes, p_minus_1_bytes);\n\n // checking that incrementing this byte produces 32 BE bytes for (modulus + 1)\n let mut p_plus_1_bytes: [u8; 32] = modulus_be_bytes().as_array();\n assert(p_plus_1_bytes[32 - 1] < 255);\n p_plus_1_bytes[32 - 1] += 1;\n\n let p_plus_1 = Field::from_be_bytes::<32>(p_plus_1_bytes);\n assert_eq(p_plus_1, 1);\n\n // checking that converting p_plus_1 to 32 BE bytes produces the same\n // byte set to 1 as p_plus_1_bytes and otherwise zeroes\n let mut p_plus_1_converted_bytes: [u8; 32] = p_plus_1.to_be_bytes();\n assert_eq(p_plus_1_converted_bytes[32 - 1], 1);\n p_plus_1_converted_bytes[32 - 1] = 0;\n assert_eq(p_plus_1_converted_bytes, [0; 32]);\n\n // checking that Field::from_be_bytes::<32> on the Field modulus produces 0\n assert_eq(modulus_be_bytes().len(), 32);\n let p = Field::from_be_bytes::<32>(modulus_be_bytes().as_array());\n assert_eq(p, 0);\n\n // checking that converting 0 to 32 BE bytes produces 32 zeroes\n let p_bytes: [u8; 32] = 0.to_be_bytes();\n assert_eq(p_bytes, [0; 32]);\n }\n }\n\n #[test]\n fn test_to_from_le_bytes_bn254_edge_cases() {\n if crate::compat::is_bn254() {\n // checking that decrementing this byte produces the expected 32 LE bytes for (modulus - 1)\n let mut p_minus_1_bytes: [u8; 32] = modulus_le_bytes().as_array();\n assert(p_minus_1_bytes[0] > 0);\n p_minus_1_bytes[0] -= 1;\n\n let p_minus_1 = Field::from_le_bytes::<32>(p_minus_1_bytes);\n assert_eq(p_minus_1 + 1, 0);\n\n // checking that converting (modulus - 1) from and then to 32 BE bytes produces the same bytes\n let p_minus_1_converted_bytes: [u8; 32] = p_minus_1.to_le_bytes();\n assert_eq(p_minus_1_converted_bytes, p_minus_1_bytes);\n\n // checking that incrementing this byte produces 32 LE bytes for (modulus + 1)\n let mut p_plus_1_bytes: [u8; 32] = modulus_le_bytes().as_array();\n assert(p_plus_1_bytes[0] < 255);\n p_plus_1_bytes[0] += 1;\n\n let p_plus_1 = Field::from_le_bytes::<32>(p_plus_1_bytes);\n assert_eq(p_plus_1, 1);\n\n // checking that converting p_plus_1 to 32 LE bytes produces the same\n // byte set to 1 as p_plus_1_bytes and otherwise zeroes\n let mut p_plus_1_converted_bytes: [u8; 32] = p_plus_1.to_le_bytes();\n assert_eq(p_plus_1_converted_bytes[0], 1);\n p_plus_1_converted_bytes[0] = 0;\n assert_eq(p_plus_1_converted_bytes, [0; 32]);\n\n // checking that Field::from_le_bytes::<32> on the Field modulus produces 0\n assert_eq(modulus_le_bytes().len(), 32);\n let p = Field::from_le_bytes::<32>(modulus_le_bytes().as_array());\n assert_eq(p, 0);\n\n // checking that converting 0 to 32 LE bytes produces 32 zeroes\n let p_bytes: [u8; 32] = 0.to_le_bytes();\n assert_eq(p_bytes, [0; 32]);\n }\n }\n\n /// Convert a little endian bit array to a field element.\n /// If the provided bit array overflows the field modulus then the Field will silently wrap around.\n fn from_le_bits(bits: [u1; N]) -> Field {\n static_assert(\n N <= modulus_le_bits().len(),\n \"N must be less than or equal to modulus_le_bits().len()\",\n );\n let mut v = 1;\n let mut result = 0;\n\n for i in 0..N {\n result += (bits[i] as Field) * v;\n v = v * 2;\n }\n result\n }\n\n /// Convert a big endian bit array to a field element.\n /// If the provided bit array overflows the field modulus then the Field will silently wrap around.\n fn from_be_bits(bits: [u1; N]) -> Field {\n let mut v = 1;\n let mut result = 0;\n\n for i in 0..N {\n result += (bits[N - 1 - i] as Field) * v;\n v = v * 2;\n }\n result\n }\n\n #[test]\n fn test_to_from_be_bits_bn254_edge_cases() {\n if crate::compat::is_bn254() {\n // checking that decrementing this bit produces the expected 254 BE bits for (modulus - 1)\n let mut p_minus_1_bits: [u1; 254] = modulus_be_bits().as_array();\n assert(p_minus_1_bits[254 - 1] > 0);\n p_minus_1_bits[254 - 1] -= 1;\n\n let p_minus_1 = from_be_bits::<254>(p_minus_1_bits);\n assert_eq(p_minus_1 + 1, 0);\n\n // checking that converting (modulus - 1) from and then to 254 BE bits produces the same bits\n let p_minus_1_converted_bits: [u1; 254] = p_minus_1.to_be_bits();\n assert_eq(p_minus_1_converted_bits, p_minus_1_bits);\n\n // checking that incrementing this bit produces 254 BE bits for (modulus + 4)\n let mut p_plus_4_bits: [u1; 254] = modulus_be_bits().as_array();\n assert(p_plus_4_bits[254 - 3] < 1);\n p_plus_4_bits[254 - 3] += 1;\n\n let p_plus_4 = from_be_bits::<254>(p_plus_4_bits);\n assert_eq(p_plus_4, 4);\n\n // checking that converting p_plus_4 to 254 BE bits produces the same\n // bit set to 1 as p_plus_4_bits and otherwise zeroes\n let mut p_plus_4_converted_bits: [u1; 254] = p_plus_4.to_be_bits();\n assert_eq(p_plus_4_converted_bits[254 - 3], 1);\n p_plus_4_converted_bits[254 - 3] = 0;\n assert_eq(p_plus_4_converted_bits, [0; 254]);\n\n // checking that Field::from_be_bits::<254> on the Field modulus produces 0\n assert_eq(modulus_be_bits().len(), 254);\n let p = from_be_bits::<254>(modulus_be_bits().as_array());\n assert_eq(p, 0);\n\n // checking that converting 0 to 254 BE bytes produces 254 zeroes\n let p_bits: [u1; 254] = 0.to_be_bits();\n assert_eq(p_bits, [0; 254]);\n }\n }\n\n #[test]\n fn test_to_from_le_bits_bn254_edge_cases() {\n if crate::compat::is_bn254() {\n // checking that decrementing this bit produces the expected 254 LE bits for (modulus - 1)\n let mut p_minus_1_bits: [u1; 254] = modulus_le_bits().as_array();\n assert(p_minus_1_bits[0] > 0);\n p_minus_1_bits[0] -= 1;\n\n let p_minus_1 = from_le_bits::<254>(p_minus_1_bits);\n assert_eq(p_minus_1 + 1, 0);\n\n // checking that converting (modulus - 1) from and then to 254 BE bits produces the same bits\n let p_minus_1_converted_bits: [u1; 254] = p_minus_1.to_le_bits();\n assert_eq(p_minus_1_converted_bits, p_minus_1_bits);\n\n // checking that incrementing this bit produces 254 LE bits for (modulus + 4)\n let mut p_plus_4_bits: [u1; 254] = modulus_le_bits().as_array();\n assert(p_plus_4_bits[2] < 1);\n p_plus_4_bits[2] += 1;\n\n let p_plus_4 = from_le_bits::<254>(p_plus_4_bits);\n assert_eq(p_plus_4, 4);\n\n // checking that converting p_plus_4 to 254 LE bits produces the same\n // bit set to 1 as p_plus_4_bits and otherwise zeroes\n let mut p_plus_4_converted_bits: [u1; 254] = p_plus_4.to_le_bits();\n assert_eq(p_plus_4_converted_bits[2], 1);\n p_plus_4_converted_bits[2] = 0;\n assert_eq(p_plus_4_converted_bits, [0; 254]);\n\n // checking that Field::from_le_bits::<254> on the Field modulus produces 0\n assert_eq(modulus_le_bits().len(), 254);\n let p = from_le_bits::<254>(modulus_le_bits().as_array());\n assert_eq(p, 0);\n\n // checking that converting 0 to 254 LE bytes produces 254 zeroes\n let p_bits: [u1; 254] = 0.to_le_bits();\n assert_eq(p_bits, [0; 254]);\n }\n }\n}\n"},"180":{"path":"/home/nerses/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.2/noir-projects/aztec-nr/aztec/src/state_vars/map.nr","source":"use crate::state_vars::storage::HasStorageSlot;\nuse dep::protocol_types::{storage::map::derive_storage_slot_in_map, traits::ToField};\n\n/// Map\n///\n/// A key-value storage container that maps keys to state variables, similar\n/// to Solidity mappings.\n///\n/// `Map` enables you to associate keys (like addresses or other identifiers)\n/// with state variables in your Aztec smart contract. This is conceptually\n/// similar to Solidity's `mapping(K => V)` syntax, where you can store and\n/// retrieve values by their associated keys.\n///\n/// You can declare a state variable contained within a Map in your contract's\n/// #[storage] struct.\n///\n/// For example, you might use\n/// `Map, Context>` to track\n/// token balances for different users, similar to how you'd use\n/// `mapping(address => uint256)` in Solidity.\n///\n/// > Aside: the verbose `Context` in the declaration is a consequence of\n/// > leveraging Noir's regular syntax for generics to ensure that certain\n/// > state variable methods can only be called in some contexts (private,\n/// > public, utility).\n///\n/// The methods of Map are:\n/// - `at` (access state variable for a given key)\n/// (see the method's own doc comments for more info).\n///\n/// ## Generic Parameters\n/// - `K`: The key type (must implement `ToField` trait for hashing)\n/// - `V`: The value type:\n/// - any Aztec state variable:\n/// - `PublicMutable`\n/// - `PublicImmutable`\n/// - `PrivateMutable`\n/// - `PrivateImmutable`\n/// - `PrivateSet`\n/// - `DelayedPublicMutable`\n/// - `Map`\n/// - `Context`: The execution context (handles private/public function\n/// contexts)\n///\n/// ## Usage\n/// Maps are typically declared in your contract's #[storage] struct and\n/// accessed\n/// using the `at(key)` method to get the state variable for a specific key.\n/// The resulting state variable can then be read from or written to using its\n/// own methods.\n///\n/// ## Advanced\n/// Internally, `Map` uses a single base storage slot to represent the\n/// mapping\n/// itself, similar to Solidity's approach. Individual key-value pairs are\n/// stored at derived storage slots computed by hashing the base storage\n/// slot\n/// with the key using Poseidon2. This ensures:\n/// - No storage slot collisions between different keys\n/// - Uniform distribution of storage slots across the storage space\n/// - Compatibility with Aztec's storage tree structure\n/// - Gas-efficient storage access patterns similar to Solidity mappings\n///\n/// The storage slot derivation uses `derive_storage_slot_in_map(base_slot,\n/// key)` which computes `poseidon2_hash([base_slot, key.to_field()])`,\n/// ensuring cryptographically secure slot separation.\n///\n/// docs:start:map\npub struct Map {\n pub context: Context,\n storage_slot: Field,\n state_var_constructor: fn(Context, Field) -> V,\n}\n\n// Map reserves a single storage slot regardless of what it stores because\n// nothing is stored at said slot: it is only used to derive the storage slots\n// of nested state variables, which is expected to never result in collisions\n// or slots being close to one another due to these being hashes. This mirrors\n// the strategy adopted by Solidity mappings.\nimpl HasStorageSlot<1> for Map {\n fn get_storage_slot(self) -> Field {\n self.storage_slot\n }\n}\n\nimpl Map {\n /// Initializes a new Map state variable.\n ///\n /// This function is usually automatically called within the #[storage]\n /// macro.\n /// You typically don't need to call this directly when writing smart contracts.\n ///\n /// # Arguments\n ///\n /// * `context` - One of `PrivateContext`/`PublicContext`/`UtilityContext`.\n /// The Context determines which methods of this struct will\n /// be made available to the calling smart contract function.\n /// * `storage_slot` - A unique identifier for this Map within the contract.\n /// Usually, the #[storage] macro will determine an\n /// appropriate storage_slot automatically. A smart\n /// contract dev shouldn't have to worry about this, as\n /// it's managed behind the scenes.\n /// * `state_var_constructor` - A function that creates the value type (V)\n /// given a context and storage slot. This is\n /// typically the constructor of the state\n /// variable type being stored in the Map.\n ///\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\n /// Returns the state variable associated with the given key.\n ///\n /// This is equivalent to accessing `mapping[key]` in Solidity. It returns\n /// the state variable instance for the specified key, which can then be\n /// used to read or write the value at that key.\n ///\n /// Unlike Solidity mappings which return the value directly, this returns\n /// the state variable wrapper (like PrivateMutable, PublicMutable, etc.)\n /// that you then call methods on to interact with the actual value.\n ///\n /// # Arguments\n ///\n /// * `key` - The key to look up in the map. Must implement the ToField\n /// trait (which most basic Noir & Aztec types do).\n ///\n /// # Returns\n ///\n /// * `V` - The state variable instance for this key. You can then call\n /// methods like `.read()`, `.write()`, `.get_note()`, etc. on this\n /// depending on the specific state variable type.\n ///\n /// # Example\n ///\n /// ```noir\n /// // Get a user's balance (assuming PrivateMutable)\n /// let user_balance = storage.balances.at(user_address);\n /// let current_note = user_balance.get_note();\n ///\n /// // Update the balance\n /// user_balance.replace(new_note);\n /// ```\n ///\n pub fn at(self, key: K) -> V\n where\n K: ToField,\n {\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}\n"},"19":{"path":"std/hash/mod.nr","source":"// Exposed only for usage in `std::meta`\npub(crate) mod poseidon2;\n\nuse crate::default::Default;\nuse crate::embedded_curve_ops::{\n EmbeddedCurvePoint, EmbeddedCurveScalar, multi_scalar_mul, multi_scalar_mul_array_return,\n};\nuse crate::meta::derive_via;\n\n#[foreign(sha256_compression)]\n// docs:start:sha256_compression\npub fn sha256_compression(input: [u32; 16], state: [u32; 8]) -> [u32; 8] {}\n// docs:end:sha256_compression\n\n#[foreign(keccakf1600)]\n// docs:start:keccakf1600\npub fn keccakf1600(input: [u64; 25]) -> [u64; 25] {}\n// docs:end:keccakf1600\n\npub mod keccak {\n #[deprecated(\"This function has been moved to std::hash::keccakf1600\")]\n pub fn keccakf1600(input: [u64; 25]) -> [u64; 25] {\n super::keccakf1600(input)\n }\n}\n\n#[foreign(blake2s)]\n// docs:start:blake2s\npub fn blake2s(input: [u8; N]) -> [u8; 32]\n// docs:end:blake2s\n{}\n\n// docs:start:blake3\npub fn blake3(input: [u8; N]) -> [u8; 32]\n// docs:end:blake3\n{\n if crate::runtime::is_unconstrained() {\n // Temporary measure while Barretenberg is main proving system.\n // Please open an issue if you're working on another proving system and running into problems due to this.\n crate::static_assert(\n N <= 1024,\n \"Barretenberg cannot prove blake3 hashes with inputs larger than 1024 bytes\",\n );\n }\n __blake3(input)\n}\n\n#[foreign(blake3)]\nfn __blake3(input: [u8; N]) -> [u8; 32] {}\n\n// docs:start:pedersen_commitment\npub fn pedersen_commitment(input: [Field; N]) -> EmbeddedCurvePoint {\n // docs:end:pedersen_commitment\n pedersen_commitment_with_separator(input, 0)\n}\n\n#[inline_always]\npub fn pedersen_commitment_with_separator(\n input: [Field; N],\n separator: u32,\n) -> EmbeddedCurvePoint {\n let mut points = [EmbeddedCurveScalar { lo: 0, hi: 0 }; N];\n for i in 0..N {\n // we use the unsafe version because the multi_scalar_mul will constrain the scalars.\n points[i] = from_field_unsafe(input[i]);\n }\n let generators = derive_generators(\"DEFAULT_DOMAIN_SEPARATOR\".as_bytes(), separator);\n multi_scalar_mul(generators, points)\n}\n\n// docs:start:pedersen_hash\npub fn pedersen_hash(input: [Field; N]) -> Field\n// docs:end:pedersen_hash\n{\n pedersen_hash_with_separator(input, 0)\n}\n\n#[no_predicates]\npub fn pedersen_hash_with_separator(input: [Field; N], separator: u32) -> Field {\n let mut scalars: [EmbeddedCurveScalar; N + 1] = [EmbeddedCurveScalar { lo: 0, hi: 0 }; N + 1];\n let mut generators: [EmbeddedCurvePoint; N + 1] =\n [EmbeddedCurvePoint::point_at_infinity(); N + 1];\n let domain_generators: [EmbeddedCurvePoint; N] =\n derive_generators(\"DEFAULT_DOMAIN_SEPARATOR\".as_bytes(), separator);\n\n for i in 0..N {\n scalars[i] = from_field_unsafe(input[i]);\n generators[i] = domain_generators[i];\n }\n scalars[N] = EmbeddedCurveScalar { lo: N as Field, hi: 0 as Field };\n\n let length_generator: [EmbeddedCurvePoint; 1] =\n derive_generators(\"pedersen_hash_length\".as_bytes(), 0);\n generators[N] = length_generator[0];\n multi_scalar_mul_array_return(generators, scalars, true)[0].x\n}\n\n#[field(bn254)]\n#[inline_always]\npub fn derive_generators(\n domain_separator_bytes: [u8; M],\n starting_index: u32,\n) -> [EmbeddedCurvePoint; N] {\n crate::assert_constant(domain_separator_bytes);\n // TODO(https://github.com/noir-lang/noir/issues/5672): Add back assert_constant on starting_index\n __derive_generators(domain_separator_bytes, starting_index)\n}\n\n#[builtin(derive_pedersen_generators)]\n#[field(bn254)]\nfn __derive_generators(\n domain_separator_bytes: [u8; M],\n starting_index: u32,\n) -> [EmbeddedCurvePoint; N] {}\n\n#[field(bn254)]\n// Same as from_field but:\n// does not assert the limbs are 128 bits\n// does not assert the decomposition does not overflow the EmbeddedCurveScalar\nfn from_field_unsafe(scalar: Field) -> EmbeddedCurveScalar {\n // Safety: xlo and xhi decomposition is checked below\n let (xlo, xhi) = unsafe { crate::field::bn254::decompose_hint(scalar) };\n // Check that the decomposition is correct\n assert_eq(scalar, xlo + crate::field::bn254::TWO_POW_128 * xhi);\n EmbeddedCurveScalar { lo: xlo, hi: xhi }\n}\n\npub fn poseidon2_permutation(input: [Field; N], state_len: u32) -> [Field; N] {\n assert_eq(input.len(), state_len);\n poseidon2_permutation_internal(input)\n}\n\n#[foreign(poseidon2_permutation)]\nfn poseidon2_permutation_internal(input: [Field; N]) -> [Field; N] {}\n\n// Generic hashing support.\n// Partially ported and impacted by rust.\n\n// Hash trait shall be implemented per type.\n#[derive_via(derive_hash)]\npub trait Hash {\n fn hash(self, state: &mut H)\n where\n H: Hasher;\n}\n\n// docs:start:derive_hash\ncomptime fn derive_hash(s: TypeDefinition) -> Quoted {\n let name = quote { $crate::hash::Hash };\n let signature = quote { fn hash(_self: Self, _state: &mut H) where H: $crate::hash::Hasher };\n let for_each_field = |name| quote { _self.$name.hash(_state); };\n crate::meta::make_trait_impl(\n s,\n name,\n signature,\n for_each_field,\n quote {},\n |fields| fields,\n )\n}\n// docs:end:derive_hash\n\n// Hasher trait shall be implemented by algorithms to provide hash-agnostic means.\n// TODO: consider making the types generic here ([u8], [Field], etc.)\npub trait Hasher {\n fn finish(self) -> Field;\n\n fn write(&mut self, input: Field);\n}\n\n// BuildHasher is a factory trait, responsible for production of specific Hasher.\npub trait BuildHasher {\n type H: Hasher;\n\n fn build_hasher(self) -> H;\n}\n\npub struct BuildHasherDefault;\n\nimpl BuildHasher for BuildHasherDefault\nwhere\n H: Hasher + Default,\n{\n type H = H;\n\n fn build_hasher(_self: Self) -> H {\n H::default()\n }\n}\n\nimpl Default for BuildHasherDefault\nwhere\n H: Hasher + Default,\n{\n fn default() -> Self {\n BuildHasherDefault {}\n }\n}\n\nimpl Hash for Field {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self);\n }\n}\n\nimpl Hash for u1 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u8 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u16 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u32 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u64 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u128 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for i8 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u8 as Field);\n }\n}\n\nimpl Hash for i16 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u16 as Field);\n }\n}\n\nimpl Hash for i32 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u32 as Field);\n }\n}\n\nimpl Hash for i64 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u64 as Field);\n }\n}\n\nimpl Hash for bool {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for () {\n fn hash(_self: Self, _state: &mut H)\n where\n H: Hasher,\n {}\n}\n\nimpl Hash for [T; N]\nwhere\n T: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n for elem in self {\n elem.hash(state);\n }\n }\n}\n\nimpl Hash for [T]\nwhere\n T: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n self.len().hash(state);\n for elem in self {\n elem.hash(state);\n }\n }\n}\n\nimpl Hash for (A, B)\nwhere\n A: Hash,\n B: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n }\n}\n\nimpl Hash for (A, B, C)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n }\n}\n\nimpl Hash for (A, B, C, D)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n D: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n self.3.hash(state);\n }\n}\n\nimpl Hash for (A, B, C, D, E)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n D: Hash,\n E: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n self.3.hash(state);\n self.4.hash(state);\n }\n}\n\n// Some test vectors for Pedersen hash and Pedersen Commitment.\n// They have been generated using the same functions so the tests are for now useless\n// but they will be useful when we switch to Noir implementation.\n#[test]\nfn assert_pedersen() {\n assert_eq(\n pedersen_hash_with_separator([1], 1),\n 0x1b3f4b1a83092a13d8d1a59f7acb62aba15e7002f4440f2275edb99ebbc2305f,\n );\n assert_eq(\n pedersen_commitment_with_separator([1], 1),\n EmbeddedCurvePoint {\n x: 0x054aa86a73cb8a34525e5bbed6e43ba1198e860f5f3950268f71df4591bde402,\n y: 0x209dcfbf2cfb57f9f6046f44d71ac6faf87254afc7407c04eb621a6287cac126,\n is_infinite: false,\n },\n );\n\n assert_eq(\n pedersen_hash_with_separator([1, 2], 2),\n 0x26691c129448e9ace0c66d11f0a16d9014a9e8498ee78f4d69f0083168188255,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2], 2),\n EmbeddedCurvePoint {\n x: 0x2e2b3b191e49541fe468ec6877721d445dcaffe41728df0a0eafeb15e87b0753,\n y: 0x2ff4482400ad3a6228be17a2af33e2bcdf41be04795f9782bd96efe7e24f8778,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3], 3),\n 0x0bc694b7a1f8d10d2d8987d07433f26bd616a2d351bc79a3c540d85b6206dbe4,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3], 3),\n EmbeddedCurvePoint {\n x: 0x1fee4e8cf8d2f527caa2684236b07c4b1bad7342c01b0f75e9a877a71827dc85,\n y: 0x2f9fedb9a090697ab69bf04c8bc15f7385b3e4b68c849c1536e5ae15ff138fd1,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4], 4),\n 0xdae10fb32a8408521803905981a2b300d6a35e40e798743e9322b223a5eddc,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4], 4),\n EmbeddedCurvePoint {\n x: 0x07ae3e202811e1fca39c2d81eabe6f79183978e6f12be0d3b8eda095b79bdbc9,\n y: 0x0afc6f892593db6fbba60f2da558517e279e0ae04f95758587760ba193145014,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5], 5),\n 0xfc375b062c4f4f0150f7100dfb8d9b72a6d28582dd9512390b0497cdad9c22,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5], 5),\n EmbeddedCurvePoint {\n x: 0x1754b12bd475a6984a1094b5109eeca9838f4f81ac89c5f0a41dbce53189bb29,\n y: 0x2da030e3cfcdc7ddad80eaf2599df6692cae0717d4e9f7bfbee8d073d5d278f7,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6], 6),\n 0x1696ed13dc2730062a98ac9d8f9de0661bb98829c7582f699d0273b18c86a572,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6], 6),\n EmbeddedCurvePoint {\n x: 0x190f6c0e97ad83e1e28da22a98aae156da083c5a4100e929b77e750d3106a697,\n y: 0x1f4b60f34ef91221a0b49756fa0705da93311a61af73d37a0c458877706616fb,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7], 7),\n 0x128c0ff144fc66b6cb60eeac8a38e23da52992fc427b92397a7dffd71c45ede3,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7], 7),\n EmbeddedCurvePoint {\n x: 0x015441e9d29491b06563fac16fc76abf7a9534c715421d0de85d20dbe2965939,\n y: 0x1d2575b0276f4e9087e6e07c2cb75aa1baafad127af4be5918ef8a2ef2fea8fc,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7, 8], 8),\n 0x2f960e117482044dfc99d12fece2ef6862fba9242be4846c7c9a3e854325a55c,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7, 8], 8),\n EmbeddedCurvePoint {\n x: 0x1657737676968887fceb6dd516382ea13b3a2c557f509811cd86d5d1199bc443,\n y: 0x1f39f0cb569040105fa1e2f156521e8b8e08261e635a2b210bdc94e8d6d65f77,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9], 9),\n 0x0c96db0790602dcb166cc4699e2d306c479a76926b81c2cb2aaa92d249ec7be7,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9], 9),\n EmbeddedCurvePoint {\n x: 0x0a3ceae42d14914a432aa60ec7fded4af7dad7dd4acdbf2908452675ec67e06d,\n y: 0xfc19761eaaf621ad4aec9a8b2e84a4eceffdba78f60f8b9391b0bd9345a2f2,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 10),\n 0x2cd37505871bc460a62ea1e63c7fe51149df5d0801302cf1cbc48beb8dff7e94,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 10),\n EmbeddedCurvePoint {\n x: 0x2fb3f8b3d41ddde007c8c3c62550f9a9380ee546fcc639ffbb3fd30c8d8de30c,\n y: 0x300783be23c446b11a4c0fabf6c91af148937cea15fcf5fb054abf7f752ee245,\n is_infinite: false,\n },\n );\n}\n"},"190":{"path":"/home/nerses/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.2/noir-projects/aztec-nr/aztec/src/state_vars/public_mutable.nr","source":"use crate::context::{PublicContext, UtilityContext};\nuse crate::state_vars::storage::HasStorageSlot;\nuse dep::protocol_types::traits::Packable;\n\n/// # PublicMutable\n///\n/// PublicMutable is a public state variable type for values that can be read\n/// and written within #[external(\"public\")] functions of your smart contract.\n///\n/// You can declare a state variable of type PublicMutable within your contract's\n/// #[storage] struct:\n///\n/// E.g.:\n/// `your_variable: PublicMutable`\n/// or:\n/// `your_mapping: Map>`\n///\n/// The methods of PublicMutable are:\n/// - `read`\n/// - `write`\n/// (see the methods' own doc comments for more info).\n///\n/// ## Example.\n///\n/// A voting contract's proposal count can be represented as a PublicMutable.\n/// The count can be read by anyone to see how many proposals exist, and incremented\n/// when new proposals are submitted.\n///\n/// # Generic Parameters:\n///\n/// * `T` - The type of value stored (must implement Packable).\n/// * `Context` - The execution context (PublicContext or UtilityContext).\n///\n/// # Advanced\n///\n/// Unlike private state variables which use notes, PublicMutable stores values\n/// directly in Aztec's public data tree. This enables direct read and write\n/// access to the current state during public function execution.\n///\n/// docs:start:public_mutable_struct\npub struct PublicMutable {\n context: Context,\n storage_slot: Field,\n}\n\nimpl HasStorageSlot for PublicMutable\nwhere\n T: Packable,\n{\n fn get_storage_slot(self) -> Field {\n self.storage_slot\n }\n}\n\nimpl PublicMutable {\n /// Initializes a new PublicMutable state variable.\n ///\n /// This function is usually automatically called within the #[storage] macro.\n /// You typically don't need to call this directly when writing smart contracts.\n ///\n /// # Arguments\n ///\n /// * `context` - One of `PublicContext`/`UtilityContext`. The Context determines\n /// which methods of this struct will be made available to the calling\n /// smart contract function.\n /// * `storage_slot` - A unique identifier for this state variable within the\n /// contract. Usually, the #[storage] macro will determine an\n /// appropriate storage_slot automatically. A smart contract\n /// dev shouldn't have to worry about this, as it's managed\n /// behind the scenes.\n ///\n /// docs:start:public_mutable_struct_new\n pub fn new(\n // Note: Passing the contexts to new(...) just to have an interface compatible with a Map.\n context: Context,\n storage_slot: Field,\n ) -> Self {\n assert(storage_slot != 0, \"Storage slot 0 not allowed. Storage slots must start from 1.\");\n PublicMutable { context, storage_slot }\n }\n}\n\nimpl PublicMutable {\n /// Reads the current value stored in this PublicMutable state variable.\n ///\n /// # Returns\n ///\n /// * `T` - The current value stored in this PublicMutable.\n ///\n /// docs:start:public_mutable_struct_read\n pub fn read(self) -> T\n where\n T: Packable,\n {\n self.context.storage_read(self.storage_slot)\n }\n\n /// Writes a new value to this PublicMutable state variable.\n ///\n /// # Arguments\n ///\n /// * `value` - The new value to store in this PublicMutable.\n ///\n /// # Advanced\n ///\n /// This function updates the value stored in Aztec's public data tree.\n /// The new value becomes immediately available to subsequent reads within\n /// the same transaction.\n ///\n /// docs:start:public_mutable_struct_write\n pub fn write(self, value: T)\n where\n T: Packable,\n {\n self.context.storage_write(self.storage_slot, value);\n }\n}\n\nimpl PublicMutable {\n /// Reads the current value stored in this PublicMutable state variable.\n ///\n /// Notice that this function is executable only within a UtilityContext, which\n /// is an unconstrained environment on the user's local device.\n ///\n /// # Returns\n ///\n /// * `T` - The current value stored in this PublicMutable.\n ///\n pub unconstrained fn read(self) -> T\n where\n T: Packable,\n {\n self.context.storage_read(self.storage_slot)\n }\n}\n"},"210":{"path":"/home/nerses/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.2/noir-projects/aztec-nr/aztec/src/utils/array/append.nr","source":"/// Appends the elements of the second `BoundedVec` to the end of the first one. The resulting `BoundedVec` can have any arbitrary maximum length, but it must be\n/// large enough to fit all of the elements of both the first and second vectors.\npub fn append(\n a: BoundedVec,\n b: BoundedVec,\n) -> BoundedVec {\n let mut dst = BoundedVec::new();\n\n dst.extend_from_bounded_vec(a);\n dst.extend_from_bounded_vec(b);\n\n dst\n}\n\nmod test {\n use super::append;\n\n #[test]\n unconstrained fn append_empty_vecs() {\n let a: BoundedVec<_, 3> = BoundedVec::new();\n let b: BoundedVec<_, 14> = BoundedVec::new();\n\n let result: BoundedVec = append(a, b);\n\n assert_eq(result.len(), 0);\n assert_eq(result.storage(), std::mem::zeroed());\n }\n\n #[test]\n unconstrained fn append_non_empty_vecs() {\n let a: BoundedVec<_, 3> = BoundedVec::from_array([1, 2, 3]);\n let b: BoundedVec<_, 14> = BoundedVec::from_array([4, 5, 6]);\n\n let result: BoundedVec = append(a, b);\n\n assert_eq(result.len(), 6);\n assert_eq(result.storage(), [1, 2, 3, 4, 5, 6, std::mem::zeroed(), std::mem::zeroed()]);\n }\n\n #[test(should_fail_with = \"out of bounds\")]\n unconstrained fn append_non_empty_vecs_insufficient_max_len() {\n let a: BoundedVec<_, 3> = BoundedVec::from_array([1, 2, 3]);\n let b: BoundedVec<_, 14> = BoundedVec::from_array([4, 5, 6]);\n\n let _: BoundedVec = append(a, b);\n }\n}\n"},"213":{"path":"/home/nerses/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.2/noir-projects/aztec-nr/aztec/src/utils/array/subarray.nr","source":"/// Returns `DstLen` elements from a source array, starting at `offset`. `DstLen` must not be larger than the number\n/// of elements past `offset`.\n///\n/// Examples:\n/// ```\n/// let foo: [Field; 2] = subarray([1, 2, 3, 4, 5], 2);\n/// assert_eq(foo, [3, 4]);\n///\n/// let bar: [Field; 5] = subarray([1, 2, 3, 4, 5], 2); // fails - we can't return 5 elements since only 3 remain\n/// ```\npub fn subarray(src: [T; SrcLen], offset: u32) -> [T; DstLen] {\n assert(offset + DstLen <= SrcLen, \"DstLen too large for offset\");\n\n let mut dst: [T; DstLen] = std::mem::zeroed();\n for i in 0..DstLen {\n dst[i] = src[i + offset];\n }\n\n dst\n}\n\nmod test {\n use super::subarray;\n\n #[test]\n unconstrained fn subarray_into_empty() {\n // In all of these cases we're setting DstLen to be 0, so we always get back an empty array.\n assert_eq(subarray::([], 0), []);\n assert_eq(subarray([1, 2, 3, 4, 5], 0), []);\n assert_eq(subarray([1, 2, 3, 4, 5], 2), []);\n }\n\n #[test]\n unconstrained fn subarray_complete() {\n assert_eq(subarray::([], 0), []);\n assert_eq(subarray([1, 2, 3, 4, 5], 0), [1, 2, 3, 4, 5]);\n }\n\n #[test]\n unconstrained fn subarray_different_end_sizes() {\n // We implicitly select how many values to read in the size of the return array\n assert_eq(subarray([1, 2, 3, 4, 5], 1), [2, 3, 4, 5]);\n assert_eq(subarray([1, 2, 3, 4, 5], 1), [2, 3, 4]);\n assert_eq(subarray([1, 2, 3, 4, 5], 1), [2, 3]);\n assert_eq(subarray([1, 2, 3, 4, 5], 1), [2]);\n }\n\n #[test(should_fail_with = \"DstLen too large for offset\")]\n unconstrained fn subarray_offset_too_large() {\n // With an offset of 1 we can only request up to 4 elements\n let _: [_; 5] = subarray([1, 2, 3, 4, 5], 1);\n }\n\n #[test(should_fail)]\n unconstrained fn subarray_bad_return_value() {\n assert_eq(subarray([1, 2, 3, 4, 5], 1), [3, 3, 4, 5]);\n }\n}\n"},"214":{"path":"/home/nerses/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.2/noir-projects/aztec-nr/aztec/src/utils/array/subbvec.nr","source":"use crate::utils::array;\n\n/// Returns `DstMaxLen` elements from a source BoundedVec, starting at `offset`. `offset` must not be larger than the\n/// original length, and `DstLen` must not be larger than the total number of elements past `offset` (including the\n/// zeroed elements past `len()`).\n///\n/// Only elements at the beginning of the vector can be removed: it is not possible to also remove elements at the end\n/// of the vector by passing a value for `DstLen` that is smaller than `len() - offset`.\n///\n/// Examples:\n/// ```\n/// let foo = BoundedVec::<_, 10>::from_array([1, 2, 3, 4, 5]);\n/// assert_eq(subbvec(foo, 2), BoundedVec::<_, 8>::from_array([3, 4, 5]));\n///\n/// let bar: BoundedVec<_, 1> = subbvec(foo, 2); // fails - we can't return just 1 element since 3 remain\n/// let baz: BoundedVec<_, 10> = subbvec(foo, 3); // fails - we can't return 10 elements since only 7 remain\n/// ```\npub fn subbvec(\n bvec: BoundedVec,\n offset: u32,\n) -> BoundedVec {\n // from_parts_unchecked does not verify that the elements past len are zeroed, but that is not an issue in our case\n // because we're constructing the new storage array as a subarray of the original one (which should have zeroed\n // storage past len), guaranteeing correctness. This is because `subarray` does not allow extending arrays past\n // their original length.\n BoundedVec::from_parts_unchecked(array::subarray(bvec.storage(), offset), bvec.len() - offset)\n}\n\nmod test {\n use super::subbvec;\n\n #[test]\n unconstrained fn subbvec_empty() {\n let bvec = BoundedVec::::from_array([]);\n assert_eq(subbvec(bvec, 0), bvec);\n }\n\n #[test]\n unconstrained fn subbvec_complete() {\n let bvec = BoundedVec::<_, 10>::from_array([1, 2, 3, 4, 5]);\n assert_eq(subbvec(bvec, 0), bvec);\n\n let smaller_capacity = BoundedVec::<_, 5>::from_array([1, 2, 3, 4, 5]);\n assert_eq(subbvec(bvec, 0), smaller_capacity);\n }\n\n #[test]\n unconstrained fn subbvec_partial() {\n let bvec = BoundedVec::<_, 10>::from_array([1, 2, 3, 4, 5]);\n\n assert_eq(subbvec(bvec, 2), BoundedVec::<_, 8>::from_array([3, 4, 5]));\n assert_eq(subbvec(bvec, 2), BoundedVec::<_, 3>::from_array([3, 4, 5]));\n }\n\n #[test]\n unconstrained fn subbvec_into_empty() {\n let bvec: BoundedVec<_, 10> = BoundedVec::from_array([1, 2, 3, 4, 5]);\n assert_eq(subbvec(bvec, 5), BoundedVec::<_, 5>::from_array([]));\n }\n\n #[test(should_fail)]\n unconstrained fn subbvec_offset_past_len() {\n let bvec = BoundedVec::<_, 10>::from_array([1, 2, 3, 4, 5]);\n let _: BoundedVec<_, 1> = subbvec(bvec, 6);\n }\n\n #[test(should_fail)]\n unconstrained fn subbvec_insufficient_dst_len() {\n let bvec = BoundedVec::<_, 10>::from_array([1, 2, 3, 4, 5]);\n\n // We're not providing enough space to hold all of the items inside the original BoundedVec. subbvec can cause\n // for the capacity to reduce, but not the length (other than by len - offset).\n let _: BoundedVec<_, 1> = subbvec(bvec, 2);\n }\n\n #[test(should_fail_with = \"DstLen too large for offset\")]\n unconstrained fn subbvec_dst_len_causes_enlarge() {\n let bvec = BoundedVec::<_, 10>::from_array([1, 2, 3, 4, 5]);\n\n // subbvec does not supprt capacity increases\n let _: BoundedVec<_, 11> = subbvec(bvec, 0);\n }\n\n #[test(should_fail_with = \"DstLen too large for offset\")]\n unconstrained fn subbvec_dst_len_too_large_for_offset() {\n let bvec = BoundedVec::<_, 10>::from_array([1, 2, 3, 4, 5]);\n\n // This effectively requests a capacity increase, since there'd be just one element plus the 5 empty slots,\n // which is less than 7.\n let _: BoundedVec<_, 7> = subbvec(bvec, 4);\n }\n}\n"},"216":{"path":"/home/nerses/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.2/noir-projects/aztec-nr/aztec/src/utils/conversion/bytes_to_fields.nr","source":"use std::static_assert;\n\n// These functions are used to facilitate the conversion of log ciphertext between byte and field representations.\n//\n// `bytes_to_fields` uses fixed-size arrays since encryption contexts have compile-time size information.\n// `bytes_from_fields` uses BoundedVec for flexibility in unconstrained contexts where sizes are dynamic.\n//\n// Together they provide bidirectional conversion between bytes and fields when processing encrypted logs.\n\n/// Converts the input bytes into an array of fields. A Field is ~254 bits meaning that each field can store 31 whole\n/// bytes. Use `bytes_from_fields` to obtain the original bytes array.\n///\n/// The input bytes are chunked into chunks of 31 bytes. Each 31-byte chunk is viewed as big-endian, and is converted\n/// into a Field.\n/// For example, [1, 10, 3, ..., 0] (31 bytes) is encoded as [1 * 256^30 + 10 * 256^29 + 3 * 256^28 + ... + 0]\n/// Note: N must be a multiple of 31 bytes\npub fn bytes_to_fields(bytes: [u8; N]) -> [Field; N / 31] {\n // Assert that N is a multiple of 31\n static_assert(N % 31 == 0, \"N must be a multiple of 31\");\n\n let mut fields = [0; N / 31];\n\n // Since N is a multiple of 31, we can simply process all chunks fully\n for i in 0..N / 31 {\n let mut field = 0;\n for j in 0..31 {\n // Shift the existing value left by 8 bits and add the new byte\n field = field * 256 + bytes[i * 31 + j] as Field;\n }\n fields[i] = field;\n }\n\n fields\n}\n\n/// Converts an input BoundedVec of fields into a BoundedVec of bytes in big-endian order. Arbitrary Field arrays\n/// are not allowed: this is assumed to be an array obtained via `bytes_to_fields`, i.e. one that actually represents\n/// bytes. To convert a Field array into bytes, use `fields_to_bytes`.\n///\n/// Each input field must contain at most 31 bytes (this is constrained to be so).\n/// Each field is converted into 31 big-endian bytes, and the resulting 31-byte chunks are concatenated\n/// back together in the order of the original fields.\npub fn bytes_from_fields(fields: BoundedVec) -> BoundedVec {\n let mut bytes = BoundedVec::new();\n\n for i in 0..fields.len() {\n let field = fields.get(i);\n\n // We expect that the field contains at most 31 bytes of information.\n field.assert_max_bit_size::<248>();\n\n // Now we can safely convert the field to 31 bytes.\n let field_as_bytes: [u8; 31] = field.to_be_bytes();\n\n for j in 0..31 {\n bytes.push(field_as_bytes[j]);\n }\n }\n\n bytes\n}\n\nmod tests {\n use crate::utils::array::subarray;\n use super::{bytes_from_fields, bytes_to_fields};\n\n #[test]\n unconstrained fn random_bytes_to_fields_and_back(input: [u8; 93]) {\n let fields = bytes_to_fields(input);\n\n // At this point in production, the log flies through the system and we get a BoundedVec on the other end.\n // So we need to convert the field array to a BoundedVec to be able to feed it to the `bytes_from_fields`\n // function.\n let fields_as_bounded_vec = BoundedVec::<_, 6>::from_array(fields);\n\n let bytes_back = bytes_from_fields(fields_as_bounded_vec);\n\n // Compare the original input with the round-tripped result\n assert_eq(bytes_back.len(), input.len());\n assert_eq(subarray(bytes_back.storage(), 0), input);\n }\n\n #[test(should_fail_with = \"N must be a multiple of 31\")]\n unconstrained fn bytes_to_fields_input_length_not_multiple_of_31() {\n // Try to convert 32 bytes (not a multiple of 31) to fields\n let _fields = bytes_to_fields([0; 32]);\n }\n\n}\n"},"217":{"path":"/home/nerses/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.2/noir-projects/aztec-nr/aztec/src/utils/conversion/fields_to_bytes.nr","source":"// These functions are used to facilitate the conversion of log plaintext represented as fields into bytes and back.\n//\n// `fields_to_bytes` uses fixed-size arrays since encryption contexts have compile-time size information.\n// `fields_from_bytes` uses BoundedVec for flexibility in unconstrained contexts where sizes are dynamic.\n//\n// Together they provide bidirectional conversion between fields and bytes.\n\n/// Converts an input array of fields into a single array of bytes. Use `fields_from_bytes` to obtain the original\n/// field array.\n/// Each field is converted to a 32-byte big-endian array.\n///\n/// For example, if you have a field array [123, 456], it will be converted to a 64-byte array:\n/// [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,123, // First field (32 bytes)\n/// 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,200] // Second field (32 bytes)\n///\n/// Since a field is ~254 bits, you'll end up with a subtle 2-bit \"gap\" at the big end, every 32 bytes. Be careful\n/// that such a gap doesn't leak information! This could happen if you for example expected the output to be\n/// indistinguishable from random bytes.\npub fn fields_to_bytes(fields: [Field; N]) -> [u8; 32 * N] {\n let mut bytes = [0; 32 * N];\n\n for i in 0..N {\n let field_as_bytes: [u8; 32] = fields[i].to_be_bytes();\n\n for j in 0..32 {\n bytes[i * 32 + j] = field_as_bytes[j];\n }\n }\n\n bytes\n}\n\n/// Converts an input BoundedVec of bytes into a BoundedVec of fields. Arbitrary byte arrays are not allowed: this\n/// is assumed to be an array obtained via `fields_to_bytes`, i.e. one that actually represents fields. To convert\n/// a byte array into Fields, use `bytes_to_fields`.\n///\n/// The input bytes are chunked into chunks of 32 bytes. Each 32-byte chunk is viewed as big-endian, and is converted\n/// into a Field.\n/// For example, [1, 10, 3, ..., 0] (32 bytes) is encoded as [1 * 256^31 + 10 * 256^30 + 3 * 256^29 + ... + 0]\n/// Note 1: N must be a multiple of 32 bytes\n/// Note 2: The max value check code was taken from std::field::to_be_bytes function.\npub fn fields_from_bytes(bytes: BoundedVec) -> BoundedVec {\n // Assert that input length is a multiple of 32\n assert(bytes.len() % 32 == 0, \"Input length must be a multiple of 32\");\n\n let mut fields = BoundedVec::new();\n\n let p = std::field::modulus_be_bytes();\n\n // Since input length is a multiple of 32, we can simply process all chunks fully\n for i in 0..bytes.len() / 32 {\n let mut field = 0;\n\n // Process each byte in the 32-byte chunk\n let mut ok = false;\n\n for j in 0..32 {\n let next_byte = bytes.get(i * 32 + j);\n field = field * 256 + next_byte as Field;\n\n if !ok {\n if next_byte != p[j] {\n assert(next_byte < p[j], \"Value does not fit in field\");\n ok = true;\n }\n }\n }\n assert(ok, \"Value does not fit in field\");\n\n fields.push(field);\n }\n\n fields\n}\n\nmod tests {\n use crate::utils::array::subarray;\n use super::{fields_from_bytes, fields_to_bytes};\n\n #[test]\n unconstrained fn random_fields_to_bytes_and_back(input: [Field; 3]) {\n // Convert to bytes\n let bytes = fields_to_bytes(input);\n\n // At this point in production, the log flies through the system and we get a BoundedVec on the other end.\n // So we need to convert the field array to a BoundedVec to be able to feed it to the `fields_from_bytes`\n // function.\n // 113 is an arbitrary max length that is larger than the input length of 96.\n let bytes_as_bounded_vec = BoundedVec::<_, 113>::from_array(bytes);\n\n // Convert back to fields\n let fields_back = fields_from_bytes(bytes_as_bounded_vec);\n\n // Compare the original input with the round-tripped result\n assert_eq(fields_back.len(), input.len());\n assert_eq(subarray(fields_back.storage(), 0), input);\n }\n\n #[test(should_fail_with = \"Input length must be a multiple of 32\")]\n unconstrained fn to_fields_assert() {\n // 143 is an arbitrary max length that is larger than 33\n let input = BoundedVec::<_, 143>::from_array([\n 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,\n 25, 26, 27, 28, 29, 30, 31, 32, 33,\n ]);\n\n // This should fail since 33 is not a multiple of 32\n let _fields = fields_from_bytes(input);\n }\n\n #[test]\n unconstrained fn fields_from_bytes_max_value() {\n let max_field_as_bytes: [u8; 32] = (-1).to_be_bytes();\n let input = BoundedVec::<_, 32>::from_array(max_field_as_bytes);\n\n let fields = fields_from_bytes(input);\n\n // The result should be a largest value storable in a field (-1 since we are modulo-ing)\n assert_eq(fields.get(0), -1);\n }\n\n // In this test we verify that overflow check works by taking the max allowed value, bumping a random byte\n // and then feeding it to `fields_from_bytes` as input.\n #[test(should_fail_with = \"Value does not fit in field\")]\n unconstrained fn fields_from_bytes_overflow(random_value: u8) {\n let index_of_byte_to_bump = random_value % 32;\n\n // Obtain the byte representation of the maximum field value\n let max_field_value_as_bytes: [u8; 32] = (-1).to_be_bytes();\n\n let byte_to_bump = max_field_value_as_bytes[index_of_byte_to_bump as u32];\n\n // Skip test execution if the selected byte is already at maximum value (255).\n // This is acceptable since we are using fuzz testing to generate many test cases.\n if byte_to_bump != 255 {\n let mut input = BoundedVec::<_, 32>::from_array(max_field_value_as_bytes);\n\n // Increment the selected byte to exceed the field's maximum value\n input.set(index_of_byte_to_bump as u32, byte_to_bump + 1);\n\n // Attempt the conversion, which should fail due to the value exceeding the field's capacity\n let _fields = fields_from_bytes(input);\n }\n }\n\n}\n"},"220":{"path":"/home/nerses/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.2/noir-projects/aztec-nr/aztec/src/utils/point.nr","source":"use protocol_types::{point::Point, utils::field::sqrt};\n\n// I am storing the modulus minus 1 divided by 2 here because full modulus would throw \"String literal too large\" error\n// Full modulus is 21888242871839275222246405745257275088548364400416034343698204186575808495617\nglobal BN254_FR_MODULUS_DIV_2: Field =\n 10944121435919637611123202872628637544274182200208017171849102093287904247808;\n\n/// Converts a point to a byte array.\n///\n/// We don't serialize the point at infinity flag because this function is used in situations where we do not want\n/// to waste the extra byte (encrypted log).\npub fn point_to_bytes(p: Point) -> [u8; 32] {\n // Note that there is 1 more free bit in the 32 bytes (254 bits currently occupied by the x coordinate, 1 bit for\n // the \"sign\") so it's possible to use that last bit as an \"is_infinite\" flag if desired in the future.\n assert(!p.is_infinite, \"Cannot serialize point at infinity as bytes.\");\n\n let mut result: [u8; 32] = p.x.to_be_bytes();\n\n if get_sign_of_point(p) {\n // y is <= (modulus - 1) / 2 so we set the sign bit to 1\n // Here we leverage that field fits into 254 bits (log2(Fr.MODULUS) < 254) and given that we serialize Fr to 32\n // bytes and we use big-endian the 2 most significant bits are never populated. Hence we can use one of\n // the bits as a sign bit.\n result[0] += 128;\n }\n\n result\n}\n\n/**\n * Returns: true if p.y <= MOD_DIV_2, else false.\n */\npub fn get_sign_of_point(p: Point) -> bool {\n // We store only a \"sign\" of the y coordinate because the rest can be derived from the x coordinate. To get\n // the sign we check if the y coordinate is less or equal than the curve's order minus 1 divided by 2.\n // Ideally we'd do `y <= MOD_DIV_2`, but there's no `lte` function, so instead we do `!(y > MOD_DIV_2)`, which is\n // equivalent, and then rewrite that as `!(MOD_DIV_2 < y)`, since we also have no `gt` function.\n !BN254_FR_MODULUS_DIV_2.lt(p.y)\n}\n\n/// Returns a `Point` in the Grumpkin curve given its x coordinate.\n///\n/// Because not all values in the field are valid x coordinates of points in the curve (i.e. there\n/// is no corresponding y value in the field that satisfies the curve equation), it may not be\n/// possible to reconstruct a `Point`. `Option::none()` is returned in such cases.\npub fn point_from_x_coord(x: Field) -> Option {\n // y ^ 2 = x ^ 3 - 17\n let rhs = x * x * x - 17;\n sqrt(rhs).map(|y| Point { x, y, is_infinite: false })\n}\n\n/// Returns a `Point` in the Grumpkin curve given its x coordinate and sign for the y coordinate.\n///\n/// Because not all values in the field are valid x coordinates of points in the curve (i.e. there\n/// is no corresponding y value in the field that satisfies the curve equation), it may not be\n/// possible to reconstruct a `Point`. `Option::none()` is returned in such cases.\n///\n/// @param x - The x coordinate of the point\n/// @param sign - The \"sign\" of the y coordinate - determines whether y <= (Fr.MODULUS - 1) / 2\npub fn point_from_x_coord_and_sign(x: Field, sign: bool) -> Option {\n // y ^ 2 = x ^ 3 - 17\n let rhs = x * x * x - 17;\n\n sqrt(rhs).map(|y| {\n // If there is a square root, we need to ensure it has the correct \"sign\"\n let y_is_positive = !BN254_FR_MODULUS_DIV_2.lt(y);\n let final_y = if y_is_positive == sign { y } else { -y };\n Point { x, y: final_y, is_infinite: false }\n })\n}\n\nmod test {\n use crate::utils::point::{point_from_x_coord, point_from_x_coord_and_sign, point_to_bytes};\n use dep::protocol_types::point::Point;\n use dep::protocol_types::utils::field::pow;\n\n #[test]\n unconstrained fn test_point_to_bytes_positive_sign() {\n let p = Point {\n x: 0x1af41f5de96446dc3776a1eb2d98bb956b7acd9979a67854bec6fa7c2973bd73,\n y: 0x07fc22c7f2c7057571f137fe46ea9c95114282bc95d37d71ec4bfb88de457d4a,\n is_infinite: false,\n };\n\n let compressed_point = point_to_bytes(p);\n\n let expected_compressed_point_positive_sign = [\n 154, 244, 31, 93, 233, 100, 70, 220, 55, 118, 161, 235, 45, 152, 187, 149, 107, 122,\n 205, 153, 121, 166, 120, 84, 190, 198, 250, 124, 41, 115, 189, 115,\n ];\n assert_eq(expected_compressed_point_positive_sign, compressed_point);\n }\n\n #[test]\n unconstrained fn test_point_to_bytes_negative_sign() {\n let p = Point {\n x: 0x247371652e55dd74c9af8dbe9fb44931ba29a9229994384bd7077796c14ee2b5,\n y: 0x26441aec112e1ae4cee374f42556932001507ad46e255ffb27369c7e3766e5c0,\n is_infinite: false,\n };\n\n let compressed_point = point_to_bytes(p);\n\n let expected_compressed_point_negative_sign = [\n 36, 115, 113, 101, 46, 85, 221, 116, 201, 175, 141, 190, 159, 180, 73, 49, 186, 41, 169,\n 34, 153, 148, 56, 75, 215, 7, 119, 150, 193, 78, 226, 181,\n ];\n\n assert_eq(expected_compressed_point_negative_sign, compressed_point);\n }\n\n #[test]\n unconstrained fn test_point_from_x_coord_and_sign() {\n // Test positive y coordinate\n let x = 0x1af41f5de96446dc3776a1eb2d98bb956b7acd9979a67854bec6fa7c2973bd73;\n let sign = true;\n let p = point_from_x_coord_and_sign(x, sign).unwrap();\n\n assert_eq(p.x, x);\n assert_eq(p.y, 0x07fc22c7f2c7057571f137fe46ea9c95114282bc95d37d71ec4bfb88de457d4a);\n assert_eq(p.is_infinite, false);\n\n // Test negative y coordinate\n let x2 = 0x247371652e55dd74c9af8dbe9fb44931ba29a9229994384bd7077796c14ee2b5;\n let sign2 = false;\n let p2 = point_from_x_coord_and_sign(x2, sign2).unwrap();\n\n assert_eq(p2.x, x2);\n assert_eq(p2.y, 0x26441aec112e1ae4cee374f42556932001507ad46e255ffb27369c7e3766e5c0);\n assert_eq(p2.is_infinite, false);\n }\n\n #[test]\n unconstrained fn test_point_from_x_coord_valid() {\n // x = 8 is a known quadratic residue - should give a valid point\n let result = point_from_x_coord(Field::from(8));\n assert(result.is_some());\n\n let point = result.unwrap();\n assert_eq(point.x, Field::from(8));\n // Check curve equation y^2 = x^3 - 17\n assert_eq(pow(point.y, 2), pow(point.x, 3) - 17);\n }\n\n #[test]\n unconstrained fn test_point_from_x_coord_invalid() {\n // x = 3 is a non-residue for this curve - should give None\n let x = Field::from(3);\n let maybe_point = point_from_x_coord(x);\n assert(maybe_point.is_none());\n }\n\n}\n"},"231":{"path":"/home/nerses/nargo/github.com/noir-lang/poseidon/v0.1.1/src/poseidon2.nr","source":"use std::default::Default;\nuse std::hash::Hasher;\n\ncomptime global RATE: u32 = 3;\n\npub struct Poseidon2 {\n cache: [Field; 3],\n state: [Field; 4],\n cache_size: u32,\n squeeze_mode: bool, // 0 => absorb, 1 => squeeze\n}\n\nimpl Poseidon2 {\n #[no_predicates]\n pub fn hash(input: [Field; N], message_size: u32) -> Field {\n Poseidon2::hash_internal(input, message_size, message_size != N)\n }\n\n pub(crate) fn new(iv: Field) -> Poseidon2 {\n let mut result =\n Poseidon2 { cache: [0; 3], state: [0; 4], cache_size: 0, squeeze_mode: false };\n result.state[RATE] = iv;\n result\n }\n\n fn perform_duplex(&mut self) {\n // add the cache into sponge state\n for i in 0..RATE {\n // We effectively zero-pad the cache by only adding to the state\n // cache that is less than the specified `cache_size`\n if i < self.cache_size {\n self.state[i] += self.cache[i];\n }\n }\n self.state = crate::poseidon2_permutation(self.state, 4);\n }\n\n fn absorb(&mut self, input: Field) {\n assert(!self.squeeze_mode);\n if self.cache_size == RATE {\n // If we're absorbing, and the cache is full, apply the sponge permutation to compress the cache\n self.perform_duplex();\n self.cache[0] = input;\n self.cache_size = 1;\n } else {\n // If we're absorbing, and the cache is not full, add the input into the cache\n self.cache[self.cache_size] = input;\n self.cache_size += 1;\n }\n }\n\n fn squeeze(&mut self) -> Field {\n assert(!self.squeeze_mode);\n // If we're in absorb mode, apply sponge permutation to compress the cache.\n self.perform_duplex();\n self.squeeze_mode = true;\n\n // Pop one item off the top of the permutation and return it.\n self.state[0]\n }\n\n fn hash_internal(\n input: [Field; N],\n in_len: u32,\n is_variable_length: bool,\n ) -> 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\npub struct Poseidon2Hasher {\n _state: [Field],\n}\n\nimpl Hasher for Poseidon2Hasher {\n fn finish(self) -> Field {\n let iv: Field = (self._state.len() as Field) * 18446744073709551616; // iv = (self._state.len() << 64)\n let mut sponge = Poseidon2::new(iv);\n for i in 0..self._state.len() {\n sponge.absorb(self._state[i]);\n }\n sponge.squeeze()\n }\n\n fn write(&mut self, input: Field) {\n self._state = self._state.push_back(input);\n }\n}\n\nimpl Default for Poseidon2Hasher {\n fn default() -> Self {\n Poseidon2Hasher { _state: &[] }\n }\n}\n"},"25":{"path":"std/meta/expr.nr","source":"//! Contains methods on the built-in `Expr` type for quoted, syntactically valid expressions.\n\nuse crate::meta::op::BinaryOp;\nuse crate::meta::op::UnaryOp;\nuse crate::option::Option;\n\nimpl Expr {\n /// If this expression is an array literal `[elem1, ..., elemN]`, this returns a slice of each element in the array.\n #[builtin(expr_as_array)]\n // docs:start:as_array\n pub comptime fn as_array(self) -> Option<[Expr]> {}\n // docs:end:as_array\n\n /// If this expression is an assert, this returns the assert expression and the optional message.\n #[builtin(expr_as_assert)]\n // docs:start:as_assert\n pub comptime fn as_assert(self) -> Option<(Expr, Option)> {}\n // docs:end:as_assert\n\n /// If this expression is an assert_eq, this returns the left-hand-side and right-hand-side\n /// expressions, together with the optional message.\n #[builtin(expr_as_assert_eq)]\n // docs:start:as_assert_eq\n pub comptime fn as_assert_eq(self) -> Option<(Expr, Expr, Option)> {}\n // docs:end:as_assert_eq\n\n /// If this expression is an assignment, this returns a tuple with the left hand side\n /// and right hand side in order.\n #[builtin(expr_as_assign)]\n // docs:start:as_assign\n pub comptime fn as_assign(self) -> Option<(Expr, Expr)> {}\n // docs:end:as_assign\n\n /// If this expression is a binary operator operation ` `,\n /// return the left-hand side, operator, and the right-hand side of the operation.\n #[builtin(expr_as_binary_op)]\n // docs:start:as_binary_op\n pub comptime fn as_binary_op(self) -> Option<(Expr, BinaryOp, Expr)> {}\n // docs:end:as_binary_op\n\n /// If this expression is a block `{ stmt1; stmt2; ...; stmtN }`, return\n /// a slice containing each statement.\n #[builtin(expr_as_block)]\n // docs:start:as_block\n pub comptime fn as_block(self) -> Option<[Expr]> {}\n // docs:end:as_block\n\n /// If this expression is a boolean literal, return that literal.\n #[builtin(expr_as_bool)]\n // docs:start:as_bool\n pub comptime fn as_bool(self) -> Option {}\n // docs:end:as_bool\n\n /// If this expression is a cast expression `expr as type`, returns the casted\n /// expression and the type to cast to.\n // docs:start:as_cast\n #[builtin(expr_as_cast)]\n pub comptime fn as_cast(self) -> Option<(Expr, UnresolvedType)> {}\n // docs:end:as_cast\n\n /// If this expression is a `comptime { stmt1; stmt2; ...; stmtN }` block,\n /// return each statement in the block.\n #[builtin(expr_as_comptime)]\n // docs:start:as_comptime\n pub comptime fn as_comptime(self) -> Option<[Expr]> {}\n // docs:end:as_comptime\n\n /// If this expression is a constructor `Type { field1: expr1, ..., fieldN: exprN }`,\n /// return the type and the fields.\n #[builtin(expr_as_constructor)]\n // docs:start:as_constructor\n pub comptime fn as_constructor(self) -> Option<(UnresolvedType, [(Quoted, Expr)])> {}\n // docs:end:as_constructor\n\n /// If this expression is a for statement over a single expression, return the identifier,\n /// the expression and the for loop body.\n #[builtin(expr_as_for)]\n // docs:start:as_for\n pub comptime fn as_for(self) -> Option<(Quoted, Expr, Expr)> {}\n // docs:end:as_for\n\n /// If this expression is a for statement over a range, return the identifier,\n /// the range start, the range end and the for loop body.\n #[builtin(expr_as_for_range)]\n // docs:start:as_for_range\n pub comptime fn as_for_range(self) -> Option<(Quoted, Expr, Expr, Expr)> {}\n // docs:end:as_for_range\n\n /// If this expression is a function call `foo(arg1, ..., argN)`, return\n /// the function and a slice of each argument.\n #[builtin(expr_as_function_call)]\n // docs:start:as_function_call\n pub comptime fn as_function_call(self) -> Option<(Expr, [Expr])> {}\n // docs:end:as_function_call\n\n /// If this expression is an `if condition { then_branch } else { else_branch }`,\n /// return the condition, then branch, and else branch. If there is no else branch,\n /// `None` is returned for that branch instead.\n #[builtin(expr_as_if)]\n // docs:start:as_if\n pub comptime fn as_if(self) -> Option<(Expr, Expr, Option)> {}\n // docs:end:as_if\n\n /// If this expression is an index into an array `array[index]`, return the\n /// array and the index.\n #[builtin(expr_as_index)]\n // docs:start:as_index\n pub comptime fn as_index(self) -> Option<(Expr, Expr)> {}\n // docs:end:as_index\n\n /// If this expression is an integer literal, return the integer as a field\n /// as well as whether the integer is negative (true) or not (false).\n #[builtin(expr_as_integer)]\n // docs:start:as_integer\n pub comptime fn as_integer(self) -> Option<(Field, bool)> {}\n // docs:end:as_integer\n\n /// If this expression is a lambda, returns the parameters, return type and body.\n #[builtin(expr_as_lambda)]\n // docs:start:as_lambda\n pub comptime fn as_lambda(\n self,\n ) -> Option<([(Expr, Option)], Option, Expr)> {}\n // docs:end:as_lambda\n\n /// If this expression is a let statement, returns the let pattern as an `Expr`,\n /// the optional type annotation, and the assigned expression.\n #[builtin(expr_as_let)]\n // docs:start:as_let\n pub comptime fn as_let(self) -> Option<(Expr, Option, Expr)> {}\n // docs:end:as_let\n\n /// If this expression is a member access `foo.bar`, return the struct/tuple\n /// expression and the field. The field will be represented as a quoted value.\n #[builtin(expr_as_member_access)]\n // docs:start:as_member_access\n pub comptime fn as_member_access(self) -> Option<(Expr, Quoted)> {}\n // docs:end:as_member_access\n\n /// If this expression is a method call `foo.bar::(arg1, ..., argN)`, return\n /// the receiver, method name, a slice of each generic argument, and a slice of each argument.\n #[builtin(expr_as_method_call)]\n // docs:start:as_method_call\n pub comptime fn as_method_call(self) -> Option<(Expr, Quoted, [UnresolvedType], [Expr])> {}\n // docs:end:as_method_call\n\n /// If this expression is a repeated element array `[elem; length]`, return\n /// the repeated element and the length expressions.\n #[builtin(expr_as_repeated_element_array)]\n // docs:start:as_repeated_element_array\n pub comptime fn as_repeated_element_array(self) -> Option<(Expr, Expr)> {}\n // docs:end:as_repeated_element_array\n\n /// If this expression is a repeated element slice `[elem; length]`, return\n /// the repeated element and the length expressions.\n #[builtin(expr_as_repeated_element_slice)]\n // docs:start:as_repeated_element_slice\n pub comptime fn as_repeated_element_slice(self) -> Option<(Expr, Expr)> {}\n // docs:end:as_repeated_element_slice\n\n /// If this expression is a slice literal `&[elem1, ..., elemN]`,\n /// return each element of the slice.\n #[builtin(expr_as_slice)]\n // docs:start:as_slice\n pub comptime fn as_slice(self) -> Option<[Expr]> {}\n // docs:end:as_slice\n\n /// If this expression is a tuple `(field1, ..., fieldN)`,\n /// return each element of the tuple.\n #[builtin(expr_as_tuple)]\n // docs:start:as_tuple\n pub comptime fn as_tuple(self) -> Option<[Expr]> {}\n // docs:end:as_tuple\n\n /// If this expression is a unary operation ` `,\n /// return the unary operator as well as the right-hand side expression.\n #[builtin(expr_as_unary_op)]\n // docs:start:as_unary_op\n pub comptime fn as_unary_op(self) -> Option<(UnaryOp, Expr)> {}\n // docs:end:as_unary_op\n\n /// If this expression is an `unsafe { stmt1; ...; stmtN }` block,\n /// return each statement inside in a slice.\n #[builtin(expr_as_unsafe)]\n // docs:start:as_unsafe\n pub comptime fn as_unsafe(self) -> Option<[Expr]> {}\n // docs:end:as_unsafe\n\n /// Returns `true` if this expression is trailed by a semicolon.\n ///\n /// Example:\n ///\n /// ```noir\n /// comptime {\n /// let expr1 = quote { 1 + 2 }.as_expr().unwrap();\n /// let expr2 = quote { 1 + 2; }.as_expr().unwrap();\n ///\n /// assert(expr1.as_binary_op().is_some());\n /// assert(expr2.as_binary_op().is_some());\n ///\n /// assert(!expr1.has_semicolon());\n /// assert(expr2.has_semicolon());\n /// }\n /// ```\n #[builtin(expr_has_semicolon)]\n // docs:start:has_semicolon\n pub comptime fn has_semicolon(self) -> bool {}\n // docs:end:has_semicolon\n\n /// Returns `true` if this expression is `break`.\n #[builtin(expr_is_break)]\n // docs:start:is_break\n pub comptime fn is_break(self) -> bool {}\n // docs:end:is_break\n\n /// Returns `true` if this expression is `continue`.\n #[builtin(expr_is_continue)]\n // docs:start:is_continue\n pub comptime fn is_continue(self) -> bool {}\n // docs:end:is_continue\n\n /// Applies a mapping function to this expression and to all of its sub-expressions.\n /// `f` will be applied to each sub-expression first, then applied to the expression itself.\n ///\n /// This happens recursively for every expression within `self`.\n ///\n /// For example, calling `modify` on `(&[1], &[2, 3])` with an `f` that returns `Option::some`\n /// for expressions that are integers, doubling them, would return `(&[2], &[4, 6])`.\n // docs:start:modify\n pub comptime fn modify(self, f: fn[Env](Expr) -> Option) -> Expr {\n // docs:end:modify\n let result = modify_array(self, f);\n let result = result.or_else(|| modify_assert(self, f));\n let result = result.or_else(|| modify_assert_eq(self, f));\n let result = result.or_else(|| modify_assign(self, f));\n let result = result.or_else(|| modify_binary_op(self, f));\n let result = result.or_else(|| modify_block(self, f));\n let result = result.or_else(|| modify_cast(self, f));\n let result = result.or_else(|| modify_comptime(self, f));\n let result = result.or_else(|| modify_constructor(self, f));\n let result = result.or_else(|| modify_if(self, f));\n let result = result.or_else(|| modify_index(self, f));\n let result = result.or_else(|| modify_for(self, f));\n let result = result.or_else(|| modify_for_range(self, f));\n let result = result.or_else(|| modify_lambda(self, f));\n let result = result.or_else(|| modify_let(self, f));\n let result = result.or_else(|| modify_function_call(self, f));\n let result = result.or_else(|| modify_member_access(self, f));\n let result = result.or_else(|| modify_method_call(self, f));\n let result = result.or_else(|| modify_repeated_element_array(self, f));\n let result = result.or_else(|| modify_repeated_element_slice(self, f));\n let result = result.or_else(|| modify_slice(self, f));\n let result = result.or_else(|| modify_tuple(self, f));\n let result = result.or_else(|| modify_unary_op(self, f));\n let result = result.or_else(|| modify_unsafe(self, f));\n if result.is_some() {\n let result = result.unwrap_unchecked();\n let modified = f(result);\n modified.unwrap_or(result)\n } else {\n f(self).unwrap_or(self)\n }\n }\n\n /// Returns this expression as a `Quoted` value. It's the same as `quote { $self }`.\n // docs:start:quoted\n pub comptime fn quoted(self) -> Quoted {\n // docs:end:quoted\n quote { $self }\n }\n\n /// Resolves and type-checks this expression and returns the result as a `TypedExpr`.\n ///\n /// The `in_function` argument specifies where the expression is resolved:\n /// - If it's `none`, the expression is resolved in the function where `resolve` was called\n /// - If it's `some`, the expression is resolved in the given function\n ///\n /// If any names used by this expression are not in scope or if there are any type errors,\n /// this will give compiler errors as if the expression was written directly into\n /// the current `comptime` function.\n #[builtin(expr_resolve)]\n // docs:start:resolve\n pub comptime fn resolve(self, in_function: Option) -> TypedExpr {}\n // docs:end:resolve\n}\n\ncomptime fn modify_array(expr: Expr, f: fn[Env](Expr) -> Option) -> Option {\n expr.as_array().map(|exprs| {\n let exprs = modify_expressions(exprs, f);\n new_array(exprs)\n })\n}\n\ncomptime fn modify_assert(expr: Expr, f: fn[Env](Expr) -> Option) -> Option {\n expr.as_assert().map(|(predicate, msg)| {\n let predicate = predicate.modify(f);\n let msg = msg.map(|msg| msg.modify(f));\n new_assert(predicate, msg)\n })\n}\n\ncomptime fn modify_assert_eq(expr: Expr, f: fn[Env](Expr) -> Option) -> Option {\n expr.as_assert_eq().map(|(lhs, rhs, msg)| {\n let lhs = lhs.modify(f);\n let rhs = rhs.modify(f);\n let msg = msg.map(|msg| msg.modify(f));\n new_assert_eq(lhs, rhs, msg)\n })\n}\n\ncomptime fn modify_assign(expr: Expr, f: fn[Env](Expr) -> Option) -> Option {\n expr.as_assign().map(|expr| {\n let (lhs, rhs) = expr;\n let lhs = lhs.modify(f);\n let rhs = rhs.modify(f);\n new_assign(lhs, rhs)\n })\n}\n\ncomptime fn modify_binary_op(expr: Expr, f: fn[Env](Expr) -> Option) -> Option {\n expr.as_binary_op().map(|(lhs, op, rhs)| {\n let lhs = lhs.modify(f);\n let rhs = rhs.modify(f);\n new_binary_op(lhs, op, rhs)\n })\n}\n\ncomptime fn modify_block(expr: Expr, f: fn[Env](Expr) -> Option) -> Option {\n expr.as_block().map(|exprs| {\n let exprs = modify_expressions(exprs, f);\n new_block(exprs)\n })\n}\n\ncomptime fn modify_cast(expr: Expr, f: fn[Env](Expr) -> Option) -> Option {\n expr.as_cast().map(|(expr, typ)| {\n let expr = expr.modify(f);\n new_cast(expr, typ)\n })\n}\n\ncomptime fn modify_comptime(expr: Expr, f: fn[Env](Expr) -> Option) -> Option {\n expr.as_comptime().map(|exprs| {\n let exprs = exprs.map(|expr| expr.modify(f));\n new_comptime(exprs)\n })\n}\n\ncomptime fn modify_constructor(expr: Expr, f: fn[Env](Expr) -> Option) -> Option {\n expr.as_constructor().map(|(typ, fields)| {\n let fields = fields.map(|(name, value)| (name, value.modify(f)));\n new_constructor(typ, fields)\n })\n}\n\ncomptime fn modify_function_call(\n expr: Expr,\n f: fn[Env](Expr) -> Option,\n) -> Option {\n expr.as_function_call().map(|(function, arguments)| {\n let function = function.modify(f);\n let arguments = arguments.map(|arg| arg.modify(f));\n new_function_call(function, arguments)\n })\n}\n\ncomptime fn modify_if(expr: Expr, f: fn[Env](Expr) -> Option) -> Option {\n expr.as_if().map(|(condition, consequence, alternative)| {\n let condition = condition.modify(f);\n let consequence = consequence.modify(f);\n let alternative = alternative.map(|alternative| alternative.modify(f));\n new_if(condition, consequence, alternative)\n })\n}\n\ncomptime fn modify_index(expr: Expr, f: fn[Env](Expr) -> Option) -> Option {\n expr.as_index().map(|(object, index)| {\n let object = object.modify(f);\n let index = index.modify(f);\n new_index(object, index)\n })\n}\n\ncomptime fn modify_for(expr: Expr, f: fn[Env](Expr) -> Option) -> Option {\n expr.as_for().map(|(identifier, array, body)| {\n let array = array.modify(f);\n let body = body.modify(f);\n new_for(identifier, array, body)\n })\n}\n\ncomptime fn modify_for_range(expr: Expr, f: fn[Env](Expr) -> Option) -> Option {\n expr.as_for_range().map(|(identifier, from, to, body)| {\n let from = from.modify(f);\n let to = to.modify(f);\n let body = body.modify(f);\n new_for_range(identifier, from, to, body)\n })\n}\n\ncomptime fn modify_lambda(expr: Expr, f: fn[Env](Expr) -> Option) -> Option {\n expr.as_lambda().map(|(params, return_type, body)| {\n let params = params.map(|(name, typ)| (name.modify(f), typ));\n let body = body.modify(f);\n new_lambda(params, return_type, body)\n })\n}\n\ncomptime fn modify_let(expr: Expr, f: fn[Env](Expr) -> Option) -> Option {\n expr.as_let().map(|(pattern, typ, expr)| {\n let pattern = pattern.modify(f);\n let expr = expr.modify(f);\n new_let(pattern, typ, expr)\n })\n}\n\ncomptime fn modify_member_access(\n expr: Expr,\n f: fn[Env](Expr) -> Option,\n) -> Option {\n expr.as_member_access().map(|(object, name)| {\n let object = object.modify(f);\n new_member_access(object, name)\n })\n}\n\ncomptime fn modify_method_call(expr: Expr, f: fn[Env](Expr) -> Option) -> Option {\n expr.as_method_call().map(|(object, name, generics, arguments)| {\n let object = object.modify(f);\n let arguments = arguments.map(|arg| arg.modify(f));\n new_method_call(object, name, generics, arguments)\n })\n}\n\ncomptime fn modify_repeated_element_array(\n expr: Expr,\n f: fn[Env](Expr) -> Option,\n) -> Option {\n expr.as_repeated_element_array().map(|(expr, length)| {\n let expr = expr.modify(f);\n let length = length.modify(f);\n new_repeated_element_array(expr, length)\n })\n}\n\ncomptime fn modify_repeated_element_slice(\n expr: Expr,\n f: fn[Env](Expr) -> Option,\n) -> Option {\n expr.as_repeated_element_slice().map(|(expr, length)| {\n let expr = expr.modify(f);\n let length = length.modify(f);\n new_repeated_element_slice(expr, length)\n })\n}\n\ncomptime fn modify_slice(expr: Expr, f: fn[Env](Expr) -> Option) -> Option {\n expr.as_slice().map(|exprs| {\n let exprs = modify_expressions(exprs, f);\n new_slice(exprs)\n })\n}\n\ncomptime fn modify_tuple(expr: Expr, f: fn[Env](Expr) -> Option) -> Option {\n expr.as_tuple().map(|exprs| {\n let exprs = modify_expressions(exprs, f);\n new_tuple(exprs)\n })\n}\n\ncomptime fn modify_unary_op(expr: Expr, f: fn[Env](Expr) -> Option) -> Option {\n expr.as_unary_op().map(|(op, rhs)| {\n let rhs = rhs.modify(f);\n new_unary_op(op, rhs)\n })\n}\n\ncomptime fn modify_unsafe(expr: Expr, f: fn[Env](Expr) -> Option) -> Option {\n expr.as_unsafe().map(|exprs| {\n let exprs = exprs.map(|expr| expr.modify(f));\n new_unsafe(exprs)\n })\n}\n\ncomptime fn modify_expressions(exprs: [Expr], f: fn[Env](Expr) -> Option) -> [Expr] {\n exprs.map(|expr| expr.modify(f))\n}\n\ncomptime fn new_array(exprs: [Expr]) -> Expr {\n let exprs = join_expressions(exprs, quote { , });\n quote { [$exprs]}.as_expr().unwrap()\n}\n\ncomptime fn new_assert(predicate: Expr, msg: Option) -> Expr {\n if msg.is_some() {\n let msg = msg.unwrap();\n quote { assert($predicate, $msg) }.as_expr().unwrap()\n } else {\n quote { assert($predicate) }.as_expr().unwrap()\n }\n}\n\ncomptime fn new_assert_eq(lhs: Expr, rhs: Expr, msg: Option) -> Expr {\n if msg.is_some() {\n let msg = msg.unwrap();\n quote { assert_eq($lhs, $rhs, $msg) }.as_expr().unwrap()\n } else {\n quote { assert_eq($lhs, $rhs) }.as_expr().unwrap()\n }\n}\n\ncomptime fn new_assign(lhs: Expr, rhs: Expr) -> Expr {\n quote { $lhs = $rhs }.as_expr().unwrap()\n}\n\ncomptime fn new_binary_op(lhs: Expr, op: BinaryOp, rhs: Expr) -> Expr {\n let op = op.quoted();\n quote { ($lhs) $op ($rhs) }.as_expr().unwrap()\n}\n\ncomptime fn new_block(exprs: [Expr]) -> Expr {\n let exprs = join_expressions(exprs, quote { ; });\n quote { { $exprs }}.as_expr().unwrap()\n}\n\ncomptime fn new_cast(expr: Expr, typ: UnresolvedType) -> Expr {\n quote { ($expr) as $typ }.as_expr().unwrap()\n}\n\ncomptime fn new_comptime(exprs: [Expr]) -> Expr {\n let exprs = join_expressions(exprs, quote { ; });\n quote { comptime { $exprs }}.as_expr().unwrap()\n}\n\ncomptime fn new_constructor(typ: UnresolvedType, fields: [(Quoted, Expr)]) -> Expr {\n let fields = fields.map(|(name, value)| quote { $name: $value }).join(quote { , });\n quote { $typ { $fields }}.as_expr().unwrap()\n}\n\ncomptime fn new_if(condition: Expr, consequence: Expr, alternative: Option) -> Expr {\n if alternative.is_some() {\n let alternative = alternative.unwrap();\n quote { if $condition { $consequence } else { $alternative }}.as_expr().unwrap()\n } else {\n quote { if $condition { $consequence } }.as_expr().unwrap()\n }\n}\n\ncomptime fn new_for(identifier: Quoted, array: Expr, body: Expr) -> Expr {\n quote { for $identifier in $array { $body } }.as_expr().unwrap()\n}\n\ncomptime fn new_for_range(identifier: Quoted, from: Expr, to: Expr, body: Expr) -> Expr {\n quote { for $identifier in $from .. $to { $body } }.as_expr().unwrap()\n}\n\ncomptime fn new_index(object: Expr, index: Expr) -> Expr {\n quote { $object[$index] }.as_expr().unwrap()\n}\n\ncomptime fn new_lambda(\n params: [(Expr, Option)],\n return_type: Option,\n body: Expr,\n) -> Expr {\n let params = params\n .map(|(name, typ)| {\n if typ.is_some() {\n let typ = typ.unwrap();\n quote { $name: $typ }\n } else {\n quote { $name }\n }\n })\n .join(quote { , });\n\n if return_type.is_some() {\n let return_type = return_type.unwrap();\n quote { |$params| -> $return_type { $body } }.as_expr().unwrap()\n } else {\n quote { |$params| { $body } }.as_expr().unwrap()\n }\n}\n\ncomptime fn new_let(pattern: Expr, typ: Option, expr: Expr) -> Expr {\n if typ.is_some() {\n let typ = typ.unwrap();\n quote { let $pattern : $typ = $expr; }.as_expr().unwrap()\n } else {\n quote { let $pattern = $expr; }.as_expr().unwrap()\n }\n}\n\ncomptime fn new_member_access(object: Expr, name: Quoted) -> Expr {\n quote { $object.$name }.as_expr().unwrap()\n}\n\ncomptime fn new_function_call(function: Expr, arguments: [Expr]) -> Expr {\n let arguments = join_expressions(arguments, quote { , });\n\n quote { $function($arguments) }.as_expr().unwrap()\n}\n\ncomptime fn new_method_call(\n object: Expr,\n name: Quoted,\n generics: [UnresolvedType],\n arguments: [Expr],\n) -> Expr {\n let arguments = join_expressions(arguments, quote { , });\n\n if generics.len() == 0 {\n quote { $object.$name($arguments) }.as_expr().unwrap()\n } else {\n let generics = generics.map(|generic| quote { $generic }).join(quote { , });\n quote { $object.$name::<$generics>($arguments) }.as_expr().unwrap()\n }\n}\n\ncomptime fn new_repeated_element_array(expr: Expr, length: Expr) -> Expr {\n quote { [$expr; $length] }.as_expr().unwrap()\n}\n\ncomptime fn new_repeated_element_slice(expr: Expr, length: Expr) -> Expr {\n quote { &[$expr; $length] }.as_expr().unwrap()\n}\n\ncomptime fn new_slice(exprs: [Expr]) -> Expr {\n let exprs = join_expressions(exprs, quote { , });\n quote { &[$exprs]}.as_expr().unwrap()\n}\n\ncomptime fn new_tuple(exprs: [Expr]) -> Expr {\n let exprs = join_expressions(exprs, quote { , });\n quote { ($exprs) }.as_expr().unwrap()\n}\n\ncomptime fn new_unary_op(op: UnaryOp, rhs: Expr) -> Expr {\n let op = op.quoted();\n quote { $op($rhs) }.as_expr().unwrap()\n}\n\ncomptime fn new_unsafe(exprs: [Expr]) -> Expr {\n let exprs = join_expressions(exprs, quote { ; });\n quote { \n // Safety: generated by macro\n unsafe { $exprs }\n }\n .as_expr()\n .unwrap()\n}\n\ncomptime fn join_expressions(exprs: [Expr], separator: Quoted) -> Quoted {\n exprs.map(|expr| expr.quoted()).join(separator)\n}\n"},"253":{"path":"/home/nerses/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.2/noir-projects/noir-protocol-circuits/crates/types/src/abis/function_selector.nr","source":"use crate::traits::{Deserialize, Empty, FromField, Serialize, ToField};\nuse std::meta::derive;\n\n#[derive(Deserialize, Eq, Serialize)]\npub struct FunctionSelector {\n // 1st 4-bytes (big-endian leftmost) of abi-encoding of an event.\n pub inner: u32,\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(signature: str) -> Self {\n let bytes = signature.as_bytes();\n let hash = crate::hash::poseidon2_hash_bytes(bytes);\n\n // `hash` is automatically truncated to fit within 32 bits.\n FunctionSelector::from_field(hash)\n }\n\n pub fn zero() -> Self {\n Self { inner: 0 }\n }\n}\n\n#[test]\nfn test_is_valid_selector() {\n let selector = FunctionSelector::from_signature(\"IS_VALID()\");\n assert_eq(selector.to_field(), 0x73cdda47);\n}\n\n#[test]\nfn test_long_selector() {\n let selector =\n FunctionSelector::from_signature(\"foo_and_bar_and_baz_and_foo_bar_baz_and_bar_foo\");\n assert_eq(selector.to_field(), 0x7590a997);\n}\n"},"294":{"path":"/home/nerses/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.2/noir-projects/noir-protocol-circuits/crates/types/src/address/aztec_address.nr","source":"use crate::{\n address::{\n partial_address::PartialAddress, salted_initialization_hash::SaltedInitializationHash,\n },\n constants::{\n AZTEC_ADDRESS_LENGTH, GENERATOR_INDEX__CONTRACT_ADDRESS_V1, MAX_FIELD_VALUE,\n MAX_PROTOCOL_CONTRACTS,\n },\n contract_class_id::ContractClassId,\n hash::poseidon2_hash_with_separator,\n public_keys::{IvpkM, NpkM, OvpkM, PublicKeys, ToPoint, TpkM},\n traits::{Deserialize, Empty, FromField, Packable, Serialize, ToField},\n utils::field::{pow, sqrt},\n};\n\n// We do below because `use crate::point::Point;` does not work\nuse dep::std::embedded_curve_ops::EmbeddedCurvePoint as Point;\n\nuse crate::public_keys::AddressPoint;\nuse std::{\n embedded_curve_ops::{EmbeddedCurveScalar, fixed_base_scalar_mul as derive_public_key},\n ops::Add,\n};\nuse std::meta::derive;\n\n// Aztec address\n#[derive(Deserialize, Eq, Packable, Serialize)]\npub struct AztecAddress {\n pub inner: Field,\n}\n\nimpl Empty for AztecAddress {\n fn empty() -> Self {\n Self { inner: 0 }\n }\n}\n\nimpl ToField for AztecAddress {\n fn to_field(self) -> Field {\n self.inner\n }\n}\n\nimpl FromField for AztecAddress {\n fn from_field(value: Field) -> AztecAddress {\n AztecAddress { inner: value }\n }\n}\n\nimpl AztecAddress {\n pub fn zero() -> Self {\n Self { inner: 0 }\n }\n\n /// Returns an address's `AddressPoint`, which can be used to create shared secrets with the owner\n /// of the address. If the address is invalid (i.e. it is not a properly derived Aztec address), then this\n /// returns `Option::none()`, and no shared secrets can be created.\n pub fn to_address_point(self) -> Option {\n // We compute the address point by taking our address, setting it to x, and then solving for y in the\n // equation which defines our bn curve:\n // y^2 = x^3 - 17; x = address\n let x = self.inner;\n let y_squared = pow(x, 3) - 17;\n\n // An invalid AztecAddress is one for which no y coordinate satisfies the curve equation, which we'll\n // identify by proving that the square root of y_squared does not exist.\n let mut y_opt = sqrt(y_squared);\n if y_opt.is_none() {\n Option::none()\n } else {\n let mut y = y_opt.unwrap();\n\n // If we get a negative y coordinate (any y where y > MAX_FIELD_VALUE / 2), we pin it to the\n // positive one (any value where y <= MAX_FIELD_VALUE / 2) by subtracting it from the Field modulus\n // note: The field modulus is MAX_FIELD_VALUE + 1\n if (!(y.lt(MAX_FIELD_VALUE / 2) | y.eq(MAX_FIELD_VALUE / 2))) {\n y = (MAX_FIELD_VALUE + 1) - y;\n }\n\n Option::some(\n AddressPoint { inner: Point { x: self.inner, y, is_infinite: false } },\n )\n }\n }\n\n pub fn compute(public_keys: PublicKeys, partial_address: PartialAddress) -> AztecAddress {\n let public_keys_hash = public_keys.hash();\n\n let pre_address = poseidon2_hash_with_separator(\n [public_keys_hash.to_field(), partial_address.to_field()],\n GENERATOR_INDEX__CONTRACT_ADDRESS_V1,\n );\n\n let address_point = derive_public_key(EmbeddedCurveScalar::from_field(pre_address)).add(\n public_keys.ivpk_m.to_point(),\n );\n\n // Note that our address is only the x-coordinate of the full address_point. This is okay because when people want to encrypt something and send it to us\n // they can recover our full point using the x-coordinate (our address itself). To do this, they recompute the y-coordinate according to the equation y^2 = x^3 - 17.\n // When they do this, they may get a positive y-coordinate (a value that is less than or equal to MAX_FIELD_VALUE / 2) or\n // a negative y-coordinate (a value that is more than MAX_FIELD_VALUE), and we cannot dictate which one they get and hence the recovered point may sometimes be different than the one\n // our secret can decrypt. Regardless though, they should and will always encrypt using point with the positive y-coordinate by convention.\n // This ensures that everyone encrypts to the same point given an arbitrary x-coordinate (address). This is allowed because even though our original point may not have a positive y-coordinate,\n // with our original secret, we will be able to derive the secret to the point with the flipped (and now positive) y-coordinate that everyone encrypts to.\n AztecAddress::from_field(address_point.x)\n }\n\n pub fn compute_from_class_id(\n contract_class_id: ContractClassId,\n salted_initialization_hash: SaltedInitializationHash,\n public_keys: PublicKeys,\n ) -> Self {\n let partial_address = PartialAddress::compute_from_salted_initialization_hash(\n contract_class_id,\n salted_initialization_hash,\n );\n\n AztecAddress::compute(public_keys, partial_address)\n }\n\n pub fn is_protocol_contract(self) -> bool {\n self.inner.lt(MAX_PROTOCOL_CONTRACTS as Field)\n }\n\n pub fn is_zero(self) -> bool {\n self.inner == 0\n }\n\n pub fn assert_is_zero(self) {\n assert(self.to_field() == 0);\n }\n}\n\n#[test]\nfn compute_address_from_partial_and_pub_keys() {\n let public_keys = PublicKeys {\n npk_m: NpkM {\n inner: Point {\n x: 0x22f7fcddfa3ce3e8f0cc8e82d7b94cdd740afa3e77f8e4a63ea78a239432dcab,\n y: 0x0471657de2b6216ade6c506d28fbc22ba8b8ed95c871ad9f3e3984e90d9723a7,\n is_infinite: false,\n },\n },\n ivpk_m: IvpkM {\n inner: Point {\n x: 0x111223493147f6785514b1c195bb37a2589f22a6596d30bb2bb145fdc9ca8f1e,\n y: 0x273bbffd678edce8fe30e0deafc4f66d58357c06fd4a820285294b9746c3be95,\n is_infinite: false,\n },\n },\n ovpk_m: OvpkM {\n inner: Point {\n x: 0x09115c96e962322ffed6522f57194627136b8d03ac7469109707f5e44190c484,\n y: 0x0c49773308a13d740a7f0d4f0e6163b02c5a408b6f965856b6a491002d073d5b,\n is_infinite: false,\n },\n },\n tpk_m: TpkM {\n inner: Point {\n x: 0x00d3d81beb009873eb7116327cf47c612d5758ef083d4fda78e9b63980b2a762,\n y: 0x2f567d22d2b02fe1f4ad42db9d58a36afd1983e7e2909d1cab61cafedad6193a,\n is_infinite: false,\n },\n },\n };\n\n let partial_address = PartialAddress::from_field(\n 0x0a7c585381b10f4666044266a02405bf6e01fa564c8517d4ad5823493abd31de,\n );\n\n let address = AztecAddress::compute(public_keys, partial_address);\n\n // The following value was generated by `derivation.test.ts`.\n // --> Run the test with AZTEC_GENERATE_TEST_DATA=1 flag to update test data.\n let expected_computed_address_from_partial_and_pubkeys =\n 0x24e4646f58b9fbe7d38e317db8d5636c423fbbdfbe119fc190fe9c64747e0c62;\n assert(address.to_field() == expected_computed_address_from_partial_and_pubkeys);\n}\n\n#[test]\nfn compute_preaddress_from_partial_and_pub_keys() {\n let pre_address = poseidon2_hash_with_separator([1, 2], GENERATOR_INDEX__CONTRACT_ADDRESS_V1);\n let expected_computed_preaddress_from_partial_and_pubkey =\n 0x23ce9be3fa3c846b0f9245cc796902e731d04f086e8a42473bb29e405fc98075;\n assert(pre_address == expected_computed_preaddress_from_partial_and_pubkey);\n}\n\n#[test]\nfn from_field_to_field() {\n let address = AztecAddress { inner: 37 };\n assert_eq(FromField::from_field(address.to_field()), address);\n}\n\n#[test]\nfn serde() {\n let address = AztecAddress { inner: 37 };\n // We use the AZTEC_ADDRESS_LENGTH constant to ensure that there is a match between the derived trait\n // implementation and the constant.\n let serialized: [Field; AZTEC_ADDRESS_LENGTH] = address.serialize();\n let deserialized = AztecAddress::deserialize(serialized);\n assert_eq(address, deserialized);\n}\n\n#[test]\nfn to_address_point_valid() {\n // x = 8 where x^3 - 17 = 512 - 17 = 495, which is a residue in this field\n let address = AztecAddress { inner: 8 };\n let maybe_point = address.to_address_point();\n assert(maybe_point.is_some());\n\n let point = maybe_point.unwrap().inner;\n // check that x is preserved\n assert_eq(point.x, Field::from(8));\n\n // check that the curve equation holds: y^2 == x^3 - 17\n assert_eq(pow(point.y, 2), pow(point.x, 3) - 17);\n}\n\n#[test]\nunconstrained fn to_address_point_invalid() {\n // x = 3 where x^3 - 17 = 27 - 17 = 10, which is a non-residue in this field\n let address = AztecAddress { inner: 3 }; //\n let maybe_point = address.to_address_point();\n assert(maybe_point.is_none());\n}\n"},"3":{"path":"std/array/mod.nr","source":"use crate::cmp::{Eq, Ord};\nuse crate::convert::From;\nuse crate::runtime::is_unconstrained;\n\nmod check_shuffle;\nmod quicksort;\n\nimpl [T; N] {\n /// Returns the length of this array.\n ///\n /// ```noir\n /// fn len(self) -> Field\n /// ```\n ///\n /// example\n ///\n /// ```noir\n /// fn main() {\n /// let array = [42, 42];\n /// assert(array.len() == 2);\n /// }\n /// ```\n #[builtin(array_len)]\n pub fn len(self) -> u32 {}\n\n /// Returns this array as a slice.\n ///\n /// ```noir\n /// let array = [1, 2];\n /// let slice = array.as_slice();\n /// assert_eq(slice, &[1, 2]);\n /// ```\n #[builtin(as_slice)]\n pub fn as_slice(self) -> [T] {}\n\n /// Applies a function to each element of this array, returning a new array containing the mapped elements.\n ///\n /// Example:\n ///\n /// ```rust\n /// let a = [1, 2, 3];\n /// let b = a.map(|a| a * 2);\n /// assert_eq(b, [2, 4, 6]);\n /// ```\n pub fn map(self, f: fn[Env](T) -> U) -> [U; N] {\n let uninitialized = crate::mem::zeroed();\n let mut ret = [uninitialized; N];\n\n for i in 0..self.len() {\n ret[i] = f(self[i]);\n }\n\n ret\n }\n\n /// Applies a function to each element of this array along with its index,\n /// returning a new array containing the mapped elements.\n ///\n /// Example:\n ///\n /// ```rust\n /// let a = [1, 2, 3];\n /// let b = a.mapi(|i, a| i + a * 2);\n /// assert_eq(b, [2, 5, 8]);\n /// ```\n pub fn mapi(self, f: fn[Env](u32, T) -> U) -> [U; N] {\n let uninitialized = crate::mem::zeroed();\n let mut ret = [uninitialized; N];\n\n for i in 0..self.len() {\n ret[i] = f(i, self[i]);\n }\n\n ret\n }\n\n /// Applies a function to each element of this array.\n ///\n /// Example:\n ///\n /// ```rust\n /// let a = [1, 2, 3];\n /// let mut b = [0; 3];\n /// let mut i = 0;\n /// a.for_each(|x| {\n /// b[i] = x;\n /// i += 1;\n /// });\n /// assert_eq(a, b);\n /// ```\n pub fn for_each(self, f: fn[Env](T) -> ()) {\n for i in 0..self.len() {\n f(self[i]);\n }\n }\n\n /// Applies a function to each element of this array along with its index.\n ///\n /// Example:\n ///\n /// ```rust\n /// let a = [1, 2, 3];\n /// let mut b = [0; 3];\n /// a.for_eachi(|i, x| {\n /// b[i] = x;\n /// });\n /// assert_eq(a, b);\n /// ```\n pub fn for_eachi(self, f: fn[Env](u32, T) -> ()) {\n for i in 0..self.len() {\n f(i, self[i]);\n }\n }\n\n /// Applies a function to each element of the array, returning the final accumulated value. The first\n /// parameter is the initial value.\n ///\n /// This is a left fold, so the given function will be applied to the accumulator and first element of\n /// the array, then the second, and so on. For a given call the expected result would be equivalent to:\n ///\n /// ```rust\n /// let a1 = [1];\n /// let a2 = [1, 2];\n /// let a3 = [1, 2, 3];\n ///\n /// let f = |a, b| a - b;\n /// a1.fold(10, f); //=> f(10, 1)\n /// a2.fold(10, f); //=> f(f(10, 1), 2)\n /// a3.fold(10, f); //=> f(f(f(10, 1), 2), 3)\n ///\n /// assert_eq(a3.fold(10, f), 10 - 1 - 2 - 3);\n /// ```\n pub fn fold(self, mut accumulator: U, f: fn[Env](U, T) -> U) -> U {\n for elem in self {\n accumulator = f(accumulator, elem);\n }\n accumulator\n }\n\n /// Same as fold, but uses the first element as the starting element.\n ///\n /// Requires the input array to be non-empty.\n ///\n /// Example:\n ///\n /// ```noir\n /// fn main() {\n /// let arr = [1, 2, 3, 4];\n /// let reduced = arr.reduce(|a, b| a + b);\n /// assert(reduced == 10);\n /// }\n /// ```\n pub fn reduce(self, f: fn[Env](T, T) -> T) -> T {\n let mut accumulator = self[0];\n for i in 1..self.len() {\n accumulator = f(accumulator, self[i]);\n }\n accumulator\n }\n\n /// Returns true if all the elements in this array satisfy the given predicate.\n ///\n /// Example:\n ///\n /// ```noir\n /// fn main() {\n /// let arr = [2, 2, 2, 2, 2];\n /// let all = arr.all(|a| a == 2);\n /// assert(all);\n /// }\n /// ```\n pub fn all(self, predicate: fn[Env](T) -> bool) -> bool {\n let mut ret = true;\n for elem in self {\n ret &= predicate(elem);\n }\n ret\n }\n\n /// Returns true if any of the elements in this array satisfy the given predicate.\n ///\n /// Example:\n ///\n /// ```noir\n /// fn main() {\n /// let arr = [2, 2, 2, 2, 5];\n /// let any = arr.any(|a| a == 5);\n /// assert(any);\n /// }\n /// ```\n pub fn any(self, predicate: fn[Env](T) -> bool) -> bool {\n let mut ret = false;\n for elem in self {\n ret |= predicate(elem);\n }\n ret\n }\n\n /// Concatenates this array with another array.\n ///\n /// Example:\n ///\n /// ```noir\n /// fn main() {\n /// let arr1 = [1, 2, 3, 4];\n /// let arr2 = [6, 7, 8, 9, 10, 11];\n /// let concatenated_arr = arr1.concat(arr2);\n /// assert(concatenated_arr == [1, 2, 3, 4, 6, 7, 8, 9, 10, 11]);\n /// }\n /// ```\n pub fn concat(self, array2: [T; M]) -> [T; N + M] {\n let mut result = [crate::mem::zeroed(); N + M];\n for i in 0..N {\n result[i] = self[i];\n }\n for i in 0..M {\n result[i + N] = array2[i];\n }\n result\n }\n}\n\nimpl [T; N]\nwhere\n T: Ord + Eq,\n{\n /// Returns a new sorted array. The original array remains untouched. Notice that this function will\n /// only work for arrays of fields or integers, not for any arbitrary type. This is because the sorting\n /// logic it uses internally is optimized specifically for these values. If you need a sort function to\n /// sort any type, you should use the `sort_via` function.\n ///\n /// Example:\n ///\n /// ```rust\n /// fn main() {\n /// let arr = [42, 32];\n /// let sorted = arr.sort();\n /// assert(sorted == [32, 42]);\n /// }\n /// ```\n pub fn sort(self) -> Self {\n self.sort_via(|a, b| a <= b)\n }\n}\n\nimpl [T; N]\nwhere\n T: Eq,\n{\n /// Returns a new sorted array by sorting it with a custom comparison function.\n /// The original array remains untouched.\n /// The ordering function must return true if the first argument should be sorted to be before the second argument or is equal to the second argument.\n ///\n /// Using this method with an operator like `<` that does not return `true` for equal values will result in an assertion failure for arrays with equal elements.\n ///\n /// Example:\n ///\n /// ```rust\n /// fn main() {\n /// let arr = [42, 32]\n /// let sorted_ascending = arr.sort_via(|a, b| a <= b);\n /// assert(sorted_ascending == [32, 42]); // verifies\n ///\n /// let sorted_descending = arr.sort_via(|a, b| a >= b);\n /// assert(sorted_descending == [32, 42]); // does not verify\n /// }\n /// ```\n pub fn sort_via(self, ordering: fn[Env](T, T) -> bool) -> Self {\n // Safety: `sorted` array is checked to be:\n // a. a permutation of `input`'s elements\n // b. satisfying the predicate `ordering`\n let sorted = unsafe { quicksort::quicksort(self, ordering) };\n\n if !is_unconstrained() {\n for i in 0..N - 1 {\n assert(\n ordering(sorted[i], sorted[i + 1]),\n \"Array has not been sorted correctly according to `ordering`.\",\n );\n }\n check_shuffle::check_shuffle(self, sorted);\n }\n sorted\n }\n}\n\nimpl [u8; N] {\n /// Converts a byte array of type `[u8; N]` to a string. Note that this performs no UTF-8 validation -\n /// the given array is interpreted as-is as a string.\n ///\n /// Example:\n ///\n /// ```rust\n /// fn main() {\n /// let hi = [104, 105].as_str_unchecked();\n /// assert_eq(hi, \"hi\");\n /// }\n /// ```\n #[builtin(array_as_str_unchecked)]\n pub fn as_str_unchecked(self) -> str {}\n}\n\nimpl From> for [u8; N] {\n /// Returns an array of the string bytes.\n fn from(s: str) -> Self {\n s.as_bytes()\n }\n}\n\nmod test {\n #[test]\n fn map_empty() {\n assert_eq([].map(|x| x + 1), []);\n }\n\n global arr_with_100_values: [u32; 100] = [\n 42, 123, 87, 93, 48, 80, 50, 5, 104, 84, 70, 47, 119, 66, 71, 121, 3, 29, 42, 118, 2, 54,\n 89, 44, 81, 0, 26, 106, 68, 96, 84, 48, 95, 54, 45, 32, 89, 100, 109, 19, 37, 41, 19, 98,\n 53, 114, 107, 66, 6, 74, 13, 19, 105, 64, 123, 28, 44, 50, 89, 58, 123, 126, 21, 43, 86, 35,\n 21, 62, 82, 0, 108, 120, 72, 72, 62, 80, 12, 71, 70, 86, 116, 73, 38, 15, 127, 81, 30, 8,\n 125, 28, 26, 69, 114, 63, 27, 28, 61, 42, 13, 32,\n ];\n global expected_with_100_values: [u32; 100] = [\n 0, 0, 2, 3, 5, 6, 8, 12, 13, 13, 15, 19, 19, 19, 21, 21, 26, 26, 27, 28, 28, 28, 29, 30, 32,\n 32, 35, 37, 38, 41, 42, 42, 42, 43, 44, 44, 45, 47, 48, 48, 50, 50, 53, 54, 54, 58, 61, 62,\n 62, 63, 64, 66, 66, 68, 69, 70, 70, 71, 71, 72, 72, 73, 74, 80, 80, 81, 81, 82, 84, 84, 86,\n 86, 87, 89, 89, 89, 93, 95, 96, 98, 100, 104, 105, 106, 107, 108, 109, 114, 114, 116, 118,\n 119, 120, 121, 123, 123, 123, 125, 126, 127,\n ];\n fn sort_u32(a: u32, b: u32) -> bool {\n a <= b\n }\n\n #[test]\n fn test_sort() {\n let mut arr: [u32; 7] = [3, 6, 8, 10, 1, 2, 1];\n\n let sorted = arr.sort();\n\n let expected: [u32; 7] = [1, 1, 2, 3, 6, 8, 10];\n assert(sorted == expected);\n }\n\n #[test]\n fn test_sort_100_values() {\n let mut arr: [u32; 100] = [\n 42, 123, 87, 93, 48, 80, 50, 5, 104, 84, 70, 47, 119, 66, 71, 121, 3, 29, 42, 118, 2,\n 54, 89, 44, 81, 0, 26, 106, 68, 96, 84, 48, 95, 54, 45, 32, 89, 100, 109, 19, 37, 41,\n 19, 98, 53, 114, 107, 66, 6, 74, 13, 19, 105, 64, 123, 28, 44, 50, 89, 58, 123, 126, 21,\n 43, 86, 35, 21, 62, 82, 0, 108, 120, 72, 72, 62, 80, 12, 71, 70, 86, 116, 73, 38, 15,\n 127, 81, 30, 8, 125, 28, 26, 69, 114, 63, 27, 28, 61, 42, 13, 32,\n ];\n\n let sorted = arr.sort();\n\n let expected: [u32; 100] = [\n 0, 0, 2, 3, 5, 6, 8, 12, 13, 13, 15, 19, 19, 19, 21, 21, 26, 26, 27, 28, 28, 28, 29, 30,\n 32, 32, 35, 37, 38, 41, 42, 42, 42, 43, 44, 44, 45, 47, 48, 48, 50, 50, 53, 54, 54, 58,\n 61, 62, 62, 63, 64, 66, 66, 68, 69, 70, 70, 71, 71, 72, 72, 73, 74, 80, 80, 81, 81, 82,\n 84, 84, 86, 86, 87, 89, 89, 89, 93, 95, 96, 98, 100, 104, 105, 106, 107, 108, 109, 114,\n 114, 116, 118, 119, 120, 121, 123, 123, 123, 125, 126, 127,\n ];\n assert(sorted == expected);\n }\n\n #[test]\n fn test_sort_100_values_comptime() {\n let sorted = arr_with_100_values.sort();\n assert(sorted == expected_with_100_values);\n }\n\n #[test]\n fn test_sort_via() {\n let mut arr: [u32; 7] = [3, 6, 8, 10, 1, 2, 1];\n\n let sorted = arr.sort_via(sort_u32);\n\n let expected: [u32; 7] = [1, 1, 2, 3, 6, 8, 10];\n assert(sorted == expected);\n }\n\n #[test]\n fn test_sort_via_100_values() {\n let mut arr: [u32; 100] = [\n 42, 123, 87, 93, 48, 80, 50, 5, 104, 84, 70, 47, 119, 66, 71, 121, 3, 29, 42, 118, 2,\n 54, 89, 44, 81, 0, 26, 106, 68, 96, 84, 48, 95, 54, 45, 32, 89, 100, 109, 19, 37, 41,\n 19, 98, 53, 114, 107, 66, 6, 74, 13, 19, 105, 64, 123, 28, 44, 50, 89, 58, 123, 126, 21,\n 43, 86, 35, 21, 62, 82, 0, 108, 120, 72, 72, 62, 80, 12, 71, 70, 86, 116, 73, 38, 15,\n 127, 81, 30, 8, 125, 28, 26, 69, 114, 63, 27, 28, 61, 42, 13, 32,\n ];\n\n let sorted = arr.sort_via(sort_u32);\n\n let expected: [u32; 100] = [\n 0, 0, 2, 3, 5, 6, 8, 12, 13, 13, 15, 19, 19, 19, 21, 21, 26, 26, 27, 28, 28, 28, 29, 30,\n 32, 32, 35, 37, 38, 41, 42, 42, 42, 43, 44, 44, 45, 47, 48, 48, 50, 50, 53, 54, 54, 58,\n 61, 62, 62, 63, 64, 66, 66, 68, 69, 70, 70, 71, 71, 72, 72, 73, 74, 80, 80, 81, 81, 82,\n 84, 84, 86, 86, 87, 89, 89, 89, 93, 95, 96, 98, 100, 104, 105, 106, 107, 108, 109, 114,\n 114, 116, 118, 119, 120, 121, 123, 123, 123, 125, 126, 127,\n ];\n assert(sorted == expected);\n }\n\n #[test]\n fn mapi_empty() {\n assert_eq([].mapi(|i, x| i * x + 1), []);\n }\n\n #[test]\n fn for_each_empty() {\n let empty_array: [Field; 0] = [];\n empty_array.for_each(|_x| assert(false));\n }\n\n #[test]\n fn for_eachi_empty() {\n let empty_array: [Field; 0] = [];\n empty_array.for_eachi(|_i, _x| assert(false));\n }\n\n #[test]\n fn map_example() {\n let a = [1, 2, 3];\n let b = a.map(|a| a * 2);\n assert_eq(b, [2, 4, 6]);\n }\n\n #[test]\n fn mapi_example() {\n let a = [1, 2, 3];\n let b = a.mapi(|i, a| i + a * 2);\n assert_eq(b, [2, 5, 8]);\n }\n\n #[test]\n fn for_each_example() {\n let a = [1, 2, 3];\n let mut b = [0, 0, 0];\n let b_ref = &mut b;\n let mut i = 0;\n let i_ref = &mut i;\n a.for_each(|x| {\n b_ref[*i_ref] = x * 2;\n *i_ref += 1;\n });\n assert_eq(b, [2, 4, 6]);\n assert_eq(i, 3);\n }\n\n #[test]\n fn for_eachi_example() {\n let a = [1, 2, 3];\n let mut b = [0, 0, 0];\n let b_ref = &mut b;\n a.for_eachi(|i, a| { b_ref[i] = i + a * 2; });\n assert_eq(b, [2, 5, 8]);\n }\n\n #[test]\n fn concat() {\n let arr1 = [1, 2, 3, 4];\n let arr2 = [6, 7, 8, 9, 10, 11];\n let concatenated_arr = arr1.concat(arr2);\n assert_eq(concatenated_arr, [1, 2, 3, 4, 6, 7, 8, 9, 10, 11]);\n }\n\n #[test]\n fn concat_zero_length_with_something() {\n let arr1 = [];\n let arr2 = [1];\n let concatenated_arr = arr1.concat(arr2);\n assert_eq(concatenated_arr, [1]);\n }\n\n #[test]\n fn concat_something_with_zero_length() {\n let arr1 = [1];\n let arr2 = [];\n let concatenated_arr = arr1.concat(arr2);\n assert_eq(concatenated_arr, [1]);\n }\n\n #[test]\n fn concat_zero_lengths() {\n let arr1: [Field; 0] = [];\n let arr2: [Field; 0] = [];\n let concatenated_arr = arr1.concat(arr2);\n assert_eq(concatenated_arr, []);\n }\n}\n"},"309":{"path":"/home/nerses/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.2/noir-projects/noir-protocol-circuits/crates/types/src/debug_log.nr","source":"// TODO: Expose other wrapped functions than debug (info, warn)\n// ['silent', 'fatal', 'error', 'warn', 'info', 'verbose', 'debug', 'trace']\n\npub global SILENT_LOG_LEVEL: u8 = 0;\npub global FATAL_LOG_LEVEL: u8 = 1;\npub global ERROR_LOG_LEVEL: u8 = 2;\npub global WARN_LOG_LEVEL: u8 = 3;\npub global INFO_LOG_LEVEL: u8 = 4;\npub global VERBOSE_LOG_LEVEL: u8 = 5;\npub global DEBUG_LOG_LEVEL: u8 = 6;\npub global TRACE_LOG_LEVEL: u8 = 7;\n\n/// Utility function to console.log data in the acir simulator.\n/// Example:\n/// debug_log(\"blah blah this is a debug string\");\npub fn debug_log(msg: str) {\n debug_log_format(msg, []);\n}\n\n/// Same as debug_log, but allows to customize the log level.\n/// Consider changing just to 'log'\npub fn debug_log_with_level(log_level: u8, msg: str) {\n debug_log_format_with_level(log_level, msg, []);\n}\n\n/// Utility function to console.log data in the acir simulator. This variant receives a format string in which the\n/// `${k}` tokens will be replaced with the k-eth value in the `args` array.\n/// Examples:\n/// debug_log_format(\"get_2(slot:{0}) =>\\n\\t0:{1}\\n\\t1:{2}\", [storage_slot, note0_hash, note1_hash]);\n/// debug_log_format(\"whole array: {}\", [e1, e2, e3, e4]);\npub fn debug_log_format(msg: str, args: [Field; N]) {\n // Safety: This oracle call returns nothing: we only call it for its side effects. It is therefore always safe\n // to call.\n unsafe { debug_log_array_oracle_wrapper(DEBUG_LOG_LEVEL, msg, args) };\n}\n\n/// Same as debug_log_format, but allows to customize the log level.\n/// Consider changing just to 'log_format'\npub fn debug_log_format_with_level(\n log_level: u8,\n msg: str,\n args: [Field; N],\n) {\n // Safety: This oracle call returns nothing: we only call it for its side effects. It is therefore always safe\n // to call.\n unsafe { debug_log_array_oracle_wrapper(log_level, msg, args) };\n}\n\n/// Utility function to console.log data in the acir simulator. This variant receives a format string in which the\n/// `${k}` tokens will be replaced with the k-eth value in the `args` slice.\n/// Examples:\n/// debug_log_format(\"get_2(slot:{0}) =>\\n\\t0:{1}\\n\\t1:{2}\", [storage_slot, note0_hash, note1_hash]);\n/// debug_log_format(\"whole slice: {}\", [e1, e2, e3, e4]);\npub fn debug_log_format_slice(log_level: u8, msg: str, args: [Field]) {\n // Safety: This oracle call returns nothing: we only call it for its side effects. It is therefore always safe\n // to call.\n unsafe { debug_log_slice_oracle_wrapper(log_level, msg, args) };\n}\n\n// We provide two versions of the debug log oracle: one that takes args as a slice and another one that takes args as an array.\n// We do this since conversion from array to slice generates overhead in public functions, since opcodes need to be emitted for the conversion.\n// By exposing the two flavors, we avoid conversions since the AVM is able to handle both arrays an slices in this oracle.\n\nunconstrained fn debug_log_slice_oracle_wrapper(\n log_level: u8,\n msg: str,\n args: [Field],\n) {\n debug_log_slice_oracle(log_level, msg, args);\n}\n\n// WARNING: sometimes when using debug logs the ACVM errors with: `thrown: \"solver opcode resolution error: cannot solve opcode: expression has too many unknowns x155\"`\n#[oracle(utilityDebugLog)]\nunconstrained fn debug_log_slice_oracle(log_level: u8, msg: str, args: [Field]) {}\n\nunconstrained fn debug_log_array_oracle_wrapper(\n log_level: u8,\n msg: str,\n args: [Field; N],\n) {\n debug_log_array_oracle(log_level, msg, N, args);\n}\n\n#[oracle(utilityDebugLog)]\nunconstrained fn debug_log_array_oracle(\n log_level: u8,\n msg: str,\n length: u32,\n args: [Field; N],\n) {}\n"},"319":{"path":"/home/nerses/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.2/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr","source":"mod poseidon2_chunks;\n\nuse crate::{\n abis::{\n contract_class_function_leaf_preimage::ContractClassFunctionLeafPreimage,\n function_selector::FunctionSelector,\n note_hash::NoteHash,\n nullifier::Nullifier,\n private_log::{PrivateLog, PrivateLogData},\n },\n address::{AztecAddress, EthAddress},\n constants::{\n CONTRACT_CLASS_LOG_SIZE_IN_FIELDS, FUNCTION_TREE_HEIGHT, GENERATOR_INDEX__NOTE_HASH_NONCE,\n GENERATOR_INDEX__OUTER_NULLIFIER, GENERATOR_INDEX__SILOED_NOTE_HASH,\n GENERATOR_INDEX__UNIQUE_NOTE_HASH, TWO_POW_64,\n },\n merkle_tree::root_from_sibling_path,\n messaging::l2_to_l1_message::L2ToL1Message,\n poseidon2::Poseidon2Sponge,\n side_effect::{Counted, Scoped},\n traits::{FromField, Hash, ToField},\n utils::field::{field_from_bytes, field_from_bytes_32_trunc},\n};\n\npub use poseidon2_chunks::poseidon2_absorb_in_chunks_existing_sponge;\nuse poseidon2_chunks::poseidon2_absorb_in_chunks;\nuse std::embedded_curve_ops::EmbeddedCurveScalar;\n\npub fn sha256_to_field(bytes_to_hash: [u8; N]) -> Field {\n let sha256_hashed = sha256::digest(bytes_to_hash);\n let hash_in_a_field = field_from_bytes_32_trunc(sha256_hashed);\n\n hash_in_a_field\n}\n\npub fn private_functions_root_from_siblings(\n selector: FunctionSelector,\n vk_hash: Field,\n function_leaf_index: Field,\n function_leaf_sibling_path: [Field; FUNCTION_TREE_HEIGHT],\n) -> Field {\n let function_leaf_preimage = ContractClassFunctionLeafPreimage { selector, vk_hash };\n let function_leaf = function_leaf_preimage.hash();\n root_from_sibling_path(\n function_leaf,\n function_leaf_index,\n function_leaf_sibling_path,\n )\n}\n\npub fn compute_note_hash_nonce(first_nullifier_in_tx: Field, note_index_in_tx: u32) -> Field {\n // Hashing the first nullifier with note index in tx is guaranteed to be unique (because all nullifiers are also\n // unique).\n poseidon2_hash_with_separator(\n [first_nullifier_in_tx, note_index_in_tx as Field],\n GENERATOR_INDEX__NOTE_HASH_NONCE,\n )\n}\n\npub fn compute_unique_note_hash(note_nonce: Field, siloed_note_hash: Field) -> Field {\n let inputs = [note_nonce, siloed_note_hash];\n poseidon2_hash_with_separator(inputs, GENERATOR_INDEX__UNIQUE_NOTE_HASH)\n}\n\npub fn compute_nonce_and_unique_note_hash(\n siloed_note_hash: Field,\n first_nullifier: Field,\n note_index_in_tx: u32,\n) -> Field {\n let note_nonce = compute_note_hash_nonce(first_nullifier, note_index_in_tx);\n compute_unique_note_hash(note_nonce, siloed_note_hash)\n}\n\npub fn compute_siloed_note_hash(app: AztecAddress, note_hash: Field) -> Field {\n poseidon2_hash_with_separator(\n [app.to_field(), note_hash],\n GENERATOR_INDEX__SILOED_NOTE_HASH,\n )\n}\n\n/// Computes unique note hashes from siloed note hashes\npub fn compute_unique_siloed_note_hash(\n siloed_note_hash: Field,\n first_nullifier: Field,\n note_index_in_tx: u32,\n) -> Field {\n if siloed_note_hash == 0 {\n 0\n } else {\n compute_nonce_and_unique_note_hash(siloed_note_hash, first_nullifier, note_index_in_tx)\n }\n}\n\n/// Siloing in the context of Aztec refers to the process of hashing a note hash with a contract address (this way\n/// the note hash is scoped to a specific contract). This is used to prevent intermingling of notes between contracts.\npub fn silo_note_hash(note_hash: Scoped>) -> Field {\n if note_hash.contract_address.is_zero() {\n 0\n } else {\n compute_siloed_note_hash(note_hash.contract_address, note_hash.innermost())\n }\n}\n\npub fn compute_siloed_nullifier(app: AztecAddress, nullifier: Field) -> Field {\n poseidon2_hash_with_separator(\n [app.to_field(), nullifier],\n GENERATOR_INDEX__OUTER_NULLIFIER,\n )\n}\n\npub fn silo_nullifier(nullifier: Scoped>) -> Field {\n let value = nullifier.innermost().value;\n // Q: shouldn't we be checking whether the _whole_ nullifier is empty?\n // A: We don't have to. The init and inner circuits add contract address to non-empty nullifiers.\n // So we know we should silo it if the contract address is not empty.\n if nullifier.contract_address.is_zero() {\n value // Return `value` instead of 0 because an already-siloed nullifier's contract address is zero.\n } else {\n compute_siloed_nullifier(nullifier.contract_address, value)\n }\n}\n\npub fn compute_siloed_private_log_field(contract_address: AztecAddress, field: Field) -> Field {\n poseidon2_hash([contract_address.to_field(), field])\n}\n\npub fn silo_private_log(private_log: Scoped>) -> PrivateLog {\n let log = private_log.innermost().log;\n if private_log.contract_address.is_zero() {\n log\n } else {\n let mut fields = log.fields;\n fields[0] = compute_siloed_private_log_field(private_log.contract_address, fields[0]);\n PrivateLog::new(fields, log.length)\n }\n}\n\npub fn compute_contract_class_log_hash(log: [Field; CONTRACT_CLASS_LOG_SIZE_IN_FIELDS]) -> Field {\n poseidon2_hash(log)\n}\n\npub fn compute_app_secret_key(\n master_secret_key: EmbeddedCurveScalar,\n app_address: AztecAddress,\n app_secret_generator: Field,\n) -> Field {\n poseidon2_hash_with_separator(\n [master_secret_key.hi, master_secret_key.lo, app_address.to_field()],\n app_secret_generator,\n )\n}\n\npub fn merkle_hash(left: Field, right: Field) -> Field {\n poseidon2_hash([left, right])\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 contract_address_bytes: [u8; 32] = contract_address.to_field().to_be_bytes();\n let recipient_bytes: [u8; 20] = recipient.to_be_bytes();\n let content_bytes: [u8; 32] = content.to_be_bytes();\n let rollup_version_id_bytes: [u8; 32] = rollup_version_id.to_be_bytes();\n let chain_id_bytes: [u8; 32] = chain_id.to_be_bytes();\n\n let mut bytes: [u8; 148] = std::mem::zeroed();\n for i in 0..32 {\n bytes[i] = contract_address_bytes[i];\n bytes[i + 32] = rollup_version_id_bytes[i];\n // 64 - 84 are for recipient.\n bytes[i + 84] = chain_id_bytes[i];\n bytes[i + 116] = content_bytes[i];\n }\n\n for i in 0..20 {\n bytes[64 + i] = recipient_bytes[i];\n }\n\n sha256_to_field(bytes)\n}\n\npub fn silo_l2_to_l1_message(\n msg: Scoped,\n rollup_version_id: Field,\n chain_id: Field,\n) -> Field {\n if msg.contract_address.is_zero() {\n 0\n } else {\n compute_l2_to_l1_hash(\n msg.contract_address,\n msg.inner.recipient,\n msg.inner.content,\n rollup_version_id,\n chain_id,\n )\n }\n}\n\n/// Computes sha256 hash of 2 input fields.\n///\n/// @returns A truncated field (i.e., the first byte is always 0).\npub fn accumulate_sha256(v0: Field, v1: Field) -> Field {\n // Concatenate two fields into 32 x 2 = 64 bytes\n let v0_as_bytes: [u8; 32] = v0.to_be_bytes();\n let v1_as_bytes: [u8; 32] = v1.to_be_bytes();\n let hash_input_flattened = v0_as_bytes.concat(v1_as_bytes);\n\n sha256_to_field(hash_input_flattened)\n}\n\n#[inline_always]\npub fn pedersen_hash(inputs: [Field; N], hash_index: u32) -> Field {\n std::hash::pedersen_hash_with_separator(inputs, hash_index)\n}\n\npub fn poseidon2_hash(inputs: [Field; N]) -> Field {\n poseidon::poseidon2::Poseidon2::hash(inputs, N)\n}\n\n#[no_predicates]\npub fn poseidon2_hash_with_separator(inputs: [Field; N], separator: T) -> Field\nwhere\n T: ToField,\n{\n let inputs_with_separator = [separator.to_field()].concat(inputs);\n poseidon2_hash(inputs_with_separator)\n}\n\n/// Computes a Poseidon2 hash over a dynamic-length subarray of the given input.\n/// Only the first `in_len` fields of `input` are absorbed; any remaining fields are ignored.\n/// The caller is responsible for ensuring that the input is padded with zeros if required.\n#[no_predicates]\npub fn poseidon2_hash_subarray(input: [Field; N], in_len: u32) -> Field {\n let mut sponge = poseidon2_absorb_in_chunks(input, in_len);\n sponge.squeeze()\n}\n\n// NB the below is the same as poseidon::poseidon2::Poseidon2::hash(), but replacing a range check with a bit check,\n// and absorbing in chunks of 3 below.\n#[no_predicates]\npub fn poseidon2_cheaper_variable_hash(input: [Field; N], in_len: u32) -> Field {\n let mut sponge = poseidon2_absorb_in_chunks(input, in_len);\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 in_len != N {\n sponge.absorb(1);\n }\n sponge.squeeze()\n}\n\npub fn poseidon2_hash_with_separator_slice(inputs: [Field], separator: T) -> Field\nwhere\n T: ToField,\n{\n let in_len = inputs.len() + 1;\n let iv: Field = (in_len as Field) * TWO_POW_64;\n let mut sponge = Poseidon2Sponge::new(iv);\n sponge.absorb(separator.to_field());\n\n for i in 0..inputs.len() {\n sponge.absorb(inputs[i]);\n }\n\n sponge.squeeze()\n}\n\n// This function is unconstrained because it is intended to be used in unconstrained context only as\n// in constrained contexts it would be too inefficient.\npub unconstrained fn poseidon2_hash_with_separator_bounded_vec(\n inputs: BoundedVec,\n separator: T,\n) -> Field\nwhere\n T: ToField,\n{\n let in_len = inputs.len() + 1;\n let iv: Field = (in_len as Field) * TWO_POW_64;\n let mut sponge = Poseidon2Sponge::new(iv);\n sponge.absorb(separator.to_field());\n\n for i in 0..inputs.len() {\n sponge.absorb(inputs.get(i));\n }\n\n sponge.squeeze()\n}\n\n#[no_predicates]\npub fn poseidon2_hash_bytes(inputs: [u8; N]) -> Field {\n let mut fields = [0; (N + 30) / 31];\n let mut field_index = 0;\n let mut current_field = [0; 31];\n for i in 0..inputs.len() {\n let index = i % 31;\n current_field[index] = inputs[i];\n if index == 30 {\n fields[field_index] = field_from_bytes(current_field, false);\n current_field = [0; 31];\n field_index += 1;\n }\n }\n if field_index != fields.len() {\n fields[field_index] = field_from_bytes(current_field, false);\n }\n poseidon2_hash(fields)\n}\n\n#[test]\nfn poseidon_chunks_matches_fixed() {\n let in_len = 501;\n let mut input: [Field; 4096] = [0; 4096];\n let mut fixed_input = [3; 501];\n assert(in_len == fixed_input.len()); // sanity check\n for i in 0..in_len {\n input[i] = 3;\n }\n let sub_chunk_hash = poseidon2_hash_subarray(input, in_len);\n let fixed_len_hash = poseidon::poseidon2::Poseidon2::hash(fixed_input, fixed_input.len());\n assert(sub_chunk_hash == fixed_len_hash);\n}\n\n#[test]\nfn poseidon_chunks_matches_variable() {\n let in_len = 501;\n let mut input: [Field; 4096] = [0; 4096];\n for i in 0..in_len {\n input[i] = 3;\n }\n let variable_chunk_hash = poseidon2_cheaper_variable_hash(input, in_len);\n let variable_len_hash = poseidon::poseidon2::Poseidon2::hash(input, in_len);\n assert(variable_chunk_hash == variable_len_hash);\n}\n\n#[test]\nfn smoke_sha256_to_field() {\n let full_buffer = [\n 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,\n 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,\n 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70,\n 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93,\n 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112,\n 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130,\n 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148,\n 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,\n ];\n let result = sha256_to_field(full_buffer);\n\n assert(result == 0x448ebbc9e1a31220a2f3830c18eef61b9bd070e5084b7fa2a359fe729184c7);\n\n // to show correctness of the current ver (truncate one byte) vs old ver (mod full bytes):\n let result_bytes = sha256::digest(full_buffer);\n let truncated_field = crate::utils::field::field_from_bytes_32_trunc(result_bytes);\n assert(truncated_field == result);\n let mod_res = result + (result_bytes[31] as Field);\n assert(mod_res == 0x448ebbc9e1a31220a2f3830c18eef61b9bd070e5084b7fa2a359fe729184e0);\n}\n\n#[test]\nfn compute_l2_l1_hash() {\n // All zeroes\n let hash_result =\n compute_l2_to_l1_hash(AztecAddress::from_field(0), EthAddress::zero(), 0, 0, 0);\n assert(hash_result == 0x3b18c58c739716e76429634a61375c45b3b5cd470c22ab6d3e14cee23dd992);\n\n // Non-zero case\n let hash_result = compute_l2_to_l1_hash(\n AztecAddress::from_field(1),\n EthAddress::from_field(3),\n 5,\n 2,\n 4,\n );\n assert(hash_result == 0xaab2a5828156782b12a1dc6f336e2bc627eb1b9514b02d511f66296990c050);\n}\n\n#[test]\nfn silo_l2_to_l1_message_matches_typescript() {\n let version = 4;\n let chainId = 5;\n\n let hash = silo_l2_to_l1_message(\n L2ToL1Message { recipient: EthAddress::from_field(1), content: 2 }.scope(\n AztecAddress::from_field(3),\n ),\n version,\n chainId,\n );\n\n // The following value was generated by `yarn-project/stdlib/src/hash/hash.test.ts`\n let hash_from_typescript = 0x0081edf209e087ad31b3fd24263698723d57190bd1d6e9fe056fc0c0a68ee661;\n\n assert_eq(hash, hash_from_typescript);\n}\n\n#[test]\nunconstrained fn poseidon2_hash_with_separator_bounded_vec_matches_non_bounded_vec_version() {\n let inputs = BoundedVec::::from_array([1, 2, 3]);\n let separator = 42;\n\n // Hash using bounded vec version\n let bounded_result = poseidon2_hash_with_separator_bounded_vec(inputs, separator);\n\n // Hash using regular version\n let regular_result = poseidon2_hash_with_separator([1, 2, 3], separator);\n\n // Results should match\n assert_eq(bounded_result, regular_result);\n}\n"},"332":{"path":"/home/nerses/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.2/noir-projects/noir-protocol-circuits/crates/types/src/meta/mod.nr","source":"use utils::derive_serialization_quotes;\n\npub mod utils;\n\n/// Generates the generic parameter declarations for a struct's trait implementation.\n///\n/// This function takes a struct type definition and generates the generic parameter declarations\n/// that go after the `impl` keyword. For example, given a struct with generics `N: u32` and `T`,\n/// it generates ``.\n///\n/// # Parameters\n/// - `s`: The struct type definition to generate generic declarations for\n///\n/// # Returns\n/// A quoted code block containing the generic parameter declarations, or an empty quote if the struct\n/// has no generic parameters\n///\n/// # Example\n/// For a struct defined as:\n/// ```\n/// struct Container {\n/// items: [T; N],\n/// count: u32\n/// }\n/// ```\n///\n/// This function generates:\n/// ```\n/// \n/// ```\ncomptime fn get_generics_declarations(s: TypeDefinition) -> Quoted {\n let generics = s.generics();\n\n if generics.len() > 0 {\n let generics_declarations_items = generics\n .map(|(name, maybe_integer_typ)| {\n // The second item in the generics tuple is an Option of an integer type that is Some only if\n // the generic is numeric.\n if maybe_integer_typ.is_some() {\n // The generic is numeric, so we return a quote defined as e.g. \"let N: u32\"\n let integer_type = maybe_integer_typ.unwrap();\n quote {let $name: $integer_type}\n } else {\n // The generic is not numeric, so we return a quote containing the name of the generic (e.g. \"T\")\n quote {$name}\n }\n })\n .join(quote {,});\n quote {<$generics_declarations_items>}\n } else {\n // The struct doesn't have any generics defined, so we just return an empty quote.\n quote {}\n }\n}\n\n/// Generates the `where` clause for a trait implementation that constrains non-numeric generic type parameters.\n///\n/// This function takes a struct type definition and a trait name, and generates a `where` clause that\n/// requires all non-numeric generic type parameters to implement the specified trait.\n///\n/// # Parameters\n/// - `s`: The struct type definition to generate the where clause for\n/// - `trait_name`: The name of the trait that non-numeric generic parameters must implement\n///\n/// # Returns\n/// A quoted code block containing the where clause, or an empty quote if the struct has no non-numeric\n/// generic parameters\n///\n/// # Example\n/// For a struct defined as:\n/// ```\n/// struct Container {\n/// items: [T; N],\n/// count: u32\n/// }\n/// ```\n///\n/// And trait name \"Serialize\", this function generates:\n/// ```\n/// where T: Serialize\n/// ```\ncomptime fn get_where_trait_clause(s: TypeDefinition, trait_name: Quoted) -> Quoted {\n let generics = s.generics();\n\n // The second item in the generics tuple is an Option of an integer type that is Some only if the generic is\n // numeric.\n let non_numeric_generics =\n generics.filter(|(_, maybe_integer_typ)| maybe_integer_typ.is_none());\n\n if non_numeric_generics.len() > 0 {\n let non_numeric_generics_declarations =\n non_numeric_generics.map(|(name, _)| quote {$name: $trait_name}).join(quote {,});\n quote {where $non_numeric_generics_declarations}\n } else {\n // There are no non-numeric generics, so we return an empty quote.\n quote {}\n }\n}\n\n/// Generates a `Serialize` trait implementation for a struct type.\n///\n/// # Parameters\n/// - `s`: The struct type definition to generate the implementation for\n///\n/// # Returns\n/// A quoted code block containing the trait implementation\n///\n/// # Example\n/// For a struct defined as:\n/// ```\n/// struct Log {\n/// fields: [Field; N],\n/// length: u32\n/// }\n/// ```\n///\n/// This function generates code equivalent to:\n/// ```\n/// impl Serialize for Log {\n/// let N: u32 = <[Field; N] as Serialize>::N + ::N;\n///\n/// #[inline_always]\n/// fn serialize(self) -> [Field; Self::N] {\n/// let mut serialized_params = [0; _];\n/// let mut offset = 0;\n///\n/// let serialized_member = Serialize::serialize(self.fields);\n/// let serialized_member_len = <[Field; N] as Serialize>::N;\n/// for i in 0..serialized_member_len {\n/// serialized_params[i + offset] = serialized_member[i];\n/// }\n/// offset += serialized_member_len;\n///\n/// let serialized_member = Serialize::serialize(self.length);\n/// let serialized_member_len = ::N;\n/// for i in 0..serialized_member_len {\n/// serialized_params[i + offset] = serialized_member[i];\n/// }\n/// offset += serialized_member_len;\n///\n/// serialized_params\n/// }\n/// }\n/// ```\npub comptime fn derive_serialize(s: TypeDefinition) -> Quoted {\n let typ = s.as_type();\n let nested_struct = typ.as_data_type().unwrap();\n\n // We care only about the name and type so we drop the last item of the tuple\n let params = nested_struct.0.fields(nested_struct.1).map(|(name, typ, _)| (name, typ));\n\n // Generates the generic parameter declarations (to be placed after the `impl` keyword) and the `where` clause\n // for the `Serialize` trait.\n let generics_declarations = get_generics_declarations(s);\n let where_serialize_clause = get_where_trait_clause(s, quote {Serialize});\n\n let (function_body, params_len_quote, serialized_params_name) =\n derive_serialization_quotes(params, true);\n\n quote {\n impl$generics_declarations $crate::traits::Serialize for $typ\n $where_serialize_clause\n {\n let N: u32 = $params_len_quote;\n\n #[inline_always]\n fn serialize(self) -> [Field; Self::N] {\n $function_body\n\n $serialized_params_name\n }\n }\n }\n}\n\n/// Generates a `Deserialize` trait implementation for a given struct `s`.\n///\n/// # Arguments\n/// * `s` - The struct type definition to generate the implementation for\n///\n/// # Returns\n/// A `Quoted` block containing the generated trait implementation\n///\n/// # Requirements\n/// Each struct member type must implement the `Deserialize` trait (it gets used in the generated code).\n///\n/// # Example\n/// For a struct like:\n/// ```\n/// struct MyStruct {\n/// x: AztecAddress,\n/// y: Field,\n/// }\n/// ```\n///\n/// This generates:\n/// ```\n/// impl Deserialize for MyStruct {\n/// let N: u32 = ::N + ::N;\n///\n/// fn deserialize(serialized: [Field; Self::N]) -> Self {\n/// let mut offset = 0;\n/// let mut member_fields = [0; ::N];\n/// for i in 0..::N {\n/// member_fields[i] = serialized[i + offset];\n/// }\n/// let x = ::deserialize(member_fields);\n/// offset += ::N;\n///\n/// let mut member_fields = [0; ::N];\n/// for i in 0..::N {\n/// member_fields[i] = serialized[i + offset];\n/// }\n/// let y = ::deserialize(member_fields);\n/// offset += ::N;\n///\n/// Self { x, y }\n/// }\n/// }\n/// ```\npub(crate) comptime fn derive_deserialize(s: TypeDefinition) -> Quoted {\n let typ = s.as_type();\n let nested_struct = typ.as_data_type().unwrap();\n let params = nested_struct.0.fields(nested_struct.1);\n\n // Generates the generic parameter declarations (to be placed after the `impl` keyword) and the `where` clause\n // for the `Deserialize` trait.\n let generics_declarations = get_generics_declarations(s);\n let where_deserialize_clause = get_where_trait_clause(s, quote {Deserialize});\n\n // The following will give us ::N + ::N + ...\n let right_hand_side_of_definition_of_n = params\n .map(|(_, param_type, _): (Quoted, Type, Quoted)| {\n quote {\n <$param_type as $crate::traits::Deserialize>::N\n }\n })\n .join(quote {+});\n\n // For structs containing a single member, we can enhance performance by directly deserializing the input array,\n // bypassing the need for loop-based array construction. While this optimization yields significant benefits in\n // Brillig where the loops are expected to not be optimized, it is not relevant in ACIR where the loops are\n // expected to be optimized away.\n let function_body = if params.len() > 1 {\n // This generates deserialization code for each struct member and concatenates them together.\n let deserialization_of_struct_members = params\n .map(|(param_name, param_type, _): (Quoted, Type, Quoted)| {\n quote {\n let mut member_fields = [0; <$param_type as Deserialize>::N];\n for i in 0..<$param_type as Deserialize>::N {\n member_fields[i] = serialized[i + offset];\n }\n let $param_name = <$param_type as Deserialize>::deserialize(member_fields);\n offset += <$param_type as Deserialize>::N;\n }\n })\n .join(quote {});\n\n // We join the struct member names with a comma to be used in the `Self { ... }` syntax\n // This will give us e.g. `a, b, c` for a struct with three fields named `a`, `b`, and `c`.\n let struct_members = params\n .map(|(param_name, _, _): (Quoted, Type, Quoted)| quote { $param_name })\n .join(quote {,});\n\n quote {\n let mut offset = 0;\n\n $deserialization_of_struct_members\n\n Self { $struct_members }\n }\n } else {\n let param_name = params[0].0;\n quote {\n Self { $param_name: $crate::traits::Deserialize::deserialize(serialized) }\n }\n };\n\n quote {\n impl$generics_declarations $crate::traits::Deserialize for $typ\n $where_deserialize_clause\n {\n let N: u32 = $right_hand_side_of_definition_of_n;\n\n #[inline_always]\n fn deserialize(serialized: [Field; Self::N]) -> Self {\n $function_body\n }\n }\n }\n}\n\n/// Generates a `Packable` trait implementation for a given struct `s`.\n///\n/// # Arguments\n/// * `s` - The struct type definition to generate the implementation for\n///\n/// # Returns\n/// A `Quoted` block containing the generated trait implementation\n///\n/// # Requirements\n/// Each struct member type must implement the `Packable` trait (it gets used in the generated code).\n///\n/// # Example\n/// For a struct like:\n/// ```\n/// struct MyStruct {\n/// x: AztecAddress,\n/// y: Field,\n/// }\n/// ```\n///\n/// This generates:\n/// ```\n/// impl Packable for MyStruct {\n/// let N: u32 = 2;\n///\n/// fn pack(self) -> [Field; 2] {\n/// let mut result: [Field; 2] = [0_Field; 2];\n/// let mut offset: u32 = 0_u32;\n/// let packed_member: [Field; 1] = self.x.pack();\n/// let packed_member_len: u32 = ::N;\n/// for i in 0_u32..packed_member_len {\n/// {\n/// result[i + offset] = packed_member[i];\n/// }\n/// }\n/// offset = offset + packed_member_len;\n/// let packed_member: [Field; 1] = self.y.pack();\n/// let packed_member_len: u32 = ::N;\n/// for i in 0_u32..packed_member_len {\n/// {\n/// result[i + offset] = packed_member[i];\n/// }\n/// }\n/// offset = offset + packed_member_len;\n/// result\n/// }\n///\n/// fn unpack(packed: [Field; 2]) -> Self {\n/// let mut offset: u32 = 0_u32;\n/// let mut member_fields: [Field; 1] = [0_Field; 1];\n/// for i in 0_u32..::N {\n/// member_fields[i] = packed[i + offset];\n/// }\n/// let x: AztecAddress = ::unpack(member_fields);\n/// offset = offset + ::N;\n/// let mut member_fields: [Field; 1] = [0_Field; 1];\n/// for i in 0_u32..::N {\n/// member_fields[i] = packed[i + offset];\n/// }\n/// let y: Field = ::unpack(member_fields);\n/// offset = offset + ::N;\n/// Self { x: x, y: y }\n/// }\n/// }\n/// ```\npub comptime fn derive_packable(s: TypeDefinition) -> Quoted {\n let typ = s.as_type();\n let nested_struct = typ.as_data_type().unwrap();\n let params = nested_struct.0.fields(nested_struct.1);\n\n // Generates the generic parameter declarations (to be placed after the `impl` keyword) and the `where` clause\n // for the `Packable` trait.\n let generics_declarations = get_generics_declarations(s);\n let where_packable_clause = get_where_trait_clause(s, quote {Packable});\n\n // The following will give us ::N + ::N + ...\n let right_hand_side_of_definition_of_n = params\n .map(|(_, param_type, _): (Quoted, Type, Quoted)| {\n quote {\n <$param_type as $crate::traits::Packable>::N\n }\n })\n .join(quote {+});\n\n // For structs containing a single member, we can enhance performance by directly returning the packed member,\n // bypassing the need for loop-based array construction. While this optimization yields significant benefits in\n // Brillig where the loops are expected to not be optimized, it is not relevant in ACIR where the loops are\n // expected to be optimized away.\n let pack_function_body = if params.len() > 1 {\n // For multiple struct members, generate packing code that:\n // 1. Packs each member\n // 2. Copies the packed fields into the result array at the correct offset\n // 3. Updates the offset for the next member\n let packing_of_struct_members = params\n .map(|(param_name, param_type, _): (Quoted, Type, Quoted)| {\n quote {\n let packed_member = $crate::traits::Packable::pack(self.$param_name);\n let packed_member_len = <$param_type as $crate::traits::Packable>::N;\n for i in 0..packed_member_len {\n result[i + offset] = packed_member[i];\n }\n offset += packed_member_len;\n }\n })\n .join(quote {});\n\n quote {\n let mut result = [0; Self::N];\n let mut offset = 0;\n\n $packing_of_struct_members\n\n result\n }\n } else {\n let param_name = params[0].0;\n quote {\n $crate::traits::Packable::pack(self.$param_name)\n }\n };\n\n // For structs containing a single member, we can enhance performance by directly unpacking the input array,\n // bypassing the need for loop-based array construction. While this optimization yields significant benefits in\n // Brillig where the loops are expected to not be optimized, it is not relevant in ACIR where the loops are\n // expected to be optimized away.\n let unpack_function_body = if params.len() > 1 {\n // For multiple struct members, generate unpacking code that:\n // 1. Unpacks each member\n // 2. Copies packed fields into member array at correct offset\n // 3. Updates offset for next member\n let unpacking_of_struct_members = params\n .map(|(param_name, param_type, _): (Quoted, Type, Quoted)| {\n quote {\n let mut member_fields = [0; <$param_type as $crate::traits::Packable>::N];\n for i in 0..<$param_type as $crate::traits::Packable>::N {\n member_fields[i] = packed[i + offset];\n }\n let $param_name = <$param_type as $crate::traits::Packable>::unpack(member_fields);\n offset += <$param_type as $crate::traits::Packable>::N;\n }\n })\n .join(quote {});\n\n // We join the struct member names with a comma to be used in the `Self { ... }` syntax\n let struct_members = params\n .map(|(param_name, _, _): (Quoted, Type, Quoted)| quote { $param_name })\n .join(quote {,});\n\n quote {\n let mut offset = 0;\n $unpacking_of_struct_members\n Self { $struct_members }\n }\n } else {\n let param_name = params[0].0;\n quote {\n Self { $param_name: $crate::traits::Packable::unpack(packed) }\n }\n };\n\n quote {\n impl$generics_declarations $crate::traits::Packable for $typ\n $where_packable_clause\n {\n let N: u32 = $right_hand_side_of_definition_of_n;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n $pack_function_body\n }\n\n #[inline_always]\n fn unpack(packed: [Field; Self::N]) -> Self {\n $unpack_function_body\n }\n }\n }\n}\n\nmod test {\n use crate::traits::{Deserialize, Packable, Serialize};\n\n #[derive(Deserialize, Eq, Packable, Serialize)]\n pub struct Smol {\n a: Field,\n b: Field,\n }\n\n #[derive(Deserialize, Eq, Serialize)]\n pub struct HasArray {\n a: [Field; 2],\n b: bool,\n }\n\n #[derive(Deserialize, Eq, Serialize)]\n pub struct Fancier {\n a: Smol,\n b: [Field; 2],\n c: [u8; 3],\n d: str<16>,\n }\n\n #[derive(Deserialize, Eq, Packable, Serialize)]\n pub struct HasArrayWithGenerics {\n pub fields: [T; N],\n pub length: u32,\n }\n\n #[test]\n fn serde_on_smol() {\n let smol = Smol { a: 1, b: 2 };\n let serialized = smol.serialize();\n assert(serialized == [1, 2], serialized);\n let deserialized = Smol::deserialize(serialized);\n assert(deserialized == smol);\n\n // None of the struct members implements the `Packable` trait so the packed and serialized data should be the same\n let packed = smol.pack();\n assert_eq(packed, serialized, \"Packed does not match serialized\");\n }\n\n #[test]\n fn serde_on_has_array() {\n let has_array = HasArray { a: [1, 2], b: true };\n let serialized = has_array.serialize();\n assert(serialized == [1, 2, 1], serialized);\n let deserialized = HasArray::deserialize(serialized);\n assert(deserialized == has_array);\n }\n\n #[test]\n fn serde_on_fancier() {\n let fancier =\n Fancier { a: Smol { a: 1, b: 2 }, b: [0, 1], c: [1, 2, 3], d: \"metaprogramming!\" };\n let serialized = fancier.serialize();\n assert(\n serialized\n == [\n 1, 2, 0, 1, 1, 2, 3, 0x6d, 0x65, 0x74, 0x61, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61,\n 0x6d, 0x6d, 0x69, 0x6e, 0x67, 0x21,\n ],\n serialized,\n );\n let deserialized = Fancier::deserialize(serialized);\n assert(deserialized == fancier);\n }\n\n #[test]\n fn serde_on_contains_array_with_generics() {\n let struct_with_array_of_generics = HasArrayWithGenerics { fields: [1, 2, 3], length: 3 };\n let serialized = struct_with_array_of_generics.serialize();\n assert(serialized == [1, 2, 3, 3], serialized);\n let deserialized = HasArrayWithGenerics::deserialize(serialized);\n assert(deserialized == struct_with_array_of_generics);\n }\n\n #[test]\n fn packable_on_contains_array_with_generics() {\n let struct_with_array_of_generics = HasArrayWithGenerics { fields: [1, 2, 3], length: 3 };\n let packed = struct_with_array_of_generics.pack();\n assert(packed == [1, 2, 3, 3], packed);\n\n let unpacked = HasArrayWithGenerics::unpack(packed);\n assert(unpacked == struct_with_array_of_generics);\n }\n\n}\n"},"333":{"path":"/home/nerses/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.2/noir-projects/noir-protocol-circuits/crates/types/src/meta/utils.nr","source":"/// Generates serialization code for a list of parameters and the total length of the serialized array\n///\n/// # Parameters\n/// - `params`: A list of (name, type) tuples to serialize\n/// - `use_self_prefix`: If true, parameters are accessed as `self.$param_name` (for struct members).\n/// If false, parameters are accessed directly as `$param_name` (for function parameters).\n///\n/// # Returns\n/// A tuple containing:\n/// - Quoted code that serializes the parameters into an array named `serialized_params`\n/// - Quoted code that evaluates to the total length of the serialized array\n/// - Quoted code containing the name of the serialized array\npub comptime fn derive_serialization_quotes(\n params: [(Quoted, Type)],\n use_self_prefix: bool,\n) -> (Quoted, Quoted, Quoted) {\n let prefix_quote = if use_self_prefix {\n quote { self. }\n } else {\n quote {}\n };\n\n let params_len_quote = get_params_len_quote(params);\n let serialized_params_name = quote { serialized_params };\n\n let body = if params.len() == 0 {\n quote {\n let $serialized_params_name: [Field; 0] = [];\n }\n } else if params.len() == 1 {\n // When we have only a single parameter on the input, we can enhance performance by directly returning\n // the serialized member, bypassing the need for loop-based array construction. While this optimization yields\n // significant benefits in Brillig where the loops are expected to not be optimized, it is not relevant in ACIR\n // where the loops are expected to be optimized away.\n\n let param_name = params[0].0;\n quote {\n let $serialized_params_name = $crate::traits::Serialize::serialize($prefix_quote$param_name);\n }\n } else {\n // For multiple struct members, generate serialization code that:\n // 1. Serializes each member\n // 2. Copies the serialized fields into the serialize array at the correct offset\n // 3. Updates the offset for the next member\n let serialization_of_struct_members = params\n .map(|(param_name, param_type): (Quoted, Type)| {\n quote {\n let serialized_member = $crate::traits::Serialize::serialize($prefix_quote$param_name);\n let serialized_member_len = <$param_type as $crate::traits::Serialize>::N;\n for i in 0..serialized_member_len {\n $serialized_params_name[i + offset] = serialized_member[i];\n }\n offset += serialized_member_len;\n }\n })\n .join(quote {});\n\n quote {\n let mut $serialized_params_name = [0; $params_len_quote];\n let mut offset = 0;\n\n $serialization_of_struct_members\n }\n };\n\n (body, params_len_quote, serialized_params_name)\n}\n\n/// Generates a quoted expression that computes the total serialized length of function parameters.\n///\n/// # Parameters\n/// * `params` - An array of tuples where each tuple contains a quoted parameter name and its Type. The type needs\n/// to implement the Serialize trait.\n///\n/// # Returns\n/// A quoted expression that evaluates to:\n/// * `0` if there are no parameters\n/// * `(::N + ::N + ...)` for one or more parameters\npub comptime fn get_params_len_quote(params: [(Quoted, Type)]) -> Quoted {\n if params.len() == 0 {\n quote { 0 }\n } else {\n let params_quote_without_parentheses = params\n .map(|(_, param_type): (Quoted, Type)| {\n quote {\n <$param_type as $crate::traits::Serialize>::N\n }\n })\n .join(quote {+});\n quote { ($params_quote_without_parentheses) }\n }\n}\n"},"334":{"path":"/home/nerses/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.2/noir-projects/noir-protocol-circuits/crates/types/src/point.nr","source":"pub use dep::std::embedded_curve_ops::EmbeddedCurvePoint as Point;\nuse crate::{hash::poseidon2_hash, traits::{Deserialize, Empty, Hash, Packable, Serialize}};\n\npub global POINT_LENGTH: u32 = 3;\n\n// Note: Not deriving this because it's not supported to call derive_serialize on a \"remote\" struct (and it will never\n// be supported).\nimpl Serialize for Point {\n let N: u32 = POINT_LENGTH;\n\n fn serialize(self: Self) -> [Field; Self::N] {\n [self.x, self.y, self.is_infinite as Field]\n }\n}\n\nimpl Hash for Point {\n fn hash(self) -> Field {\n poseidon2_hash(self.serialize())\n }\n}\n\nimpl Empty for Point {\n /// Note: Does not return a valid point on curve - instead represents an empty/\"unpopulated\" point struct (e.g.\n /// empty/unpopulated value in an array of points).\n fn empty() -> Self {\n Point { x: 0, y: 0, is_infinite: false }\n }\n}\n\nimpl Deserialize for Point {\n let N: u32 = POINT_LENGTH;\n\n fn deserialize(serialized: [Field; Self::N]) -> Self {\n Point { x: serialized[0], y: serialized[1], is_infinite: serialized[2] != 0 }\n }\n}\n\n// TODO(#11356): use compact representation here.\nimpl Packable for Point {\n let N: u32 = POINT_LENGTH;\n\n fn pack(self) -> [Field; Self::N] {\n self.serialize()\n }\n\n fn unpack(packed: [Field; Self::N]) -> Self {\n Self::deserialize(packed)\n }\n}\n"},"335":{"path":"/home/nerses/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.2/noir-projects/noir-protocol-circuits/crates/types/src/poseidon2.nr","source":"use crate::constants::TWO_POW_64;\nuse crate::traits::{Deserialize, Serialize};\nuse std::meta::derive;\n// NB: This is a clone of noir/noir-repo/noir_stdlib/src/hash/poseidon2.nr\n// It exists as we sometimes need to perform custom absorption, but the stdlib version\n// has a private absorb() method (it's also designed to just be a hasher)\n// Can be removed when standalone noir poseidon lib exists: See noir#6679\n\ncomptime global RATE: u32 = 3;\n\n#[derive(Deserialize, Eq, Serialize)]\npub struct Poseidon2Sponge {\n pub cache: [Field; 3],\n pub state: [Field; 4],\n pub cache_size: u32,\n pub squeeze_mode: bool, // 0 => absorb, 1 => squeeze\n}\n\nimpl Poseidon2Sponge {\n #[no_predicates]\n pub fn hash(input: [Field; N], message_size: u32) -> Field {\n Poseidon2Sponge::hash_internal(input, message_size, message_size != N)\n }\n\n pub(crate) fn new(iv: Field) -> Poseidon2Sponge {\n let mut result =\n Poseidon2Sponge { cache: [0; 3], state: [0; 4], cache_size: 0, squeeze_mode: false };\n result.state[RATE] = iv;\n result\n }\n\n fn perform_duplex(&mut self) {\n // add the cache into sponge state\n for i in 0..RATE {\n // We effectively zero-pad the cache by only adding to the state\n // cache that is less than the specified `cache_size`\n if i < self.cache_size {\n self.state[i] += self.cache[i];\n }\n }\n self.state = std::hash::poseidon2_permutation(self.state, 4);\n }\n\n pub fn absorb(&mut self, input: Field) {\n assert(!self.squeeze_mode);\n if self.cache_size == RATE {\n // If we're absorbing, and the cache is full, apply the sponge permutation to compress the cache\n self.perform_duplex();\n self.cache[0] = input;\n self.cache_size = 1;\n } else {\n // If we're absorbing, and the cache is not full, add the input into the cache\n self.cache[self.cache_size] = input;\n self.cache_size += 1;\n }\n }\n\n pub fn squeeze(&mut self) -> Field {\n assert(!self.squeeze_mode);\n // If we're in absorb mode, apply sponge permutation to compress the cache.\n self.perform_duplex();\n self.squeeze_mode = true;\n\n // Pop one item off the top of the permutation and return it.\n self.state[0]\n }\n\n fn hash_internal(\n input: [Field; N],\n in_len: u32,\n is_variable_length: bool,\n ) -> Field {\n let iv: Field = (in_len as Field) * TWO_POW_64;\n let mut sponge = Poseidon2Sponge::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"},"342":{"path":"/home/nerses/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.2/noir-projects/noir-protocol-circuits/crates/types/src/public_keys.nr","source":"use crate::{\n address::public_keys_hash::PublicKeysHash,\n constants::{\n DEFAULT_IVPK_M_X, DEFAULT_IVPK_M_Y, DEFAULT_NPK_M_X, DEFAULT_NPK_M_Y, DEFAULT_OVPK_M_X,\n DEFAULT_OVPK_M_Y, DEFAULT_TPK_M_X, DEFAULT_TPK_M_Y, GENERATOR_INDEX__PUBLIC_KEYS_HASH,\n },\n hash::poseidon2_hash_with_separator,\n traits::{Deserialize, Hash, Serialize},\n};\n\nuse dep::std::embedded_curve_ops::EmbeddedCurvePoint as Point;\nuse std::{default::Default, meta::derive};\n\npub trait ToPoint {\n fn to_point(self) -> Point;\n}\n\n#[derive(Deserialize, Eq, Serialize)]\npub struct NpkM {\n pub inner: Point,\n}\n\nimpl ToPoint for NpkM {\n fn to_point(self) -> Point {\n self.inner\n }\n}\n\n// Note: If we store npk_m_hash directly we can remove this trait implementation. See #8091\nimpl Hash for NpkM {\n fn hash(self) -> Field {\n self.inner.hash()\n }\n}\n\n#[derive(Deserialize, Eq, Serialize)]\npub struct IvpkM {\n pub inner: Point,\n}\n\nimpl ToPoint for IvpkM {\n fn to_point(self) -> Point {\n self.inner\n }\n}\n\n#[derive(Deserialize, Eq, Serialize)]\npub struct OvpkM {\n pub inner: Point,\n}\n\nimpl Hash for OvpkM {\n fn hash(self) -> Field {\n self.inner.hash()\n }\n}\n\nimpl ToPoint for OvpkM {\n fn to_point(self) -> Point {\n self.inner\n }\n}\n\n#[derive(Deserialize, Eq, Serialize)]\npub struct TpkM {\n pub inner: Point,\n}\n\nimpl ToPoint for TpkM {\n fn to_point(self) -> Point {\n self.inner\n }\n}\n\n#[derive(Deserialize, Eq, Serialize)]\npub struct PublicKeys {\n pub npk_m: NpkM,\n pub ivpk_m: IvpkM,\n pub ovpk_m: OvpkM,\n pub tpk_m: TpkM,\n}\n\nimpl Default for PublicKeys {\n fn default() -> Self {\n PublicKeys {\n npk_m: NpkM {\n inner: Point { x: DEFAULT_NPK_M_X, y: DEFAULT_NPK_M_Y, is_infinite: false },\n },\n ivpk_m: IvpkM {\n inner: Point { x: DEFAULT_IVPK_M_X, y: DEFAULT_IVPK_M_Y, is_infinite: false },\n },\n ovpk_m: OvpkM {\n inner: Point { x: DEFAULT_OVPK_M_X, y: DEFAULT_OVPK_M_Y, is_infinite: false },\n },\n tpk_m: TpkM {\n inner: Point { x: DEFAULT_TPK_M_X, y: DEFAULT_TPK_M_Y, is_infinite: false },\n },\n }\n }\n}\n\nimpl PublicKeys {\n pub fn hash(self) -> PublicKeysHash {\n PublicKeysHash::from_field(poseidon2_hash_with_separator(\n self.serialize(),\n GENERATOR_INDEX__PUBLIC_KEYS_HASH as Field,\n ))\n }\n}\n\npub struct AddressPoint {\n pub inner: Point,\n}\n\nimpl ToPoint for AddressPoint {\n fn to_point(self) -> Point {\n self.inner\n }\n}\n\nmod test {\n use crate::{\n point::POINT_LENGTH,\n public_keys::{IvpkM, NpkM, OvpkM, PublicKeys, TpkM},\n traits::{Deserialize, Serialize},\n };\n use dep::std::embedded_curve_ops::EmbeddedCurvePoint as Point;\n\n #[test]\n unconstrained fn compute_public_keys_hash() {\n let keys = PublicKeys {\n npk_m: NpkM { inner: Point { x: 1, y: 2, is_infinite: false } },\n ivpk_m: IvpkM { inner: Point { x: 3, y: 4, is_infinite: false } },\n ovpk_m: OvpkM { inner: Point { x: 5, y: 6, is_infinite: false } },\n tpk_m: TpkM { inner: Point { x: 7, y: 8, is_infinite: false } },\n };\n\n let actual = keys.hash();\n let expected_public_keys_hash =\n 0x0fecd9a32db731fec1fded1b9ff957a1625c069245a3613a2538bd527068b0ad;\n\n assert(actual.to_field() == expected_public_keys_hash);\n }\n\n #[test]\n unconstrained fn compute_default_hash() {\n let keys = PublicKeys::default();\n\n let actual = keys.hash();\n let test_data_default_hash =\n 0x1d3bf1fb93ae0e9cda83b203dd91c3bfb492a9aecf30ec90e1057eced0f0e62d;\n\n assert(actual.to_field() == test_data_default_hash);\n }\n\n #[test]\n unconstrained fn serde() {\n let keys = PublicKeys {\n npk_m: NpkM { inner: Point { x: 1, y: 2, is_infinite: false } },\n ivpk_m: IvpkM { inner: Point { x: 3, y: 4, is_infinite: false } },\n ovpk_m: OvpkM { inner: Point { x: 5, y: 6, is_infinite: false } },\n tpk_m: TpkM { inner: Point { x: 7, y: 8, is_infinite: false } },\n };\n\n // We use the PUBLIC_KEYS_LENGTH constant to ensure that there is a match between the derived trait\n let serialized: [Field; POINT_LENGTH * 4] = keys.serialize();\n let deserialized = PublicKeys::deserialize(serialized);\n\n assert_eq(keys, deserialized);\n }\n}\n"},"347":{"path":"/home/nerses/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.2/noir-projects/noir-protocol-circuits/crates/types/src/storage/map.nr","source":"use crate::{hash::poseidon2_hash, traits::ToField};\n\npub fn derive_storage_slot_in_map(storage_slot: Field, key: K) -> Field\nwhere\n K: ToField,\n{\n poseidon2_hash([storage_slot, key.to_field()])\n}\n\nmod test {\n use crate::{address::AztecAddress, storage::map::derive_storage_slot_in_map, traits::FromField};\n\n #[test]\n fn test_derive_storage_slot_in_map_matches_typescript() {\n let map_slot = 0x132258fb6962c4387ba659d9556521102d227549a386d39f0b22d1890d59c2b5;\n let key = AztecAddress::from_field(\n 0x302dbc2f9b50a73283d5fb2f35bc01eae8935615817a0b4219a057b2ba8a5a3f,\n );\n\n let slot = derive_storage_slot_in_map(map_slot, key);\n\n // The following value was generated by `map_slot.test.ts`\n let slot_from_typescript =\n 0x15b9fe39449affd8b377461263e9d2b610b9ad40580553500b4e41d9cbd887ac;\n\n assert_eq(slot, slot_from_typescript);\n }\n}\n"},"363":{"path":"/home/nerses/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.2/noir-projects/noir-protocol-circuits/crates/types/src/traits.nr","source":"use crate::meta::{derive_deserialize, derive_packable, derive_serialize};\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.\npub trait Empty: Eq {\n fn empty() -> Self;\n\n fn is_empty(self) -> bool {\n self.eq(Self::empty())\n }\n\n // Requires this Noir fix: https://github.com/noir-lang/noir/issues/9002\n // fn assert_not_empty(self, msg: str) { // This msg version was failing with weird compiler errors.\n // // We provide a default impl but it's likely inefficient.\n // // The reason we include this function is because there's a lot of\n // // opportunity for optimisation on a per-struct basis.\n // // You only need to show one element is not empty to know that the whole thing\n // // is not empty.\n // // If you know an element of your struct which should always be nonempty,\n // // you can write an impl that solely checks that that element is nonempty.\n // assert(!self.is_empty(), msg);\n // }\n\n // This default impl is overwritten by types like arrays, because there's a much\n // more efficient approach.\n fn assert_empty(self, msg: str) {\n assert(self.is_empty(), msg);\n }\n}\n\nimpl Empty for Field {\n #[inline_always]\n fn empty() -> Self {\n 0\n }\n}\n\nimpl Empty for u1 {\n #[inline_always]\n fn empty() -> Self {\n 0\n }\n}\nimpl Empty for u8 {\n #[inline_always]\n fn empty() -> Self {\n 0\n }\n}\nimpl Empty for u16 {\n fn empty() -> Self {\n 0\n }\n}\nimpl Empty for u32 {\n #[inline_always]\n fn empty() -> Self {\n 0\n }\n}\nimpl Empty for u64 {\n #[inline_always]\n fn empty() -> Self {\n 0\n }\n}\nimpl Empty for u128 {\n #[inline_always]\n fn empty() -> Self {\n 0\n }\n}\n\nimpl Empty for [T; N]\nwhere\n T: Empty,\n{\n #[inline_always]\n fn empty() -> Self {\n [T::empty(); N]\n }\n\n fn is_empty(self) -> bool {\n self.all(|elem| elem.is_empty())\n }\n\n fn assert_empty(self, msg: str) -> () {\n self.for_each(|elem| elem.assert_empty(msg))\n }\n}\n\nimpl Empty for [T]\nwhere\n T: Empty,\n{\n #[inline_always]\n fn empty() -> Self {\n [T::empty()]\n }\n\n fn is_empty(self) -> bool {\n self.all(|elem| elem.is_empty())\n }\n\n fn assert_empty(self, msg: str) -> () {\n self.for_each(|elem| elem.assert_empty(msg))\n }\n}\nimpl Empty for (A, B)\nwhere\n A: Empty,\n B: Empty,\n{\n #[inline_always]\n fn empty() -> Self {\n (A::empty(), B::empty())\n }\n}\n\nimpl Empty for Option\nwhere\n T: Eq,\n{\n #[inline_always]\n fn empty() -> Self {\n Option::none()\n }\n}\n\n// pub fn is_empty(item: T) -> bool\n// where\n// T: Empty,\n// {\n// item.eq(T::empty())\n// }\n\n// pub fn is_empty_array(array: [T; N]) -> bool\n// where\n// T: Empty,\n// {\n// array.all(|elem| is_empty(elem))\n// }\n\n// pub fn assert_empty(item: T) -> ()\n// where\n// T: Empty,\n// {\n// assert(item.eq(T::empty()))\n// }\n\n// pub fn assert_empty_array(array: [T; N]) -> ()\n// where\n// T: Empty,\n// {\n// // A cheaper option than `is_empty_array` for if you don't need to gracefully\n// // handle a bool result.\n// // Avoids the `&` operator of `is_empty_array`'s `.all()` call.\n// for i in 0..N {\n// assert(is_empty(array[i]));\n// }\n// }\n\npub trait Hash {\n fn hash(self) -> Field;\n}\n\npub trait ToField {\n fn to_field(self) -> Field;\n}\n\nimpl ToField for Field {\n #[inline_always]\n fn to_field(self) -> Field {\n self\n }\n}\n\nimpl ToField for bool {\n #[inline_always]\n fn to_field(self) -> Field {\n self as Field\n }\n}\nimpl ToField for u1 {\n #[inline_always]\n fn to_field(self) -> Field {\n self as Field\n }\n}\nimpl ToField for u8 {\n #[inline_always]\n fn to_field(self) -> Field {\n self as Field\n }\n}\nimpl ToField for u16 {\n fn to_field(self) -> Field {\n self as Field\n }\n}\nimpl ToField for u32 {\n #[inline_always]\n fn to_field(self) -> Field {\n self as Field\n }\n}\nimpl ToField for u64 {\n #[inline_always]\n fn to_field(self) -> Field {\n self as Field\n }\n}\nimpl ToField for u128 {\n #[inline_always]\n fn to_field(self) -> Field {\n self as Field\n }\n}\nimpl ToField for str {\n #[inline_always]\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\npub trait FromField {\n fn from_field(value: Field) -> Self;\n}\n\nimpl FromField for Field {\n #[inline_always]\n fn from_field(value: Field) -> Self {\n value\n }\n}\n\nimpl FromField for bool {\n #[inline_always]\n fn from_field(value: Field) -> Self {\n value != 0\n }\n}\nimpl FromField for u1 {\n #[inline_always]\n fn from_field(value: Field) -> Self {\n value as u1\n }\n}\nimpl FromField for u8 {\n #[inline_always]\n fn from_field(value: Field) -> Self {\n value as u8\n }\n}\nimpl FromField for u16 {\n fn from_field(value: Field) -> Self {\n value as u16\n }\n}\nimpl FromField for u32 {\n #[inline_always]\n fn from_field(value: Field) -> Self {\n value as u32\n }\n}\nimpl FromField for u64 {\n #[inline_always]\n fn from_field(value: Field) -> Self {\n value as u64\n }\n}\nimpl FromField for u128 {\n #[inline_always]\n fn from_field(value: Field) -> Self {\n value as u128\n }\n}\n\n// docs:start:serialize\n/// Trait for serializing Noir types into arrays of Fields.\n///\n/// An implementation of the Serialize trait has to follow Noir's intrinsic serialization (each member of a struct\n/// converted directly into one or more Fields without any packing or compression). This trait (and Deserialize) are\n/// typically used to communicate between Noir and TypeScript (via oracles and function arguments).\n///\n/// # On Following Noir's Intrinsic Serialization\n/// When calling a Noir function from TypeScript (TS), first the function arguments are serialized into an array\n/// of fields. This array is then included in the initial witness. Noir's intrinsic serialization is then used\n/// to deserialize the arguments from the witness. When the same Noir function is called from Noir this Serialize trait\n/// is used instead of the serialization in TS. For this reason we need to have a match between TS serialization,\n/// Noir's intrinsic serialization and the implementation of this trait. If there is a mismatch, the function calls\n/// fail with an arguments hash mismatch error message.\n///\n/// # Associated Constants\n/// * `N` - The length of the output Field array, known at compile time\n///\n/// # Example\n/// ```\n/// impl Serialize for str {\n/// let N: u32 = N;\n///\n/// fn serialize(self) -> [Field; Self::N] {\n/// let bytes = self.as_bytes();\n/// let mut fields = [0; Self::N];\n/// for i in 0..bytes.len() {\n/// fields[i] = bytes[i] as Field; // Each byte gets its own Field\n/// }\n/// fields\n/// }\n/// }\n/// ```\n#[derive_via(derive_serialize)]\npub trait Serialize {\n let N: u32;\n\n fn serialize(self) -> [Field; N];\n}\n// docs:end:serialize\n\nimpl Serialize for str {\n let N: u32 = M;\n\n #[inline_always]\n fn serialize(self) -> [Field; Self::N] {\n let bytes = self.as_bytes();\n let mut fields = [0; Self::N];\n for i in 0..bytes.len() {\n fields[i] = bytes[i] as Field;\n }\n fields\n }\n}\n\n/// Implementation of Deserialize for BoundedVec.\n///\n/// This implementation deserializes a BoundedVec from an array of Fields. The array contains:\n/// 1. The serialized items, each taking up T::N Fields\n/// 2. The length of the BoundedVec as the last Field\n///\n/// # Type Parameters\n/// * `T` - The type of items stored in the BoundedVec, must implement Deserialize\n/// * `M` - The maximum length of the BoundedVec\n///\n/// # Fields Array Layout\n/// [item1_field1, item1_field2, ..., item2_field1, item2_field2, ..., length]\n/// Where:\n/// - itemN_fieldM: The M-th Field of the N-th item (T::N Fields per item)\n/// - length: The number of items in the BoundedVec (1 Field)\n///\n/// Total length N = T::N * M + 1, where:\n/// - T::N is the number of Fields needed to deserialize one item\n/// - M is the maximum length of the BoundedVec\n/// - +1 is for storing the length\n///\n/// # Note\n/// Not deriving this because it's not supported to call derive_deserialize on a \"remote\" struct (and it will never\n/// be supported).\nimpl Deserialize for BoundedVec\nwhere\n T: Deserialize,\n{\n let N: u32 = ::N * M + 1;\n\n #[inline_always]\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut new_bounded_vec: BoundedVec = BoundedVec::new();\n\n // Length is stored in the last field as we need to match intrinsic Noir serialization and the `len` struct\n // field is after `storage` struct field (see `bounded_vec.nr` in noir-stdlib)\n let len = fields[::N * M] as u32;\n\n for i in 0..len {\n let mut nested_fields = [0; ::N];\n for j in 0..::N {\n nested_fields[j] = fields[i * ::N + j];\n }\n\n let item = T::deserialize(nested_fields);\n new_bounded_vec.push(item);\n }\n\n new_bounded_vec\n }\n}\n\n// This may cause issues if used as program input, because noir disallows empty arrays for program input.\n// I think this is okay because I don't foresee a unit type being used as input. But leaving this comment as a hint\n// if someone does run into this in the future.\nimpl Deserialize for () {\n let N: u32 = 0;\n\n fn deserialize(_fields: [Field; Self::N]) -> Self {\n ()\n }\n}\n\n// Note: Not deriving this because it's not supported to call derive_serialize on a \"remote\" struct (and it will never\n// be supported).\nimpl Serialize for BoundedVec\nwhere\n T: Serialize,\n{\n let N: u32 = ::N * M + 1; // +1 for the length of the BoundedVec\n\n #[inline_always]\n fn serialize(self) -> [Field; Self::N] {\n let mut fields = [0; Self::N];\n\n let storage = self.storage();\n\n for i in 0..M {\n let serialized_item = storage[i].serialize();\n\n for j in 0..::N {\n fields[i * ::N + j] = serialized_item[j];\n }\n }\n\n // Length is stored in the last field as we need to match intrinsic Noir serialization and the `len` struct\n // field is after `storage` struct field (see `bounded_vec.nr` in noir-stdlib)\n fields[::N * M] = self.len() as Field;\n\n fields\n }\n}\n\n// docs:start:deserialize\n/// Trait for deserializing Noir types from arrays of Fields.\n///\n/// An implementation of the Deserialize trait has to follow Noir's intrinsic serialization (each member of a struct\n/// converted directly into one or more Fields without any packing or compression). This trait is typically used when\n/// deserializing return values from function calls in Noir. Since the same function could be called from TypeScript\n/// (TS), in which case the TS deserialization would get used, we need to have a match between the 2.\n///\n/// # Associated Constants\n/// * `N` - The length of the input Field array, known at compile time\n///\n/// # Example\n/// ```\n/// impl Deserialize for str {\n/// let N: u32 = M;\n///\n/// #[inline_always]\n/// fn deserialize(fields: [Field; Self::N]) -> Self {\n/// str::::from(fields.map(|value| value as u8))\n/// }\n/// }\n/// ```\n#[derive_via(derive_deserialize)]\npub trait Deserialize {\n let N: u32;\n\n fn deserialize(fields: [Field; N]) -> Self;\n}\n// docs:end:deserialize\n\nimpl Deserialize for str {\n let N: u32 = M;\n\n #[inline_always]\n fn deserialize(fields: [Field; Self::N]) -> Self {\n str::::from(fields.map(|value| value as u8))\n }\n}\n\n/// Trait for efficiently packing and unpacking Noir types into and from arrays of Fields.\n///\n/// The `Packable` trait allows types to be serialized and deserialized with a focus on minimizing the size of\n/// the resulting Field array. This trait is used when storage efficiency is critical (e.g. when storing data\n/// in the contract's public storage).\n///\n/// # Associated Constants\n/// * `N` - The length of the Field array, known at compile time\n#[derive_via(derive_packable)]\npub trait Packable {\n let N: u32;\n\n /// Packs the current value into a compact array of `Field` elements.\n fn pack(self) -> [Field; N];\n\n /// Unpacks a compact array of `Field` elements into the original value.\n fn unpack(fields: [Field; N]) -> Self;\n}\n\n#[test]\nunconstrained fn bounded_vec_serialization() {\n // Test empty BoundedVec\n let empty_vec: BoundedVec = BoundedVec::from_array([]);\n let serialized = empty_vec.serialize();\n let deserialized = BoundedVec::::deserialize(serialized);\n assert_eq(empty_vec, deserialized);\n assert_eq(deserialized.len(), 0);\n\n // Test partially filled BoundedVec\n let partial_vec: BoundedVec<[u32; 2], 3> = BoundedVec::from_array([[1, 2]]);\n let serialized = partial_vec.serialize();\n let deserialized = BoundedVec::<[u32; 2], 3>::deserialize(serialized);\n assert_eq(partial_vec, deserialized);\n assert_eq(deserialized.len(), 1);\n assert_eq(deserialized.get(0), [1, 2]);\n\n // Test full BoundedVec\n let full_vec: BoundedVec<[u32; 2], 3> = BoundedVec::from_array([[1, 2], [3, 4], [5, 6]]);\n let serialized = full_vec.serialize();\n let deserialized = BoundedVec::<[u32; 2], 3>::deserialize(serialized);\n assert_eq(full_vec, deserialized);\n assert_eq(deserialized.len(), 3);\n assert_eq(deserialized.get(0), [1, 2]);\n assert_eq(deserialized.get(1), [3, 4]);\n assert_eq(deserialized.get(2), [5, 6]);\n}\n"},"365":{"path":"/home/nerses/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.2/noir-projects/noir-protocol-circuits/crates/types/src/type_packing.nr","source":"use crate::traits::Packable;\n\nglobal BOOL_PACKED_LEN: u32 = 1;\nglobal U8_PACKED_LEN: u32 = 1;\nglobal U16_PACKED_LEN: u32 = 1;\nglobal U32_PACKED_LEN: u32 = 1;\nglobal U64_PACKED_LEN: u32 = 1;\nglobal U128_PACKED_LEN: u32 = 1;\nglobal FIELD_PACKED_LEN: u32 = 1;\nglobal I8_PACKED_LEN: u32 = 1;\nglobal I16_PACKED_LEN: u32 = 1;\nglobal I32_PACKED_LEN: u32 = 1;\nglobal I64_PACKED_LEN: u32 = 1;\n\nimpl Packable for bool {\n let N: u32 = BOOL_PACKED_LEN;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n [self as Field]\n }\n\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> bool {\n (fields[0] as u1) != 0\n }\n}\n\nimpl Packable for u8 {\n let N: u32 = U8_PACKED_LEN;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n [self as Field]\n }\n\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> Self {\n fields[0] as u8\n }\n}\n\nimpl Packable for u16 {\n let N: u32 = U16_PACKED_LEN;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n [self as Field]\n }\n\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> Self {\n fields[0] as u16\n }\n}\n\nimpl Packable for u32 {\n let N: u32 = U32_PACKED_LEN;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n [self as Field]\n }\n\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> Self {\n fields[0] as u32\n }\n}\n\nimpl Packable for u64 {\n let N: u32 = U64_PACKED_LEN;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n [self as Field]\n }\n\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> Self {\n fields[0] as u64\n }\n}\n\nimpl Packable for u128 {\n let N: u32 = U128_PACKED_LEN;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n [self as Field]\n }\n\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> Self {\n fields[0] as u128\n }\n}\n\nimpl Packable for Field {\n let N: u32 = FIELD_PACKED_LEN;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n [self]\n }\n\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> Self {\n fields[0]\n }\n}\n\nimpl Packable for i8 {\n let N: u32 = I8_PACKED_LEN;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n [self as u8 as Field]\n }\n\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> Self {\n fields[0] as u8 as i8\n }\n}\n\nimpl Packable for i16 {\n let N: u32 = I16_PACKED_LEN;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n [self as u16 as Field]\n }\n\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> Self {\n fields[0] as u16 as i16\n }\n}\n\nimpl Packable for i32 {\n let N: u32 = I32_PACKED_LEN;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n [self as u32 as Field]\n }\n\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> Self {\n fields[0] as u32 as i32\n }\n}\n\nimpl Packable for i64 {\n let N: u32 = I64_PACKED_LEN;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n [self as u64 as Field]\n }\n\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> Self {\n fields[0] as u64 as i64\n }\n}\n\nimpl Packable for [T; M]\nwhere\n T: Packable,\n{\n let N: u32 = M * ::N;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n let mut result: [Field; Self::N] = std::mem::zeroed();\n for i in 0..M {\n let serialized = self[i].pack();\n for j in 0..::N {\n result[i * ::N + j] = serialized[j];\n }\n }\n result\n }\n\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> Self {\n let mut reader = crate::utils::reader::Reader::new(fields);\n let mut result: [T; M] = std::mem::zeroed();\n reader.read_struct_array::::N, M>(Packable::unpack, result)\n }\n}\n\n#[test]\nfn test_u16_packing() {\n let a: u16 = 10;\n assert_eq(a, u16::unpack(a.pack()));\n}\n\n#[test]\nfn test_i8_packing() {\n let a: i8 = -10;\n assert_eq(a, i8::unpack(a.pack()));\n}\n\n#[test]\nfn test_i16_packing() {\n let a: i16 = -10;\n assert_eq(a, i16::unpack(a.pack()));\n}\n\n#[test]\nfn test_i32_packing() {\n let a: i32 = -10;\n assert_eq(a, i32::unpack(a.pack()));\n}\n\n#[test]\nfn test_i64_packing() {\n let a: i64 = -10;\n assert_eq(a, i64::unpack(a.pack()));\n}\n"},"366":{"path":"/home/nerses/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.2/noir-projects/noir-protocol-circuits/crates/types/src/type_serialization.nr","source":"use crate::traits::{Deserialize, Serialize};\n\nglobal U1_SERIALIZED_LEN: u32 = 1;\nglobal BOOL_SERIALIZED_LEN: u32 = 1;\nglobal U8_SERIALIZED_LEN: u32 = 1;\nglobal U16_SERIALIZED_LEN: u32 = 1;\nglobal U32_SERIALIZED_LEN: u32 = 1;\nglobal U64_SERIALIZED_LEN: u32 = 1;\nglobal U128_SERIALIZED_LEN: u32 = 1;\nglobal FIELD_SERIALIZED_LEN: u32 = 1;\nglobal I8_SERIALIZED_LEN: u32 = 1;\nglobal I16_SERIALIZED_LEN: u32 = 1;\nglobal I32_SERIALIZED_LEN: u32 = 1;\nglobal I64_SERIALIZED_LEN: u32 = 1;\n\nimpl Serialize for bool {\n let N: u32 = BOOL_SERIALIZED_LEN;\n\n #[inline_always]\n fn serialize(self) -> [Field; Self::N] {\n [self as Field]\n }\n}\n\nimpl Deserialize for bool {\n let N: u32 = BOOL_SERIALIZED_LEN;\n\n #[inline_always]\n fn deserialize(fields: [Field; Self::N]) -> bool {\n fields[0] != 0\n }\n}\n\nimpl Serialize for u1 {\n let N: u32 = U1_SERIALIZED_LEN;\n\n #[inline_always]\n fn serialize(self) -> [Field; Self::N] {\n [self as Field]\n }\n}\n\nimpl Deserialize for u1 {\n let N: u32 = U1_SERIALIZED_LEN;\n\n #[inline_always]\n fn deserialize(fields: [Field; Self::N]) -> Self {\n fields[0] as u1\n }\n}\n\nimpl Serialize for u8 {\n let N: u32 = U8_SERIALIZED_LEN;\n\n #[inline_always]\n fn serialize(self) -> [Field; Self::N] {\n [self as Field]\n }\n}\n\nimpl Deserialize for u8 {\n let N: u32 = U8_SERIALIZED_LEN;\n\n #[inline_always]\n fn deserialize(fields: [Field; Self::N]) -> Self {\n fields[0] as u8\n }\n}\n\nimpl Serialize for u16 {\n let N: u32 = U16_SERIALIZED_LEN;\n\n #[inline_always]\n fn serialize(self) -> [Field; Self::N] {\n [self as Field]\n }\n}\n\nimpl Deserialize for u16 {\n let N: u32 = U16_SERIALIZED_LEN;\n\n #[inline_always]\n fn deserialize(fields: [Field; Self::N]) -> Self {\n fields[0] as u16\n }\n}\n\nimpl Serialize for u32 {\n let N: u32 = U32_SERIALIZED_LEN;\n\n #[inline_always]\n fn serialize(self) -> [Field; Self::N] {\n [self as Field]\n }\n}\n\nimpl Deserialize for u32 {\n let N: u32 = U32_SERIALIZED_LEN;\n\n #[inline_always]\n fn deserialize(fields: [Field; Self::N]) -> Self {\n fields[0] as u32\n }\n}\n\nimpl Serialize for u64 {\n let N: u32 = U64_SERIALIZED_LEN;\n\n #[inline_always]\n fn serialize(self) -> [Field; Self::N] {\n [self as Field]\n }\n}\n\nimpl Deserialize for u64 {\n let N: u32 = U64_SERIALIZED_LEN;\n\n #[inline_always]\n fn deserialize(fields: [Field; Self::N]) -> Self {\n fields[0] as u64\n }\n}\n\nimpl Serialize for u128 {\n let N: u32 = U128_SERIALIZED_LEN;\n\n #[inline_always]\n fn serialize(self) -> [Field; Self::N] {\n [self as Field]\n }\n}\n\nimpl Deserialize for u128 {\n let N: u32 = U128_SERIALIZED_LEN;\n\n #[inline_always]\n fn deserialize(fields: [Field; Self::N]) -> Self {\n fields[0] as u128\n }\n}\n\nimpl Serialize for Field {\n let N: u32 = FIELD_SERIALIZED_LEN;\n\n #[inline_always]\n fn serialize(self) -> [Field; Self::N] {\n [self]\n }\n}\n\nimpl Deserialize for Field {\n let N: u32 = FIELD_SERIALIZED_LEN;\n\n #[inline_always]\n fn deserialize(fields: [Field; Self::N]) -> Self {\n fields[0]\n }\n}\n\nimpl Serialize for i8 {\n let N: u32 = I8_SERIALIZED_LEN;\n\n #[inline_always]\n fn serialize(self) -> [Field; Self::N] {\n [self as u8 as Field]\n }\n}\n\nimpl Deserialize for i8 {\n let N: u32 = I8_SERIALIZED_LEN;\n\n #[inline_always]\n fn deserialize(fields: [Field; Self::N]) -> Self {\n fields[0] as u8 as i8\n }\n}\n\nimpl Serialize for i16 {\n let N: u32 = I16_SERIALIZED_LEN;\n\n #[inline_always]\n fn serialize(self) -> [Field; Self::N] {\n [self as u16 as Field]\n }\n}\n\nimpl Deserialize for i16 {\n let N: u32 = I16_SERIALIZED_LEN;\n\n #[inline_always]\n fn deserialize(fields: [Field; Self::N]) -> Self {\n fields[0] as u16 as i16\n }\n}\n\nimpl Serialize for i32 {\n let N: u32 = I32_SERIALIZED_LEN;\n\n #[inline_always]\n fn serialize(self) -> [Field; Self::N] {\n [self as u32 as Field]\n }\n}\n\nimpl Deserialize for i32 {\n let N: u32 = I32_SERIALIZED_LEN;\n\n #[inline_always]\n fn deserialize(fields: [Field; Self::N]) -> Self {\n fields[0] as u32 as i32\n }\n}\n\nimpl Serialize for i64 {\n let N: u32 = I64_SERIALIZED_LEN;\n\n #[inline_always]\n fn serialize(self) -> [Field; Self::N] {\n [self as u64 as Field]\n }\n}\n\nimpl Deserialize for i64 {\n let N: u32 = I64_SERIALIZED_LEN;\n\n #[inline_always]\n fn deserialize(fields: [Field; Self::N]) -> Self {\n fields[0] as u64 as i64\n }\n}\n\nimpl Serialize for [T; M]\nwhere\n T: Serialize,\n{\n let N: u32 = ::N * M;\n\n #[inline_always]\n fn serialize(self) -> [Field; Self::N] {\n let mut result: [Field; _] = std::mem::zeroed();\n for i in 0..M {\n let serialized_t = self[i].serialize();\n for j in 0..::N {\n result[i * ::N + j] = serialized_t[j];\n }\n }\n result\n }\n}\n\nimpl Deserialize for [T; M]\nwhere\n T: Deserialize,\n{\n let N: u32 = ::N * M;\n\n #[inline_always]\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = crate::utils::reader::Reader::new(fields);\n let mut result: [T; M] = std::mem::zeroed();\n reader.read_struct_array::::N, M>(Deserialize::deserialize, result)\n }\n}\n\nimpl Serialize for Option\nwhere\n T: Serialize,\n{\n let N: u32 = ::N + 1;\n\n #[inline_always]\n fn serialize(self) -> [Field; Self::N] {\n let mut result: [Field; Self::N] = std::mem::zeroed();\n\n result[0] = if self.is_some() { 1 } else { 0 };\n\n let value_serialized = self.unwrap_unchecked().serialize();\n for i in 0..::N {\n result[1 + i] = value_serialized[i];\n }\n\n result\n }\n}\n\nimpl Deserialize for Option\nwhere\n T: Deserialize,\n{\n let N: u32 = ::N + 1;\n\n #[inline_always]\n fn deserialize(fields: [Field; Self::N]) -> Self {\n if fields[0] == 1 {\n let mut value_fields = [0; ::N];\n for i in 0..::N {\n value_fields[i] = fields[1 + i];\n }\n\n Option::some(T::deserialize(value_fields))\n } else {\n Option::none()\n }\n }\n}\n\nmod test {\n use crate::traits::{Deserialize, Serialize};\n\n #[test]\n fn u16_serialization() {\n let a: u16 = 10;\n assert_eq(a, u16::deserialize(a.serialize()));\n }\n\n #[test]\n fn i8_serialization() {\n let a: i8 = -10;\n assert_eq(a, i8::deserialize(a.serialize()));\n }\n\n #[test]\n fn i16_serialization() {\n let a: i16 = -10;\n assert_eq(a, i16::deserialize(a.serialize()));\n }\n\n #[test]\n fn i32_serialization() {\n let a: i32 = -10;\n assert_eq(a, i32::deserialize(a.serialize()));\n }\n\n #[test]\n fn i64_serialization() {\n let a: i64 = -10;\n assert_eq(a, i64::deserialize(a.serialize()));\n }\n\n #[test]\n fn option_field_serialization() {\n let opt_some = Option::some(5);\n assert_eq(Option::<_>::deserialize(opt_some.serialize()), opt_some);\n\n let opt_none = Option::none();\n assert_eq(Option::::deserialize(opt_none.serialize()), opt_none);\n }\n\n #[test]\n fn option_array_serialization() {\n let opt_some = Option::some([2, 5]);\n assert_eq(Option::<_>::deserialize(opt_some.serialize()), opt_some);\n\n let opt_none = Option::none();\n assert_eq(Option::::deserialize(opt_none.serialize()), opt_none);\n }\n}\n"},"384":{"path":"/home/nerses/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.2/noir-projects/noir-protocol-circuits/crates/types/src/utils/field.nr","source":"global KNOWN_NON_RESIDUE: Field = 5; // This is a non-residue in Noir's native Field.\n\npub fn field_from_bytes(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: This currently only exists to aid point compression in compress_to_blob_commitment().\n// Once compression is part of BigCurve it can either be removed or optimized to be used elsewhere.\npub fn byte_to_bits_be(byte: u8) -> [u1; 8] {\n let mut mut_byte = byte;\n let mut bits: [u1; 8] = [0; 8];\n for i in 0..8 {\n bits[7 - i] = (mut_byte & 1) as u1;\n mut_byte >>= 1;\n }\n bits\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\npub fn min(f1: Field, f2: Field) -> Field {\n if f1.lt(f2) {\n f1\n } else {\n f2\n }\n}\n\nglobal C1: u32 = 28;\nglobal C3: Field = 40770029410420498293352137776570907027550720424234931066070132305055;\nglobal C5: Field = 19103219067921713944291392827692070036145651957329286315305642004821462161904;\n\npub fn pow(x: Field, y: Field) -> Field {\n let mut r = 1 as Field;\n let b: [u1; 254] = y.to_le_bits();\n\n for i in 0..254 {\n r *= r;\n r *= (b[254 - 1 - i] as Field) * x + (1 - b[254 - 1 - i] as Field);\n }\n\n r\n}\n\n/// Returns Option::some(sqrt) if there is a square root, and Option::none() if there isn't.\npub fn sqrt(x: Field) -> Option {\n // Safety: if the hint returns the square root of x, then we simply square it\n // check the result equals x. If x is not square, we return a value that\n // enables us to prove that fact (see the `else` clause below).\n let (is_sq, maybe_sqrt) = unsafe { __sqrt(x) };\n\n if is_sq {\n let sqrt = maybe_sqrt;\n validate_sqrt_hint(x, sqrt);\n Option::some(sqrt)\n } else {\n let not_sqrt_hint = maybe_sqrt;\n validate_not_sqrt_hint(x, not_sqrt_hint);\n Option::none()\n }\n}\n\n// Boolean indicating whether Field element is a square, i.e. whether there exists a y in Field s.t. x = y*y.\nunconstrained fn is_square(x: Field) -> bool {\n let v = pow(x, -1 / 2);\n v * (v - 1) == 0\n}\n\n// Tonelli-Shanks algorithm for computing the square root of a Field element.\n// Requires C1 = max{c: 2^c divides (p-1)}, where p is the order of Field\n// as well as C3 = (C2 - 1)/2, where C2 = (p-1)/(2^c1),\n// and C5 = ZETA^C2, where ZETA is a non-square element of Field.\n// These are pre-computed above as globals.\nunconstrained fn tonelli_shanks_sqrt(x: Field) -> Field {\n let mut z = pow(x, C3);\n let mut t = z * z * x;\n z *= x;\n let mut b = t;\n let mut c = C5;\n\n for i in 0..(C1 - 1) {\n for _j in 1..(C1 - i - 1) {\n b *= b;\n }\n\n z *= if b == 1 { 1 } else { c };\n\n c *= c;\n\n t *= if b == 1 { 1 } else { c };\n\n b = t;\n }\n\n z\n}\n\n// NB: this doesn't return an option, because in the case of there _not_ being a square root, we still want to return a field element that allows us to then assert in the _constrained_ sqrt function that there is no sqrt.\nunconstrained fn __sqrt(x: Field) -> (bool, Field) {\n let is_sq = is_square(x);\n if is_sq {\n let sqrt = tonelli_shanks_sqrt(x);\n (true, sqrt)\n } else {\n // Demonstrate that x is not a square (a.k.a. a \"quadratic non-residue\").\n // Facts:\n // The Legendre symbol (\"LS\") of x, is x^((p-1)/2) (mod p).\n // - If x is a square, LS(x) = 1\n // - If x is not a square, LS(x) = -1\n // - If x = 0, LS(x) = 0.\n //\n // Hence:\n // sq * sq = sq // 1 * 1 = 1\n // non-sq * non-sq = sq // -1 * -1 = 1\n // sq * non-sq = non-sq // -1 * 1 = -1\n //\n // See: https://en.wikipedia.org/wiki/Legendre_symbol\n let demo_x_not_square = x * KNOWN_NON_RESIDUE;\n let not_sqrt = tonelli_shanks_sqrt(demo_x_not_square);\n (false, not_sqrt)\n }\n}\n\nfn validate_sqrt_hint(x: Field, hint: Field) {\n assert(hint * hint == x, f\"The claimed_sqrt {hint} is not the sqrt of x {x}\");\n}\n\nfn validate_not_sqrt_hint(x: Field, hint: Field) {\n // We need this assertion, because x = 0 would pass the other assertions in this\n // function, and we don't want people to be able to prove that 0 is not square!\n assert(x != 0, \"0 has a square root; you cannot claim it is not square\");\n // Demonstrate that x is not a square (a.k.a. a \"quadratic non-residue\").\n //\n // Facts:\n // The Legendre symbol (\"LS\") of x, is x^((p-1)/2) (mod p).\n // - If x is a square, LS(x) = 1\n // - If x is not a square, LS(x) = -1\n // - If x = 0, LS(x) = 0.\n //\n // Hence:\n // 1. sq * sq = sq // 1 * 1 = 1\n // 2. non-sq * non-sq = sq // -1 * -1 = 1\n // 3. sq * non-sq = non-sq // -1 * 1 = -1\n //\n // See: https://en.wikipedia.org/wiki/Legendre_symbol\n //\n // We want to demonstrate that this below multiplication falls under bullet-point (2):\n let demo_x_not_square = x * KNOWN_NON_RESIDUE;\n // I.e. we want to demonstrate that `demo_x_not_square` has Legendre symbol 1\n // (i.e. that it is a square), so we prove that it is square below.\n // Why do we want to prove that it has LS 1?\n // Well, since it was computed with a known-non-residue, its squareness implies we're\n // in case 2 (something multiplied by a known-non-residue yielding a result which\n // has a LS of 1), which implies that x must be a non-square. The unconstrained\n // function gave us the sqrt of demo_x_not_square, so all we need to do is\n // assert its squareness:\n assert(\n hint * hint == demo_x_not_square,\n f\"The hint {hint} does not demonstrate that {x} is not a square\",\n );\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,\n 151, 202, 67, 55, 77, 233, 80, 187, 224, 167,\n ];\n let field = field_from_bytes(inputs, true);\n let return_bytes: [u8; 31] = field.to_be_bytes();\n assert_eq(inputs, return_bytes);\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,\n 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: [u8; 31] = field.to_be_bytes();\n\n assert_eq(return_bytes2, return_bytes);\n assert_eq(field2, field);\n}\n\n#[test]\nunconstrained fn max_field_test() {\n // Tests the hardcoded value in constants.nr vs underlying modulus\n // NB: We can't use 0-1 in constants.nr as it will be transpiled incorrectly to ts and sol constants files\n let max_value = crate::constants::MAX_FIELD_VALUE;\n assert_eq(max_value, 0 - 1);\n // modulus == 0 is tested elsewhere, so below is more of a sanity check\n let max_bytes: [u8; 32] = max_value.to_be_bytes();\n let mod_bytes = std::field::modulus_be_bytes();\n for i in 0..31 {\n assert_eq(max_bytes[i], mod_bytes[i]);\n }\n assert_eq(max_bytes[31], mod_bytes[31] - 1);\n}\n\n#[test]\nunconstrained fn sqrt_valid_test() {\n let x = 16; // examples: 16, 9, 25, 81\n let result = sqrt(x);\n assert(result.is_some());\n assert_eq(result.unwrap() * result.unwrap(), x);\n}\n\n#[test]\nunconstrained fn sqrt_invalid_test() {\n let x = KNOWN_NON_RESIDUE; // has no square root in the field\n let result = sqrt(x);\n assert(result.is_none());\n}\n"},"388":{"path":"/home/nerses/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.2/noir-projects/noir-protocol-circuits/crates/types/src/utils/reader.nr","source":"pub struct Reader {\n data: [Field; N],\n offset: u32,\n}\n\nimpl Reader {\n pub fn new(data: [Field; N]) -> Self {\n Self { data, offset: 0 }\n }\n\n pub fn read(&mut self) -> Field {\n let result = self.data[self.offset];\n self.offset += 1;\n result\n }\n\n pub fn read_u32(&mut self) -> u32 {\n self.read() as u32\n }\n\n pub fn read_u64(&mut self) -> u64 {\n self.read() as u64\n }\n\n pub fn read_bool(&mut self) -> bool {\n self.read() != 0\n }\n\n pub fn read_array(&mut self) -> [Field; K] {\n let mut result = [0; K];\n for i in 0..K {\n result[i] = self.data[self.offset + i];\n }\n self.offset += K;\n result\n }\n\n pub fn read_struct(&mut self, deserialise: fn([Field; K]) -> T) -> T {\n let result = deserialise(self.read_array());\n result\n }\n\n pub fn read_struct_array(\n &mut self,\n deserialise: fn([Field; K]) -> T,\n mut result: [T; C],\n ) -> [T; C] {\n for i in 0..C {\n result[i] = self.read_struct(deserialise);\n }\n result\n }\n\n pub fn finish(self) {\n assert_eq(self.offset, self.data.len(), \"Reader did not read all data\");\n }\n}\n"},"404":{"path":"/home/nerses/nargo/github.com/noir-lang/sha256/v0.2.1/src/sha256.nr","source":"use std::hash::sha256_compression;\nuse std::runtime::is_unconstrained;\n\nuse constants::{\n BLOCK_BYTE_PTR, BLOCK_SIZE, HASH, INITIAL_STATE, INT_BLOCK, INT_BLOCK_SIZE, INT_SIZE,\n INT_SIZE_PTR, MSG_BLOCK, MSG_SIZE_PTR, STATE, TWO_POW_16, TWO_POW_24, TWO_POW_32, TWO_POW_8,\n};\n\npub(crate) mod constants;\nmod tests;\n\n// Implementation of SHA-256 mapping a byte array of variable length to\n// 32 bytes.\n\n// Deprecated in favour of `sha256_var`\n// docs:start:sha256\npub fn sha256(input: [u8; N]) -> HASH\n// docs:end:sha256\n{\n digest(input)\n}\n\n// SHA-256 hash function\n#[no_predicates]\npub fn digest(msg: [u8; N]) -> HASH {\n sha256_var(msg, N as u64)\n}\n\n// Variable size SHA-256 hash\npub fn sha256_var(msg: [u8; N], message_size: u64) -> HASH {\n let message_size = message_size as u32;\n assert(message_size <= N);\n\n if std::runtime::is_unconstrained() {\n // Safety: SHA256 is running as an unconstrained function.\n unsafe {\n __sha256_var(msg, message_size)\n }\n } else {\n let (mut h, mut msg_block) = process_full_blocks(msg, message_size, INITIAL_STATE);\n\n finalize_sha256_blocks::(message_size, h, msg_block)\n }\n}\n\npub(crate) unconstrained fn __sha_var(\n msg: [u8; N],\n message_size: u32,\n initial_state: STATE,\n) -> HASH {\n let num_full_blocks = message_size / BLOCK_SIZE;\n // Intermediate hash, starting with the canonical initial value\n let mut h: STATE = initial_state;\n // Pointer into msg_block on a 64 byte scale\n for i in 0..num_full_blocks {\n let msg_block = build_msg_block(msg, message_size, BLOCK_SIZE * i);\n h = sha256_compression(msg_block, h);\n }\n\n // Handle setup of the final msg block.\n // This case is only hit if the msg is less than the block size,\n // or our message cannot be evenly split into blocks.\n\n finalize_last_sha256_block(h, message_size, msg)\n}\n\n// Helper function to finalize the message block with padding and length\npub(crate) unconstrained fn finalize_last_sha256_block(\n mut h: STATE,\n message_size: u32,\n msg: [u8; N],\n) -> HASH {\n let modulo = message_size % BLOCK_SIZE;\n let (mut msg_block, mut msg_byte_ptr): (INT_BLOCK, u32) = if modulo != 0 {\n let num_full_blocks = message_size / BLOCK_SIZE;\n let msg_start = BLOCK_SIZE * num_full_blocks;\n let new_msg_block = build_msg_block(msg, message_size, msg_start);\n (new_msg_block, modulo)\n } else {\n // If we had modulo == 0 then it means the last block was full,\n // and we can reset the pointer to zero to overwrite it.\n ([0; INT_BLOCK_SIZE], 0)\n };\n\n // Pad the rest such that we have a [u32; 2] block at the end representing the length\n // of the message, and a block of 1 0 ... 0 following the message (i.e. [1 << 7, 0, ..., 0]).\n // Here we rely on the fact that everything beyond the available input is set to 0.\n let index = msg_byte_ptr / INT_SIZE;\n msg_block[index] = set_item_byte_then_zeros(msg_block[index], msg_byte_ptr, 1 << 7);\n\n // If we don't have room to write the size, compress the block and reset it.\n let (h, mut msg_byte_ptr): (STATE, u32) = if msg_byte_ptr >= MSG_SIZE_PTR {\n // `attach_len_to_msg_block` will zero out everything after the `msg_byte_ptr`.\n (sha256_compression(msg_block, h), 0)\n } else {\n (h, msg_byte_ptr + 1)\n };\n msg_block = attach_len_to_msg_block(msg_block, msg_byte_ptr, message_size);\n\n hash_final_block(msg_block, h)\n}\n\n// Variable size SHA-256 hash\nunconstrained fn __sha256_var(msg: [u8; N], message_size: u32) -> HASH {\n __sha_var(msg, message_size, INITIAL_STATE)\n}\n\npub(crate) fn process_full_blocks(\n msg: [u8; N],\n message_size: u32,\n h: STATE,\n) -> (STATE, MSG_BLOCK) {\n let num_blocks = N / BLOCK_SIZE;\n\n // We store the intermediate hash states and message blocks in these two arrays which allows us to select the correct state\n // for the given message size with a lookup.\n //\n // These can be reasoned about as followed:\n // Consider a message with an unknown number of bytes, `msg_size. It can be seen that this will have `msg_size / BLOCK_SIZE` full blocks.\n // - `states[i]` should then be the state after processing the first `i` blocks.\n // - `blocks[i]` should then be the next message block after processing the first `i` blocks.\n // blocks[first_partially_filled_block_index] is the last block that is partially filled or all 0 if the message is a multiple of the block size.\n //\n // In other words:\n //\n // blocks = [block 1, block 2, ..., block N / BLOCK_SIZE, block N / BLOCK_SIZE + 1]\n // states = [INITIAL_STATE, state after block 1, state after block 2, ..., state after block N / BLOCK_SIZE]\n //\n // We place the initial state in `states[0]` as in the case where the `message_size < BLOCK_SIZE` then there are no full blocks to process and no compressions should occur.\n let mut blocks: [MSG_BLOCK; N / BLOCK_SIZE + 1] = std::mem::zeroed();\n let mut states: [STATE; N / BLOCK_SIZE + 1] = [h; N / BLOCK_SIZE + 1];\n\n // Optimization for small messages. If the largest possible message is smaller than a block then we know that the first block is partially filled\n // no matter the value of `message_size`.\n //\n // Note that the condition `N >= BLOCK_SIZE` is known during monomorphization so this has no runtime cost.\n let first_partially_filled_block_index = if N >= BLOCK_SIZE {\n message_size / BLOCK_SIZE\n } else {\n 0\n };\n\n for i in 0..num_blocks {\n let msg_start = BLOCK_SIZE * i;\n let new_msg_block =\n // Safety: separate verification function\n unsafe { build_msg_block(msg, message_size, msg_start) };\n\n // Verify the block we are compressing was appropriately constructed\n verify_msg_block(msg, message_size, new_msg_block, msg_start);\n\n blocks[i] = new_msg_block;\n states[i + 1] = sha256_compression(new_msg_block, states[i]);\n }\n // If message_size/BLOCK_SIZE == N/BLOCK_SIZE, and there is a remainder, we need to process the last block.\n if N % BLOCK_SIZE != 0 {\n let new_msg_block =\n // Safety: separate verification function\n unsafe { build_msg_block(msg, message_size, BLOCK_SIZE * num_blocks) };\n\n // Verify the block we are compressing was appropriately constructed\n verify_msg_block(msg, message_size, new_msg_block, BLOCK_SIZE * num_blocks);\n\n blocks[num_blocks] = new_msg_block;\n }\n\n // verify the 0 padding is correct for the last block\n let final_block = blocks[first_partially_filled_block_index];\n verify_msg_block_zeros(final_block, message_size % BLOCK_SIZE, INT_BLOCK_SIZE);\n (states[first_partially_filled_block_index], final_block)\n}\n\n// Take `BLOCK_SIZE` number of bytes from `msg` starting at `msg_start` and pack them into a `MSG_BLOCK`.\npub(crate) unconstrained fn build_msg_block(\n msg: [u8; N],\n message_size: u32,\n msg_start: u32,\n) -> MSG_BLOCK {\n let mut msg_block: MSG_BLOCK = [0; INT_BLOCK_SIZE];\n\n // We insert `BLOCK_SIZE` bytes (or up to the end of the message)\n let block_input = if message_size < msg_start {\n // This function is sometimes called with `msg_start` past the end of the message.\n // In this case we return an empty block and zero pointer to signal that the result should be ignored.\n 0\n } else if message_size < msg_start + BLOCK_SIZE {\n message_size - msg_start\n } else {\n BLOCK_SIZE\n };\n\n // Figure out the number of items in the int array that we have to pack.\n // e.g. if the input is [0,1,2,3,4,5] then we need to pack it as 2 items: [0123, 4500]\n let int_input = (block_input + INT_SIZE - 1) / INT_SIZE;\n\n for i in 0..int_input {\n let mut msg_item: u32 = 0;\n // Always construct the integer as 4 bytes, even if it means going beyond the input.\n for j in 0..INT_SIZE {\n let k = i * INT_SIZE + j;\n let msg_byte = if k < block_input {\n msg[msg_start + k]\n } else {\n 0\n };\n msg_item = (msg_item << 8) + msg_byte as u32;\n }\n msg_block[i] = msg_item;\n }\n\n // Returning the index as if it was a 64 byte array.\n // We have to project it down to 16 items and bit shifting to get a byte back if we need it.\n msg_block\n}\n\n// Verify the block we are compressing was appropriately constructed by `build_msg_block`\n// and matches the input data.\n// If `message_size` is less than `msg_start` then this is called with the old non-empty block;\n// in that case we can skip verification, ie. no need to check that everything is zero.\nfn verify_msg_block(\n msg: [u8; N],\n message_size: u32,\n msg_block: MSG_BLOCK,\n msg_start: u32,\n) {\n let mut msg_end = msg_start + BLOCK_SIZE;\n if msg_end > N {\n msg_end = N;\n }\n // We might have to go beyond the input to pad the fields.\n if msg_end % INT_SIZE != 0 {\n msg_end = msg_end + INT_SIZE - msg_end % INT_SIZE;\n }\n\n // Reconstructed packed item.\n let mut msg_item: u32 = 0;\n\n // Inclusive at the end so that we can compare the last item.\n let mut i: u32 = 0;\n for k in msg_start..=msg_end {\n if k % INT_SIZE == 0 {\n // If we consumed some input we can compare against the block.\n if (msg_start < message_size) & (k > msg_start) {\n assert_eq(msg_block[i], msg_item as u32);\n i = i + 1;\n msg_item = 0;\n }\n }\n // Shift the accumulator\n msg_item = msg_item << 8;\n // If we have input to consume, add it at the rightmost position.\n if k < message_size & k < msg_end {\n msg_item = msg_item + msg[k] as u32;\n }\n }\n}\n\n// Verify that a region of ints in the message block are (partially) zeroed,\n// up to an (exclusive) maximum which can either be the end of the block\n// or just where the size is to be written.\nfn verify_msg_block_zeros(\n msg_block: MSG_BLOCK,\n mut msg_byte_ptr: BLOCK_BYTE_PTR,\n max_int_byte_ptr: u32,\n) {\n // First integer which is supposed to be (partially) zero.\n let mut int_byte_ptr = msg_byte_ptr / INT_SIZE;\n\n // Check partial zeros.\n let modulo = msg_byte_ptr % INT_SIZE;\n if modulo != 0 {\n let zeros = INT_SIZE - modulo;\n let mask = if zeros == 3 {\n TWO_POW_24\n } else if zeros == 2 {\n TWO_POW_16\n } else {\n TWO_POW_8\n };\n assert_eq(msg_block[int_byte_ptr] % mask, 0);\n int_byte_ptr = int_byte_ptr + 1;\n }\n\n // Check the rest of the items.\n for i in 0..max_int_byte_ptr {\n if i >= int_byte_ptr {\n assert_eq(msg_block[i], 0);\n }\n }\n}\n\n// Verify that up to the byte pointer the two blocks are equal.\n// At the byte pointer the new block can be partially zeroed.\nfn verify_msg_block_equals_last(\n msg_block: MSG_BLOCK,\n last_block: MSG_BLOCK,\n mut msg_byte_ptr: BLOCK_BYTE_PTR,\n) {\n // msg_byte_ptr is the position at which they are no longer have to be the same.\n // First integer which is supposed to be (partially) zero contains that pointer.\n let mut int_byte_ptr = msg_byte_ptr / INT_SIZE;\n\n // Check partial zeros.\n let modulo = msg_byte_ptr % INT_SIZE;\n if modulo != 0 {\n // Reconstruct the partially zero item from the last block.\n let last_field = last_block[int_byte_ptr];\n let mut msg_item: u32 = 0;\n // Reset to where they are still equal.\n msg_byte_ptr = msg_byte_ptr - modulo;\n for i in 0..INT_SIZE {\n msg_item = msg_item << 8;\n if i < modulo {\n msg_item = msg_item + get_item_byte(last_field, msg_byte_ptr) as u32;\n msg_byte_ptr = msg_byte_ptr + 1;\n }\n }\n assert_eq(msg_block[int_byte_ptr], msg_item);\n }\n\n for i in 0..INT_SIZE_PTR {\n if i < int_byte_ptr {\n assert_eq(msg_block[i], last_block[i]);\n }\n }\n}\n\n// Set the rightmost `zeros` number of bytes to 0.\n#[inline_always]\nfn set_item_zeros(item: u32, zeros: u32) -> u32 {\n lshift8(rshift8(item, zeros), zeros)\n}\n\n// Replace one byte in the item with a value, and set everything after it to zero.\nfn set_item_byte_then_zeros(msg_item: u32, msg_byte_ptr: BLOCK_BYTE_PTR, msg_byte: u8) -> u32 {\n let zeros = INT_SIZE - msg_byte_ptr % INT_SIZE;\n let zeroed_item = set_item_zeros(msg_item, zeros);\n let new_item = byte_into_item(msg_byte, msg_byte_ptr);\n zeroed_item + new_item\n}\n\n// Get a byte of a message item according to its overall position in the `BLOCK_SIZE` space.\nfn get_item_byte(mut msg_item: u32, msg_byte_ptr: BLOCK_BYTE_PTR) -> u8 {\n // How many times do we have to shift to the right to get to the position we want?\n let max_shifts = INT_SIZE - 1;\n let shifts = max_shifts - msg_byte_ptr % INT_SIZE;\n msg_item = rshift8(msg_item, shifts);\n // At this point the byte we want is in the rightmost position.\n msg_item as u8\n}\n\n// Project a byte into a position in a field based on the overall block pointer.\n// For example putting 1 into pointer 5 would be 100, because overall we would\n// have [____, 0100] with indexes [0123,4567].\n#[inline_always]\nfn byte_into_item(msg_byte: u8, msg_byte_ptr: BLOCK_BYTE_PTR) -> u32 {\n let mut msg_item = msg_byte as u32;\n // How many times do we have to shift to the left to get to the position we want?\n let max_shifts = INT_SIZE - 1;\n let shifts = max_shifts - msg_byte_ptr % INT_SIZE;\n lshift8(msg_item, shifts)\n}\n\n// Construct a field out of 4 bytes.\n#[inline_always]\nfn make_item(b0: u8, b1: u8, b2: u8, b3: u8) -> u32 {\n let mut item = b0 as u32;\n item = (item << 8) + b1 as u32;\n item = (item << 8) + b2 as u32;\n item = (item << 8) + b3 as u32;\n item\n}\n\nglobal BIT_SHIFT_TABLE: [u32; 4] = [1, TWO_POW_8, TWO_POW_16, TWO_POW_24];\n\n// Shift by 8 bits to the left between 0 and 4 times.\n// Checks `is_unconstrained()` to just use a bitshift if we're running in an unconstrained context,\n// otherwise multiplies by 256.\n#[inline_always]\nfn lshift8(item: u32, shifts: u32) -> u32 {\n if is_unconstrained() {\n // Brillig wouldn't shift 0<<4 without overflow.\n if shifts >= 4 {\n 0\n } else {\n item << (8 * shifts)\n }\n } else {\n if shifts == 4 {\n 0\n } else {\n item * BIT_SHIFT_TABLE[shifts]\n }\n }\n}\n\n// Shift by 8 bits to the right between 0 and 4 times.\n// Checks `is_unconstrained()` to just use a bitshift if we're running in an unconstrained context,\n// otherwise divides by 256.\n#[inline_always]\nfn rshift8(item: u32, shifts: u32) -> u32 {\n if is_unconstrained() {\n if shifts >= 4 {\n 0\n } else {\n item >> (8 * shifts)\n }\n } else {\n if shifts == 4 {\n 0\n } else {\n item / BIT_SHIFT_TABLE[shifts]\n }\n }\n}\n\n// Zero out all bytes between the end of the message and where the length is appended,\n// then write the length into the last 8 bytes of the block.\nunconstrained fn attach_len_to_msg_block(\n mut msg_block: MSG_BLOCK,\n mut msg_byte_ptr: BLOCK_BYTE_PTR,\n message_size: u32,\n) -> MSG_BLOCK {\n // We assume that `msg_byte_ptr` is less than 57 because if not then it is reset to zero before calling this function.\n // In any case, fill blocks up with zeros until the last 64 bits (i.e. until msg_byte_ptr = 56).\n // There can be one item which has to be partially zeroed.\n let modulo = msg_byte_ptr % INT_SIZE;\n if modulo != 0 {\n // Index of the block in which we find the item we need to partially zero.\n let i = msg_byte_ptr / INT_SIZE;\n let zeros = INT_SIZE - modulo;\n msg_block[i] = set_item_zeros(msg_block[i], zeros);\n msg_byte_ptr = msg_byte_ptr + zeros;\n }\n\n // The rest can be zeroed without bit shifting anything.\n for i in (msg_byte_ptr / INT_SIZE)..INT_SIZE_PTR {\n msg_block[i] = 0;\n }\n\n // Set the last two 4 byte ints as the first/second half of the 8 bytes of the length.\n let len = 8 * message_size;\n let len_bytes: [u8; 8] = (len as Field).to_be_bytes();\n msg_block[INT_SIZE_PTR] = (len_bytes[0] as u32) << 24\n | (len_bytes[1] as u32) << 16\n | (len_bytes[2] as u32) << 8\n | (len_bytes[3] as u32);\n\n msg_block[INT_SIZE_PTR + 1] = (len_bytes[4] as u32) << 24\n | (len_bytes[5] as u32) << 16\n | (len_bytes[6] as u32) << 8\n | (len_bytes[7] as u32);\n\n msg_block\n}\n\n// Verify that the message length was correctly written by `attach_len_to_msg_block`,\n// and that everything between the byte pointer and the size pointer was zeroed,\n// and that everything before the byte pointer was untouched.\nfn verify_msg_len(\n msg_block: MSG_BLOCK,\n last_block: MSG_BLOCK,\n msg_byte_ptr: BLOCK_BYTE_PTR,\n message_size: u32,\n) {\n // Check zeros up to the size pointer.\n verify_msg_block_zeros(msg_block, msg_byte_ptr, INT_SIZE_PTR);\n\n // Check that up to the pointer we match the last block.\n verify_msg_block_equals_last(msg_block, last_block, msg_byte_ptr);\n\n // We verify the message length was inserted correctly by reversing the byte decomposition.\n std::static_assert(\n INT_SIZE_PTR + 2 == INT_BLOCK_SIZE,\n \"INT_SIZE_PTR + 2 must equal INT_BLOCK_SIZE\",\n );\n let reconstructed_len_hi = msg_block[INT_SIZE_PTR] as Field;\n let reconstructed_len_lo = msg_block[INT_SIZE_PTR + 1] as Field;\n\n let reconstructed_len: Field =\n reconstructed_len_hi * TWO_POW_32 as Field + reconstructed_len_lo;\n let len = 8 * (message_size as Field);\n assert_eq(reconstructed_len, len);\n}\n\n// Perform the final compression, then transform the `STATE` into `HASH`.\nfn hash_final_block(msg_block: MSG_BLOCK, mut state: STATE) -> HASH {\n let mut out_h: HASH = [0; 32]; // Digest as sequence of bytes\n // Hash final padded block\n state = sha256_compression(msg_block, state);\n\n // Return final hash as byte array\n for j in 0..8 {\n let h_bytes: [u8; 4] = (state[j] as Field).to_be_bytes();\n for k in 0..4 {\n out_h[4 * j + k] = h_bytes[k];\n }\n }\n\n out_h\n}\n\npub(crate) fn finalize_sha256_blocks(\n message_size: u32,\n mut h: STATE,\n mut msg_block: MSG_BLOCK,\n) -> HASH {\n let mut msg_byte_ptr = message_size % BLOCK_SIZE;\n\n // If we had modulo == 0 then it means the last block was full,\n // and we can reset the pointer to zero to overwrite it.\n if msg_byte_ptr == BLOCK_SIZE {\n msg_byte_ptr = 0;\n }\n\n // Pad the rest such that we have a [u32; 2] block at the end representing the length\n // of the message, and a block of 1 0 ... 0 following the message (i.e. [1 << 7, 0, ..., 0]).\n // Here we rely on the fact that everything beyond the available input is set to 0.\n let index = msg_byte_ptr / INT_SIZE;\n msg_block[index] = set_item_byte_then_zeros(msg_block[index], msg_byte_ptr, 1 << 7);\n\n msg_byte_ptr = msg_byte_ptr + 1;\n let last_block = msg_block;\n\n // If we don't have room to write the size, compress the block and reset it.\n if msg_byte_ptr > MSG_SIZE_PTR {\n h = sha256_compression(msg_block, h);\n\n // `attach_len_to_msg_block` will zero out everything after the `msg_byte_ptr`.\n msg_byte_ptr = 0;\n }\n\n // Safety: separate verification function\n msg_block = unsafe { attach_len_to_msg_block(msg_block, msg_byte_ptr, message_size) };\n\n verify_msg_len(msg_block, last_block, msg_byte_ptr, message_size);\n\n hash_final_block(msg_block, h)\n}\n\n/**\n * Given some state of a partially computed sha256 hash and part of the preimage, continue hashing\n * @notice used for complex/ recursive offloading of post-partial hashing\n *\n * @param N - the maximum length of the message to hash\n * @param h - the intermediate hash state\n * @param msg - the preimage to hash\n * @param message_size - the actual length of the preimage to hash\n * @return the intermediate hash state after compressing in msg to h\n */\npub fn partial_sha256_var_interstitial(\n mut h: [u32; 8],\n msg: [u8; N],\n message_size: u32,\n) -> [u32; 8] {\n assert(message_size % BLOCK_SIZE == 0, \"Message size must be a multiple of the block size\");\n if std::runtime::is_unconstrained() {\n // Safety: running as an unconstrained function\n unsafe {\n __sha_partial_var_interstitial(h, msg, message_size)\n }\n } else {\n let (mut h, _) = process_full_blocks(msg, message_size, h);\n\n h\n }\n}\n\n/**\n * Given some state of a partially computed sha256 hash and remaining preimage, complete the hash\n * @notice used for traditional partial hashing\n *\n * @param N - the maximum length of the message to hash\n * @param h - the intermediate hash state\n * @param msg - the remaining preimage to hash\n * @param message_size - the size of the current chunk\n * @param real_message_size - the total size of the original preimage\n * @return finalized sha256 hash\n */\npub fn partial_sha256_var_end(\n mut h: [u32; 8],\n msg: [u8; N],\n message_size: u32,\n real_message_size: u32,\n) -> [u8; 32] {\n assert(message_size % BLOCK_SIZE == 0, \"Message size must be a multiple of the block size\");\n if std::runtime::is_unconstrained() {\n // Safety: running as an unconstrained function\n unsafe {\n h = __sha_partial_var_interstitial(h, msg, message_size);\n\n // Handle setup of the final msg block.\n // This case is only hit if the msg is less than the block size,\n // or our message cannot be evenly split into blocks.\n\n finalize_last_sha256_block(h, real_message_size, msg)\n }\n } else {\n let (mut h, mut msg_block) = process_full_blocks(msg, message_size, h);\n finalize_sha256_blocks::(real_message_size, h, msg_block)\n }\n}\n\nunconstrained fn __sha_partial_var_interstitial(\n mut h: [u32; 8],\n msg: [u8; N],\n message_size: u32,\n) -> [u32; 8] {\n let num_full_blocks = message_size / BLOCK_SIZE;\n // Intermediate hash, starting with the canonical initial value\n // Pointer into msg_block on a 64 byte scale\n for i in 0..num_full_blocks {\n let msg_block = build_msg_block(msg, message_size, BLOCK_SIZE * i);\n h = sha256_compression(msg_block, h);\n }\n h\n}\n\nmod equivalence_test {\n\n #[test]\n fn test_implementations_agree(msg: [u8; 100], message_size: u64) {\n let message_size = message_size % 100;\n // Safety: test function\n let unconstrained_sha = unsafe { super::__sha256_var(msg, message_size as u32) };\n let sha = super::sha256_var(msg, message_size);\n assert_eq(sha, unconstrained_sha);\n }\n}\n"},"42":{"path":"std/option.nr","source":"use crate::cmp::{Eq, Ord, Ordering};\nuse crate::default::Default;\nuse crate::hash::{Hash, Hasher};\n\npub struct Option {\n _is_some: bool,\n _value: T,\n}\n\nimpl Option {\n /// Constructs a None value\n pub fn none() -> Self {\n Self { _is_some: false, _value: crate::mem::zeroed() }\n }\n\n /// Constructs a Some wrapper around the given value\n pub fn some(_value: T) -> Self {\n Self { _is_some: true, _value }\n }\n\n /// True if this Option is None\n pub fn is_none(self) -> bool {\n !self._is_some\n }\n\n /// True if this Option is Some\n pub fn is_some(self) -> bool {\n self._is_some\n }\n\n /// Asserts `self.is_some()` and returns the wrapped value.\n pub fn unwrap(self) -> T {\n assert(self._is_some);\n self._value\n }\n\n /// Returns the inner value without asserting `self.is_some()`\n /// Note that if `self` is `None`, there is no guarantee what value will be returned,\n /// only that it will be of type `T`.\n pub fn unwrap_unchecked(self) -> T {\n self._value\n }\n\n /// Returns the wrapped value if `self.is_some()`. Otherwise, returns the given default value.\n pub fn unwrap_or(self, default: T) -> T {\n if self._is_some {\n self._value\n } else {\n default\n }\n }\n\n /// Returns the wrapped value if `self.is_some()`. Otherwise, calls the given function to return\n /// a default value.\n pub fn unwrap_or_else(self, default: fn[Env]() -> T) -> T {\n if self._is_some {\n self._value\n } else {\n default()\n }\n }\n\n /// Asserts `self.is_some()` with a provided custom message and returns the contained `Some` value\n pub fn expect(self, message: fmtstr) -> T {\n assert(self.is_some(), message);\n self._value\n }\n\n /// If self is `Some(x)`, this returns `Some(f(x))`. Otherwise, this returns `None`.\n pub fn map(self, f: fn[Env](T) -> U) -> Option {\n if self._is_some {\n Option::some(f(self._value))\n } else {\n Option::none()\n }\n }\n\n /// If self is `Some(x)`, this returns `f(x)`. Otherwise, this returns the given default value.\n pub fn map_or(self, default: U, f: fn[Env](T) -> U) -> U {\n if self._is_some {\n f(self._value)\n } else {\n default\n }\n }\n\n /// If self is `Some(x)`, this returns `f(x)`. Otherwise, this returns `default()`.\n pub fn map_or_else(self, default: fn[Env1]() -> U, f: fn[Env2](T) -> U) -> U {\n if self._is_some {\n f(self._value)\n } else {\n default()\n }\n }\n\n /// Returns None if self is None. Otherwise, this returns `other`.\n pub fn and(self, other: Self) -> Self {\n if self.is_none() {\n Option::none()\n } else {\n other\n }\n }\n\n /// If self is None, this returns None. Otherwise, this calls the given function\n /// with the Some value contained within self, and returns the result of that call.\n ///\n /// In some languages this function is called `flat_map` or `bind`.\n pub fn and_then(self, f: fn[Env](T) -> Option) -> Option {\n if self._is_some {\n f(self._value)\n } else {\n Option::none()\n }\n }\n\n /// If self is Some, return self. Otherwise, return `other`.\n pub fn or(self, other: Self) -> Self {\n if self._is_some {\n self\n } else {\n other\n }\n }\n\n /// If self is Some, return self. Otherwise, return `default()`.\n pub fn or_else(self, default: fn[Env]() -> Self) -> Self {\n if self._is_some {\n self\n } else {\n default()\n }\n }\n\n // If only one of the two Options is Some, return that option.\n // Otherwise, if both options are Some or both are None, None is returned.\n pub fn xor(self, other: Self) -> Self {\n if self._is_some {\n if other._is_some {\n Option::none()\n } else {\n self\n }\n } else if other._is_some {\n other\n } else {\n Option::none()\n }\n }\n\n /// Returns `Some(x)` if self is `Some(x)` and `predicate(x)` is true.\n /// Otherwise, this returns `None`\n pub fn filter(self, predicate: fn[Env](T) -> bool) -> Self {\n if self._is_some {\n if predicate(self._value) {\n self\n } else {\n Option::none()\n }\n } else {\n Option::none()\n }\n }\n\n /// Flattens an Option> into a Option.\n /// This returns None if the outer Option is None. Otherwise, this returns the inner Option.\n pub fn flatten(option: Option>) -> Option {\n if option._is_some {\n option._value\n } else {\n Option::none()\n }\n }\n}\n\nimpl Default for Option {\n fn default() -> Self {\n Option::none()\n }\n}\n\nimpl Eq for Option\nwhere\n T: Eq,\n{\n fn eq(self, other: Self) -> bool {\n if self._is_some == other._is_some {\n if self._is_some {\n self._value == other._value\n } else {\n true\n }\n } else {\n false\n }\n }\n}\n\nimpl Hash for Option\nwhere\n T: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n self._is_some.hash(state);\n if self._is_some {\n self._value.hash(state);\n }\n }\n}\n\n// For this impl we're declaring Option::none < Option::some\nimpl Ord for Option\nwhere\n T: Ord,\n{\n fn cmp(self, other: Self) -> Ordering {\n if self._is_some {\n if other._is_some {\n self._value.cmp(other._value)\n } else {\n Ordering::greater()\n }\n } else if other._is_some {\n Ordering::less()\n } else {\n Ordering::equal()\n }\n }\n}\n"},"425":{"path":"/home/nerses/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.2/noir-projects/aztec-nr/uint-note/src/uint_note.nr","source":"use dep::aztec::{\n context::{PrivateContext, PublicContext},\n history::nullifier_inclusion::ProveNullifierInclusion,\n keys::getters::{get_nsk_app, get_public_keys},\n macros::notes::custom_note,\n messages::logs::note,\n note::note_interface::{NoteHash, NoteType},\n oracle::random::random,\n protocol_types::{\n address::AztecAddress,\n constants::{\n GENERATOR_INDEX__NOTE_HASH, GENERATOR_INDEX__NOTE_NULLIFIER,\n GENERATOR_INDEX__PARTIAL_NOTE_VALIDITY_COMMITMENT, PRIVATE_LOG_SIZE_IN_FIELDS,\n },\n hash::{compute_siloed_nullifier, poseidon2_hash_with_separator},\n traits::{Deserialize, FromField, Hash, Packable, Serialize, ToField},\n },\n};\n\n// UintNote supports partial notes, i.e. the ability to create an incomplete note in private, hiding certain values (the\n// owner, storage slot and randomness), and then completing the note in public with the ones missing (the amount).\n// Partial notes are being actively developed and are not currently fully supported via macros, and so we rely on the\n// #[custom_note] macro to implement it manually, resulting in some boilerplate. This is expected to be unnecessary once\n// macro support is expanded.\n\n/// A private note representing a numeric value associated to an account (e.g. a token balance).\n#[derive(Deserialize, Eq, Serialize, Packable)]\n#[custom_note]\npub struct UintNote {\n // The ordering of these fields is important given that it must:\n // a) match that of UintPartialNotePrivateContent, and\n // b) have the public field at the end\n // Correct ordering is checked by the tests in this module.\n\n /// The owner of the note, i.e. the account whose nullifier secret key is required to compute the nullifier.\n owner: AztecAddress,\n /// Random value, protects against note hash preimage attacks.\n randomness: Field,\n /// The number stored in the note.\n value: u128,\n}\n\nimpl NoteHash for UintNote {\n fn compute_note_hash(self, storage_slot: Field) -> Field {\n // Partial notes can be implemented by having the note hash be either the result of multiscalar multiplication\n // (MSM), or two rounds of poseidon. MSM results in more constraints and is only required when multiple variants\n // of partial notes are supported. Because UintNote has just one variant (where the value is public), we use\n // poseidon instead.\n\n // We must compute the same note hash as would be produced by a partial note created and completed with the same\n // values, so that notes all behave the same way regardless of how they were created. To achieve this, we\n // perform both steps of the partial note computation.\n\n // First we create the partial note from a commitment to the private content (including storage slot).\n let private_content =\n UintPartialNotePrivateContent { owner: self.owner, randomness: self.randomness };\n let partial_note = PartialUintNote {\n commitment: private_content.compute_partial_commitment(storage_slot),\n };\n\n // Then compute the completion note hash. In a real partial note this step would be performed in public.\n partial_note.compute_complete_note_hash(self.value)\n }\n\n // The nullifiers are nothing special - this is just the canonical implementation that would be injected by the\n // #[note] macro.\n\n fn compute_nullifier(\n self,\n context: &mut PrivateContext,\n note_hash_for_nullification: Field,\n ) -> Field {\n let owner_npk_m = get_public_keys(self.owner).npk_m;\n let owner_npk_m_hash = owner_npk_m.hash();\n let secret = context.request_nsk_app(owner_npk_m_hash);\n poseidon2_hash_with_separator(\n [note_hash_for_nullification, secret],\n GENERATOR_INDEX__NOTE_NULLIFIER,\n )\n }\n\n unconstrained fn compute_nullifier_unconstrained(\n self,\n note_hash_for_nullification: Field,\n ) -> Field {\n let owner_npk_m = get_public_keys(self.owner).npk_m;\n let owner_npk_m_hash = owner_npk_m.hash();\n let secret = get_nsk_app(owner_npk_m_hash);\n poseidon2_hash_with_separator(\n [note_hash_for_nullification, secret],\n GENERATOR_INDEX__NOTE_NULLIFIER,\n )\n }\n}\n\nimpl UintNote {\n pub fn new(value: u128, owner: AztecAddress) -> Self {\n // Safety: We use the randomness to preserve the privacy of the note recipient by preventing brute-forcing,\n // so a malicious sender could use non-random values to make the note less private. But they already know\n // the full note pre-image anyway, and so the recipient already trusts them to not disclose this\n // information. We can therefore assume that the sender will cooperate in the random value generation.\n let randomness = unsafe { random() };\n Self { value, owner, randomness }\n }\n\n pub fn get_value(self) -> u128 {\n self.value\n }\n\n pub fn get_owner(self) -> AztecAddress {\n self.owner\n }\n\n /// Creates a partial note that will hide the owner and storage slot but not the value, since the note will be later\n /// completed in public. This is a powerful technique for scenarios in which the value cannot be known in private\n /// (e.g. because it depends on some public state, such as a DEX).\n ///\n /// This function inserts a partial note validity commitment into the nullifier tree to be later on able to verify\n /// that the partial note and completer are legitimate. See function docs of `compute_validity_commitment` for more\n /// details.\n ///\n /// Each partial note should only be used once, since otherwise multiple notes would be linked together and known to\n /// belong to the same owner.\n ///\n /// As part of the partial note creation process, a log will be sent to `recipient` so that they can discover the\n /// note. `recipient` will typically be the same as `owner`.\n pub fn partial(\n owner: AztecAddress,\n storage_slot: Field,\n context: &mut PrivateContext,\n recipient: AztecAddress,\n completer: AztecAddress,\n ) -> PartialUintNote {\n // Safety: We use the randomness to preserve the privacy of the note recipient by preventing brute-forcing,\n // so a malicious sender could use non-random values to make the note less private. But they already know\n // the full note pre-image anyway, and so the recipient already trusts them to not disclose this\n // information. We can therefore assume that the sender will cooperate in the random value generation.\n let randomness = unsafe { random() };\n\n // We create a commitment to the private data, which we then use to construct the log we send to the recipient.\n let commitment = UintPartialNotePrivateContent { owner, randomness }\n .compute_partial_commitment(storage_slot);\n\n // Our partial note log encoding scheme includes a field with the tag of the public completion log, and we use\n // the commitment as the tag. This is good for multiple reasons:\n // - the commitment is uniquely tied to this partial note\n // - the commitment is already public information, so we're not revealing anything else\n // - we don't need to create any additional information, private or public, for the tag\n // - other contracts cannot impersonate us and emit logs with the same tag due to public log siloing\n let private_log_content =\n UintPartialNotePrivateLogContent { owner, randomness, public_log_tag: commitment };\n\n let encrypted_log = note::compute_partial_note_private_content_log(\n private_log_content,\n storage_slot,\n recipient,\n );\n // Regardless of the original content size, the log is padded with random bytes up to\n // `PRIVATE_LOG_SIZE_IN_FIELDS` to prevent leaking information about the actual size.\n let length = encrypted_log.len();\n context.emit_private_log(encrypted_log, length);\n\n let partial_note = PartialUintNote { commitment };\n\n // Now we compute the validity commitment and push it to the nullifier tree. It can be safely pushed to\n // the nullifier tree since it uses its own separator, making collisions with actual note nullifiers\n // practically impossible.\n let validity_commitment = partial_note.compute_validity_commitment(completer);\n context.push_nullifier(validity_commitment);\n\n partial_note\n }\n}\n\n/// The private content of a partial UintNote, i.e. the fields that will remain private. All other note fields will be\n/// made public.\n#[derive(Packable)]\nstruct UintPartialNotePrivateContent {\n // The ordering of these fields is important given that it must match that of UintNote.\n // Correct ordering is checked by the tests in this module.\n owner: AztecAddress,\n randomness: Field,\n}\n\nimpl UintPartialNotePrivateContent {\n fn compute_partial_commitment(self, storage_slot: Field) -> Field {\n // Here we commit to all private values, including the storage slot.\n poseidon2_hash_with_separator(\n self.pack().concat([storage_slot]),\n GENERATOR_INDEX__NOTE_HASH,\n )\n }\n}\n\n#[derive(Packable)]\nstruct UintPartialNotePrivateLogContent {\n // The ordering of these fields is important given that it must:\n // a) match that of UintNote, and\n // b) have the public log tag at the beginning\n // Correct ordering is checked by the tests in this module.\n public_log_tag: Field,\n owner: AztecAddress,\n randomness: Field,\n}\n\nimpl NoteType for UintPartialNotePrivateLogContent {\n fn get_id() -> Field {\n UintNote::get_id()\n }\n}\n\n/// A partial instance of a UintNote. This value represents a private commitment to the owner, randomness and storage\n/// slot, but the value field has not yet been set. A partial note can be completed in public with the `complete`\n/// function (revealing the value to the public), resulting in a UintNote that can be used like any other one (except\n/// of course that its value is known).\n#[derive(Packable, Serialize, Deserialize, Eq)]\npub struct PartialUintNote {\n commitment: Field,\n}\n\nglobal NOTE_COMPLETION_LOG_LENGTH: u32 = 2;\n\nimpl PartialUintNote {\n /// Completes the partial note, creating a new note that can be used like any other UintNote.\n pub fn complete(self, context: &mut PublicContext, completer: AztecAddress, value: u128) {\n // A note with a value of zero is valid, but we cannot currently complete a partial note with such a value\n // because this will result in the completion log having its last field set to 0. Public logs currently do not\n // track their length, and so trailing zeros are simply trimmed. This results in the completion log missing its\n // last field (the value), and note discovery failing.\n // TODO(#11636): remove this\n assert(value != 0, \"Cannot complete a PartialUintNote with a value of 0\");\n\n // We verify that the partial note we're completing is valid (i.e. completer is correct, it uses the correct\n // state variable's storage slot, and it is internally consistent).\n let validity_commitment = self.compute_validity_commitment(completer);\n assert(\n context.nullifier_exists(validity_commitment, context.this_address()),\n \"Invalid partial note or completer\",\n );\n\n // We need to do two things:\n // - emit a public log containing the public fields (the value). The contract will later find it by searching\n // for the expected tag (which is simply the partial note commitment).\n // - insert the completion note hash (i.e. the hash of the note) into the note hash tree. This is typically\n // only done in private to hide the preimage of the hash that is inserted, but completed partial notes are\n // inserted in public as the public values are provided and the note hash computed.\n context.emit_public_log(self.compute_note_completion_log(value));\n context.push_note_hash(self.compute_complete_note_hash(value));\n }\n\n /// Completes the partial note, creating a new note that can be used like any other UintNote. Same as `complete`\n /// function but works from private context.\n pub fn complete_from_private(\n self,\n context: &mut PrivateContext,\n completer: AztecAddress,\n value: u128,\n ) {\n // We verify that the partial note we're completing is valid (i.e. completer is correct, it uses the correct\n // state variable's storage slot, and it is internally consistent).\n let validity_commitment = self.compute_validity_commitment(completer);\n // `prove_nullifier_inclusion` function expects the nullifier to be siloed (hashed with the address of\n // the contract that emitted the nullifier) as it checks the value directly against the nullifier tree and all\n // the nullifiers in the tree are siloed by the protocol.\n let siloed_validity_commitment =\n compute_siloed_nullifier(context.this_address(), validity_commitment);\n context.get_anchor_block_header().prove_nullifier_inclusion(siloed_validity_commitment);\n\n // We need to do two things:\n // - emit an unencrypted log containing the public fields (the value) via the private log channel. The\n // contract will later find it by searching for the expected tag (which is simply the partial note\n // commitment).\n // - insert the completion note hash (i.e. the hash of the note) into the note hash tree. This is typically\n // only done in private to hide the preimage of the hash that is inserted, but completed partial notes are\n // inserted in public as the public values are provided and the note hash computed.\n context.emit_private_log(\n self.compute_note_completion_log_padded_for_private_log(value),\n NOTE_COMPLETION_LOG_LENGTH,\n );\n context.push_note_hash(self.compute_complete_note_hash(value));\n }\n\n /// Computes a validity commitment for this partial note. The commitment cryptographically binds the note's private\n /// data with the designated completer address. When the note is later completed in public execution, we can load\n /// this commitment from the nullifier tree and verify that both the partial note (e.g. that the storage slot\n /// corresponds to the correct owner, and that we're using the correct state variable) and completer are\n /// legitimate.\n pub fn compute_validity_commitment(self, completer: AztecAddress) -> Field {\n poseidon2_hash_with_separator(\n [self.commitment, completer.to_field()],\n GENERATOR_INDEX__PARTIAL_NOTE_VALIDITY_COMMITMENT,\n )\n }\n\n fn compute_note_completion_log(self, value: u128) -> [Field; NOTE_COMPLETION_LOG_LENGTH] {\n // The first field of this log must be the tag that the recipient of the partial note private field logs\n // expects, which is equal to the partial note commitment.\n [self.commitment, value.to_field()]\n }\n\n fn compute_note_completion_log_padded_for_private_log(\n self,\n value: u128,\n ) -> [Field; PRIVATE_LOG_SIZE_IN_FIELDS] {\n let note_completion_log = self.compute_note_completion_log(value);\n let padding = [0; PRIVATE_LOG_SIZE_IN_FIELDS - NOTE_COMPLETION_LOG_LENGTH];\n note_completion_log.concat(padding)\n }\n\n fn compute_complete_note_hash(self, value: u128) -> Field {\n // Here we finalize the note hash by including the (public) value into the partial note commitment. Note that we\n // use the same generator index as we used for the first round of poseidon - this is not an issue.\n poseidon2_hash_with_separator(\n [self.commitment, value.to_field()],\n GENERATOR_INDEX__NOTE_HASH,\n )\n }\n}\n\nimpl ToField for PartialUintNote {\n fn to_field(self) -> Field {\n self.commitment\n }\n}\n\nimpl FromField for PartialUintNote {\n fn from_field(field: Field) -> Self {\n Self { commitment: field }\n }\n}\n\nmod test {\n use super::{\n PartialUintNote, UintNote, UintPartialNotePrivateContent, UintPartialNotePrivateLogContent,\n };\n use dep::aztec::{\n note::note_interface::NoteHash,\n protocol_types::{address::AztecAddress, traits::{Deserialize, FromField, Packable}},\n utils::array::subarray,\n };\n\n global value: u128 = 17;\n global randomness: Field = 42;\n global owner: AztecAddress = AztecAddress::from_field(50);\n global storage_slot: Field = 13;\n\n #[test]\n fn note_hash_matches_completed_partial_note_hash() {\n // Tests that a UintNote has the same note hash as a PartialUintNote created and then completed with the same\n // private values. This requires for the same hash function to be used in both flows, with the fields in the\n // same order.\n\n let note = UintNote { value, randomness, owner };\n let note_hash = note.compute_note_hash(storage_slot);\n\n let partial_note_private_content = UintPartialNotePrivateContent { owner, randomness };\n\n let partial_note = PartialUintNote {\n commitment: partial_note_private_content.compute_partial_commitment(storage_slot),\n };\n let completed_partial_note_hash = partial_note.compute_complete_note_hash(value);\n\n assert_eq(note_hash, completed_partial_note_hash);\n }\n\n #[test]\n fn unpack_from_partial_note_encoding() {\n // Tests that the packed representation of a regular UintNote can be reconstructed given the partial note\n // private fields log and the public completion log, ensuring the recipient will be able to compute the\n // completed note as if it were a regular UintNote.\n\n let note = UintNote { value, randomness, owner };\n\n let partial_note_private_content = UintPartialNotePrivateContent { owner, randomness };\n let commitment = partial_note_private_content.compute_partial_commitment(storage_slot);\n\n let private_log_content =\n UintPartialNotePrivateLogContent { owner, randomness, public_log_tag: commitment };\n // The following is a misuse of the `deserialize` function, but this is just a test and it's better than\n // letting devs manually construct it when they shouldn't be able to.\n let partial_note = PartialUintNote::deserialize([commitment]);\n\n // The first field of the partial note private content is the public completion log tag, so it should match the\n // first field of the public log.\n assert_eq(\n private_log_content.pack()[0],\n partial_note.compute_note_completion_log(value)[0],\n );\n\n // Then we extract all fields except the first of both logs (i.e. the public log tag), and combine them to\n // produce the note's packed representation. This requires that the members of the intermediate structs are in\n // the same order as in UintNote.\n let private_log_without_public_tag: [_; 2] = subarray(private_log_content.pack(), 1);\n let public_log_without_tag: [_; 1] =\n subarray(partial_note.compute_note_completion_log(value), 1);\n\n assert_eq(private_log_without_public_tag.concat(public_log_without_tag), note.pack());\n }\n}\n"},"43":{"path":"std/panic.nr","source":"pub fn panic(message: fmtstr) -> U {\n assert(false, message);\n crate::mem::zeroed()\n}\n"},"46":{"path":"std/slice.nr","source":"use crate::append::Append;\n\nimpl [T] {\n /// Returns the length of the slice.\n #[builtin(array_len)]\n pub fn len(self) -> u32 {}\n\n /// Push a new element to the end of the slice, returning a\n /// new slice with a length one greater than the\n /// original unmodified slice.\n #[builtin(slice_push_back)]\n pub fn push_back(self, elem: T) -> Self {}\n\n /// Push a new element to the front of the slice, returning a\n /// new slice with a length one greater than the\n /// original unmodified slice.\n #[builtin(slice_push_front)]\n pub fn push_front(self, elem: T) -> Self {}\n\n /// Remove the last element of the slice, returning the\n /// popped slice and the element in a tuple\n #[builtin(slice_pop_back)]\n pub fn pop_back(self) -> (Self, T) {}\n\n /// Remove the first element of the slice, returning the\n /// element and the popped slice in a tuple\n #[builtin(slice_pop_front)]\n pub fn pop_front(self) -> (T, Self) {}\n\n /// Insert an element at a specified index, shifting all elements\n /// after it to the right\n #[builtin(slice_insert)]\n pub fn insert(self, index: u32, elem: T) -> Self {}\n\n /// Remove an element at a specified index, shifting all elements\n /// after it to the left, returning the altered slice and\n /// the removed element\n #[builtin(slice_remove)]\n pub fn remove(self, index: u32) -> (Self, T) {}\n\n /// Append each element of the `other` slice to the end of `self`.\n /// This returns a new slice and leaves both input slices unchanged.\n pub fn append(mut self, other: Self) -> Self {\n for elem in other {\n self = self.push_back(elem);\n }\n self\n }\n\n pub fn as_array(self) -> [T; N] {\n assert(self.len() == N);\n\n let mut array = [crate::mem::zeroed(); N];\n for i in 0..N {\n array[i] = self[i];\n }\n array\n }\n\n // Apply a function to each element of the slice, returning a new slice\n // containing the mapped elements.\n pub fn map(self, f: fn[Env](T) -> U) -> [U] {\n let mut ret = &[];\n for elem in self {\n ret = ret.push_back(f(elem));\n }\n ret\n }\n\n // Apply a function to each element of the slice with its index, returning a\n // new slice containing the mapped elements.\n pub fn mapi(self, f: fn[Env](u32, T) -> U) -> [U] {\n let mut ret = &[];\n let mut index = 0;\n for elem in self {\n ret = ret.push_back(f(index, elem));\n index += 1;\n }\n ret\n }\n\n // Apply a function to each element of the slice\n pub fn for_each(self, f: fn[Env](T) -> ()) {\n for elem in self {\n f(elem);\n }\n }\n\n // Apply a function to each element of the slice with its index\n pub fn for_eachi(self, f: fn[Env](u32, T) -> ()) {\n let mut index = 0;\n for elem in self {\n f(index, elem);\n index += 1;\n }\n }\n\n // Apply a function to each element of the slice and an accumulator value,\n // returning the final accumulated value. This function is also sometimes\n // called `foldl`, `fold_left`, `reduce`, or `inject`.\n pub fn fold(self, mut accumulator: U, f: fn[Env](U, T) -> U) -> U {\n for elem in self {\n accumulator = f(accumulator, elem);\n }\n accumulator\n }\n\n // Apply a function to each element of the slice and an accumulator value,\n // returning the final accumulated value. Unlike fold, reduce uses the first\n // element of the given slice as its starting accumulator value.\n pub fn reduce(self, f: fn[Env](T, T) -> T) -> T {\n let mut accumulator = self[0];\n for i in 1..self.len() {\n accumulator = f(accumulator, self[i]);\n }\n accumulator\n }\n\n // Returns a new slice containing only elements for which the given predicate\n // returns true.\n pub fn filter(self, predicate: fn[Env](T) -> bool) -> Self {\n let mut ret = &[];\n for elem in self {\n if predicate(elem) {\n ret = ret.push_back(elem);\n }\n }\n ret\n }\n\n // Flatten each element in the slice into one value, separated by `separator`.\n pub fn join(self, separator: T) -> T\n where\n T: Append,\n {\n let mut ret = T::empty();\n\n if self.len() != 0 {\n ret = self[0];\n\n for i in 1..self.len() {\n ret = ret.append(separator).append(self[i]);\n }\n }\n\n ret\n }\n\n // Returns true if all elements in the slice satisfy the predicate\n pub fn all(self, predicate: fn[Env](T) -> bool) -> bool {\n let mut ret = true;\n for elem in self {\n ret &= predicate(elem);\n }\n ret\n }\n\n // Returns true if any element in the slice satisfies the predicate\n pub fn any(self, predicate: fn[Env](T) -> bool) -> bool {\n let mut ret = false;\n for elem in self {\n ret |= predicate(elem);\n }\n ret\n }\n}\n\nmod test {\n #[test]\n fn map_empty() {\n assert_eq(&[].map(|x| x + 1), &[]);\n }\n\n #[test]\n fn mapi_empty() {\n assert_eq(&[].mapi(|i, x| i * x + 1), &[]);\n }\n\n #[test]\n fn for_each_empty() {\n let empty_slice: [Field] = &[];\n empty_slice.for_each(|_x| assert(false));\n assert(empty_slice == &[]);\n }\n\n #[test]\n fn for_eachi_empty() {\n let empty_slice: [Field] = &[];\n empty_slice.for_eachi(|_i, _x| assert(false));\n assert(empty_slice == &[]);\n }\n\n #[test]\n fn map_example() {\n let a = &[1, 2, 3];\n let b = a.map(|a| a * 2);\n assert_eq(b, &[2, 4, 6]);\n assert_eq(a, &[1, 2, 3]);\n }\n\n #[test]\n fn mapi_example() {\n let a = &[1, 2, 3];\n let b = a.mapi(|i, a| i + a * 2);\n assert_eq(b, &[2, 5, 8]);\n assert_eq(a, &[1, 2, 3]);\n }\n\n #[test]\n fn for_each_example() {\n let a = &[1, 2, 3];\n let mut b = &[];\n let b_ref = &mut b;\n a.for_each(|a| { *b_ref = b_ref.push_back(a * 2); });\n assert_eq(b, &[2, 4, 6]);\n }\n\n #[test]\n fn for_eachi_example() {\n let a = &[1, 2, 3];\n let mut b = &[];\n let b_ref = &mut b;\n a.for_eachi(|i, a| { *b_ref = b_ref.push_back(i + a * 2); });\n assert_eq(b, &[2, 5, 8]);\n }\n\n #[test]\n fn len_empty() {\n let empty: [Field] = &[];\n assert_eq(empty.len(), 0);\n }\n\n #[test]\n fn len_single() {\n assert_eq(&[42].len(), 1);\n }\n\n #[test]\n fn len_multiple() {\n assert_eq(&[1, 2, 3, 4, 5].len(), 5);\n }\n\n #[test]\n fn push_back_empty() {\n let empty: [Field] = &[];\n let result = empty.push_back(42);\n assert_eq(result.len(), 1);\n assert_eq(result[0], 42);\n }\n\n #[test]\n fn push_back_non_empty() {\n let slice = &[1, 2, 3];\n let result = slice.push_back(4);\n assert_eq(result.len(), 4);\n assert_eq(result, &[1, 2, 3, 4]);\n }\n\n #[test]\n fn push_front_empty() {\n let empty = &[];\n let result = empty.push_front(42);\n assert_eq(result.len(), 1);\n assert_eq(result[0], 42);\n }\n\n #[test]\n fn push_front_non_empty() {\n let slice = &[1, 2, 3];\n let result = slice.push_front(0);\n assert_eq(result.len(), 4);\n assert_eq(result, &[0, 1, 2, 3]);\n }\n\n #[test(should_fail_with = \"Index out of bounds\")]\n fn pop_back_empty() {\n let slice: [Field] = &[];\n let (_, _) = slice.pop_back();\n }\n\n #[test]\n fn pop_back_one() {\n let slice = &[42];\n let (result, elem) = slice.pop_back();\n assert_eq(result.len(), 0);\n assert_eq(elem, 42);\n }\n\n #[test]\n fn pop_back_multiple() {\n let slice = &[1, 2, 3];\n let (result, elem) = slice.pop_back();\n assert_eq(result.len(), 2);\n assert_eq(result, &[1, 2]);\n assert_eq(elem, 3);\n }\n\n #[test(should_fail_with = \"Index out of bounds\")]\n fn pop_front_empty() {\n let slice: [Field] = &[];\n let (_, _) = slice.pop_front();\n }\n\n #[test]\n fn pop_front_one() {\n let slice = &[42];\n let (elem, result) = slice.pop_front();\n assert_eq(result.len(), 0);\n assert_eq(elem, 42);\n }\n\n #[test]\n fn pop_front_multiple() {\n let slice = &[1, 2, 3];\n let (elem, result) = slice.pop_front();\n assert_eq(result.len(), 2);\n assert_eq(result, &[2, 3]);\n assert_eq(elem, 1);\n }\n\n #[test]\n fn insert_beginning() {\n let slice = &[1, 2, 3];\n let result = slice.insert(0, 0);\n assert_eq(result.len(), 4);\n assert_eq(result, &[0, 1, 2, 3]);\n }\n\n #[test]\n fn insert_middle() {\n let slice = &[1, 2, 3];\n let result = slice.insert(1, 99);\n assert_eq(result.len(), 4);\n assert_eq(result, &[1, 99, 2, 3]);\n }\n\n #[test]\n fn insert_end() {\n let slice = &[1, 2, 3];\n let result = slice.insert(3, 4);\n assert_eq(result.len(), 4);\n assert_eq(result, &[1, 2, 3, 4]);\n }\n\n #[test(should_fail_with = \"Index out of bounds\")]\n fn insert_end_out_of_bounds() {\n let slice = &[1, 2];\n let _ = slice.insert(3, 4);\n }\n\n #[test(should_fail_with = \"Index out of bounds\")]\n fn remove_empty() {\n let slice: [Field] = &[];\n let (_, _) = slice.remove(0);\n }\n\n #[test]\n fn remove_beginning() {\n let slice = &[1, 2, 3];\n let (result, elem) = slice.remove(0);\n assert_eq(result.len(), 2);\n assert_eq(result, &[2, 3]);\n assert_eq(elem, 1);\n }\n\n #[test]\n fn remove_middle() {\n let slice = &[1, 2, 3];\n let (result, elem) = slice.remove(1);\n assert_eq(result.len(), 2);\n assert_eq(result, &[1, 3]);\n assert_eq(elem, 2);\n }\n\n #[test]\n fn remove_end() {\n let slice = &[1, 2, 3];\n let (result, elem) = slice.remove(2);\n assert_eq(result.len(), 2);\n assert_eq(result, &[1, 2]);\n assert_eq(elem, 3);\n }\n\n #[test(should_fail_with = \"Index out of bounds\")]\n fn remove_end_out_of_bounds() {\n let slice = &[1, 2];\n let (_, _) = slice.remove(2);\n }\n\n #[test]\n fn fold_empty() {\n let empty = &[];\n let result = empty.fold(10, |acc, x| acc + x);\n assert_eq(result, 10);\n }\n\n #[test]\n fn fold_single() {\n let slice = &[5];\n let result = slice.fold(10, |acc, x| acc + x);\n assert_eq(result, 15);\n }\n\n #[test]\n fn fold_multiple() {\n let slice = &[1, 2, 3, 4];\n let result = slice.fold(0, |acc, x| acc + x);\n assert_eq(result, 10);\n }\n\n #[test(should_fail_with = \"Index out of bounds\")]\n fn reduce_empty() {\n let empty: [Field] = &[];\n let _ = empty.reduce(|a, b| a + b);\n }\n\n #[test]\n fn reduce_single() {\n let slice = &[42];\n let result = slice.reduce(|a, b| a + b);\n assert_eq(result, 42);\n }\n\n #[test]\n fn reduce_multiple() {\n let slice = &[1, 2, 3, 4];\n let result = slice.reduce(|a, b| a + b);\n assert_eq(result, 10);\n }\n\n #[test]\n fn filter_empty() {\n let empty = &[];\n let result = empty.filter(|x| x > 0);\n assert_eq(result.len(), 0);\n }\n\n #[test]\n fn filter_all_true() {\n let slice = &[1, 2, 3, 4];\n let result = slice.filter(|x| x > 0);\n assert_eq(result, slice);\n }\n\n #[test]\n fn filter_all_false() {\n let slice = &[1, 2, 3, 4];\n let result = slice.filter(|x| x > 10);\n assert_eq(result.len(), 0);\n }\n\n #[test]\n fn filter_some() {\n let slice = &[1, 2, 3, 4, 5];\n let result = slice.filter(|x| x % 2 == 0);\n assert_eq(result, &[2, 4]);\n }\n\n #[test]\n fn all_empty() {\n let empty = &[];\n let result = empty.all(|x| x > 0);\n assert_eq(result, true);\n }\n\n #[test]\n fn all_true() {\n let slice = &[1, 2, 3, 4];\n let result = slice.all(|x| x > 0);\n assert_eq(result, true);\n }\n\n #[test]\n fn all_false() {\n let slice = &[1, 2, 3, 4];\n let result = slice.all(|x| x > 2);\n assert_eq(result, false);\n }\n\n #[test]\n fn any_empty() {\n let empty = &[];\n let result = empty.any(|x| x > 0);\n assert_eq(result, false);\n }\n\n #[test]\n fn any_true() {\n let slice = &[1, 2, 3, 4];\n let result = slice.any(|x| x > 3);\n assert_eq(result, true);\n }\n\n #[test]\n fn any_false() {\n let slice = &[1, 2, 3, 4];\n let result = slice.any(|x| x > 10);\n assert_eq(result, false);\n }\n\n // utility method tests\n #[test]\n fn append_empty_to_empty() {\n let empty1: [Field] = &[];\n let empty2: [Field] = &[];\n let result = empty1.append(empty2);\n assert_eq(result.len(), 0);\n }\n\n #[test]\n fn append_empty_to_non_empty() {\n let slice = &[1, 2, 3];\n let empty = &[];\n let result = slice.append(empty);\n assert_eq(result, slice);\n }\n\n #[test]\n fn append_non_empty_to_empty() {\n let empty = &[];\n let slice = &[1, 2, 3];\n let result = empty.append(slice);\n assert_eq(result, slice);\n }\n\n #[test]\n fn append_two_non_empty() {\n let slice1 = &[1, 2];\n let slice2 = &[3, 4, 5];\n let result = slice1.append(slice2);\n assert_eq(result, &[1, 2, 3, 4, 5]);\n }\n\n #[test]\n fn as_array_single() {\n let slice = &[42];\n let array: [Field; 1] = slice.as_array();\n assert_eq(array[0], 42);\n }\n\n #[test]\n fn as_array_multiple() {\n let slice = &[1, 2, 3];\n let array: [Field; 3] = slice.as_array();\n assert_eq(array[0], 1);\n assert_eq(array[1], 2);\n assert_eq(array[2], 3);\n }\n\n // complex scenarios\n #[test]\n fn chain_operations() {\n let slice = &[1, 2, 3, 4, 5];\n let result = slice.filter(|x| x % 2 == 0).map(|x| x * 2).fold(0, |acc, x| acc + x);\n assert_eq(result, 12); // (2*2) + (4*2) = 4 + 8 = 12\n }\n\n #[test]\n fn nested_operations() {\n let slice = &[1, 2, 3, 4];\n let filtered = slice.filter(|x| x > 1);\n let mapped = filtered.map(|x| x * x);\n let sum = mapped.fold(0, |acc, x| acc + x);\n assert_eq(sum, 29); // 2^2 + 3^2 + 4^2 = 4 + 9 + 16 = 29\n }\n\n #[test]\n fn single_element_operations() {\n let single = &[42];\n\n // Test all operations on single element\n assert_eq(single.len(), 1);\n\n let pushed_back = single.push_back(99);\n assert_eq(pushed_back, &[42, 99]);\n\n let pushed_front = single.push_front(0);\n assert_eq(pushed_front, &[0, 42]);\n\n let (popped_back_slice, popped_back_elem) = single.pop_back();\n assert_eq(popped_back_slice.len(), 0);\n assert_eq(popped_back_elem, 42);\n\n let (popped_front_elem, popped_front_slice) = single.pop_front();\n assert_eq(popped_front_slice.len(), 0);\n assert_eq(popped_front_elem, 42);\n\n let inserted = single.insert(0, 0);\n assert_eq(inserted, &[0, 42]);\n\n let (removed_slice, removed_elem) = single.remove(0);\n assert_eq(removed_slice.len(), 0);\n assert_eq(removed_elem, 42);\n }\n\n #[test]\n fn boundary_conditions() {\n let slice = &[1, 2, 3];\n\n // insert at boundaries\n let at_start = slice.insert(0, 0);\n assert_eq(at_start, &[0, 1, 2, 3]);\n\n let at_end = slice.insert(3, 4);\n assert_eq(at_end, &[1, 2, 3, 4]);\n\n // remove at boundaries\n let (removed_start, elem_start) = slice.remove(0);\n assert_eq(removed_start, &[2, 3]);\n assert_eq(elem_start, 1);\n\n let (removed_end, elem_end) = slice.remove(2);\n assert_eq(removed_end, &[1, 2]);\n assert_eq(elem_end, 3);\n }\n\n #[test]\n fn complex_predicates() {\n let slice = &[1, 2, 3, 4, 5, 6, 7, 8, 9, 10];\n\n let even_greater_than_5 = slice.filter(|x| (x % 2 == 0) & (x > 5));\n assert_eq(even_greater_than_5, &[6, 8, 10]);\n\n let all_positive_and_less_than_20 = slice.all(|x| (x > 0) & (x < 20));\n assert_eq(all_positive_and_less_than_20, true);\n\n let any_divisible_by_7 = slice.any(|x| x % 7 == 0);\n assert_eq(any_divisible_by_7, true);\n }\n\n #[test]\n fn identity_operations() {\n let slice = &[1, 2, 3, 4, 5];\n\n let mapped_identity = slice.map(|x| x);\n assert_eq(mapped_identity, slice);\n\n let filtered_all = slice.filter(|_| true);\n assert_eq(filtered_all, slice);\n\n let filtered_none = slice.filter(|_| false);\n assert_eq(filtered_none.len(), 0);\n }\n\n #[test(should_fail)]\n fn as_array_size_mismatch() {\n let slice = &[1, 2, 3];\n let _: [Field; 5] = slice.as_array(); // size doesn't match\n }\n}\n"},"5":{"path":"std/cmp.nr","source":"use crate::meta::derive_via;\n\n#[derive_via(derive_eq)]\n// docs:start:eq-trait\npub trait Eq {\n fn eq(self, other: Self) -> bool;\n}\n// docs:end:eq-trait\n\n// docs:start:derive_eq\ncomptime fn derive_eq(s: TypeDefinition) -> Quoted {\n let signature = quote { fn eq(_self: Self, _other: Self) -> bool };\n let for_each_field = |name| quote { (_self.$name == _other.$name) };\n let body = |fields| {\n if s.fields_as_written().len() == 0 {\n quote { true }\n } else {\n fields\n }\n };\n crate::meta::make_trait_impl(\n s,\n quote { $crate::cmp::Eq },\n signature,\n for_each_field,\n quote { & },\n body,\n )\n}\n// docs:end:derive_eq\n\nimpl Eq for Field {\n fn eq(self, other: Field) -> bool {\n self == other\n }\n}\n\nimpl Eq for u128 {\n fn eq(self, other: u128) -> bool {\n self == other\n }\n}\nimpl Eq for u64 {\n fn eq(self, other: u64) -> bool {\n self == other\n }\n}\nimpl Eq for u32 {\n fn eq(self, other: u32) -> bool {\n self == other\n }\n}\nimpl Eq for u16 {\n fn eq(self, other: u16) -> bool {\n self == other\n }\n}\nimpl Eq for u8 {\n fn eq(self, other: u8) -> bool {\n self == other\n }\n}\nimpl Eq for u1 {\n fn eq(self, other: u1) -> bool {\n self == other\n }\n}\n\nimpl Eq for i8 {\n fn eq(self, other: i8) -> bool {\n self == other\n }\n}\nimpl Eq for i16 {\n fn eq(self, other: i16) -> bool {\n self == other\n }\n}\nimpl Eq for i32 {\n fn eq(self, other: i32) -> bool {\n self == other\n }\n}\nimpl Eq for i64 {\n fn eq(self, other: i64) -> bool {\n self == other\n }\n}\n\nimpl Eq for () {\n fn eq(_self: Self, _other: ()) -> bool {\n true\n }\n}\nimpl Eq for bool {\n fn eq(self, other: bool) -> bool {\n self == other\n }\n}\n\nimpl Eq for [T; N]\nwhere\n T: Eq,\n{\n fn eq(self, other: [T; N]) -> bool {\n let mut result = true;\n for i in 0..self.len() {\n result &= self[i].eq(other[i]);\n }\n result\n }\n}\n\nimpl Eq for [T]\nwhere\n T: Eq,\n{\n fn eq(self, other: [T]) -> bool {\n let mut result = self.len() == other.len();\n if result {\n for i in 0..self.len() {\n result &= self[i].eq(other[i]);\n }\n }\n result\n }\n}\n\nimpl Eq for str {\n fn eq(self, other: str) -> bool {\n let self_bytes = self.as_bytes();\n let other_bytes = other.as_bytes();\n self_bytes == other_bytes\n }\n}\n\nimpl Eq for (A, B)\nwhere\n A: Eq,\n B: Eq,\n{\n fn eq(self, other: (A, B)) -> bool {\n self.0.eq(other.0) & self.1.eq(other.1)\n }\n}\n\nimpl Eq for (A, B, C)\nwhere\n A: Eq,\n B: Eq,\n C: Eq,\n{\n fn eq(self, other: (A, B, C)) -> bool {\n self.0.eq(other.0) & self.1.eq(other.1) & self.2.eq(other.2)\n }\n}\n\nimpl Eq for (A, B, C, D)\nwhere\n A: Eq,\n B: Eq,\n C: Eq,\n D: Eq,\n{\n fn eq(self, other: (A, B, C, D)) -> bool {\n self.0.eq(other.0) & self.1.eq(other.1) & self.2.eq(other.2) & self.3.eq(other.3)\n }\n}\n\nimpl Eq for (A, B, C, D, E)\nwhere\n A: Eq,\n B: Eq,\n C: Eq,\n D: Eq,\n E: Eq,\n{\n fn eq(self, other: (A, B, C, D, E)) -> bool {\n self.0.eq(other.0)\n & self.1.eq(other.1)\n & self.2.eq(other.2)\n & self.3.eq(other.3)\n & self.4.eq(other.4)\n }\n}\n\nimpl Eq for Ordering {\n fn eq(self, other: Ordering) -> bool {\n self.result == other.result\n }\n}\n\n// Noir doesn't have enums yet so we emulate (Lt | Eq | Gt) with a struct\n// that has 3 public functions for constructing the struct.\npub struct Ordering {\n result: Field,\n}\n\nimpl Ordering {\n // Implementation note: 0, 1, and 2 for Lt, Eq, and Gt are built\n // into the compiler, do not change these without also updating\n // the compiler itself!\n pub fn less() -> Ordering {\n Ordering { result: 0 }\n }\n\n pub fn equal() -> Ordering {\n Ordering { result: 1 }\n }\n\n pub fn greater() -> Ordering {\n Ordering { result: 2 }\n }\n}\n\n#[derive_via(derive_ord)]\n// docs:start:ord-trait\npub trait Ord {\n fn cmp(self, other: Self) -> Ordering;\n}\n// docs:end:ord-trait\n\n// docs:start:derive_ord\ncomptime fn derive_ord(s: TypeDefinition) -> Quoted {\n let name = quote { $crate::cmp::Ord };\n let signature = quote { fn cmp(_self: Self, _other: Self) -> $crate::cmp::Ordering };\n let for_each_field = |name| quote {\n if result == $crate::cmp::Ordering::equal() {\n result = _self.$name.cmp(_other.$name);\n }\n };\n let body = |fields| quote {\n let mut result = $crate::cmp::Ordering::equal();\n $fields\n result\n };\n crate::meta::make_trait_impl(s, name, signature, for_each_field, quote {}, body)\n}\n// docs:end:derive_ord\n\n// Note: Field deliberately does not implement Ord\n\nimpl Ord for u128 {\n fn cmp(self, other: u128) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\nimpl Ord for u64 {\n fn cmp(self, other: u64) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for u32 {\n fn cmp(self, other: u32) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for u16 {\n fn cmp(self, other: u16) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for u8 {\n fn cmp(self, other: u8) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for i8 {\n fn cmp(self, other: i8) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for i16 {\n fn cmp(self, other: i16) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for i32 {\n fn cmp(self, other: i32) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for i64 {\n fn cmp(self, other: i64) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for () {\n fn cmp(_self: Self, _other: ()) -> Ordering {\n Ordering::equal()\n }\n}\n\nimpl Ord for bool {\n fn cmp(self, other: bool) -> Ordering {\n if self {\n if other {\n Ordering::equal()\n } else {\n Ordering::greater()\n }\n } else if other {\n Ordering::less()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for [T; N]\nwhere\n T: Ord,\n{\n // The first non-equal element of both arrays determines\n // the ordering for the whole array.\n fn cmp(self, other: [T; N]) -> Ordering {\n let mut result = Ordering::equal();\n for i in 0..self.len() {\n if result == Ordering::equal() {\n result = self[i].cmp(other[i]);\n }\n }\n result\n }\n}\n\nimpl Ord for [T]\nwhere\n T: Ord,\n{\n // The first non-equal element of both arrays determines\n // the ordering for the whole array.\n fn cmp(self, other: [T]) -> Ordering {\n let self_len = self.len();\n let other_len = other.len();\n let min_len = if self_len < other_len {\n self_len\n } else {\n other_len\n };\n\n let mut result = Ordering::equal();\n for i in 0..min_len {\n if result == Ordering::equal() {\n result = self[i].cmp(other[i]);\n }\n }\n\n if result != Ordering::equal() {\n result\n } else {\n self_len.cmp(other_len)\n }\n }\n}\n\nimpl Ord for (A, B)\nwhere\n A: Ord,\n B: Ord,\n{\n fn cmp(self, other: (A, B)) -> Ordering {\n let result = self.0.cmp(other.0);\n\n if result != Ordering::equal() {\n result\n } else {\n self.1.cmp(other.1)\n }\n }\n}\n\nimpl Ord for (A, B, C)\nwhere\n A: Ord,\n B: Ord,\n C: Ord,\n{\n fn cmp(self, other: (A, B, C)) -> Ordering {\n let mut result = self.0.cmp(other.0);\n\n if result == Ordering::equal() {\n result = self.1.cmp(other.1);\n }\n\n if result == Ordering::equal() {\n result = self.2.cmp(other.2);\n }\n\n result\n }\n}\n\nimpl Ord for (A, B, C, D)\nwhere\n A: Ord,\n B: Ord,\n C: Ord,\n D: Ord,\n{\n fn cmp(self, other: (A, B, C, D)) -> Ordering {\n let mut result = self.0.cmp(other.0);\n\n if result == Ordering::equal() {\n result = self.1.cmp(other.1);\n }\n\n if result == Ordering::equal() {\n result = self.2.cmp(other.2);\n }\n\n if result == Ordering::equal() {\n result = self.3.cmp(other.3);\n }\n\n result\n }\n}\n\nimpl Ord for (A, B, C, D, E)\nwhere\n A: Ord,\n B: Ord,\n C: Ord,\n D: Ord,\n E: Ord,\n{\n fn cmp(self, other: (A, B, C, D, E)) -> Ordering {\n let mut result = self.0.cmp(other.0);\n\n if result == Ordering::equal() {\n result = self.1.cmp(other.1);\n }\n\n if result == Ordering::equal() {\n result = self.2.cmp(other.2);\n }\n\n if result == Ordering::equal() {\n result = self.3.cmp(other.3);\n }\n\n if result == Ordering::equal() {\n result = self.4.cmp(other.4);\n }\n\n result\n }\n}\n\n// Compares and returns the maximum of two values.\n//\n// Returns the second argument if the comparison determines them to be equal.\n//\n// # Examples\n//\n// ```\n// use std::cmp;\n//\n// assert_eq(cmp::max(1, 2), 2);\n// assert_eq(cmp::max(2, 2), 2);\n// ```\npub fn max(v1: T, v2: T) -> T\nwhere\n T: Ord,\n{\n if v1 > v2 {\n v1\n } else {\n v2\n }\n}\n\n// Compares and returns the minimum of two values.\n//\n// Returns the first argument if the comparison determines them to be equal.\n//\n// # Examples\n//\n// ```\n// use std::cmp;\n//\n// assert_eq(cmp::min(1, 2), 1);\n// assert_eq(cmp::min(2, 2), 2);\n// ```\npub fn min(v1: T, v2: T) -> T\nwhere\n T: Ord,\n{\n if v1 > v2 {\n v2\n } else {\n v1\n }\n}\n\nmod cmp_tests {\n use super::{Eq, max, min, Ord};\n\n #[test]\n fn sanity_check_min() {\n assert_eq(min(0_u64, 1), 0);\n assert_eq(min(0_u64, 0), 0);\n assert_eq(min(1_u64, 1), 1);\n assert_eq(min(255_u8, 0), 0);\n }\n\n #[test]\n fn sanity_check_max() {\n assert_eq(max(0_u64, 1), 1);\n assert_eq(max(0_u64, 0), 0);\n assert_eq(max(1_u64, 1), 1);\n assert_eq(max(255_u8, 0), 255);\n }\n\n #[test]\n fn correctly_handles_unequal_length_slices() {\n let slice_1 = &[0, 1, 2, 3];\n let slice_2 = &[0, 1, 2];\n assert(!slice_1.eq(slice_2));\n }\n\n #[test]\n fn lexicographic_ordering_for_slices() {\n assert(&[2_u32].cmp(&[1_u32, 1_u32, 1_u32]) == super::Ordering::greater());\n assert(&[1_u32, 2_u32].cmp(&[1_u32, 2_u32, 3_u32]) == super::Ordering::less());\n }\n}\n"},"50":{"path":"/home/nerses/contracts/chains/aztec/contracts/train/src/lib.nr","source":"pub fn bytes_to_u128_limbs(bytes: [u8; 32]) -> (u128, u128) {\n let mut high: u128 = 0;\n let mut low: u128 = 0;\n for i in 0..16 {\n high = (high << 8) + (bytes[i] as u128);\n }\n for i in 16..32 {\n low = (low << 8) + (bytes[i] as u128);\n }\n (high, low)\n}\n\npub fn u128_limbs_to_bytes(high: u128, low: u128) -> [u8; 32] {\n let mut bytes: [u8; 32] = [0; 32];\n\n let mut temp = high;\n for i in 0..16 {\n bytes[15 - i] = (temp & 0xff) as u8;\n temp >>= 8;\n }\n\n temp = low;\n for i in 0..16 {\n bytes[31 - i] = (temp & 0xff) as u8;\n temp >>= 8;\n }\n\n bytes\n}\n"},"51":{"path":"/home/nerses/contracts/chains/aztec/contracts/train/src/main.nr","source":"// @@ @@@\n// @@@\n// @@@ @@ @@@@ @@@@@ @ @ @@@@@\n// @@@@@@@@@ @@@@@@ @@@@ @@@@@ @@@ @@@@@@ @@@@\n// @@@ @@@ @@@ @@@ @@@ @@@ @@@\n// @@@ @@@ @@@ @@@ @@@ @@@ @@@\n// @@@ @@@ @@@ @@@ @@@ @@@ @@@\n// @@@ @@@ @@@@ @@@@@ @@@ @@@ @@@\n// @@@@@ @@@ @@@@@@@@@ @@@ @@@ @@@ @@@\n\nmod lib;\nmod types;\nuse dep::aztec::macros::aztec;\n\n#[aztec]\npub contract Train {\n use std::meta::derive;\n\n use aztec::macros::{\n functions::{external, initializer, view},\n storage::storage,\n };\n\n use dep::aztec::{\n protocol_types::{address::AztecAddress, traits::{Deserialize, Packable, Serialize}},\n state_vars::{PublicMutable, map::Map},\n };\n use dep::sha256;\n use dep::token::Token;\n\n use crate::lib::{bytes_to_u128_limbs, u128_limbs_to_bytes};\n use crate::types::events::{DstLocked, SrcLocked, TokenRedeemed, TokenRefunded};\n\n #[derive(Eq, Packable, Serialize, Deserialize)]\n pub struct HTLC_Public {\n amount: u128,\n token: AztecAddress,\n hashlock_high: u128,\n hashlock_low: u128,\n secret_high: u128,\n secret_low: u128,\n sender: AztecAddress,\n src_receiver: AztecAddress,\n timelock: u64,\n claimed: u8,\n reward: u128,\n reward_timelock: u64,\n }\n\n #[external(\"public\")]\n #[initializer]\n fn constructor() {}\n\n #[storage]\n struct Storage {\n contracts: Map, Context>, Context>,\n user_swaps_count: Map, Context>,\n user_swaps: Map, Context>, Context>,\n }\n\n #[external(\"public\")]\n fn lock_src(\n swap_id: Field,\n hashlock_high: u128,\n hashlock_low: u128,\n timelock: u64,\n src_receiver: AztecAddress,\n token: AztecAddress,\n amount: u128,\n src_asset: str<30>,\n dst_chain: str<30>,\n dst_asset: str<30>,\n dst_address: str<90>,\n ) {\n assert(amount > 0, \"FundsNotSent\");\n\n let htlc_public_current = storage.contracts.at(swap_id).at(0).read();\n assert(htlc_public_current.sender == AztecAddress::zero(), \"SwapAlreadyInitialized\");\n assert(context.timestamp() + 1800 < timelock, \"InvalidTimelock\");\n\n let hashlock_tuple = (hashlock_high, hashlock_low);\n let sender = context.msg_sender().expect(f\"Sender must not be none!\");\n let htlc_public = HTLC_Public {\n amount: amount,\n token: token,\n hashlock_high: hashlock_tuple.0,\n hashlock_low: hashlock_tuple.1,\n secret_high: 0 as u128,\n secret_low: 0 as u128,\n sender: sender,\n src_receiver: src_receiver,\n timelock: timelock,\n claimed: 1 as u8,\n reward: 0 as u128,\n reward_timelock: 0 as u64,\n };\n storage.contracts.at(swap_id).at(0).write(htlc_public);\n\n // Transfer tokens from sender to contract\n Token::at(token).transfer_in_public(sender, context.this_address(), amount, 0).call(&mut context);\n\n // Track this swap for the user\n let sender = context.msg_sender().expect(f\"Sender must not be none!\");\n let current_count = storage.user_swaps_count.at(sender).read();\n storage.user_swaps.at(sender).at(current_count).write(swap_id);\n storage.user_swaps_count.at(sender).write(current_count + 1);\n\n let hashlock = u128_limbs_to_bytes(hashlock_high, hashlock_low);\n let log_msg = SrcLocked {\n swap_id: swap_id,\n hashlock: hashlock,\n dst_chain: dst_chain,\n dst_address: dst_address,\n dst_asset: dst_asset,\n sender: context.msg_sender().expect(f\"Sender must not be none!\"),\n src_receiver: src_receiver,\n src_asset: src_asset,\n amount: amount,\n timelock: timelock,\n };\n\n context.emit_public_log(log_msg.pack());\n }\n\n #[external(\"public\")]\n fn refund(swap_id: Field, htlc_id: Field) {\n let htlc_public = storage.contracts.at(swap_id).at(htlc_id).read();\n assert(htlc_public.claimed == 1, \"AlreadyClaimed\");\n assert(htlc_public.timelock < context.timestamp(), \"NotPassedTimelock\");\n\n let refund_amount = if htlc_public.reward != 0 {\n htlc_public.amount + htlc_public.reward\n } else {\n htlc_public.amount\n };\n\n // Transfer tokens back to sender\n Token::at(htlc_public.token).transfer_in_public(\n context.this_address(),\n htlc_public.sender,\n refund_amount,\n 0\n ).call(&mut context);\n \n let modified_htlc_public = HTLC_Public {\n amount: htlc_public.amount,\n token: htlc_public.token,\n hashlock_high: htlc_public.hashlock_high,\n hashlock_low: htlc_public.hashlock_low,\n secret_high: htlc_public.secret_high,\n secret_low: htlc_public.secret_low,\n sender: htlc_public.sender,\n src_receiver: htlc_public.src_receiver,\n timelock: htlc_public.timelock,\n claimed: 2 as u8,\n reward: htlc_public.reward,\n reward_timelock: htlc_public.reward_timelock,\n };\n\n storage.contracts.at(swap_id).at(htlc_id).write(modified_htlc_public);\n let log_msg = TokenRefunded { swap_id, htlc_id };\n context.emit_public_log(log_msg.pack());\n }\n\n #[external(\"public\")]\n fn lock_dst(\n swap_id: Field,\n htlc_id: Field,\n hashlock_high: u128,\n hashlock_low: u128,\n reward: u128,\n reward_timelock: u64,\n timelock: u64,\n src_receiver: AztecAddress,\n token: AztecAddress,\n total_amount: u128,\n src_asset: str<30>,\n dst_chain: str<30>,\n dst_asset: str<30>,\n dst_address: str<90>,\n ) {\n assert(total_amount > 0, \"FundsNotSent\");\n assert(reward > 0, \"InvalidRewardAmount\");\n\n let amount = total_amount - reward;\n assert(amount > 0, \"InvalidRewardAmount\");\n // Enforce reward >= 10% of amount: reward * 10 >= amount\n assert(reward * 10 >= amount, \"InvalidRewardAmount\");\n\n let htlc_public_current = storage.contracts.at(swap_id).at(htlc_id).read();\n assert(htlc_public_current.sender == AztecAddress::zero(), \"HTLCAlreadyExists\");\n assert(context.timestamp() + 900 < timelock, \"InvalidTimelock\");\n assert(reward_timelock <= timelock, \"InvalidRewardTimelock\");\n assert(reward_timelock > context.timestamp(), \"InvalidRewardTimelock\");\n\n let hashlock_tuple = (hashlock_high, hashlock_low);\n let sender = context.msg_sender().expect(f\"Sender must not be none!\");\n let htlc_public = HTLC_Public {\n amount: amount,\n token: token,\n hashlock_high: hashlock_tuple.0,\n hashlock_low: hashlock_tuple.1,\n secret_high: 0 as u128,\n secret_low: 0 as u128,\n sender: sender,\n src_receiver: src_receiver,\n timelock: timelock,\n claimed: 1 as u8,\n reward: reward,\n reward_timelock: reward_timelock,\n };\n storage.contracts.at(swap_id).at(htlc_id).write(htlc_public);\n\n // Transfer tokens from sender to contract\n Token::at(token).transfer_in_public(sender, context.this_address(), total_amount, 0).call(&mut context);\n\n let hashlock = u128_limbs_to_bytes(hashlock_high, hashlock_low);\n let log_msg = DstLocked {\n swap_id: swap_id,\n htlc_id: htlc_id,\n hashlock: hashlock,\n dst_chain: dst_chain,\n dst_address: dst_address,\n dst_asset: dst_asset,\n sender: context.msg_sender().expect(f\"Sender must not be none!\"),\n src_receiver: src_receiver,\n src_asset: src_asset,\n amount: amount,\n reward: reward,\n reward_timelock: reward_timelock,\n timelock: timelock,\n };\n\n context.emit_public_log(log_msg.pack());\n }\n\n #[external(\"public\")]\n fn redeem(swap_id: Field, htlc_id: Field, secret_high: u128, secret_low: u128) {\n let secret = u128_limbs_to_bytes(secret_high, secret_low);\n let caller = context.msg_sender().expect(f\"Sender must not be none!\");\n\n let mut htlc_public = storage.contracts.at(swap_id).at(htlc_id).read();\n assert(htlc_public.amount > 0, \"HTLCNotExists\");\n let hashed_secret = sha256::sha256_var(secret, secret.len() as u64);\n let hashed_secret_tuple = bytes_to_u128_limbs(hashed_secret);\n assert(htlc_public.hashlock_high == hashed_secret_tuple.0, \"HashlockNotMatch\");\n assert(htlc_public.hashlock_low == hashed_secret_tuple.1, \"HashlockNotMatch\");\n assert(htlc_public.claimed == 1, \"AlreadyClaimed\");\n\n let secret_limbs = bytes_to_u128_limbs(secret);\n\n let modified_htlc_public = HTLC_Public {\n amount: htlc_public.amount,\n token: htlc_public.token,\n hashlock_high: htlc_public.hashlock_high,\n hashlock_low: htlc_public.hashlock_low,\n secret_high: secret_limbs.0,\n secret_low: secret_limbs.1,\n sender: htlc_public.sender,\n src_receiver: htlc_public.src_receiver,\n timelock: htlc_public.timelock,\n claimed: 3 as u8,\n reward: htlc_public.reward,\n reward_timelock: htlc_public.reward_timelock,\n };\n\n storage.contracts.at(swap_id).at(htlc_id).write(modified_htlc_public);\n\n // Handle token transfers based on reward logic\n if htlc_public.reward == 0 {\n // No reward: transfer amount to src_receiver\n Token::at(htlc_public.token).transfer_in_public(\n context.this_address(),\n htlc_public.src_receiver,\n htlc_public.amount,\n 0\n ).call(&mut context);\n } else if htlc_public.reward_timelock > context.timestamp() {\n // Before reward timelock: amount to src_receiver, reward back to sender\n Token::at(htlc_public.token).transfer_in_public(\n context.this_address(),\n htlc_public.src_receiver,\n htlc_public.amount,\n 0\n ).call(&mut context);\n Token::at(htlc_public.token).transfer_in_public(\n context.this_address(),\n htlc_public.sender,\n htlc_public.reward,\n 0\n ).call(&mut context);\n } else {\n // After reward timelock\n if caller == htlc_public.src_receiver {\n // src_receiver gets amount + reward\n Token::at(htlc_public.token).transfer_in_public(\n context.this_address(),\n htlc_public.src_receiver,\n htlc_public.amount + htlc_public.reward,\n 0\n ).call(&mut context);\n } else {\n // amount to src_receiver, reward to caller\n Token::at(htlc_public.token).transfer_in_public(\n context.this_address(),\n htlc_public.src_receiver,\n htlc_public.amount,\n 0\n ).call(&mut context);\n Token::at(htlc_public.token).transfer_in_public(\n context.this_address(),\n caller,\n htlc_public.reward,\n 0\n ).call(&mut context);\n }\n }\n\n let log_msg = TokenRedeemed {\n swap_id: swap_id,\n htlc_id: htlc_id,\n redeem_address: caller,\n secret_high: secret_limbs.0,\n secret_low: secret_limbs.1,\n hashlock: u128_limbs_to_bytes(htlc_public.hashlock_high, htlc_public.hashlock_low),\n };\n\n context.emit_public_log(log_msg.pack());\n }\n\n #[external(\"public\")]\n #[view]\n fn has_htlc(swap_id: Field, htlc_id: Field) -> pub bool {\n let htlc = storage.contracts.at(swap_id).at(htlc_id).read();\n htlc.sender != AztecAddress::zero()\n }\n\n #[external(\"public\")]\n #[view]\n fn get_htlc(swap_id: Field, htlc_id: Field) -> pub HTLC_Public {\n storage.contracts.at(swap_id).at(htlc_id).read()\n }\n\n #[external(\"public\")]\n #[view]\n fn get_user_swaps_count(user: AztecAddress) -> pub Field {\n storage.user_swaps_count.at(user).read()\n }\n}\n"},"52":{"path":"/home/nerses/contracts/chains/aztec/contracts/train/src/types/events.nr","source":"use crate::lib::{bytes_to_u128_limbs, u128_limbs_to_bytes};\nuse dep::aztec::protocol_types::address::AztecAddress;\nuse dep::aztec::protocol_types::traits::{FromField, Packable, Serialize};\n\n#[derive(Serialize)]\npub struct SrcLocked {\n pub swap_id: Field,\n pub hashlock: [u8; 32],\n pub dst_chain: str<30>,\n pub dst_address: str<90>,\n pub dst_asset: str<30>,\n pub sender: AztecAddress,\n pub src_receiver: AztecAddress,\n pub src_asset: str<30>,\n pub amount: u128,\n pub timelock: u64,\n}\n\nimpl Packable for SrcLocked {\n let N: u32 = 13;\n fn pack(self) -> [Field; Self::N] {\n let zero: Field = 0;\n let mut out = [zero; 13];\n out[0] = 0x1A2B3C4D; // Event signature\n out[1] = self.swap_id;\n\n let (hashlock_high, hashlock_low) = bytes_to_u128_limbs(self.hashlock);\n out[2] = hashlock_high as Field;\n out[3] = hashlock_low as Field;\n\n out[4] = self.sender.inner;\n out[5] = self.src_receiver.inner;\n out[6] = self.amount as Field;\n out[7] = self.timelock as Field;\n\n let src_asset_byte_array = self.src_asset.as_bytes();\n let mut src_asset_byte_array_filled = [0 as u8; 30];\n for i in 0..src_asset_byte_array.len() {\n src_asset_byte_array_filled[i] = src_asset_byte_array[i];\n }\n out[8] = Field::from_be_bytes::<30>(src_asset_byte_array_filled);\n\n let dst_chain_byte_array = self.dst_chain.as_bytes();\n let mut dst_chain_byte_array_filled = [0 as u8; 30];\n for i in 0..dst_chain_byte_array.len() {\n dst_chain_byte_array_filled[i] = dst_chain_byte_array[i];\n }\n out[9] = Field::from_be_bytes::<30>(dst_chain_byte_array_filled);\n\n let dst_asset_byte_array = self.dst_asset.as_bytes();\n let mut dst_asset_byte_array_filled = [0 as u8; 30];\n for i in 0..dst_asset_byte_array.len() {\n dst_asset_byte_array_filled[i] = dst_asset_byte_array[i];\n }\n out[10] = Field::from_be_bytes::<30>(dst_asset_byte_array_filled);\n\n let dst_address_byte_array = self.dst_address.as_bytes();\n let mut dst_address_byte_array_filled_1 = [0 as u8; 30];\n let mut dst_address_byte_array_filled_2 = [0 as u8; 30];\n let mut dst_address_byte_array_filled_3 = [0 as u8; 30];\n\n for i in 0..30 {\n dst_address_byte_array_filled_1[i] = dst_address_byte_array[i];\n dst_address_byte_array_filled_2[i] = dst_address_byte_array[i + 30];\n dst_address_byte_array_filled_3[i] = dst_address_byte_array[i + 60];\n }\n\n out[11] = Field::from_be_bytes::<30>(dst_address_byte_array_filled_2);\n out[12] = Field::from_be_bytes::<30>(dst_address_byte_array_filled_3);\n out\n }\n\n fn unpack(fields: [Field; Self::N]) -> Self {\n assert(false, \"unpack not implemented\");\n SrcLocked {\n swap_id: fields[1],\n hashlock: [0 as u8; 32],\n dst_chain: \"000000000000000000000000000000\",\n dst_address: \"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\n dst_asset: \"000000000000000000000000000000\",\n sender: AztecAddress::zero(),\n src_receiver: AztecAddress::zero(),\n src_asset: \"000000000000000000000000000000\",\n amount: 0 as u128,\n timelock: 0 as u64,\n }\n }\n}\n\n#[derive(Serialize)]\npub struct DstLocked {\n pub swap_id: Field,\n pub htlc_id: Field,\n pub hashlock: [u8; 32],\n pub dst_chain: str<30>,\n pub dst_address: str<90>,\n pub dst_asset: str<30>,\n pub sender: AztecAddress,\n pub src_receiver: AztecAddress,\n pub src_asset: str<30>,\n pub amount: u128,\n pub reward: u128,\n pub reward_timelock: u64,\n pub timelock: u64,\n}\n\nimpl Packable for DstLocked {\n let N: u32 = 15;\n fn pack(self) -> [Field; Self::N] {\n let zero: Field = 0;\n let mut out = [zero; 15];\n out[0] = 0x2B3C4D5E; // Event signature\n out[1] = self.swap_id;\n out[2] = self.htlc_id;\n\n let (hashlock_high, hashlock_low) = bytes_to_u128_limbs(self.hashlock);\n out[3] = hashlock_high as Field;\n out[4] = hashlock_low as Field;\n\n out[5] = self.sender.inner;\n out[6] = self.src_receiver.inner;\n out[7] = self.amount as Field;\n out[8] = self.reward as Field;\n out[9] = self.reward_timelock as Field;\n out[10] = self.timelock as Field;\n\n let src_asset_byte_array = self.src_asset.as_bytes();\n let mut src_asset_byte_array_filled = [0 as u8; 30];\n for i in 0..src_asset_byte_array.len() {\n src_asset_byte_array_filled[i] = src_asset_byte_array[i];\n }\n out[11] = Field::from_be_bytes::<30>(src_asset_byte_array_filled);\n\n let dst_chain_byte_array = self.dst_chain.as_bytes();\n let mut dst_chain_byte_array_filled = [0 as u8; 30];\n for i in 0..dst_chain_byte_array.len() {\n dst_chain_byte_array_filled[i] = dst_chain_byte_array[i];\n }\n out[12] = Field::from_be_bytes::<30>(dst_chain_byte_array_filled);\n\n let dst_asset_byte_array = self.dst_asset.as_bytes();\n let mut dst_asset_byte_array_filled = [0 as u8; 30];\n for i in 0..dst_asset_byte_array.len() {\n dst_asset_byte_array_filled[i] = dst_asset_byte_array[i];\n }\n out[13] = Field::from_be_bytes::<30>(dst_asset_byte_array_filled);\n\n // Note: dst_address omitted for brevity in this packed format\n out[14] = 0;\n out\n }\n\n fn unpack(fields: [Field; Self::N]) -> Self {\n assert(false, \"unpack not implemented\");\n DstLocked {\n swap_id: fields[1],\n htlc_id: fields[2],\n hashlock: [0 as u8; 32],\n dst_chain: \"000000000000000000000000000000\",\n dst_address: \"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\n dst_asset: \"000000000000000000000000000000\",\n sender: AztecAddress::zero(),\n src_receiver: AztecAddress::zero(),\n src_asset: \"000000000000000000000000000000\",\n amount: 0 as u128,\n reward: 0 as u128,\n reward_timelock: 0 as u64,\n timelock: 0 as u64,\n }\n }\n}\n\n#[derive(Serialize)]\npub struct TokenRefunded {\n pub swap_id: Field,\n pub htlc_id: Field,\n}\n\nimpl Packable for TokenRefunded {\n let N: u32 = 3;\n fn pack(self) -> [Field; Self::N] {\n let mut out = [0 as Field; 3];\n out[0] = 0x2D17C6B8;\n out[1] = self.swap_id;\n out[2] = self.htlc_id;\n out\n }\n\n fn unpack(fields: [Field; Self::N]) -> Self {\n TokenRefunded { swap_id: fields[1], htlc_id: fields[2] }\n }\n}\n\n#[derive(Serialize)]\npub struct TokenRedeemed {\n pub swap_id: Field,\n pub htlc_id: Field,\n pub redeem_address: AztecAddress,\n pub secret_high: u128,\n pub secret_low: u128,\n pub hashlock: [u8; 32],\n}\n\nimpl Packable for TokenRedeemed {\n let N: u32 = 8;\n fn pack(self) -> [Field; Self::N] {\n let mut out = [0 as Field; 8];\n out[0] = 0x4F8B9A3E;\n out[1] = self.swap_id;\n out[2] = self.htlc_id;\n out[3] = self.redeem_address.inner;\n\n out[4] = self.secret_high as Field;\n out[5] = self.secret_low as Field;\n\n let (hashlock_high, hashlock_low) = bytes_to_u128_limbs(self.hashlock);\n out[6] = hashlock_high as Field;\n out[7] = hashlock_low as Field;\n\n out\n }\n\n fn unpack(fields: [Field; Self::N]) -> Self {\n let swap_id = fields[1];\n let htlc_id = fields[2];\n let redeem_address = AztecAddress::from_field(fields[3]);\n let secret_high = fields[4] as u128;\n let secret_low = fields[5] as u128;\n let hashlock = u128_limbs_to_bytes(fields[6] as u128, fields[7] as u128);\n\n TokenRedeemed { swap_id, htlc_id, redeem_address, secret_high, secret_low, hashlock }\n }\n}\n"},"6":{"path":"std/collections/bounded_vec.nr","source":"use crate::{cmp::Eq, convert::From, runtime::is_unconstrained, static_assert};\n\n/// A `BoundedVec` is a growable storage similar to a `Vec` except that it\n/// is bounded with a maximum possible length. Unlike `Vec`, `BoundedVec` is not implemented\n/// via slices and thus is not subject to the same restrictions slices are (notably, nested\n/// slices - and thus nested vectors as well - are disallowed).\n///\n/// Since a BoundedVec is backed by a normal array under the hood, growing the BoundedVec by\n/// pushing an additional element is also more efficient - the length only needs to be increased\n/// by one.\n///\n/// For these reasons `BoundedVec` should generally be preferred over `Vec` when there\n/// is a reasonable maximum bound that can be placed on the vector.\n///\n/// Example:\n///\n/// ```noir\n/// let mut vector: BoundedVec = BoundedVec::new();\n/// for i in 0..5 {\n/// vector.push(i);\n/// }\n/// assert(vector.len() == 5);\n/// assert(vector.max_len() == 10);\n/// ```\npub struct BoundedVec {\n storage: [T; MaxLen],\n len: u32,\n}\n\nimpl BoundedVec {\n /// Creates a new, empty vector of length zero.\n ///\n /// Since this container is backed by an array internally, it still needs an initial value\n /// to give each element. To resolve this, each element is zeroed internally. This value\n /// is guaranteed to be inaccessible unless `get_unchecked` is used.\n ///\n /// Example:\n ///\n /// ```noir\n /// let empty_vector: BoundedVec = BoundedVec::new();\n /// assert(empty_vector.len() == 0);\n /// ```\n ///\n /// Note that whenever calling `new` the maximum length of the vector should always be specified\n /// via a type signature:\n ///\n /// ```noir\n /// fn good() -> BoundedVec {\n /// // Ok! MaxLen is specified with a type annotation\n /// let v1: BoundedVec = BoundedVec::new();\n /// let v2 = BoundedVec::new();\n ///\n /// // Ok! MaxLen is known from the type of `good`'s return value\n /// v2\n /// }\n ///\n /// fn bad() {\n /// // Error: Type annotation needed\n /// // The compiler can't infer `MaxLen` from the following code:\n /// let mut v3 = BoundedVec::new();\n /// v3.push(5);\n /// }\n /// ```\n ///\n /// This defaulting of `MaxLen` (and numeric generics in general) to zero may change in future noir versions\n /// but for now make sure to use type annotations when using bounded vectors. Otherwise, you will receive a\n /// constraint failure at runtime when the vec is pushed to.\n pub fn new() -> Self {\n let zeroed = crate::mem::zeroed();\n BoundedVec { storage: [zeroed; MaxLen], len: 0 }\n }\n\n /// Retrieves an element from the vector at the given index, starting from zero.\n ///\n /// If the given index is equal to or greater than the length of the vector, this\n /// will issue a constraint failure.\n ///\n /// Example:\n ///\n /// ```noir\n /// fn foo(v: BoundedVec) {\n /// let first = v.get(0);\n /// let last = v.get(v.len() - 1);\n /// assert(first != last);\n /// }\n /// ```\n pub fn get(self, index: u32) -> T {\n assert(index < self.len, \"Attempted to read past end of BoundedVec\");\n self.get_unchecked(index)\n }\n\n /// Retrieves an element from the vector at the given index, starting from zero, without\n /// performing a bounds check.\n ///\n /// Since this function does not perform a bounds check on length before accessing the element,\n /// it is unsafe! Use at your own risk!\n ///\n /// Example:\n ///\n /// ```noir\n /// fn sum_of_first_three(v: BoundedVec) -> u32 {\n /// // Always ensure the length is larger than the largest\n /// // index passed to get_unchecked\n /// assert(v.len() > 2);\n /// let first = v.get_unchecked(0);\n /// let second = v.get_unchecked(1);\n /// let third = v.get_unchecked(2);\n /// first + second + third\n /// }\n /// ```\n pub fn get_unchecked(self, index: u32) -> T {\n self.storage[index]\n }\n\n /// Writes an element to the vector at the given index, starting from zero.\n ///\n /// If the given index is equal to or greater than the length of the vector, this will issue a constraint failure.\n ///\n /// Example:\n ///\n /// ```noir\n /// fn foo(v: BoundedVec) {\n /// let first = v.get(0);\n /// assert(first != 42);\n /// v.set(0, 42);\n /// let new_first = v.get(0);\n /// assert(new_first == 42);\n /// }\n /// ```\n pub fn set(&mut self, index: u32, value: T) {\n assert(index < self.len, \"Attempted to write past end of BoundedVec\");\n self.set_unchecked(index, value)\n }\n\n /// Writes an element to the vector at the given index, starting from zero, without performing a bounds check.\n ///\n /// Since this function does not perform a bounds check on length before accessing the element, it is unsafe! Use at your own risk!\n ///\n /// Example:\n ///\n /// ```noir\n /// fn set_unchecked_example() {\n /// let mut vec: BoundedVec = BoundedVec::new();\n /// vec.extend_from_array([1, 2]);\n ///\n /// // Here we're safely writing within the valid range of `vec`\n /// // `vec` now has the value [42, 2]\n /// vec.set_unchecked(0, 42);\n ///\n /// // We can then safely read this value back out of `vec`.\n /// // Notice that we use the checked version of `get` which would prevent reading unsafe values.\n /// assert_eq(vec.get(0), 42);\n ///\n /// // We've now written past the end of `vec`.\n /// // As this index is still within the maximum potential length of `v`,\n /// // it won't cause a constraint failure.\n /// vec.set_unchecked(2, 42);\n /// println(vec);\n ///\n /// // This will write past the end of the maximum potential length of `vec`,\n /// // it will then trigger a constraint failure.\n /// vec.set_unchecked(5, 42);\n /// println(vec);\n /// }\n /// ```\n pub fn set_unchecked(&mut self, index: u32, value: T) {\n self.storage[index] = value;\n }\n\n /// Pushes an element to the end of the vector. This increases the length\n /// of the vector by one.\n ///\n /// Panics if the new length of the vector will be greater than the max length.\n ///\n /// Example:\n ///\n /// ```noir\n /// let mut v: BoundedVec = BoundedVec::new();\n ///\n /// v.push(1);\n /// v.push(2);\n ///\n /// // Panics with failed assertion \"push out of bounds\"\n /// v.push(3);\n /// ```\n pub fn push(&mut self, elem: T) {\n assert(self.len < MaxLen, \"push out of bounds\");\n\n self.storage[self.len] = elem;\n self.len += 1;\n }\n\n /// Returns the current length of this vector\n ///\n /// Example:\n ///\n /// ```noir\n /// let mut v: BoundedVec = BoundedVec::new();\n /// assert(v.len() == 0);\n ///\n /// v.push(100);\n /// assert(v.len() == 1);\n ///\n /// v.push(200);\n /// v.push(300);\n /// v.push(400);\n /// assert(v.len() == 4);\n ///\n /// let _ = v.pop();\n /// let _ = v.pop();\n /// assert(v.len() == 2);\n /// ```\n pub fn len(self) -> u32 {\n self.len\n }\n\n /// Returns the maximum length of this vector. This is always\n /// equal to the `MaxLen` parameter this vector was initialized with.\n ///\n /// Example:\n ///\n /// ```noir\n /// let mut v: BoundedVec = BoundedVec::new();\n ///\n /// assert(v.max_len() == 5);\n /// v.push(10);\n /// assert(v.max_len() == 5);\n /// ```\n pub fn max_len(_self: BoundedVec) -> u32 {\n MaxLen\n }\n\n /// Returns the internal array within this vector.\n ///\n /// Since arrays in Noir are immutable, mutating the returned storage array will not mutate\n /// the storage held internally by this vector.\n ///\n /// Note that uninitialized elements may be zeroed out!\n ///\n /// Example:\n ///\n /// ```noir\n /// let mut v: BoundedVec = BoundedVec::new();\n ///\n /// assert(v.storage() == [0, 0, 0, 0, 0]);\n ///\n /// v.push(57);\n /// assert(v.storage() == [57, 0, 0, 0, 0]);\n /// ```\n pub fn storage(self) -> [T; MaxLen] {\n self.storage\n }\n\n /// Pushes each element from the given array to this vector.\n ///\n /// Panics if pushing each element would cause the length of this vector\n /// to exceed the maximum length.\n ///\n /// Example:\n ///\n /// ```noir\n /// let mut vec: BoundedVec = BoundedVec::new();\n /// vec.extend_from_array([2, 4]);\n ///\n /// assert(vec.len == 2);\n /// assert(vec.get(0) == 2);\n /// assert(vec.get(1) == 4);\n /// ```\n pub fn extend_from_array(&mut self, array: [T; Len]) {\n let new_len = self.len + array.len();\n assert(new_len <= MaxLen, \"extend_from_array out of bounds\");\n for i in 0..array.len() {\n self.storage[self.len + i] = array[i];\n }\n self.len = new_len;\n }\n\n /// Pushes each element from the given slice to this vector.\n ///\n /// Panics if pushing each element would cause the length of this vector\n /// to exceed the maximum length.\n ///\n /// Example:\n ///\n /// ```noir\n /// let mut vec: BoundedVec = BoundedVec::new();\n /// vec.extend_from_slice(&[2, 4]);\n ///\n /// assert(vec.len == 2);\n /// assert(vec.get(0) == 2);\n /// assert(vec.get(1) == 4);\n /// ```\n pub fn extend_from_slice(&mut self, slice: [T]) {\n let new_len = self.len + slice.len();\n assert(new_len <= MaxLen, \"extend_from_slice out of bounds\");\n for i in 0..slice.len() {\n self.storage[self.len + i] = slice[i];\n }\n self.len = new_len;\n }\n\n /// Pushes each element from the other vector to this vector. The length of\n /// the other vector is left unchanged.\n ///\n /// Panics if pushing each element would cause the length of this vector\n /// to exceed the maximum length.\n ///\n /// ```noir\n /// let mut v1: BoundedVec = BoundedVec::new();\n /// let mut v2: BoundedVec = BoundedVec::new();\n ///\n /// v2.extend_from_array([1, 2, 3]);\n /// v1.extend_from_bounded_vec(v2);\n ///\n /// assert(v1.storage() == [1, 2, 3, 0, 0]);\n /// assert(v2.storage() == [1, 2, 3, 0, 0, 0, 0]);\n /// ```\n pub fn extend_from_bounded_vec(&mut self, vec: BoundedVec) {\n let append_len = vec.len();\n let new_len = self.len + append_len;\n assert(new_len <= MaxLen, \"extend_from_bounded_vec out of bounds\");\n\n if is_unconstrained() {\n for i in 0..append_len {\n self.storage[self.len + i] = vec.get_unchecked(i);\n }\n } else {\n let mut exceeded_len = false;\n for i in 0..Len {\n exceeded_len |= i == append_len;\n if !exceeded_len {\n self.storage[self.len + i] = vec.get_unchecked(i);\n }\n }\n }\n self.len = new_len;\n }\n\n /// Creates a new vector, populating it with values derived from an array input.\n /// The maximum length of the vector is determined based on the type signature.\n ///\n /// Example:\n ///\n /// ```noir\n /// let bounded_vec: BoundedVec = BoundedVec::from_array([1, 2, 3])\n /// ```\n pub fn from_array(array: [T; Len]) -> Self {\n static_assert(Len <= MaxLen, \"from array out of bounds\");\n let mut vec: BoundedVec = BoundedVec::new();\n vec.extend_from_array(array);\n vec\n }\n\n /// Pops the element at the end of the vector. This will decrease the length\n /// of the vector by one.\n ///\n /// Panics if the vector is empty.\n ///\n /// Example:\n ///\n /// ```noir\n /// let mut v: BoundedVec = BoundedVec::new();\n /// v.push(1);\n /// v.push(2);\n ///\n /// let two = v.pop();\n /// let one = v.pop();\n ///\n /// assert(two == 2);\n /// assert(one == 1);\n ///\n /// // error: cannot pop from an empty vector\n /// let _ = v.pop();\n /// ```\n pub fn pop(&mut self) -> T {\n assert(self.len > 0, \"cannot pop from an empty vector\");\n self.len -= 1;\n\n let elem = self.storage[self.len];\n self.storage[self.len] = crate::mem::zeroed();\n elem\n }\n\n /// Returns true if the given predicate returns true for any element\n /// in this vector.\n ///\n /// Example:\n ///\n /// ```noir\n /// let mut v: BoundedVec = BoundedVec::new();\n /// v.extend_from_array([2, 4, 6]);\n ///\n /// let all_even = !v.any(|elem: u32| elem % 2 != 0);\n /// assert(all_even);\n /// ```\n pub fn any(self, predicate: fn[Env](T) -> bool) -> bool {\n let mut ret = false;\n if is_unconstrained() {\n for i in 0..self.len {\n ret |= predicate(self.storage[i]);\n }\n } else {\n let mut exceeded_len = false;\n for i in 0..MaxLen {\n exceeded_len |= i == self.len;\n if !exceeded_len {\n ret |= predicate(self.storage[i]);\n }\n }\n }\n ret\n }\n\n /// Creates a new vector of equal size by calling a closure on each element in this vector.\n ///\n /// Example:\n ///\n /// ```noir\n /// let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);\n /// let result = vec.map(|value| value * 2);\n ///\n /// let expected = BoundedVec::from_array([2, 4, 6, 8]);\n /// assert_eq(result, expected);\n /// ```\n pub fn map(self, f: fn[Env](T) -> U) -> BoundedVec {\n let mut ret = BoundedVec::new();\n ret.len = self.len();\n\n if is_unconstrained() {\n for i in 0..self.len() {\n ret.storage[i] = f(self.get_unchecked(i));\n }\n } else {\n for i in 0..MaxLen {\n if i < self.len() {\n ret.storage[i] = f(self.get_unchecked(i));\n }\n }\n }\n\n ret\n }\n\n /// Creates a new vector of equal size by calling a closure on each element\n /// in this vector, along with its index.\n ///\n /// Example:\n ///\n /// ```noir\n /// let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);\n /// let result = vec.mapi(|i, value| i + value * 2);\n ///\n /// let expected = BoundedVec::from_array([2, 5, 8, 11]);\n /// assert_eq(result, expected);\n /// ```\n pub fn mapi(self, f: fn[Env](u32, T) -> U) -> BoundedVec {\n let mut ret = BoundedVec::new();\n ret.len = self.len();\n\n if is_unconstrained() {\n for i in 0..self.len() {\n ret.storage[i] = f(i, self.get_unchecked(i));\n }\n } else {\n for i in 0..MaxLen {\n if i < self.len() {\n ret.storage[i] = f(i, self.get_unchecked(i));\n }\n }\n }\n\n ret\n }\n\n /// Calls a closure on each element in this vector.\n ///\n /// Example:\n ///\n /// ```noir\n /// let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);\n /// let mut result = BoundedVec::::new();\n /// vec.for_each(|value| result.push(value * 2));\n ///\n /// let expected = BoundedVec::from_array([2, 4, 6, 8]);\n /// assert_eq(result, expected);\n /// ```\n pub fn for_each(self, f: fn[Env](T) -> ()) {\n if is_unconstrained() {\n for i in 0..self.len() {\n f(self.get_unchecked(i));\n }\n } else {\n for i in 0..MaxLen {\n if i < self.len() {\n f(self.get_unchecked(i));\n }\n }\n }\n }\n\n /// Calls a closure on each element in this vector, along with its index.\n ///\n /// Example:\n ///\n /// ```noir\n /// let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);\n /// let mut result = BoundedVec::::new();\n /// vec.for_eachi(|i, value| result.push(i + value * 2));\n ///\n /// let expected = BoundedVec::from_array([2, 5, 8, 11]);\n /// assert_eq(result, expected);\n /// ```\n pub fn for_eachi(self, f: fn[Env](u32, T) -> ()) {\n if is_unconstrained() {\n for i in 0..self.len() {\n f(i, self.get_unchecked(i));\n }\n } else {\n for i in 0..MaxLen {\n if i < self.len() {\n f(i, self.get_unchecked(i));\n }\n }\n }\n }\n\n /// Creates a new BoundedVec from the given array and length.\n /// The given length must be less than or equal to the length of the array.\n ///\n /// This function will zero out any elements at or past index `len` of `array`.\n /// This incurs an extra runtime cost of O(MaxLen). If you are sure your array is\n /// zeroed after that index, you can use `from_parts_unchecked` to remove the extra loop.\n ///\n /// Example:\n ///\n /// ```noir\n /// let vec: BoundedVec = BoundedVec::from_parts([1, 2, 3, 0], 3);\n /// assert_eq(vec.len(), 3);\n /// ```\n pub fn from_parts(mut array: [T; MaxLen], len: u32) -> Self {\n assert(len <= MaxLen);\n let zeroed = crate::mem::zeroed();\n\n if is_unconstrained() {\n for i in len..MaxLen {\n array[i] = zeroed;\n }\n } else {\n for i in 0..MaxLen {\n if i >= len {\n array[i] = zeroed;\n }\n }\n }\n\n BoundedVec { storage: array, len }\n }\n\n /// Creates a new BoundedVec from the given array and length.\n /// The given length must be less than or equal to the length of the array.\n ///\n /// This function is unsafe because it expects all elements past the `len` index\n /// of `array` to be zeroed, but does not check for this internally. Use `from_parts`\n /// for a safe version of this function which does zero out any indices past the\n /// given length. Invalidating this assumption can notably cause `BoundedVec::eq`\n /// to give incorrect results since it will check even elements past `len`.\n ///\n /// Example:\n ///\n /// ```noir\n /// let vec: BoundedVec = BoundedVec::from_parts_unchecked([1, 2, 3, 0], 3);\n /// assert_eq(vec.len(), 3);\n ///\n /// // invalid use!\n /// let vec1: BoundedVec = BoundedVec::from_parts_unchecked([1, 2, 3, 1], 3);\n /// let vec2: BoundedVec = BoundedVec::from_parts_unchecked([1, 2, 3, 2], 3);\n ///\n /// // both vecs have length 3 so we'd expect them to be equal, but this\n /// // fails because elements past the length are still checked in eq\n /// assert_eq(vec1, vec2); // fails\n /// ```\n pub fn from_parts_unchecked(array: [T; MaxLen], len: u32) -> Self {\n assert(len <= MaxLen);\n BoundedVec { storage: array, len }\n }\n}\n\nimpl Eq for BoundedVec\nwhere\n T: Eq,\n{\n fn eq(self, other: BoundedVec) -> bool {\n // TODO: https://github.com/noir-lang/noir/issues/4837\n //\n // We make the assumption that the user has used the proper interface for working with `BoundedVec`s\n // rather than directly manipulating the internal fields as this can result in an inconsistent internal state.\n if self.len == other.len {\n self.storage == other.storage\n } else {\n false\n }\n }\n}\n\nimpl From<[T; Len]> for BoundedVec {\n fn from(array: [T; Len]) -> BoundedVec {\n BoundedVec::from_array(array)\n }\n}\n\nmod bounded_vec_tests {\n\n mod get {\n use crate::collections::bounded_vec::BoundedVec;\n\n #[test(should_fail_with = \"Attempted to read past end of BoundedVec\")]\n fn panics_when_reading_elements_past_end_of_vec() {\n let vec: BoundedVec = BoundedVec::new();\n\n let _ = vec.get(0);\n }\n\n #[test(should_fail_with = \"Attempted to read past end of BoundedVec\")]\n fn panics_when_reading_beyond_length() {\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3]);\n let _ = vec.get(3);\n }\n\n #[test]\n fn get_works_within_bounds() {\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4, 5]);\n assert_eq(vec.get(0), 1);\n assert_eq(vec.get(2), 3);\n assert_eq(vec.get(4), 5);\n }\n\n #[test]\n fn get_unchecked_works() {\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3]);\n assert_eq(vec.get_unchecked(0), 1);\n assert_eq(vec.get_unchecked(2), 3);\n }\n\n #[test]\n fn get_unchecked_works_past_len() {\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3]);\n assert_eq(vec.get_unchecked(4), 0);\n }\n }\n\n mod set {\n use crate::collections::bounded_vec::BoundedVec;\n\n #[test]\n fn set_updates_values_properly() {\n let mut vec = BoundedVec::from_array([0, 0, 0, 0, 0]);\n\n vec.set(0, 42);\n assert_eq(vec.storage, [42, 0, 0, 0, 0]);\n\n vec.set(1, 43);\n assert_eq(vec.storage, [42, 43, 0, 0, 0]);\n\n vec.set(2, 44);\n assert_eq(vec.storage, [42, 43, 44, 0, 0]);\n\n vec.set(1, 10);\n assert_eq(vec.storage, [42, 10, 44, 0, 0]);\n\n vec.set(0, 0);\n assert_eq(vec.storage, [0, 10, 44, 0, 0]);\n }\n\n #[test(should_fail_with = \"Attempted to write past end of BoundedVec\")]\n fn panics_when_writing_elements_past_end_of_vec() {\n let mut vec: BoundedVec = BoundedVec::new();\n vec.set(0, 42);\n }\n\n #[test(should_fail_with = \"Attempted to write past end of BoundedVec\")]\n fn panics_when_setting_beyond_length() {\n let mut vec: BoundedVec = BoundedVec::from_array([1, 2, 3]);\n vec.set(3, 4);\n }\n\n #[test]\n fn set_unchecked_operations() {\n let mut vec: BoundedVec = BoundedVec::new();\n vec.push(1);\n vec.push(2);\n\n vec.set_unchecked(0, 10);\n assert_eq(vec.get(0), 10);\n }\n\n #[test(should_fail_with = \"Attempted to read past end of BoundedVec\")]\n fn set_unchecked_operations_past_len() {\n let mut vec: BoundedVec = BoundedVec::new();\n vec.push(1);\n vec.push(2);\n\n vec.set_unchecked(3, 40);\n assert_eq(vec.get(3), 40);\n }\n\n #[test]\n fn set_preserves_other_elements() {\n let mut vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4, 5]);\n\n vec.set(2, 30);\n assert_eq(vec.get(0), 1);\n assert_eq(vec.get(1), 2);\n assert_eq(vec.get(2), 30);\n assert_eq(vec.get(3), 4);\n assert_eq(vec.get(4), 5);\n }\n }\n\n mod any {\n use crate::collections::bounded_vec::BoundedVec;\n\n #[test]\n fn returns_false_if_predicate_not_satisfied() {\n let vec: BoundedVec = BoundedVec::from_array([false, false, false, false]);\n let result = vec.any(|value| value);\n\n assert(!result);\n }\n\n #[test]\n fn returns_true_if_predicate_satisfied() {\n let vec: BoundedVec = BoundedVec::from_array([false, false, true, true]);\n let result = vec.any(|value| value);\n\n assert(result);\n }\n\n #[test]\n fn returns_false_on_empty_boundedvec() {\n let vec: BoundedVec = BoundedVec::new();\n let result = vec.any(|value| value);\n\n assert(!result);\n }\n\n #[test]\n fn any_with_complex_predicates() {\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4, 5]);\n\n assert(vec.any(|x| x > 3));\n assert(!vec.any(|x| x > 10));\n assert(vec.any(|x| x % 2 == 0)); // has a even number\n assert(vec.any(|x| x == 3)); // has a specific value\n }\n\n #[test]\n fn any_with_partial_vector() {\n let mut vec: BoundedVec = BoundedVec::new();\n vec.push(1);\n vec.push(2);\n\n assert(vec.any(|x| x == 1));\n assert(vec.any(|x| x == 2));\n assert(!vec.any(|x| x == 3));\n }\n }\n\n mod map {\n use crate::collections::bounded_vec::BoundedVec;\n\n #[test]\n fn applies_function_correctly() {\n // docs:start:bounded-vec-map-example\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);\n let result = vec.map(|value| value * 2);\n // docs:end:bounded-vec-map-example\n let expected = BoundedVec::from_array([2, 4, 6, 8]);\n\n assert_eq(result, expected);\n }\n\n #[test]\n fn applies_function_that_changes_return_type() {\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);\n let result = vec.map(|value| (value * 2) as Field);\n let expected: BoundedVec = BoundedVec::from_array([2, 4, 6, 8]);\n\n assert_eq(result, expected);\n }\n\n #[test]\n fn does_not_apply_function_past_len() {\n let vec: BoundedVec = BoundedVec::from_array([0, 1]);\n let result = vec.map(|value| if value == 0 { 5 } else { value });\n let expected = BoundedVec::from_array([5, 1]);\n\n assert_eq(result, expected);\n assert_eq(result.get_unchecked(2), 0);\n }\n\n #[test]\n fn map_with_conditional_logic() {\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);\n\n let result = vec.map(|x| if x % 2 == 0 { x * 2 } else { x });\n let expected = BoundedVec::from_array([1, 4, 3, 8]);\n assert_eq(result, expected);\n }\n\n #[test]\n fn map_preserves_length() {\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);\n let result = vec.map(|x| x * 2);\n\n assert_eq(result.len(), vec.len());\n assert_eq(result.max_len(), vec.max_len());\n }\n\n #[test]\n fn map_on_empty_vector() {\n let vec: BoundedVec = BoundedVec::new();\n let result = vec.map(|x| x * 2);\n assert_eq(result, vec);\n assert_eq(result.len(), 0);\n assert_eq(result.max_len(), 5);\n }\n }\n\n mod mapi {\n use crate::collections::bounded_vec::BoundedVec;\n\n #[test]\n fn applies_function_correctly() {\n // docs:start:bounded-vec-mapi-example\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);\n let result = vec.mapi(|i, value| i + value * 2);\n // docs:end:bounded-vec-mapi-example\n let expected = BoundedVec::from_array([2, 5, 8, 11]);\n\n assert_eq(result, expected);\n }\n\n #[test]\n fn applies_function_that_changes_return_type() {\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);\n let result = vec.mapi(|i, value| (i + value * 2) as Field);\n let expected: BoundedVec = BoundedVec::from_array([2, 5, 8, 11]);\n\n assert_eq(result, expected);\n }\n\n #[test]\n fn does_not_apply_function_past_len() {\n let vec: BoundedVec = BoundedVec::from_array([0, 1]);\n let result = vec.mapi(|_, value| if value == 0 { 5 } else { value });\n let expected = BoundedVec::from_array([5, 1]);\n\n assert_eq(result, expected);\n assert_eq(result.get_unchecked(2), 0);\n }\n\n #[test]\n fn mapi_with_index_branching_logic() {\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);\n\n let result = vec.mapi(|i, x| if i % 2 == 0 { x * 2 } else { x });\n let expected = BoundedVec::from_array([2, 2, 6, 4]);\n assert_eq(result, expected);\n }\n }\n\n mod for_each {\n use crate::collections::bounded_vec::BoundedVec;\n\n // map in terms of for_each\n fn for_each_map(\n input: BoundedVec,\n f: fn[Env](T) -> U,\n ) -> BoundedVec {\n let mut output = BoundedVec::::new();\n let output_ref = &mut output;\n input.for_each(|x| output_ref.push(f(x)));\n output\n }\n\n #[test]\n fn smoke_test() {\n let mut acc = 0;\n let acc_ref = &mut acc;\n // docs:start:bounded-vec-for-each-example\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3]);\n vec.for_each(|value| { *acc_ref += value; });\n // docs:end:bounded-vec-for-each-example\n assert_eq(acc, 6);\n }\n\n #[test]\n fn applies_function_correctly() {\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);\n let result = for_each_map(vec, |value| value * 2);\n let expected = BoundedVec::from_array([2, 4, 6, 8]);\n\n assert_eq(result, expected);\n }\n\n #[test]\n fn applies_function_that_changes_return_type() {\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);\n let result = for_each_map(vec, |value| (value * 2) as Field);\n let expected: BoundedVec = BoundedVec::from_array([2, 4, 6, 8]);\n\n assert_eq(result, expected);\n }\n\n #[test]\n fn does_not_apply_function_past_len() {\n let vec: BoundedVec = BoundedVec::from_array([0, 1]);\n let result = for_each_map(vec, |value| if value == 0 { 5 } else { value });\n let expected = BoundedVec::from_array([5, 1]);\n\n assert_eq(result, expected);\n assert_eq(result.get_unchecked(2), 0);\n }\n\n #[test]\n fn for_each_on_empty_vector() {\n let vec: BoundedVec = BoundedVec::new();\n let mut count = 0;\n let count_ref = &mut count;\n vec.for_each(|_| { *count_ref += 1; });\n assert_eq(count, 0);\n }\n\n #[test]\n fn for_each_with_side_effects() {\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3]);\n let mut seen = BoundedVec::::new();\n let seen_ref = &mut seen;\n vec.for_each(|x| seen_ref.push(x));\n assert_eq(seen, vec);\n }\n }\n\n mod for_eachi {\n use crate::collections::bounded_vec::BoundedVec;\n\n // mapi in terms of for_eachi\n fn for_eachi_mapi(\n input: BoundedVec,\n f: fn[Env](u32, T) -> U,\n ) -> BoundedVec {\n let mut output = BoundedVec::::new();\n let output_ref = &mut output;\n input.for_eachi(|i, x| output_ref.push(f(i, x)));\n output\n }\n\n #[test]\n fn smoke_test() {\n let mut acc = 0;\n let acc_ref = &mut acc;\n // docs:start:bounded-vec-for-eachi-example\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3]);\n vec.for_eachi(|i, value| { *acc_ref += i * value; });\n // docs:end:bounded-vec-for-eachi-example\n\n // 0 * 1 + 1 * 2 + 2 * 3\n assert_eq(acc, 8);\n }\n\n #[test]\n fn applies_function_correctly() {\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);\n let result = for_eachi_mapi(vec, |i, value| i + value * 2);\n let expected = BoundedVec::from_array([2, 5, 8, 11]);\n\n assert_eq(result, expected);\n }\n\n #[test]\n fn applies_function_that_changes_return_type() {\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);\n let result = for_eachi_mapi(vec, |i, value| (i + value * 2) as Field);\n let expected: BoundedVec = BoundedVec::from_array([2, 5, 8, 11]);\n\n assert_eq(result, expected);\n }\n\n #[test]\n fn does_not_apply_function_past_len() {\n let vec: BoundedVec = BoundedVec::from_array([0, 1]);\n let result = for_eachi_mapi(vec, |_, value| if value == 0 { 5 } else { value });\n let expected = BoundedVec::from_array([5, 1]);\n\n assert_eq(result, expected);\n assert_eq(result.get_unchecked(2), 0);\n }\n\n #[test]\n fn for_eachi_on_empty_vector() {\n let vec: BoundedVec = BoundedVec::new();\n let mut count = 0;\n let count_ref = &mut count;\n vec.for_eachi(|_, _| { *count_ref += 1; });\n assert_eq(count, 0);\n }\n\n #[test]\n fn for_eachi_with_index_tracking() {\n let vec: BoundedVec = BoundedVec::from_array([10, 20, 30]);\n let mut indices = BoundedVec::::new();\n let indices_ref = &mut indices;\n vec.for_eachi(|i, _| indices_ref.push(i));\n\n let expected = BoundedVec::from_array([0, 1, 2]);\n assert_eq(indices, expected);\n }\n\n }\n\n mod from_array {\n use crate::collections::bounded_vec::BoundedVec;\n\n #[test]\n fn empty() {\n let empty_array: [Field; 0] = [];\n let bounded_vec = BoundedVec::from_array([]);\n\n assert_eq(bounded_vec.max_len(), 0);\n assert_eq(bounded_vec.len(), 0);\n assert_eq(bounded_vec.storage(), empty_array);\n }\n\n #[test]\n fn equal_len() {\n let array = [1, 2, 3];\n let bounded_vec = BoundedVec::from_array(array);\n\n assert_eq(bounded_vec.max_len(), 3);\n assert_eq(bounded_vec.len(), 3);\n assert_eq(bounded_vec.storage(), array);\n }\n\n #[test]\n fn max_len_greater_then_array_len() {\n let array = [1, 2, 3];\n let bounded_vec: BoundedVec = BoundedVec::from_array(array);\n\n assert_eq(bounded_vec.max_len(), 10);\n assert_eq(bounded_vec.len(), 3);\n assert_eq(bounded_vec.get(0), 1);\n assert_eq(bounded_vec.get(1), 2);\n assert_eq(bounded_vec.get(2), 3);\n }\n\n #[test(should_fail_with = \"from array out of bounds\")]\n fn max_len_lower_then_array_len() {\n let _: BoundedVec = BoundedVec::from_array([0; 3]);\n }\n\n #[test]\n fn from_array_preserves_order() {\n let array = [5, 3, 1, 4, 2];\n let vec: BoundedVec = BoundedVec::from_array(array);\n for i in 0..array.len() {\n assert_eq(vec.get(i), array[i]);\n }\n }\n\n #[test]\n fn from_array_with_different_types() {\n let bool_array = [true, false, true];\n let bool_vec: BoundedVec = BoundedVec::from_array(bool_array);\n assert_eq(bool_vec.len(), 3);\n assert_eq(bool_vec.get(0), true);\n assert_eq(bool_vec.get(1), false);\n }\n }\n\n mod trait_from {\n use crate::collections::bounded_vec::BoundedVec;\n use crate::convert::From;\n\n #[test]\n fn simple() {\n let array = [1, 2];\n let bounded_vec: BoundedVec = BoundedVec::from(array);\n\n assert_eq(bounded_vec.max_len(), 10);\n assert_eq(bounded_vec.len(), 2);\n assert_eq(bounded_vec.get(0), 1);\n assert_eq(bounded_vec.get(1), 2);\n }\n }\n\n mod trait_eq {\n use crate::collections::bounded_vec::BoundedVec;\n\n #[test]\n fn empty_equality() {\n let mut bounded_vec1: BoundedVec = BoundedVec::new();\n let mut bounded_vec2: BoundedVec = BoundedVec::new();\n\n assert_eq(bounded_vec1, bounded_vec2);\n }\n\n #[test]\n fn inequality() {\n let mut bounded_vec1: BoundedVec = BoundedVec::new();\n let mut bounded_vec2: BoundedVec = BoundedVec::new();\n bounded_vec1.push(1);\n bounded_vec2.push(2);\n\n assert(bounded_vec1 != bounded_vec2);\n }\n }\n\n mod from_parts {\n use crate::collections::bounded_vec::BoundedVec;\n\n #[test]\n fn from_parts() {\n // docs:start:from-parts\n let vec: BoundedVec = BoundedVec::from_parts([1, 2, 3, 0], 3);\n assert_eq(vec.len(), 3);\n\n // Any elements past the given length are zeroed out, so these\n // two BoundedVecs will be completely equal\n let vec1: BoundedVec = BoundedVec::from_parts([1, 2, 3, 1], 3);\n let vec2: BoundedVec = BoundedVec::from_parts([1, 2, 3, 2], 3);\n assert_eq(vec1, vec2);\n // docs:end:from-parts\n }\n\n #[test]\n fn from_parts_unchecked() {\n // docs:start:from-parts-unchecked\n let vec: BoundedVec = BoundedVec::from_parts_unchecked([1, 2, 3, 0], 3);\n assert_eq(vec.len(), 3);\n\n // invalid use!\n let vec1: BoundedVec = BoundedVec::from_parts_unchecked([1, 2, 3, 1], 3);\n let vec2: BoundedVec = BoundedVec::from_parts_unchecked([1, 2, 3, 2], 3);\n\n // both vecs have length 3 so we'd expect them to be equal, but this\n // fails because elements past the length are still checked in eq\n assert(vec1 != vec2);\n // docs:end:from-parts-unchecked\n }\n }\n\n mod push_pop {\n use crate::collections::bounded_vec::BoundedVec;\n\n #[test]\n fn push_and_pop_operations() {\n let mut vec: BoundedVec = BoundedVec::new();\n\n assert_eq(vec.len(), 0);\n\n vec.push(1);\n assert_eq(vec.len(), 1);\n assert_eq(vec.get(0), 1);\n\n vec.push(2);\n assert_eq(vec.len(), 2);\n assert_eq(vec.get(1), 2);\n\n let popped = vec.pop();\n assert_eq(popped, 2);\n assert_eq(vec.len(), 1);\n\n let popped2 = vec.pop();\n assert_eq(popped2, 1);\n assert_eq(vec.len(), 0);\n }\n\n #[test(should_fail_with = \"push out of bounds\")]\n fn push_to_full_vector() {\n let mut vec: BoundedVec = BoundedVec::new();\n vec.push(1);\n vec.push(2);\n vec.push(3); // should panic\n }\n\n #[test(should_fail_with = \"cannot pop from an empty vector\")]\n fn pop_from_empty_vector() {\n let mut vec: BoundedVec = BoundedVec::new();\n let _ = vec.pop(); // should panic\n }\n\n #[test]\n fn push_pop_cycle() {\n let mut vec: BoundedVec = BoundedVec::new();\n\n // push to full\n vec.push(1);\n vec.push(2);\n vec.push(3);\n assert_eq(vec.len(), 3);\n\n // pop all\n assert_eq(vec.pop(), 3);\n assert_eq(vec.pop(), 2);\n assert_eq(vec.pop(), 1);\n assert_eq(vec.len(), 0);\n\n // push again\n vec.push(4);\n assert_eq(vec.len(), 1);\n assert_eq(vec.get(0), 4);\n }\n }\n\n mod extend {\n use crate::collections::bounded_vec::BoundedVec;\n\n #[test]\n fn extend_from_array() {\n let mut vec: BoundedVec = BoundedVec::new();\n vec.push(1);\n vec.extend_from_array([2, 3]);\n\n assert_eq(vec.len(), 3);\n assert_eq(vec.get(0), 1);\n assert_eq(vec.get(1), 2);\n assert_eq(vec.get(2), 3);\n }\n\n #[test]\n fn extend_from_slice() {\n let mut vec: BoundedVec = BoundedVec::new();\n vec.push(1);\n vec.extend_from_slice(&[2, 3]);\n\n assert_eq(vec.len(), 3);\n assert_eq(vec.get(0), 1);\n assert_eq(vec.get(1), 2);\n assert_eq(vec.get(2), 3);\n }\n\n #[test]\n fn extend_from_bounded_vec() {\n let mut vec1: BoundedVec = BoundedVec::new();\n let mut vec2: BoundedVec = BoundedVec::new();\n\n vec1.push(1);\n vec2.push(2);\n vec2.push(3);\n\n vec1.extend_from_bounded_vec(vec2);\n\n assert_eq(vec1.len(), 3);\n assert_eq(vec1.get(0), 1);\n assert_eq(vec1.get(1), 2);\n assert_eq(vec1.get(2), 3);\n }\n\n #[test(should_fail_with = \"extend_from_array out of bounds\")]\n fn extend_array_beyond_max_len() {\n let mut vec: BoundedVec = BoundedVec::new();\n vec.push(1);\n vec.extend_from_array([2, 3, 4]); // should panic\n }\n\n #[test(should_fail_with = \"extend_from_slice out of bounds\")]\n fn extend_slice_beyond_max_len() {\n let mut vec: BoundedVec = BoundedVec::new();\n vec.push(1);\n vec.extend_from_slice(&[2, 3, 4]); // S]should panic\n }\n\n #[test(should_fail_with = \"extend_from_bounded_vec out of bounds\")]\n fn extend_bounded_vec_beyond_max_len() {\n let mut vec: BoundedVec = BoundedVec::new();\n let other: BoundedVec = BoundedVec::from_array([1, 2, 3, 4, 5]);\n vec.extend_from_bounded_vec(other); // should panic\n }\n\n #[test]\n fn extend_with_empty_collections() {\n let mut vec: BoundedVec = BoundedVec::new();\n let original_len = vec.len();\n\n vec.extend_from_array([]);\n assert_eq(vec.len(), original_len);\n\n vec.extend_from_slice(&[]);\n assert_eq(vec.len(), original_len);\n\n let empty: BoundedVec = BoundedVec::new();\n vec.extend_from_bounded_vec(empty);\n assert_eq(vec.len(), original_len);\n }\n }\n\n mod storage {\n use crate::collections::bounded_vec::BoundedVec;\n\n #[test]\n fn storage_consistency() {\n let mut vec: BoundedVec = BoundedVec::new();\n\n // test initial storage state\n assert_eq(vec.storage(), [0, 0, 0, 0, 0]);\n\n vec.push(1);\n vec.push(2);\n\n // test storage after modifications\n assert_eq(vec.storage(), [1, 2, 0, 0, 0]);\n\n // storage doesn't change length\n assert_eq(vec.len(), 2);\n assert_eq(vec.max_len(), 5);\n }\n\n #[test]\n fn storage_after_pop() {\n let mut vec: BoundedVec = BoundedVec::from_array([1, 2, 3]);\n\n let _ = vec.pop();\n // after pop, the last element should be zeroed\n assert_eq(vec.storage(), [1, 2, 0]);\n assert_eq(vec.len(), 2);\n }\n\n #[test]\n fn vector_immutable() {\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3]);\n let storage = vec.storage();\n\n assert_eq(storage, [1, 2, 3]);\n\n // Verify that the original vector is unchanged\n assert_eq(vec.len(), 3);\n assert_eq(vec.get(0), 1);\n assert_eq(vec.get(1), 2);\n assert_eq(vec.get(2), 3);\n }\n }\n}\n"},"62":{"path":"/home/nerses/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.2/noir-projects/aztec-nr/aztec/src/capsules/mod.nr","source":"use crate::oracle::capsules;\nuse protocol_types::{address::AztecAddress, traits::{Deserialize, Serialize}};\n\n/// A dynamically sized array backed by PXE's non-volatile database (called capsules). Values are persisted until\n/// deleted, so they can be e.g. stored during simulation of a transaction and later retrieved during witness\n/// generation. All values are scoped per contract address, so external contracts cannot access them.\npub struct CapsuleArray {\n contract_address: AztecAddress,\n /// The base slot is where the array length is stored in capsules. Array elements are stored in consecutive slots\n /// after the base slot. For example, with base slot 5: the length is at slot 5, the first element (index 0) is at\n /// slot 6, the second element (index 1) is at slot 7, and so on.\n base_slot: Field,\n}\n\nimpl CapsuleArray {\n /// Returns a CapsuleArray connected to a contract's capsules at a base slot. Array elements are stored in\n /// contiguous slots following the base slot, so there should be sufficient space between array base slots to\n /// accommodate elements. A reasonable strategy is to make the base slot a hash of a unique value.\n pub unconstrained fn at(contract_address: AztecAddress, base_slot: Field) -> Self {\n Self { contract_address, base_slot }\n }\n\n /// Returns the number of elements stored in the array.\n pub unconstrained fn len(self) -> u32 {\n // An uninitialized array defaults to a length of 0.\n capsules::load(self.contract_address, self.base_slot).unwrap_or(0) as u32\n }\n\n /// Stores a value at the end of the array.\n pub unconstrained fn push(self, value: T)\n where\n T: Serialize,\n {\n let current_length = self.len();\n\n // The slot corresponding to the index `current_length` is the first slot immediately after the end of the\n // array, which is where we want to place the new value.\n capsules::store(self.contract_address, self.slot_at(current_length), value);\n\n // Then we simply update the length.\n let new_length = current_length + 1;\n capsules::store(self.contract_address, self.base_slot, new_length);\n }\n\n /// Retrieves the value stored in the array at `index`. Throws if the index is out of bounds.\n pub unconstrained fn get(self, index: u32) -> T\n where\n T: Deserialize,\n {\n assert(index < self.len(), \"Attempted to read past the length of a CapsuleArray\");\n\n capsules::load(self.contract_address, self.slot_at(index)).unwrap()\n }\n\n /// Deletes the value stored in the array at `index`. Throws if the index is out of bounds.\n pub unconstrained fn remove(self, index: u32) {\n let current_length = self.len();\n assert(index < current_length, \"Attempted to delete past the length of a CapsuleArray\");\n\n // In order to be able to remove elements at arbitrary indices, we need to shift the entire contents of the\n // array past the removed element one slot backward so that we don't end up with a gap and preserve the\n // contiguous slots. We can skip this when deleting the last element however.\n if index != current_length - 1 {\n // The source and destination regions overlap, but `copy` supports this.\n capsules::copy(\n self.contract_address,\n self.slot_at(index + 1),\n self.slot_at(index),\n current_length - index - 1,\n );\n }\n\n // We can now delete the last element (which has either been copied to the slot immediately before it, or was\n // the element we meant to delete in the first place) and update the length.\n capsules::delete(self.contract_address, self.slot_at(current_length - 1));\n capsules::store(self.contract_address, self.base_slot, current_length - 1);\n }\n\n /// Iterates over the entire array, calling the callback with all values and their array index. The order in which\n /// values are processed is arbitrary.\n ///\n /// It is safe to delete the current element (and only the current element) from inside the callback via `remove`:\n /// ```noir\n /// array.for_each(|index, value| {\n /// if some_condition(value) {\n /// array.remove(index); // safe only for this index\n /// }\n /// }\n /// ```\n ///\n /// If all elements in the array need to iterated over and then removed, then using `for_each` results in optimal\n /// efficiency.\n ///\n /// It is **not** safe to push new elements into the array from inside the callback.\n pub unconstrained fn for_each(self, f: unconstrained fn[Env](u32, T) -> ())\n where\n T: Deserialize,\n {\n // Iterating over all elements is simple, but we want to do it in such a way that a) deleting the current\n // element is safe to do, and b) deleting *all* elements is optimally efficient. This is because CapsuleArrays\n // are typically used to hold pending tasks, so iterating them while clearing completed tasks (sometimes\n // unconditionally, resulting in a full clear) is a very common access pattern.\n //\n // The way we achieve this is by iterating backwards: each element can always be deleted since it won't change\n // any preceding (lower) indices, and if every element is deleted then every element will (in turn) be the last\n // element. This results in an optimal full clear since `remove` will be able to skip the `capsules::copy` call\n // to shift any elements past the deleted one (because there will be none).\n let mut i = self.len();\n while i > 0 {\n i -= 1;\n f(i, self.get(i));\n }\n }\n\n unconstrained fn slot_at(self, index: u32) -> Field {\n // Elements are stored immediately after the base slot, so we add 1 to it to compute the slot for the first\n // element.\n self.base_slot + 1 + index as Field\n }\n}\n\nmod test {\n use crate::test::helpers::test_environment::TestEnvironment;\n use super::CapsuleArray;\n\n global SLOT: Field = 1230;\n\n #[test]\n unconstrained fn empty_array() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n\n let array: CapsuleArray = CapsuleArray::at(contract_address, SLOT);\n assert_eq(array.len(), 0);\n });\n }\n\n #[test(should_fail_with = \"Attempted to read past the length of a CapsuleArray\")]\n unconstrained fn empty_array_read() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n\n let array = CapsuleArray::at(contract_address, SLOT);\n let _: Field = array.get(0);\n });\n }\n\n #[test]\n unconstrained fn array_push() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n\n let array = CapsuleArray::at(contract_address, SLOT);\n array.push(5);\n\n assert_eq(array.len(), 1);\n assert_eq(array.get(0), 5);\n });\n }\n\n #[test(should_fail_with = \"Attempted to read past the length of a CapsuleArray\")]\n unconstrained fn read_past_len() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n\n let array = CapsuleArray::at(contract_address, SLOT);\n array.push(5);\n\n let _ = array.get(1);\n });\n }\n\n #[test]\n unconstrained fn array_remove_last() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n\n let array = CapsuleArray::at(contract_address, SLOT);\n\n array.push(5);\n array.remove(0);\n\n assert_eq(array.len(), 0);\n });\n }\n\n #[test]\n unconstrained fn array_remove_some() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n\n let array = CapsuleArray::at(contract_address, SLOT);\n\n array.push(7);\n array.push(8);\n array.push(9);\n\n assert_eq(array.len(), 3);\n assert_eq(array.get(0), 7);\n assert_eq(array.get(1), 8);\n assert_eq(array.get(2), 9);\n\n array.remove(1);\n\n assert_eq(array.len(), 2);\n assert_eq(array.get(0), 7);\n assert_eq(array.get(1), 9);\n });\n }\n\n #[test]\n unconstrained fn array_remove_all() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n\n let array = CapsuleArray::at(contract_address, SLOT);\n\n array.push(7);\n array.push(8);\n array.push(9);\n\n array.remove(1);\n array.remove(1);\n array.remove(0);\n\n assert_eq(array.len(), 0);\n });\n }\n\n #[test]\n unconstrained fn for_each_called_with_all_elements() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n let array = CapsuleArray::at(contract_address, SLOT);\n\n array.push(4);\n array.push(5);\n array.push(6);\n\n // We store all values that we were called with and check that all (value, index) tuples are present. Note that\n // we do not care about the order in which each tuple was passed to the closure.\n let called_with = &mut BoundedVec::<(u32, Field), 3>::new();\n array.for_each(|index, value| { called_with.push((index, value)); });\n\n assert_eq(called_with.len(), 3);\n assert(called_with.any(|(index, value)| (index == 0) & (value == 4)));\n assert(called_with.any(|(index, value)| (index == 1) & (value == 5)));\n assert(called_with.any(|(index, value)| (index == 2) & (value == 6)));\n });\n }\n\n #[test]\n unconstrained fn for_each_remove_some() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n let array = CapsuleArray::at(contract_address, SLOT);\n\n array.push(4);\n array.push(5);\n array.push(6);\n\n array.for_each(|index, _| {\n if index == 1 {\n array.remove(index);\n }\n });\n\n assert_eq(array.len(), 2);\n assert_eq(array.get(0), 4);\n assert_eq(array.get(1), 6);\n });\n }\n\n #[test]\n unconstrained fn for_each_remove_all() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n let array = CapsuleArray::at(contract_address, SLOT);\n\n array.push(4);\n array.push(5);\n array.push(6);\n\n array.for_each(|index, _| { array.remove(index); });\n\n assert_eq(array.len(), 0);\n });\n }\n\n #[test]\n unconstrained fn for_each_remove_all_no_copy() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n let array = CapsuleArray::at(contract_address, SLOT);\n\n array.push(4);\n array.push(5);\n array.push(6);\n\n // We test that the utilityCopyCapsule was never called, which is the expensive operation we want to avoid.\n let mock = std::test::OracleMock::mock(\"utilityCopyCapsule\");\n\n array.for_each(|index, _| { array.remove(index); });\n\n assert_eq(mock.times_called(), 0);\n });\n }\n}\n"},"63":{"path":"/home/nerses/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.2/noir-projects/aztec-nr/aztec/src/context/call_interfaces.nr","source":"use dep::protocol_types::{\n abis::function_selector::FunctionSelector,\n address::AztecAddress,\n traits::{Deserialize, ToField},\n};\n\nuse crate::context::{gas::GasOpts, private_context::PrivateContext, public_context::PublicContext};\nuse crate::hash::{hash_args, hash_calldata};\nuse crate::oracle::execution_cache;\n\npub trait CallInterface {\n fn get_args(self) -> [Field];\n fn get_selector(self) -> FunctionSelector;\n fn get_name(self) -> str;\n fn get_contract_address(self) -> AztecAddress;\n fn get_is_static(self) -> bool;\n}\n\n// PrivateCallInterface\n\npub struct PrivateCallInterface {\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args_hash: Field,\n args: [Field],\n return_type: T,\n is_static: bool,\n}\n\nimpl PrivateCallInterface\nwhere\n T: Deserialize,\n{\n pub fn new(\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args: [Field],\n is_static: bool,\n ) -> Self {\n let args_hash = hash_args(args);\n Self {\n target_contract,\n selector,\n name,\n args_hash,\n args,\n return_type: std::mem::zeroed(),\n is_static,\n }\n }\n\n /// Makes the call to this private function.\n ///\n /// # Arguments\n /// * `context` - The PrivateContext -- made magically available to the body\n /// of every #[external(\"private\")] function as `context`, through the\n /// #[external(\"private\")] annotation's macro.\n ///\n /// # Returns\n /// * `T` - Whatever data the called function has returned.\n ///\n /// This enables contracts to interact with each other while maintaining\n /// privacy. This \"composability\" of private contract functions is a key\n /// feature of the Aztec network.\n ///\n /// If a user's transaction includes multiple private function calls, then\n /// by the design of Aztec, the following information will remain private[1]:\n /// - The function selectors and contract addresses of all private function\n /// calls will remain private, so an observer of the public mempool will\n /// not be able to look at a tx and deduce which private functions have\n /// been executed.\n /// - The arguments and return values of all private function calls will\n /// remain private.\n /// - The person who initiated the tx will remain private.\n /// - The notes and nullifiers and private logs that are emitted by all\n /// private function calls will (if designed well) not leak any user\n /// secrets, nor leak which functions have been executed.\n ///\n /// [1] Caveats: Some of these privacy guarantees depend on how app\n /// developers design their smart contracts. Some actions _can_ leak\n /// information, such as:\n /// - Calling an internal public function.\n /// - Calling a public function and not setting msg_sender to Option::none\n /// (see https://github.com/AztecProtocol/aztec-packages/pull/16433)\n /// - Calling any public function will always leak details about the nature\n /// of the transaction, so devs should be careful in their contract\n /// designs. If it can be done in a private function, then that will give\n /// the best privacy.\n /// - Not padding the side-effects of a tx to some standardised, uniform\n /// size. The kernel circuits can take hints to pad side-effects, so a\n /// wallet should be able to request for a particular amount of padding.\n /// Wallets should ideally agree on some standard.\n /// - Padding should include:\n /// - Padding the lengths of note & nullifier arrays\n /// - Padding private logs with random fields, up to some standardised\n /// size.\n /// See also: https://docs.aztec.network/developers/reference/considerations/privacy_considerations\n ///\n /// # Advanced\n /// * The call is added to the private call stack and executed by kernel\n /// circuits after this function completes\n /// * The called function can modify its own contract's private state\n /// * Side effects from the called function are included in this transaction\n /// * The call inherits the current transaction's context and gas limits\n ///\n /// # Arguments\n /// * `context` - The PrivateContext -- made magically available to the body\n /// of every #[external(\"private\")] function as `context`, through the\n /// #[external(\"private\")] annotation's macro.\n ///\n /// # Returns\n /// * `T` - Whatever data the called function has returned.\n ///\n pub fn call(self, context: &mut PrivateContext) -> T {\n execution_cache::store(self.args, self.args_hash);\n let returns_hash = context.call_private_function_with_args_hash(\n self.target_contract,\n self.selector,\n self.args_hash,\n false,\n );\n\n // If T is () (i.e. if the function does not return anything) then `get_preimage` will constrain that the\n // returns hash is empty as per the protocol rules.\n returns_hash.get_preimage()\n }\n\n /// Makes a _read-only_ call to this private function.\n ///\n /// This is similar to Solidity's `staticcall`. The called function\n /// cannot modify state, emit L2->L1 messages, nor emit events. Any nested\n /// calls are constrained to also be staticcalls.\n ///\n /// See `call` for more general info on private function calls.\n ///\n /// # Arguments\n /// * `context` - The PrivateContext -- made magically available to the body\n /// of every #[external(\"private\")] function as `context`, through the\n /// #[external(\"private\")] annotation's macro.\n ///\n /// # Returns\n /// * `T` - Whatever data the called function has returned.\n ///\n pub fn view(self, context: &mut PrivateContext) -> T {\n execution_cache::store(self.args, self.args_hash);\n let returns_hash = context.call_private_function_with_args_hash(\n self.target_contract,\n self.selector,\n self.args_hash,\n true,\n );\n // If T is () (i.e. if the function does not return anything) then `get_preimage` will constrain that the\n // returns hash is empty as per the protocol rules.\n returns_hash.get_preimage()\n }\n}\n\nimpl CallInterface for PrivateCallInterface {\n fn get_args(self) -> [Field] {\n self.args\n }\n\n fn get_selector(self) -> FunctionSelector {\n self.selector\n }\n\n fn get_name(self) -> str {\n self.name\n }\n\n fn get_contract_address(self) -> AztecAddress {\n self.target_contract\n }\n\n fn get_is_static(self) -> bool {\n self.is_static\n }\n}\n\n// PrivateStaticCallInterface\n\npub struct PrivateStaticCallInterface {\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args_hash: Field,\n args: [Field],\n return_type: T,\n is_static: bool,\n}\n\nimpl PrivateStaticCallInterface {\n pub fn new(\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args: [Field],\n ) -> Self {\n let args_hash = hash_args(args);\n Self {\n target_contract,\n selector,\n name,\n args_hash,\n args,\n return_type: std::mem::zeroed(),\n is_static: true,\n }\n }\n\n /// Makes a read-only call to this private function.\n ///\n /// This is similar to Solidity's `staticcall`. The called function\n /// cannot modify state, emit L2->L1 messages, nor emit events. Any nested\n /// calls are constrained to also be staticcalls.\n ///\n /// # Arguments\n /// * `context` - The PrivateContext -- made magically available to the body\n /// of every #[external(\"private\")] function as `context`, through the\n /// #[external(\"private\")] annotation's macro.\n ///\n pub fn view(self, context: &mut PrivateContext) -> T\n where\n T: Deserialize,\n {\n execution_cache::store(self.args, self.args_hash);\n let returns = context.call_private_function_with_args_hash(\n self.target_contract,\n self.selector,\n self.args_hash,\n true,\n );\n returns.get_preimage()\n }\n}\n\nimpl CallInterface for PrivateStaticCallInterface {\n fn get_args(self) -> [Field] {\n self.args\n }\n\n fn get_selector(self) -> FunctionSelector {\n self.selector\n }\n\n fn get_name(self) -> str {\n self.name\n }\n\n fn get_contract_address(self) -> AztecAddress {\n self.target_contract\n }\n\n fn get_is_static(self) -> bool {\n self.is_static\n }\n}\n\n// PublicCallInterface\n\npub struct PublicCallInterface {\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args: [Field],\n gas_opts: GasOpts,\n return_type: T,\n is_static: bool,\n}\n\nimpl PublicCallInterface\nwhere\n T: Deserialize,\n{\n pub fn new(\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args: [Field],\n is_static: bool,\n ) -> Self {\n Self {\n target_contract,\n selector,\n name,\n args,\n gas_opts: GasOpts::default(),\n return_type: std::mem::zeroed(),\n is_static,\n }\n }\n\n pub fn with_gas(self: &mut Self, gas_opts: GasOpts) -> &mut Self {\n self.gas_opts = gas_opts;\n self\n }\n\n /// Makes the call to this public function.\n ///\n /// Will revert if the called function reverts or runs out of gas.\n ///\n /// # Arguments\n /// * `context` - The PublicContext -- made magically available to the body\n /// of every #[external(\"public\")] function as `context`, through the\n /// #[external(\"public\")] annotation's macro.\n ///\n /// # Returns\n /// * `T` - Whatever data the called function has returned.\n ///\n pub unconstrained fn call(self, context: &mut PublicContext) -> T {\n let returns = context.call_public_function(\n self.target_contract,\n self.selector,\n self.args,\n self.gas_opts,\n );\n // If T is () (i.e. if the function does not return anything) then `as_array` will constrain that `returns` has\n // a length of 0 (since that is ()'s deserialization length).\n Deserialize::deserialize(returns.as_array())\n }\n\n /// Makes a read-only call to this public function.\n ///\n /// This is similar to Solidity's `staticcall`. The called function\n /// cannot modify state or emit events. Any nested calls are constrained to\n /// also be staticcalls.\n ///\n /// Will revert if the called function reverts or runs out of gas.\n ///\n /// # Arguments\n /// * `context` - The PublicContext -- made magically available to the body\n /// of every #[external(\"public\")] function as `context`, through the\n /// #[external(\"public\")] annotation's macro.\n ///\n /// # Returns\n /// * `T` - Whatever data the called function has returned.\n ///\n pub unconstrained fn view(self, context: &mut PublicContext) -> T {\n let returns = context.static_call_public_function(\n self.target_contract,\n self.selector,\n self.args,\n self.gas_opts,\n );\n // If T is () (i.e. if the function does not return anything) then `as_array` will constrain that `returns` has\n // a length of 0 (since that is ()'s deserialization length).\n Deserialize::deserialize(returns.as_array())\n }\n\n /// Enqueues a call to this public function, to be executed later.\n ///\n /// Unlike private functions which execute immediately on the user's device,\n /// public function calls are \"enqueued\" and executed some time later by a\n /// block proposer.\n ///\n /// This means a public function cannot return any values back to a private\n /// function, because by the time the public function is being executed,\n /// the private function which called it has already completed execution.\n /// (In fact, the private function has been executed and proven, along with\n /// all other private function calls of the user's tx. A single proof of the\n /// tx has been submitted to the Aztec network, and some time later a\n /// proposer has picked the tx up from the mempool and begun executing all\n /// of the enqueued public functions).\n ///\n /// # Privacy warning\n /// Enqueueing a public function call is an inherently leaky action.\n /// Many interesting applications will require some interaction with public\n /// state, but smart contract developers should try to use public function\n /// calls sparingly, and carefully.\n /// _Internal_ public function calls are especially leaky, because they\n /// completely leak which private contract made the call.\n /// See also: https://docs.aztec.network/developers/reference/considerations/privacy_considerations\n ///\n /// # Arguments\n /// * `context` - The PrivateContext -- made magically available to the body\n /// of every #[external(\"private\")] function as `context`, through the\n /// #[external(\"private\")] annotation's macro.\n ///\n pub fn enqueue(self, context: &mut PrivateContext) {\n self.enqueue_impl(context, false, false)\n }\n\n /// Enqueues a call to this public function, to be executed later.\n ///\n /// As per `enqueue`, but hides this calling contract's address from the\n /// target public function.\n /// This means the origin of the call (msg_sender) will not be publicly\n /// visible to any blockchain observers, nor to the target public function.\n /// When the target public function reads `context.msg_sender()` it will\n /// receive an `Option::none`.\n ///\n /// NOTES:\n /// - Not all public functions will accept a msg_sender of \"none\". Many\n /// public functions will require that msg_sender is \"some\" and will\n /// revert otherwise. Therefore, if using `enqueue_incognito`, you must\n /// understand whether the function you're calling will accept a\n /// msg_sender of \"none\".\n /// Lots of public bookkeeping patterns rely on knowing which address made\n /// the call, so as to ascribe state against the caller's address.\n /// (There are patterns whereby bookkeeping could instead be done in\n /// private-land).\n /// - If you are enqueueing a call to an _internal_ public function (i.e.\n /// a public function that will only accept calls from other functions\n /// of its own contract), then by definition a call to it cannot possibly\n /// be \"incognito\": the msg_sender must be its own address, and indeed the\n /// called public function will assert this. Tl;dr this is not usable for\n /// enqueued internal public calls.\n ///\n /// # Arguments\n /// * `context` - The PrivateContext -- made magically available to the body\n /// of every #[external(\"private\")] function as `context`, through the\n /// #[external(\"private\")] annotation's macro.\n ///\n /// Advanced:\n /// - The kernel circuits will permit _any_ private function to set the\n /// msg_sender field of any enqueued public function call to\n /// NULL_MSG_SENDER_CONTRACT_ADDRESS.\n /// - When the called public function calls `PublicContext::msg_sender()`,\n /// aztec-nr will translate NULL_MSG_SENDER_CONTRACT_ADDRESS into\n /// `Option::none` for familiarity to devs.\n ///\n pub fn enqueue_incognito(self, context: &mut PrivateContext) {\n self.enqueue_impl(context, false, true)\n }\n\n /// Enqueues a read-only call to this public function.\n ///\n /// This is similar to Solidity's `staticcall`. The called function\n /// cannot modify state, emit L2->L1 messages, nor emit events. Any nested\n /// calls are constrained to also be staticcalls.\n ///\n /// # Arguments\n /// * `context` - The PrivateContext -- made magically available to the body\n /// of every #[external(\"private\")] function as `context`, through the\n /// #[external(\"private\")] annotation's macro.\n ///\n pub fn enqueue_view(self, context: &mut PrivateContext) {\n self.enqueue_impl(context, true, false)\n }\n\n /// Enqueues a read-only call to this public function.\n ///\n /// As per `enqueue_view`, but hides this calling contract's address from\n /// the target public function.\n ///\n /// See `enqueue_incognito` for more details relating to hiding msg_sender.\n ///\n /// # Arguments\n /// * `context` - The PrivateContext -- made magically available to the body\n /// of every #[external(\"private\")] function as `context`, through the\n /// #[external(\"private\")] annotation's macro.\n ///\n pub fn enqueue_view_incognito(self, context: &mut PrivateContext) {\n self.enqueue_impl(context, true, true)\n }\n\n fn enqueue_impl(\n self,\n context: &mut PrivateContext,\n is_static_call: bool,\n hide_msg_sender: bool,\n ) {\n let calldata = self.args.push_front(self.selector.to_field());\n let calldata_hash = hash_calldata(calldata);\n execution_cache::store(calldata, calldata_hash);\n context.call_public_function_with_calldata_hash(\n self.target_contract,\n calldata_hash,\n is_static_call,\n hide_msg_sender,\n )\n }\n\n /// Enqueues a call to this public function, and designates it to be the\n /// teardown function for this tx. Only one teardown function call can be\n /// made by a tx.\n ///\n /// Niche function: Only wallet developers and paymaster contract developers\n /// (aka Fee-payment contracts) will need to make use of this function.\n ///\n /// Aztec supports a three-phase execution model: setup, app logic, teardown.\n /// The phases exist to enable a fee payer to take on the risk of paying\n /// a transaction fee, safe in the knowledge that their payment (in whatever\n /// token or method the user chooses) will succeed, regardless of whether\n /// the app logic will succeed. The \"setup\" phase ensures the fee payer\n /// has sufficient balance to pay the proposer their fees.\n /// The teardown phase is primarily intended to: calculate exactly\n /// how much the user owes, based on gas consumption, and refund the user\n /// any change.\n ///\n /// Note: in some cases, the cost of refunding the user (i.e. DA costs of\n /// tx side-effects) might exceed the refund amount. For app logic with\n /// fairly stable and predictable gas consumption, a material refund amount\n /// is unlikely. For app logic with unpredictable gas consumption, a\n /// refund might be important to the user (e.g. if a hefty function reverts\n /// very early). Wallet/FPC/Paymaster developers should be mindful of this.\n ///\n /// See `enqueue` for more information about enqueuing public function calls.\n ///\n /// # Arguments\n /// * `context` - The PrivateContext -- made magically available to the body\n /// of every #[external(\"private\")] function as `context`, through the\n /// #[external(\"private\")] annotation's macro.\n ///\n pub fn set_as_teardown(self, context: &mut PrivateContext) {\n self.set_as_teardown_impl(context, false);\n }\n\n /// Enqueues a call to this public function, and designates it to be the teardown\n /// function for this tx. Only one teardown function call can be made by a\n /// tx.\n ///\n /// As per `set_as_teardown`, but hides this calling contract's address from\n /// the target public function.\n ///\n /// See `enqueue_incognito` for more details relating to hiding msg_sender.\n ///\n pub fn set_as_teardown_incognito(self, context: &mut PrivateContext) {\n self.set_as_teardown_impl(context, true);\n }\n\n fn set_as_teardown_impl(self, context: &mut PrivateContext, hide_msg_sender: bool) {\n let calldata = self.args.push_front(self.selector.to_field());\n let calldata_hash = hash_calldata(calldata);\n execution_cache::store(calldata, calldata_hash);\n context.set_public_teardown_function_with_calldata_hash(\n self.target_contract,\n calldata_hash,\n false,\n hide_msg_sender,\n )\n }\n}\n\nimpl CallInterface for PublicCallInterface {\n fn get_args(self) -> [Field] {\n self.args\n }\n\n fn get_selector(self) -> FunctionSelector {\n self.selector\n }\n\n fn get_name(self) -> str {\n self.name\n }\n\n fn get_contract_address(self) -> AztecAddress {\n self.target_contract\n }\n\n fn get_is_static(self) -> bool {\n self.is_static\n }\n}\n\n// PublicStaticCallInterface\n\npub struct PublicStaticCallInterface {\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args: [Field],\n return_type: T,\n is_static: bool,\n gas_opts: GasOpts,\n}\n\nimpl PublicStaticCallInterface\nwhere\n T: Deserialize,\n{\n pub fn new(\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args: [Field],\n ) -> Self {\n Self {\n target_contract,\n selector,\n name,\n args,\n return_type: std::mem::zeroed(),\n is_static: true,\n gas_opts: GasOpts::default(),\n }\n }\n\n pub fn with_gas(self: &mut Self, gas_opts: GasOpts) -> &mut Self {\n self.gas_opts = gas_opts;\n self\n }\n\n /// Makes the read-only call to this public function.\n ///\n /// This is similar to Solidity's `staticcall`. The called function\n /// cannot modify state or emit events. Any nested calls are constrained to\n /// also be staticcalls.\n ///\n /// Will revert if the called function reverts or runs out of gas.\n ///\n /// # Arguments\n /// * `context` - The PublicContext -- made magically available to the body\n /// of every #[external(\"public\")] function as `context`, through the\n /// #[external(\"public\")] annotation's macro.\n ///\n /// # Returns\n /// * `T` - Whatever data the called function has returned.\n ///\n pub unconstrained fn view(self, context: &mut PublicContext) -> T {\n let returns = context.static_call_public_function(\n self.target_contract,\n self.selector,\n self.args,\n self.gas_opts,\n );\n Deserialize::deserialize(returns.as_array())\n }\n\n /// Enqueues a read-only call to this public function.\n ///\n /// This is similar to Solidity's `staticcall`. The called function\n /// cannot modify state, emit L2->L1 messages, nor emit events. Any nested\n /// calls are constrained to also be staticcalls.\n ///\n /// # Arguments\n /// * `context` - The PrivateContext -- made magically available to the body\n /// of every #[external(\"private\")] function as `context`, through the\n /// #[external(\"private\")] annotation's macro.\n ///\n pub fn enqueue_view(self, context: &mut PrivateContext) {\n let calldata = self.args.push_front(self.selector.to_field());\n let calldata_hash = hash_calldata(calldata);\n execution_cache::store(calldata, calldata_hash);\n context.call_public_function_with_calldata_hash(\n self.target_contract,\n calldata_hash,\n /*static=*/\n true,\n false,\n )\n }\n\n pub fn enqueue_view_incognito(self, context: &mut PrivateContext) {\n let calldata = self.args.push_front(self.selector.to_field());\n let calldata_hash = hash_calldata(calldata);\n execution_cache::store(calldata, calldata_hash);\n context.call_public_function_with_calldata_hash(\n self.target_contract,\n calldata_hash,\n /*static=*/\n true,\n true,\n )\n }\n}\n\nimpl CallInterface for PublicStaticCallInterface {\n fn get_args(self) -> [Field] {\n self.args\n }\n\n fn get_selector(self) -> FunctionSelector {\n self.selector\n }\n\n fn get_name(self) -> str {\n self.name\n }\n\n fn get_contract_address(self) -> AztecAddress {\n self.target_contract\n }\n\n fn get_is_static(self) -> bool {\n self.is_static\n }\n}\n\n// UtilityCallInterface\n\npub struct UtilityCallInterface {\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args_hash: Field,\n args: [Field],\n return_type: T,\n}\n\nimpl CallInterface for UtilityCallInterface {\n fn get_args(self) -> [Field] {\n self.args\n }\n\n fn get_selector(self) -> FunctionSelector {\n self.selector\n }\n\n fn get_name(self) -> str {\n self.name\n }\n\n fn get_contract_address(self) -> AztecAddress {\n self.target_contract\n }\n\n fn get_is_static(self) -> bool {\n false\n }\n}\n\nimpl UtilityCallInterface {\n pub fn new(\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args: [Field],\n ) -> Self {\n let args_hash = hash_args(args);\n Self { target_contract, selector, name, args_hash, args, return_type: std::mem::zeroed() }\n }\n\n pub fn get_args(self) -> [Field] {\n self.args\n }\n\n pub fn get_selector(self) -> FunctionSelector {\n self.selector\n }\n\n pub fn get_name(self) -> str {\n self.name\n }\n\n pub fn get_contract_address(self) -> AztecAddress {\n self.target_contract\n }\n}\n"},"71":{"path":"/home/nerses/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.2/noir-projects/aztec-nr/aztec/src/context/public_context.nr","source":"use crate::context::gas::GasOpts;\nuse crate::hash::{\n compute_l1_to_l2_message_hash, compute_l1_to_l2_message_nullifier, compute_secret_hash,\n};\nuse dep::protocol_types::abis::function_selector::FunctionSelector;\nuse dep::protocol_types::address::{AztecAddress, EthAddress};\nuse dep::protocol_types::constants::{MAX_U32_VALUE, NULL_MSG_SENDER_CONTRACT_ADDRESS};\nuse dep::protocol_types::traits::{Empty, FromField, Packable, Serialize, ToField};\n\n/// # PublicContext\n///\n/// The **main interface** between an #[external(\"public\")] function and the Aztec blockchain.\n///\n/// An instance of the PublicContext is initialized automatically at the outset\n/// of every public function, within the #[external(\"public\")] macro, so you'll never\n/// need to consciously instantiate this yourself.\n///\n/// The instance is always named `context`, and it will always be available\n/// within the body of every #[external(\"public\")] function in your smart contract.\n///\n/// Typical usage for a smart contract developer will be to call getter\n/// methods of the PublicContext.\n///\n/// _Pushing_ data and requests to the context is mostly handled within\n/// aztec-nr's own functions, so typically a smart contract developer won't\n/// need to call any setter methods directly.\n///\n/// ## Responsibilities\n/// - Exposes contextual data to a public function:\n/// - Data relating to how this public function was called:\n/// - msg_sender, this_address\n/// - Data relating to the current blockchain state:\n/// - timestamp, block_number, chain_id, version\n/// - Gas and fee information\n/// - Provides state access:\n/// - Read/write public storage (key-value mapping)\n/// - Check existence of notes and nullifiers\n/// (Some patterns use notes & nullifiers to store public (not private)\n/// information)\n/// - Enables consumption of L1->L2 messages.\n/// - Enables calls to other public smart contract functions:\n/// - Writes data to the blockchain:\n/// - Updates to public state variables\n/// - New public logs (for events)\n/// - New L2->L1 messages\n/// - New notes & nullifiers\n/// (E.g. pushing public info to notes/nullifiers, or for completing\n/// \"partial notes\")\n///\n/// ## Key Differences from Private Execution\n///\n/// Unlike private functions -- which are executed on the user's device and which\n/// can only reference historic state -- public functions are executed by a block\n/// proposer and are executed \"live\" on the _current_ tip of the chain.\n/// This means public functions can:\n/// - Read and write _current_ public state\n/// - Immediately see the effects of earlier transactions in the same block\n///\n/// Also, public functions are executed within a zkVM (the \"AVM\"), so that they\n/// can _revert_ whilst still ensuring payment to the proposer and prover.\n/// (Private functions cannot revert: they either succeed, or they cannot be\n/// included).\n///\n/// ## Optimising Public Functions\n///\n/// Using the AVM to execute public functions means they compile down to \"AVM\n/// bytecode\" instead of the ACIR that private functions (standalone circuits)\n/// compile to. Therefore the approach to optimising a public function is\n/// fundamentally different from optimising a public function.\n///\npub struct PublicContext {\n pub args_hash: Option,\n pub compute_args_hash: fn() -> Field,\n}\n\nimpl Eq for PublicContext {\n fn eq(self, other: Self) -> bool {\n (self.args_hash == other.args_hash)\n // Can't compare the function compute_args_hash\n }\n}\n\nimpl PublicContext {\n /// Creates a new PublicContext instance.\n ///\n /// Low-level function: This is called automatically by the #[external(\"public\")]\n /// macro, so you shouldn't need to be called directly by smart contract\n /// developers.\n ///\n /// # Arguments\n /// * `compute_args_hash` - Function to compute the args_hash\n ///\n /// # Returns\n /// * A new PublicContext instance\n ///\n pub fn new(compute_args_hash: fn() -> Field) -> Self {\n PublicContext { args_hash: Option::none(), compute_args_hash }\n }\n\n /// Emits a _public_ log that will be visible onchain to everyone.\n ///\n /// # Arguments\n /// * `log` - The data to log, must implement Serialize trait\n ///\n pub fn emit_public_log(_self: &mut Self, log: T)\n where\n T: Serialize,\n {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe { emit_public_log(Serialize::serialize(log).as_slice()) };\n }\n\n /// Checks if a given note hash exists in the note hash tree at a particular\n /// leaf_index.\n ///\n /// # Arguments\n /// * `note_hash` - The note hash to check for existence\n /// * `leaf_index` - The index where the note hash should be located\n ///\n /// # Returns\n /// * `bool` - True if the note hash exists at the specified index\n ///\n pub fn note_hash_exists(_self: Self, note_hash: Field, leaf_index: u64) -> bool {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe { note_hash_exists(note_hash, leaf_index) } == 1\n }\n\n /// Checks if a specific L1-to-L2 message exists in the L1-to-L2 message\n /// tree at a particular leaf index.\n ///\n /// Common use cases include token bridging, cross-chain governance, and\n /// triggering L2 actions based on L1 events.\n ///\n /// This function should be called before attempting to consume an L1-to-L2\n /// message.\n ///\n /// # Arguments\n /// * `msg_hash` - Hash of the L1-to-L2 message to check\n /// * `msg_leaf_index` - The index where the message should be located\n ///\n /// # Returns\n /// * `bool` - True if the message exists at the specified index\n ///\n /// # Advanced\n /// * Uses the AVM l1_to_l2_msg_exists opcode for tree lookup\n /// * Messages are copied from L1 Inbox to L2 by block proposers\n ///\n pub fn l1_to_l2_msg_exists(_self: Self, msg_hash: Field, msg_leaf_index: Field) -> bool {\n // Safety: AVM opcodes are constrained by the AVM itself\n // TODO(alvaro): Make l1l2msg leaf index a u64 upstream\n unsafe { l1_to_l2_msg_exists(msg_hash, msg_leaf_index as u64) } == 1\n }\n\n /// Checks if a specific nullifier has been emitted by a given contract.\n ///\n /// Whilst nullifiers are primarily intended as a _privacy-preserving_\n /// record of a one-time action, they can also be used to efficiently\n /// record _public_ one-time actions too. An example is to check\n /// whether a contract has been published: we emit a nullifier that is\n /// deterministic, but whose preimage is _not_ private. This is more\n /// efficient than using mutable storage, and can be done directly\n /// from a private function.\n ///\n /// Nullifiers can be tested for non-existence in public, which is not the\n /// case in private. Because private functions do not have access to\n /// the tip of the blockchain (but only the anchor block they are built\n /// at) they can only prove nullifier non-existence in the past. But between\n /// an anchor block and the block in which a tx is included, the nullifier\n /// might have been inserted into the nullifier tree by some other\n /// transaction.\n /// Public functions _do_ have access to the tip of the state, and so\n /// this pattern is safe.\n ///\n /// # Arguments\n /// * `unsiloed_nullifier` - The raw nullifier value (before siloing with\n /// the contract address that emitted it).\n /// * `address` - The claimed contract address that emitted the nullifier\n ///\n /// # Returns\n /// * `bool` - True if the nullifier has been emitted by the specified contract\n ///\n pub fn nullifier_exists(_self: Self, unsiloed_nullifier: Field, address: AztecAddress) -> bool {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe { nullifier_exists(unsiloed_nullifier, address.to_field()) } == 1\n }\n\n /// Consumes a message sent from Ethereum (L1) to Aztec (L2) -- effectively\n /// marking it as \"read\".\n ///\n /// Use this function if you only want the message to ever be \"referred to\"\n /// once. Once consumed using this method, the message cannot be consumed\n /// again, because a nullifier is emitted.\n /// If your use case wants for the message to be read unlimited times, then\n /// you can always read any historic message from the L1-to-L2 messages tree,\n /// using the `l1_to_l2_msg_exists` method. Messages never technically get\n /// deleted from that tree.\n ///\n /// The message will first be inserted into an Aztec \"Inbox\" smart contract\n /// on L1. It will not be available for consumption immediately. Messages\n /// get copied-over from the L1 Inbox to L2 by the next Proposer in batches.\n /// So you will need to wait until the messages are copied before you can\n /// consume them.\n ///\n /// # Arguments\n /// * `content` - The message content that was sent from L1\n /// * `secret` - Secret value used for message privacy (if needed)\n /// * `sender` - Ethereum address that sent the message\n /// * `leaf_index` - Index of the message in the L1-to-L2 message tree\n ///\n /// # Advanced\n /// * Validates message existence in the L1-to-L2 message tree\n /// * Prevents double-consumption by emitting a nullifier\n /// * Message hash is computed from all parameters + chain context\n /// * Will revert if message doesn't exist or was already consumed\n ///\n pub 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_l1_to_l2_message_hash(\n sender,\n self.chain_id(),\n /*recipient=*/\n self.this_address(),\n self.version(),\n content,\n secret_hash,\n leaf_index,\n );\n let nullifier = compute_l1_to_l2_message_nullifier(message_hash, secret);\n\n assert(\n !self.nullifier_exists(nullifier, self.this_address()),\n \"L1-to-L2 message is already nullified\",\n );\n assert(\n self.l1_to_l2_msg_exists(message_hash, leaf_index),\n \"Tried to consume nonexistent L1-to-L2 message\",\n );\n\n self.push_nullifier(nullifier);\n }\n\n /// Sends an \"L2 -> L1 message\" from this function (Aztec, L2) to a smart\n /// contract on Ethereum (L1). L1 contracts which are designed to\n /// send/receive messages to/from Aztec are called \"Portal Contracts\".\n ///\n /// Common use cases include withdrawals, cross-chain asset transfers, and\n /// triggering L1 actions based on L2 state changes.\n ///\n /// The message will be inserted into an Aztec \"Outbox\" contract on L1,\n /// when this transaction's block is proposed to L1.\n /// Sending the message will not result in any immediate state changes in\n /// the target portal contract. The message will need to be manually\n /// consumed from the Outbox through a separate Ethereum transaction: a user\n /// will need to call a function of the portal contract -- a function\n /// specifically designed to make a call to the Outbox to consume the\n /// message.\n /// The message will only be available for consumption once the _epoch_\n /// proof has been submitted. Given that there are multiple Aztec blocks\n /// within an epoch, it might take some time for this epoch proof to be\n /// submitted -- especially if the block was near the start of an epoch.\n ///\n /// # Arguments\n /// * `recipient` - Ethereum address that will receive the message\n /// * `content` - Message content (32 bytes as a Field element)\n ///\n pub fn message_portal(_self: &mut Self, recipient: EthAddress, content: Field) {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe { send_l2_to_l1_msg(recipient, content) };\n }\n\n /// Calls a public function on another contract.\n ///\n /// Will revert if the called function reverts or runs out of gas.\n ///\n /// # Arguments\n /// * `contract_address` - Address of the contract to call\n /// * `function_selector` - Function to call on the target contract\n /// * `args` - Arguments to pass to the function\n /// * `gas_opts` - An optional allocation of gas to the called function.\n ///\n /// # Returns\n /// * `[Field]` - Return data from the called function\n ///\n pub unconstrained fn call_public_function(\n _self: &mut Self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field],\n gas_opts: GasOpts,\n ) -> [Field] {\n let calldata = args.push_front(function_selector.to_field());\n\n call(\n gas_opts.l2_gas.unwrap_or(MAX_U32_VALUE),\n gas_opts.da_gas.unwrap_or(MAX_U32_VALUE),\n contract_address,\n calldata,\n );\n // Use success_copy to determine whether the call succeeded\n let success = success_copy();\n\n let result_data = returndata_copy(0, returndata_size());\n if !success {\n // Rethrow the revert data.\n avm_revert(result_data);\n }\n result_data\n }\n\n /// Makes a read-only call to a public function on another contract.\n ///\n /// This is similar to Solidity's `staticcall`. The called function\n /// cannot modify state or emit events. Any nested calls are constrained to\n /// also be staticcalls.\n ///\n /// Useful for querying data from other contracts safely.\n ///\n /// Will revert if the called function reverts or runs out of gas.\n ///\n /// # Arguments\n /// * `contract_address` - Address of the contract to call\n /// * `function_selector` - Function to call on the target contract\n /// * `args` - Array of arguments to pass to the called function\n /// * `gas_opts` - An optional allocation of gas to the called function.\n ///\n /// # Returns\n /// * `[Field]` - Return data from the called function\n ///\n pub unconstrained fn static_call_public_function(\n _self: &mut Self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field],\n gas_opts: GasOpts,\n ) -> [Field] {\n let calldata = args.push_front(function_selector.to_field());\n\n call_static(\n gas_opts.l2_gas.unwrap_or(MAX_U32_VALUE),\n gas_opts.da_gas.unwrap_or(MAX_U32_VALUE),\n contract_address,\n calldata,\n );\n // Use success_copy to determine whether the call succeeded\n let success = success_copy();\n\n let result_data = returndata_copy(0, returndata_size());\n if !success {\n // Rethrow the revert data.\n avm_revert(result_data);\n }\n result_data\n }\n\n /// Adds a new note hash to the Aztec blockchain's global Note Hash Tree.\n ///\n /// Notes are ordinarily constructed and emitted by _private_ functions, to\n /// ensure that both the content of the note, and the contract that emitted\n /// the note, stay private.\n ///\n /// There are however some useful patterns whereby a note needs to contain\n /// _public_ data. The ability to push a new note_hash from a _public_\n /// function means that notes can be injected with public data immediately\n /// -- as soon as the public value is known. The slower alternative would\n /// be to submit a follow-up transaction so that a private function can\n /// inject the data. Both are possible on Aztec.\n ///\n /// Search \"Partial Note\" for a very common pattern which enables a note\n /// to be \"partially\" populated with some data in a _private_ function, and\n /// then later \"completed\" with some data in a public function.\n ///\n /// # Arguments\n /// * `note_hash` - The hash of the note to add to the tree\n ///\n /// # Advanced\n /// * The note hash will be siloed with the contract address by the protocol\n ///\n pub fn push_note_hash(_self: &mut Self, note_hash: Field) {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe { emit_note_hash(note_hash) };\n }\n\n /// Adds a new nullifier to the Aztec blockchain's global Nullifier Tree.\n ///\n /// Whilst nullifiers are primarily intended as a _privacy-preserving_\n /// record of a one-time action, they can also be used to efficiently\n /// record _public_ one-time actions too. Hence why you're seeing this\n /// function within the PublicContext.\n /// An example is to check whether a contract has been published: we emit\n /// a nullifier that is deterministic, but whose preimage is _not_ private.\n ///\n /// # Arguments\n /// * `nullifier` - A unique field element that represents the consumed\n /// state\n ///\n /// # Advanced\n /// * Nullifier is immediately added to the global nullifier tree\n /// * Emitted nullifiers are immediately visible to all\n /// subsequent transactions in the same block\n /// * Automatically siloed with the contract address by the protocol\n /// * Used for preventing double-spending and ensuring one-time actions\n ///\n pub fn push_nullifier(_self: &mut Self, nullifier: Field) {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe { emit_nullifier(nullifier) };\n }\n\n /// Returns the address of the current contract being executed.\n ///\n /// This is equivalent to `address(this)` in Solidity (hence the name).\n /// Use this to identify the current contract's address, commonly needed for\n /// access control or when interacting with other contracts.\n ///\n /// # Returns\n /// * `AztecAddress` - The contract address of the current function being\n /// executed.\n ///\n pub fn this_address(_self: Self) -> AztecAddress {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n address()\n }\n }\n\n /// Returns the contract address that initiated this function call.\n ///\n /// This is similar to `msg.sender` in Solidity (hence the name).\n ///\n /// Important Note: If the calling function is a _private_ function, then\n /// it had the option of hiding its address when enqueuing this public\n /// function call. In such cases, this `context.msg_sender()` method will\n /// return `Option::none`.\n /// If the calling function is a _public_ function, it will always return\n /// an `Option::some` (i.e. a non-null value).\n ///\n /// # Returns\n /// * `Option` - The address of the smart contract that called\n /// this function (be it an app contract or a user's account contract).\n ///\n /// # Advanced\n /// * Value is provided by the AVM sender opcode\n /// * In nested calls, this is the immediate caller, not the original\n /// transaction sender\n ///\n pub fn msg_sender(_self: Self) -> Option {\n // Safety: AVM opcodes are constrained by the AVM itself\n let maybe_msg_sender = unsafe { sender() };\n if maybe_msg_sender == NULL_MSG_SENDER_CONTRACT_ADDRESS {\n Option::none()\n } else {\n Option::some(maybe_msg_sender)\n }\n }\n\n /// \"Unsafe\" versus calling `context.msg_sender()`, because it doesn't\n /// translate `NULL_MSG_SENDER_CONTRACT_ADDRESS` as\n /// `Option::none`.\n /// Used by some internal aztecnr functions.\n pub fn msg_sender_unsafe(_self: Self) -> AztecAddress {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n sender()\n }\n }\n\n /// Returns the function selector of the currently-executing function.\n ///\n /// This is similar to `msg.sig` in Solidity, returning the first 4\n /// bytes of the function signature.\n ///\n /// # Returns\n /// * `FunctionSelector` - The 4-byte function identifier\n ///\n /// # Advanced\n /// * Extracted from the first element of calldata\n /// * Used internally for function dispatch in the AVM\n ///\n pub fn selector(_self: Self) -> FunctionSelector {\n // The selector is the first element of the calldata when calling a public function through dispatch.\n // Safety: AVM opcodes are constrained by the AVM itself\n let raw_selector: [Field; 1] = unsafe { calldata_copy(0, 1) };\n FunctionSelector::from_field(raw_selector[0])\n }\n\n /// Returns the hash of the arguments passed to the current function.\n ///\n /// Very low-level function: The #[external(\"public\")] macro uses this internally.\n /// Smart contract developers typically won't need to access this\n /// directly as arguments are automatically made available.\n ///\n /// # Returns\n /// * `Field` - Hash of the function arguments\n ///\n pub fn get_args_hash(mut self) -> Field {\n if !self.args_hash.is_some() {\n self.args_hash = Option::some((self.compute_args_hash)());\n }\n\n self.args_hash.unwrap_unchecked()\n }\n\n /// Returns the \"transaction fee\" for the current transaction.\n /// This is the final tx fee that will be deducted from the fee_payer's\n /// \"fee-juice\" balance (in the protocol's Base Rollup circuit).\n ///\n /// # Returns\n /// * `Field` - The actual, final cost of the transaction, taking into account:\n /// the actual gas used during the setup and app-logic phases,\n /// and the fixed amount of gas that's been allocated by the user\n /// for the teardown phase.\n /// I.e. effectiveL2FeePerGas * l2GasUsed + effectiveDAFeePerGas * daGasUsed\n ///\n /// This will return `0` during the \"setup\" and \"app-logic\" phases of\n /// tx execution (because the final tx fee is not known at that time).\n /// This will only return a nonzero value during the \"teardown\" phase of\n /// execution, where the final tx fee can actually be computed.\n ///\n /// Regardless of _when_ this function is called during the teardown phase,\n /// it will always return the same final tx fee value. The teardown phase\n /// does not consume a variable amount of gas: it always consumes a\n /// pre-allocated amount of gas, as specified by the user when they generate\n /// their tx.\n ///\n pub fn transaction_fee(_self: Self) -> Field {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n transaction_fee()\n }\n }\n\n /// Returns the chain ID of the current network.\n ///\n /// This is similar to `block.chainid` in Solidity. Returns the unique\n /// identifier for the blockchain network this transaction is executing on.\n ///\n /// Helps prevent cross-chain replay attacks. Useful if implementing\n /// multi-chain contract logic.\n ///\n /// # Returns\n /// * `Field` - The chain ID as a field element\n ///\n pub fn chain_id(_self: Self) -> Field {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n chain_id()\n }\n }\n\n /// Returns the Aztec protocol version that this transaction is executing\n /// under. Different versions may have different rules, opcodes, or\n /// cryptographic primitives.\n ///\n /// This is similar to how Ethereum has different EVM versions.\n ///\n /// Useful for forward/backward compatibility checks\n ///\n /// Not to be confused with contract versions; this is the protocol version.\n ///\n /// # Returns\n /// * `Field` - The protocol version as a field element\n ///\n pub fn version(_self: Self) -> Field {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n version()\n }\n }\n /// Returns the current block number.\n ///\n /// This is similar to `block.number` in Solidity.\n ///\n /// Note: the current block number is only available within a public function\n /// (as opposed to a private function).\n ///\n /// Note: the time intervals between blocks should not be relied upon as\n /// being consistent:\n /// - Timestamps of blocks fall within a range, rather than at exact regular\n /// intervals.\n /// - Slots can be missed.\n /// - Protocol upgrades can completely change the intervals between blocks\n /// (and indeed the current roadmap plans to reduce the time between\n /// blocks, eventually).\n /// Use `context.timestamp()` for more-reliable time-based logic.\n ///\n /// # Returns\n /// * `u32` - The current block number\n ///\n pub fn block_number(_self: Self) -> u32 {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n block_number()\n }\n }\n\n /// Returns the timestamp of the current block.\n ///\n /// This is similar to `block.timestamp` in Solidity.\n ///\n /// All functions of all transactions in a block share the exact same\n /// timestamp (even though technically each transaction is executed\n /// one-after-the-other).\n ///\n /// Important note: Timestamps of Aztec blocks are not at reliably-fixed\n /// intervals. The proposer of the block has some flexibility to choose a\n /// timestamp which is in a valid _range_: Obviously the timestamp of this\n /// block must be strictly greater than that of the previous block, and must\n /// must be less than the timestamp of whichever ethereum block the aztec\n /// block is proposed to. Furthermore, if the timestamp is not deemed close\n /// enough to the actual current time, the committee of validators will not\n /// attest to the block.\n ///\n /// # Returns\n /// * `u64` - Unix timestamp in seconds\n ///\n pub fn timestamp(_self: Self) -> u64 {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n timestamp()\n }\n }\n\n /// Returns the fee per unit of L2 gas for this transaction (aka the \"L2 gas\n /// price\"), as chosen by the user.\n ///\n /// L2 gas covers the cost of executing public functions and handling\n /// side-effects within the AVM.\n ///\n /// # Returns\n /// * `u128` - Fee per unit of L2 gas\n ///\n /// Wallet developers should be mindful that the choice of gas price (which\n /// is publicly visible) can leak information about the user, e.g.:\n /// - which wallet software the user is using;\n /// - the amount of time which has elapsed from the time the user's wallet\n /// chose a gas price (at the going rate), to the time of tx submission.\n /// This can give clues about the proving time, and hence the nature of\n /// the tx.\n /// - the urgency of the transaction (which is kind of unavoidable, if the\n /// tx is indeed urgent).\n /// - the wealth of the user.\n /// - the exact user (if the gas price is explicitly chosen by the user to\n /// be some unique number like 0.123456789, or their favourite number).\n /// Wallet devs might wish to consider fuzzing the choice of gas price.\n ///\n pub fn base_fee_per_l2_gas(_self: Self) -> u128 {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n base_fee_per_l2_gas()\n }\n }\n\n /// Returns the fee per unit of DA (Data Availability) gas (aka the \"DA gas\n /// price\").\n ///\n /// DA gas covers the cost of making transaction data available on L1.\n ///\n /// See the warning in `fee_pre_l2_gas` for how gas prices can be leaky.\n ///\n /// # Returns\n /// * `u128` - Fee per unit of DA gas\n ///\n pub fn base_fee_per_da_gas(_self: Self) -> u128 {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n base_fee_per_da_gas()\n }\n }\n\n /// Returns the remaining L2 gas available for this transaction.\n ///\n /// Different AVM opcodes consume different amounts of gas.\n ///\n /// # Returns\n /// * `u32` - Remaining L2 gas units\n ///\n pub fn l2_gas_left(_self: Self) -> u32 {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n l2_gas_left()\n }\n }\n\n /// Returns the remaining DA (Data Availability) gas available for this\n /// transaction.\n ///\n /// DA gas is consumed when emitting data that needs to be made available\n /// on L1, such as public logs or state updates.\n /// All of the side-effects from the private part of the tx also consume\n /// DA gas before execution of any public functions even begins.\n ///\n /// # Returns\n /// * `u32` - Remaining DA gas units\n ///\n pub fn da_gas_left(_self: Self) -> u32 {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n da_gas_left()\n }\n }\n\n /// Checks if the current execution is within a staticcall context, where\n /// no state changes or logs are allowed to be emitted (by this function\n /// or any nested function calls).\n ///\n /// # Returns\n /// * `bool` - True if in staticcall context, false otherwise\n ///\n pub fn is_static_call(_self: Self) -> bool {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe { is_static_call() } == 1\n }\n\n /// Reads raw field values from public storage.\n /// Reads N consecutive storage slots starting from the given slot.\n ///\n /// Very low-level function. Users should typically use the public state\n /// variable abstractions to perform reads: PublicMutable & PublicImmutable.\n ///\n /// # Arguments\n /// * `storage_slot` - The starting storage slot to read from\n ///\n /// # Returns\n /// * `[Field; N]` - Array of N field values from consecutive storage slots\n ///\n /// # Generic Parameters\n /// * `N` - the number of consecutive slots to return, starting from the\n /// `storage_slot`.\n ///\n pub fn raw_storage_read(_self: Self, storage_slot: Field) -> [Field; N] {\n let mut out = [0; N];\n for i in 0..N {\n // Safety: AVM opcodes are constrained by the AVM itself\n out[i] = unsafe { storage_read(storage_slot + i as Field) };\n }\n out\n }\n\n /// Reads a typed value from public storage.\n ///\n /// Low-level function. Users should typically use the public state\n /// variable abstractions to perform reads: PublicMutable & PublicImmutable.\n ///\n /// # Arguments\n /// * `storage_slot` - The storage slot to read from\n ///\n /// # Returns\n /// * `T` - The deserialized value from storage\n ///\n /// # Generic Parameters\n /// * `T` - The type that the caller expects to read from the `storage_slot`.\n ///\n pub fn storage_read(self, storage_slot: Field) -> T\n where\n T: Packable,\n {\n T::unpack(self.raw_storage_read(storage_slot))\n }\n\n /// Writes raw field values to public storage.\n /// Writes to N consecutive storage slots starting from the given slot.\n ///\n /// Very low-level function. Users should typically use the public state\n /// variable abstractions to perform writes: PublicMutable & PublicImmutable.\n ///\n /// Public storage writes take effect immediately.\n ///\n /// # Arguments\n /// * `storage_slot` - The starting storage slot to write to\n /// * `values` - Array of N Fields to write to storage\n ///\n pub fn raw_storage_write(_self: Self, storage_slot: Field, values: [Field; N]) {\n for i in 0..N {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe { storage_write(storage_slot + i as Field, values[i]) };\n }\n }\n\n /// Writes a typed value to public storage.\n ///\n /// Low-level function. Users should typically use the public state\n /// variable abstractions to perform writes: PublicMutable & PublicImmutable.\n ///\n /// # Arguments\n /// * `storage_slot` - The storage slot to write to\n /// * `value` - The typed value to write to storage\n ///\n /// # Generic Parameters\n /// * `T` - The type to write to storage.\n ///\n pub fn storage_write(self, storage_slot: Field, value: T)\n where\n T: Packable,\n {\n self.raw_storage_write(storage_slot, value.pack());\n }\n}\n\n// TODO: consider putting this oracle code in its own file.\n// Unconstrained opcode wrappers (do not use directly).\nunconstrained fn address() -> AztecAddress {\n address_opcode()\n}\nunconstrained fn sender() -> AztecAddress {\n sender_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() -> u32 {\n block_number_opcode()\n}\nunconstrained fn timestamp() -> u64 {\n timestamp_opcode()\n}\nunconstrained fn base_fee_per_l2_gas() -> u128 {\n base_fee_per_l2_gas_opcode()\n}\nunconstrained fn base_fee_per_da_gas() -> u128 {\n base_fee_per_da_gas_opcode()\n}\nunconstrained fn l2_gas_left() -> u32 {\n l2_gas_left_opcode()\n}\nunconstrained fn da_gas_left() -> u32 {\n da_gas_left_opcode()\n}\nunconstrained fn is_static_call() -> u1 {\n is_static_call_opcode()\n}\nunconstrained fn note_hash_exists(note_hash: Field, leaf_index: u64) -> u1 {\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) -> u1 {\n nullifier_exists_opcode(nullifier, address)\n}\nunconstrained fn emit_nullifier(nullifier: Field) {\n emit_nullifier_opcode(nullifier)\n}\nunconstrained fn emit_public_log(message: [Field]) {\n emit_public_log_opcode(message)\n}\nunconstrained fn l1_to_l2_msg_exists(msg_hash: Field, msg_leaf_index: u64) -> u1 {\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}\n\nunconstrained fn call(\n l2_gas_allocation: u32,\n da_gas_allocation: u32,\n address: AztecAddress,\n args: [Field],\n) {\n call_opcode(l2_gas_allocation, da_gas_allocation, address, args)\n}\n\nunconstrained fn call_static(\n l2_gas_allocation: u32,\n da_gas_allocation: u32,\n address: AztecAddress,\n args: [Field],\n) {\n call_static_opcode(l2_gas_allocation, da_gas_allocation, address, args)\n}\n\npub unconstrained fn calldata_copy(cdoffset: u32, copy_size: u32) -> [Field; N] {\n calldata_copy_opcode(cdoffset, copy_size)\n}\n\n// `success_copy` is placed immediately after the CALL opcode to get the success value\nunconstrained fn success_copy() -> bool {\n success_copy_opcode()\n}\n\nunconstrained fn returndata_size() -> u32 {\n returndata_size_opcode()\n}\n\nunconstrained fn returndata_copy(rdoffset: u32, copy_size: u32) -> [Field] {\n returndata_copy_opcode(rdoffset, copy_size)\n}\n\npub unconstrained fn avm_return(returndata: [Field]) {\n return_opcode(returndata)\n}\n\n// This opcode reverts using the exact data given. In general it should only be used\n// to do rethrows, where the revert data is the same as the original revert data.\n// For normal reverts, use Noir's `assert` which, on top of reverting, will also add\n// an error selector to the revert data.\nunconstrained fn avm_revert(revertdata: [Field]) {\n revert_opcode(revertdata)\n}\n\nunconstrained fn storage_read(storage_slot: Field) -> Field {\n storage_read_opcode(storage_slot)\n}\n\nunconstrained fn storage_write(storage_slot: Field, value: Field) {\n storage_write_opcode(storage_slot, value);\n}\n\nimpl Empty for PublicContext {\n fn empty() -> Self {\n PublicContext::new(|| 0)\n }\n}\n\n// TODO: consider putting this oracle code in its own file.\n// AVM oracles (opcodes) follow, do not use directly.\n#[oracle(avmOpcodeAddress)]\nunconstrained fn address_opcode() -> AztecAddress {}\n\n#[oracle(avmOpcodeSender)]\nunconstrained fn sender_opcode() -> AztecAddress {}\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() -> u32 {}\n\n#[oracle(avmOpcodeTimestamp)]\nunconstrained fn timestamp_opcode() -> u64 {}\n\n#[oracle(avmOpcodeBaseFeePerL2Gas)]\nunconstrained fn base_fee_per_l2_gas_opcode() -> u128 {}\n\n#[oracle(avmOpcodeBaseFeePerDaGas)]\nunconstrained fn base_fee_per_da_gas_opcode() -> u128 {}\n\n#[oracle(avmOpcodeL2GasLeft)]\nunconstrained fn l2_gas_left_opcode() -> u32 {}\n\n#[oracle(avmOpcodeDaGasLeft)]\nunconstrained fn da_gas_left_opcode() -> u32 {}\n\n#[oracle(avmOpcodeIsStaticCall)]\nunconstrained fn is_static_call_opcode() -> u1 {}\n\n#[oracle(avmOpcodeNoteHashExists)]\nunconstrained fn note_hash_exists_opcode(note_hash: Field, leaf_index: u64) -> u1 {}\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) -> u1 {}\n\n#[oracle(avmOpcodeEmitNullifier)]\nunconstrained fn emit_nullifier_opcode(nullifier: Field) {}\n\n// TODO(#11124): rename unencrypted to public in avm\n#[oracle(avmOpcodeEmitUnencryptedLog)]\nunconstrained fn emit_public_log_opcode(message: [Field]) {}\n\n#[oracle(avmOpcodeL1ToL2MsgExists)]\nunconstrained fn l1_to_l2_msg_exists_opcode(msg_hash: Field, msg_leaf_index: u64) -> u1 {}\n\n#[oracle(avmOpcodeSendL2ToL1Msg)]\nunconstrained fn send_l2_to_l1_msg_opcode(recipient: EthAddress, content: Field) {}\n\n#[oracle(avmOpcodeCalldataCopy)]\nunconstrained fn calldata_copy_opcode(cdoffset: u32, copy_size: u32) -> [Field; N] {}\n\n#[oracle(avmOpcodeReturndataSize)]\nunconstrained fn returndata_size_opcode() -> u32 {}\n\n#[oracle(avmOpcodeReturndataCopy)]\nunconstrained fn returndata_copy_opcode(rdoffset: u32, copy_size: u32) -> [Field] {}\n\n#[oracle(avmOpcodeReturn)]\nunconstrained fn return_opcode(returndata: [Field]) {}\n\n// This opcode reverts using the exact data given. In general it should only be used\n// to do rethrows, where the revert data is the same as the original revert data.\n// For normal reverts, use Noir's `assert` which, on top of reverting, will also add\n// an error selector to the revert data.\n#[oracle(avmOpcodeRevert)]\nunconstrained fn revert_opcode(revertdata: [Field]) {}\n\n#[oracle(avmOpcodeCall)]\nunconstrained fn call_opcode(\n l2_gas_allocation: u32,\n da_gas_allocation: u32,\n address: AztecAddress,\n args: [Field],\n) {}\n\n#[oracle(avmOpcodeStaticCall)]\nunconstrained fn call_static_opcode(\n l2_gas_allocation: u32,\n da_gas_allocation: u32,\n address: AztecAddress,\n args: [Field],\n) {}\n\n#[oracle(avmOpcodeSuccessCopy)]\nunconstrained fn success_copy_opcode() -> bool {}\n\n#[oracle(avmOpcodeStorageRead)]\nunconstrained fn storage_read_opcode(storage_slot: Field) -> Field {}\n\n#[oracle(avmOpcodeStorageWrite)]\nunconstrained fn storage_write_opcode(storage_slot: Field, value: Field) {}\n"},"73":{"path":"/home/nerses/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.2/noir-projects/aztec-nr/aztec/src/context/utility_context.nr","source":"use crate::oracle::{execution::get_utility_context, storage::storage_read};\nuse protocol_types::{address::AztecAddress, traits::Packable};\n\n// If you'll modify this struct don't forget to update utility_context.ts as well.\npub struct UtilityContext {\n block_number: u32,\n timestamp: u64,\n contract_address: AztecAddress,\n version: Field,\n chain_id: Field,\n}\n\nimpl UtilityContext {\n pub unconstrained fn new() -> Self {\n get_utility_context()\n }\n\n pub unconstrained fn at(contract_address: AztecAddress) -> Self {\n // We get a context with default contract address, and then we construct the final context with the provided\n // contract address.\n let default_context = get_utility_context();\n\n Self {\n block_number: default_context.block_number,\n timestamp: default_context.timestamp,\n contract_address,\n version: default_context.version,\n chain_id: default_context.chain_id,\n }\n }\n\n pub unconstrained fn at_historical(contract_address: AztecAddress, block_number: u32) -> Self {\n // We get a context with default contract address and block number, and then we construct the final context\n // with the provided contract address and block number.\n let default_context = get_utility_context();\n\n Self {\n block_number,\n timestamp: default_context.timestamp,\n contract_address,\n version: default_context.version,\n chain_id: default_context.chain_id,\n }\n }\n\n pub fn block_number(self) -> u32 {\n self.block_number\n }\n\n pub fn timestamp(self) -> u64 {\n self.timestamp\n }\n\n pub fn this_address(self) -> AztecAddress {\n self.contract_address\n }\n\n pub fn version(self) -> Field {\n self.version\n }\n\n pub fn chain_id(self) -> Field {\n self.chain_id\n }\n\n pub unconstrained fn raw_storage_read(\n self: Self,\n storage_slot: Field,\n ) -> [Field; N] {\n storage_read(self.this_address(), storage_slot, self.block_number())\n }\n\n pub unconstrained fn storage_read(self, storage_slot: Field) -> T\n where\n T: Packable,\n {\n T::unpack(self.raw_storage_read(storage_slot))\n }\n}\n"},"76":{"path":"/home/nerses/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.2/noir-projects/aztec-nr/aztec/src/event/event_selector.nr","source":"use dep::protocol_types::{\n hash::poseidon2_hash_bytes,\n traits::{Deserialize, Empty, FromField, Serialize, ToField},\n};\n\n#[derive(Deserialize, Eq, Serialize)]\npub struct EventSelector {\n // 1st 4-bytes (big-endian leftmost) of abi-encoding of an event.\n inner: u32,\n}\n\nimpl FromField for EventSelector {\n fn from_field(field: Field) -> Self {\n Self { inner: field as u32 }\n }\n}\n\nimpl ToField for EventSelector {\n fn to_field(self) -> Field {\n self.inner as Field\n }\n}\n\nimpl Empty for EventSelector {\n fn empty() -> Self {\n Self { inner: 0 as u32 }\n }\n}\n\nimpl EventSelector {\n pub fn from_u32(value: u32) -> Self {\n Self { inner: value }\n }\n\n pub fn from_signature(signature: str) -> Self {\n let bytes = signature.as_bytes();\n let hash = poseidon2_hash_bytes(bytes);\n\n // `hash` is automatically truncated to fit within 32 bits.\n EventSelector::from_field(hash)\n }\n\n pub fn zero() -> Self {\n Self { inner: 0 }\n }\n}\n"},"95":{"path":"/home/nerses/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.2/noir-projects/aztec-nr/aztec/src/keys/getters/mod.nr","source":"use crate::{\n keys::constants::{NULLIFIER_INDEX, OUTGOING_INDEX},\n oracle::{\n key_validation_request::get_key_validation_request,\n keys::get_public_keys_and_partial_address,\n },\n};\nuse dep::protocol_types::{address::AztecAddress, public_keys::PublicKeys};\n\npub unconstrained fn get_nsk_app(npk_m_hash: Field) -> Field {\n get_key_validation_request(npk_m_hash, NULLIFIER_INDEX).sk_app\n}\n\n// A helper function that gets app-siloed outgoing viewing key for a given `ovpk_m_hash`. This function is used\n// in unconstrained contexts only - when computing unconstrained note logs. The safe alternative is `request_ovsk_app`\n// function defined on `PrivateContext`.\npub unconstrained fn get_ovsk_app(ovpk_m_hash: Field) -> Field {\n get_key_validation_request(ovpk_m_hash, OUTGOING_INDEX).sk_app\n}\n\n// Returns all public keys for a given account, applying proper constraints to the context. We read all\n// keys at once since the constraints for reading them all are actually fewer than if we read them one at a time - any\n// read keys that are not required by the caller can simply be discarded.\npub fn get_public_keys(account: AztecAddress) -> PublicKeys {\n // Safety: Public keys are constrained by showing their inclusion in the address's preimage.\n let (public_keys, partial_address) = unsafe { get_public_keys_and_partial_address(account) };\n assert_eq(\n account,\n AztecAddress::compute(public_keys, partial_address),\n \"Invalid public keys hint for address\",\n );\n\n public_keys\n}\n\nmod test {\n use super::get_public_keys;\n\n use crate::test::helpers::test_environment::TestEnvironment;\n use protocol_types::traits::Serialize;\n use std::test::OracleMock;\n\n global KEY_ORACLE_RESPONSE_LENGTH: u32 = 13; // 12 fields for the keys, one field for the partial address\n\n #[test(should_fail_with = \"Invalid public keys hint for address\")]\n unconstrained fn get_public_keys_fails_with_bad_hint() {\n let mut env = TestEnvironment::new();\n let account = env.create_light_account();\n\n // Instead of querying for some unknown account, which would result in the oracle erroring out, we mock a bad oracle\n // response to check that the circuit properly checks the address derivation.\n let mut random_keys_and_partial_address = [0; KEY_ORACLE_RESPONSE_LENGTH];\n // We use randomly generated points on the curve, and a random partial address to ensure that\n // this combination does not derive the address and we should see the assertion fail.\n // npk_m\n random_keys_and_partial_address[0] =\n 0x292364b852c6c6f01472951e76a39cbcf074591fd0e063a81965e7b51ad868a5;\n random_keys_and_partial_address[1] =\n 0x0a687b46cdc9238f1c311f126aaaa4acbd7a737bff2efd7aeabdb8d805843a27;\n random_keys_and_partial_address[2] =\n 0x0000000000000000000000000000000000000000000000000000000000000000;\n // ivpk_m\n random_keys_and_partial_address[3] =\n 0x173c5229a00c5425255680dd6edc27e278c48883991f348fe6985de43b4ec25f;\n random_keys_and_partial_address[4] =\n 0x1698608e23b5f6c2f43c49a559108bb64e2247b8fc2da842296a416817f40b7f;\n random_keys_and_partial_address[5] =\n 0x0000000000000000000000000000000000000000000000000000000000000000;\n // ovpk_m\n random_keys_and_partial_address[6] =\n 0x1bad2f7d1ad960a1bd0fe4d2c8d17f5ab4a86ef8b103e0a9e7f67ec0d3b4795e;\n random_keys_and_partial_address[7] =\n 0x206db87110abbecc9fbaef2c865189d94ef2c106202f734ee4eba9257fd28bf1;\n random_keys_and_partial_address[8] =\n 0x0000000000000000000000000000000000000000000000000000000000000000;\n // tpk_m\n random_keys_and_partial_address[9] =\n 0x05e3bd9cfe6b47daa139613619cf7d7fd8bb0112b6f2908caa6d9b536ed948ed;\n random_keys_and_partial_address[10] =\n 0x051066f877c9df47552d02e7dc32127ff4edefc8498e813bca1cbd3f5d1be429;\n random_keys_and_partial_address[11] =\n 0x0000000000000000000000000000000000000000000000000000000000000000;\n // partial address\n random_keys_and_partial_address[12] =\n 0x236703e2cb00a182e024e98e9f759231b556d25ff19f98896cebb69e9e678cc9;\n\n let _ = OracleMock::mock(\"utilityGetPublicKeysAndPartialAddress\").returns(\n random_keys_and_partial_address.serialize(),\n );\n let _ = get_public_keys(account);\n }\n}\n"},"99":{"path":"/home/nerses/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.2/noir-projects/aztec-nr/aztec/src/macros/aztec.nr","source":"use crate::macros::{\n dispatch::generate_public_dispatch,\n functions::{stub_registry, utils::check_each_fn_macroified},\n notes::NOTES,\n storage::STORAGE_LAYOUT_NAME,\n utils::{get_trait_impl_method, module_has_storage},\n};\n\n/// Marks a contract as an Aztec contract, generating the interfaces for its functions and notes, as well as injecting\n/// the `sync_private_state` utility function.\n/// Note: This is a module annotation, so the returned quote gets injected inside the module (contract) itself.\npub comptime fn aztec(m: Module) -> Quoted {\n let interface = generate_contract_interface(m);\n\n // Functions that don't have #[external(...)], #[contract_library_method], or #[test] are not allowed in contracts.\n check_each_fn_macroified(m);\n\n // We generate `_compute_note_hash_and_nullifier`, `sync_private_state` and `process_message`\n // functions only if they are not already implemented. If they are implemented we just insert empty\n // quotes.\n let contract_library_method_compute_note_hash_and_nullifier = if !m.functions().any(|f| {\n f.name() == quote { _compute_note_hash_and_nullifier }\n }) {\n generate_contract_library_method_compute_note_hash_and_nullifier()\n } else {\n quote {}\n };\n let sync_private_state = if !m.functions().any(|f| f.name() == quote { sync_private_state }) {\n generate_sync_private_state()\n } else {\n quote {}\n };\n let process_message = if !m.functions().any(|f| f.name() == quote { process_message }) {\n generate_process_message()\n } else {\n quote {}\n };\n let public_dispatch = generate_public_dispatch(m);\n\n quote {\n $interface\n $contract_library_method_compute_note_hash_and_nullifier\n $public_dispatch\n $sync_private_state\n $process_message\n }\n}\n\ncomptime fn generate_contract_interface(m: Module) -> Quoted {\n let module_name = m.name();\n let contract_stubs = stub_registry::get(m);\n let fn_stubs_quote = if contract_stubs.is_some() {\n contract_stubs.unwrap().join(quote {})\n } else {\n quote {}\n };\n\n let has_storage_layout = module_has_storage(m) & STORAGE_LAYOUT_NAME.get(m).is_some();\n let storage_layout_getter = if has_storage_layout {\n let storage_layout_name = STORAGE_LAYOUT_NAME.get(m).unwrap();\n quote {\n pub fn storage_layout() -> StorageLayoutFields {\n $storage_layout_name.fields\n }\n }\n } else {\n quote {}\n };\n\n let library_storage_layout_getter = if has_storage_layout {\n quote {\n #[contract_library_method]\n $storage_layout_getter\n }\n } else {\n quote {}\n };\n\n quote {\n pub struct $module_name {\n pub target_contract: dep::aztec::protocol_types::address::AztecAddress\n }\n\n impl $module_name {\n $fn_stubs_quote\n\n pub fn at(\n addr: aztec::protocol_types::address::AztecAddress\n ) -> Self {\n Self { target_contract: addr }\n }\n\n pub fn interface() -> Self {\n Self { target_contract: aztec::protocol_types::address::AztecAddress::zero() }\n }\n\n $storage_layout_getter\n }\n\n #[contract_library_method]\n pub fn at(\n addr: aztec::protocol_types::address::AztecAddress\n ) -> $module_name {\n $module_name { target_contract: addr }\n }\n\n #[contract_library_method]\n pub fn interface() -> $module_name {\n $module_name { target_contract: aztec::protocol_types::address::AztecAddress::zero() }\n }\n\n $library_storage_layout_getter\n\n }\n}\n\n/// Generates a contract library method called `_compute_note_hash_and_nullifier` which is used for note\n/// discovery (to create the `aztec::messages::discovery::ComputeNoteHashAndNullifier` function) and to implement the\n/// `compute_note_hash_and_nullifier` unconstrained contract function.\ncomptime fn generate_contract_library_method_compute_note_hash_and_nullifier() -> Quoted {\n if NOTES.len() > 0 {\n // Contracts that do define notes produce an if-else chain where `note_type_id` is matched against the\n // `get_note_type_id()` function of each note type that we know of, in order to identify the note type. Once we\n // know it we call we correct `unpack` method from the `Packable` trait to obtain the underlying note type, and\n // compute the note hash (non-siloed) and inner nullifier (also non-siloed).\n\n let mut if_note_type_id_match_statements_list = &[];\n for i in 0..NOTES.len() {\n let typ = NOTES.get(i);\n\n let get_note_type_id = get_trait_impl_method(\n typ,\n quote { crate::note::note_interface::NoteType },\n quote { get_id },\n );\n let unpack = get_trait_impl_method(\n typ,\n quote { crate::protocol_types::traits::Packable },\n quote { unpack },\n );\n\n let compute_note_hash = get_trait_impl_method(\n typ,\n quote { crate::note::note_interface::NoteHash },\n quote { compute_note_hash },\n );\n\n let compute_nullifier_unconstrained = get_trait_impl_method(\n typ,\n quote { crate::note::note_interface::NoteHash },\n quote { compute_nullifier_unconstrained },\n );\n\n let if_or_else_if = if i == 0 {\n quote { if }\n } else {\n quote { else if }\n };\n\n if_note_type_id_match_statements_list = if_note_type_id_match_statements_list.push_back(\n quote {\n $if_or_else_if note_type_id == $get_note_type_id() {\n // As an extra safety check we make sure that the packed_note BoundedVec has the expected\n // length, since we're about to interpret its raw storage as a fixed-size array by calling the\n // unpack function on it.\n let expected_len = <$typ as $crate::protocol_types::traits::Packable>::N;\n let actual_len = packed_note.len();\n assert(\n actual_len == expected_len,\n f\"Expected packed note of length {expected_len} but got {actual_len} for note type id {note_type_id}\"\n );\n\n let note = $unpack(aztec::utils::array::subarray(packed_note.storage(), 0));\n\n let note_hash = $compute_note_hash(note, storage_slot);\n \n // The message discovery process finds settled notes, that is, notes that were created in prior\n // transactions and are therefore already part of the note hash tree. We therefore compute the\n // nullification note hash by treating the note as a settled note with the provided note nonce.\n let note_hash_for_nullification = aztec::note::utils::compute_note_hash_for_nullification(\n aztec::note::retrieved_note::RetrievedNote{ \n note, \n contract_address, \n metadata: aztec::note::note_metadata::SettledNoteMetadata::new(note_nonce).into()\n }, \n storage_slot,\n );\n\n let inner_nullifier = $compute_nullifier_unconstrained(note, note_hash_for_nullification);\n\n Option::some(\n aztec::messages::discovery::NoteHashAndNullifier {\n note_hash, inner_nullifier\n }\n )\n }\n },\n );\n }\n\n let if_note_type_id_match_statements = if_note_type_id_match_statements_list.join(quote {});\n\n quote {\n /// Unpacks an array into a note corresponding to `note_type_id` and then computes its note hash\n /// (non-siloed) and inner nullifier (non-siloed) assuming the note has been inserted into the note hash\n /// tree with `note_nonce`.\n ///\n /// The signature of this function notably matches the `aztec::messages::discovery::ComputeNoteHashAndNullifier` type,\n /// and so it can be used to call functions from that module such as `discover_new_messages`, \n /// `do_process_message` and `attempt_note_discovery`.\n ///\n /// This function is automatically injected by the `#[aztec]` macro.\n #[contract_library_method]\n unconstrained fn _compute_note_hash_and_nullifier(\n packed_note: BoundedVec,\n storage_slot: Field,\n note_type_id: Field,\n contract_address: aztec::protocol_types::address::AztecAddress,\n note_nonce: Field,\n ) -> Option {\n $if_note_type_id_match_statements\n else {\n Option::none()\n }\n }\n }\n } else {\n // Contracts with no notes still implement this function to avoid having special-casing, the implementation\n // simply throws immediately.\n quote {\n /// This contract does not use private notes, so this function should never be called as it will\n /// unconditionally fail.\n ///\n /// This function is automatically injected by the `#[aztec]` macro.\n #[contract_library_method]\n unconstrained fn _compute_note_hash_and_nullifier(\n _packed_note: BoundedVec,\n _storage_slot: Field,\n _note_type_id: Field,\n _contract_address: aztec::protocol_types::address::AztecAddress,\n _nonce: Field,\n ) -> Option {\n panic(f\"This contract does not use private notes\")\n }\n }\n }\n}\n\ncomptime fn generate_sync_private_state() -> Quoted {\n // We obtain the `external` function on the next line instead of directly doing\n // `#[aztec::macros::functions::external(\"utility\")]` in the returned quote because the latter would result in\n // the function attribute having the full path in the ABI. This is undesirable because we use the information in\n // the ABI only to determine whether a function is `external(\"private\")`, `external(\"public\")`, or `external(\"utility\")`.\n let external = crate::macros::functions::external;\n\n // All we need to do here is trigger message discovery, but this is already done by the #[external(\"utility\")] macro - we don't\n // need to do anything extra.\n quote {\n #[$external(\"utility\")]\n unconstrained fn sync_private_state() {\n }\n }\n}\n\ncomptime fn generate_process_message() -> Quoted {\n // We obtain the `external` function on the next line instead of directly doing\n // `#[aztec::macros::functions::external(\"utility\")]` in the returned quote because the latter would result in\n // the function attribute having the full path in the ABI. This is undesirable because we use the information in\n // the ABI only to determine whether a function is `external(\"private\")`, `external(\"public\")`, or `external(\"utility\")`.\n let external = crate::macros::functions::external;\n\n quote {\n #[$external(\"utility\")]\n unconstrained fn process_message(\n message_ciphertext: BoundedVec,\n message_context: aztec::messages::processing::message_context::MessageContext,\n ) {\n aztec::messages::discovery::process_message::process_message_ciphertext(\n context.this_address(),\n _compute_note_hash_and_nullifier,\n message_ciphertext,\n message_context,\n );\n }\n }\n}\n"}}} \ No newline at end of file +{ + "transpiled": true, + "noir_version": "1.0.0-beta.15+1a930357477fc0c210dc5a8960680282d4cfa24e", + "name": "Train", + "functions": [ + { + "name": "constructor", + "is_unconstrained": true, + "custom_attributes": [ + "abi_public", + "abi_initializer" + ], + "abi": { + "parameters": [], + "return_type": null, + "error_types": { + "9967937311635654895": { + "error_kind": "string", + "string": "Initialization hash does not match" + }, + "14415304921900233953": { + "error_kind": "string", + "string": "Initializer address is not the contract deployer" + }, + "14990209321349310352": { + "error_kind": "string", + "string": "attempt to add with overflow" + }, + "15764276373176857197": { + "error_kind": "string", + "string": "Stack too deep" + }, + "16431471497789672479": { + "error_kind": "string", + "string": "Index out of bounds" + } + } + }, + "bytecode": "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", + "debug_symbols": "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" + }, + { + "name": "get_htlc", + "is_unconstrained": true, + "custom_attributes": [ + "abi_public", + "abi_view" + ], + "abi": { + "parameters": [ + { + "name": "swap_id", + "type": { + "kind": "field" + }, + "visibility": "private" + }, + { + "name": "htlc_id", + "type": { + "kind": "field" + }, + "visibility": "private" + } + ], + "return_type": { + "abi_type": { + "kind": "struct", + "path": "Train::HTLC_Public", + "fields": [ + { + "name": "amount", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 128 + } + }, + { + "name": "token", + "type": { + "kind": "struct", + "path": "aztec::protocol_types::address::aztec_address::AztecAddress", + "fields": [ + { + "name": "inner", + "type": { + "kind": "field" + } + } + ] + } + }, + { + "name": "hashlock_high", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 128 + } + }, + { + "name": "hashlock_low", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 128 + } + }, + { + "name": "secret_high", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 128 + } + }, + { + "name": "secret_low", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 128 + } + }, + { + "name": "sender", + "type": { + "kind": "struct", + "path": "aztec::protocol_types::address::aztec_address::AztecAddress", + "fields": [ + { + "name": "inner", + "type": { + "kind": "field" + } + } + ] + } + }, + { + "name": "src_receiver", + "type": { + "kind": "struct", + "path": "aztec::protocol_types::address::aztec_address::AztecAddress", + "fields": [ + { + "name": "inner", + "type": { + "kind": "field" + } + } + ] + } + }, + { + "name": "timelock", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 64 + } + }, + { + "name": "claimed", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 8 + } + }, + { + "name": "reward", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 128 + } + }, + { + "name": "reward_timelock", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 64 + } + } + ] + }, + "visibility": "public" + }, + "error_types": { + "459713770342432051": { + "error_kind": "string", + "string": "Not initialized" + }, + "2718955667607728260": { + "error_kind": "string", + "string": "Function get_htlc can only be called statically" + }, + "13455385521185560676": { + "error_kind": "string", + "string": "Storage slot 0 not allowed. Storage slots must start from 1." + }, + "15764276373176857197": { + "error_kind": "string", + "string": "Stack too deep" + } + } + }, + "bytecode": "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", + "debug_symbols": "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" + }, + { + "name": "get_user_swaps_count", + "is_unconstrained": true, + "custom_attributes": [ + "abi_public", + "abi_view" + ], + "abi": { + "parameters": [ + { + "name": "user", + "type": { + "kind": "struct", + "path": "aztec::protocol_types::address::aztec_address::AztecAddress", + "fields": [ + { + "name": "inner", + "type": { + "kind": "field" + } + } + ] + }, + "visibility": "private" + } + ], + "return_type": { + "abi_type": { + "kind": "field" + }, + "visibility": "public" + }, + "error_types": { + "459713770342432051": { + "error_kind": "string", + "string": "Not initialized" + }, + "3781809441605198943": { + "error_kind": "string", + "string": "Function get_user_swaps_count can only be called statically" + }, + "13455385521185560676": { + "error_kind": "string", + "string": "Storage slot 0 not allowed. Storage slots must start from 1." + }, + "15764276373176857197": { + "error_kind": "string", + "string": "Stack too deep" + } + } + }, + "bytecode": "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", + "debug_symbols": "tZldbhs7DIX34mc/SJRISdlKURRu6hYGDCdwkwtcFNl7yRkejR1ghNRJXuLPdOYM/0Rp7D+bH/vvz7++HU4/H35v7r782Xw/H47Hw69vx4f73dPh4aTWP5tgf6r+TdtN5c1d2W6avotRX/VtzNtNDGYoBlWhKsTkQBEgmzvSi2JSC5FBc8hZoRk0B06A6iCwCCwFllIcagSIg3k6AwP0FilsN0QBkAH4KMGSYMmw5OrABCgOEgHiUHCLwgALULNBNQGqQyOAzJBCBDDAL08xA2ChBCgOiQCwiEVBBtXBcjgDLBWWCos5NoPMkM2xGdghBoDdIhlUByKAOEzJZAWxj8RAHKaMTZAB1WFybAJLuIaTWwTIDBwiAJYIS4SFYLFEJW0JtoacQRwyLJkdOADUsRwMqoNFMYM4WLlzNGgO5vwMetOsiWLLqoHY2pmBHcgTLpOHBikCvASSYcleAuEA8BIIewlECOAlkOolKMFLUIKXoMQAyAAvQaEE8BKUFAGe3pJhybAwLAyLwCJeglIiwEtQKizVS1BaAHgJSvMS1EAAL0GNlsxsYCXQSKst8wlsXcxQHCx1WcdXtXWR1bFaCCAONgFnyIDm0DQtbDdtZYZm/swAS4QlwkKwECzJmkQMioMlcwYG6E15Gr0ZoD6z1rTZhJwBFnN+Aksmq6tt6jqb4LZk8jSxQ+iUO5mCTctAHn8MVmqnbst6rYSJGMTdZi5KnKjhCnPSqYJKt9kkn6lSp25r3QOb5k5QVrdAEddOe461uW5HoVPuVEFZrxDbiaJ49ysxqHSbTSVJEzVQ7TabmGLbYWwJV1hLTERYaUrdNk2nmQRE3UbcqYFS6tRVcr9WECVJ7oQoyZraSTxeahnXNtwjhdypemzJ9nOnbrMOnuKd9pz5ihQ7wauUuy0josSh02LrHkjq1JVLV5kOI/Lyst3goPLt6bzf2znl4uSi55nH3Xl/etrcnZ6Px+3mv93xefqn34+70/T6tDvrp9qr+9MPfVXBn4fj3uhlu1wd1i+lVJtfTTm0LqDdcyUR1yWizqzqGsqldJESrzRoXSMRM7uGsl64ojEKpUa4oUeRuBpKHkjkyKGnQ5fN4ka+0uAPSId8bjr0tFJcIicuq+mog1DI2nWOhFgWCW2US4n2AdmI4QPSMYpFBwD8SCmtxhLpI4JJnxyMTsJemLZemDjo01J7LKVRXg1l1KZ6HoeGcntvKKqxGsqoPTSJ8IJbXZ9hgz4lPbv0ld9SltUhNnJEn1i6JynlfMOyvQxGT9arwYRRqwu1nlORpSxM17EM2lSfMuAH04WEngyuNQbjNDLGh54duoJ6dK0watKyNKmeiBeNVK81Rl3KaLAcl7JSvu4vKoPmiA250Ifutq5RR/lESTiF2xQa5rlcZOKf4qBls08XFXmtkUa7PRPWSeRcbtSQ3p9c220a+lVC73Gq6xqD/iwZnVGy3KTQMka5PsXcpKAPKH3+BVmvaxrUNdcIN3Jlulir/5BOe9b0dPKNZU29QxXrTRofEUrsk1yfi+ptK6XEPrrKYL3m9LkaUaTHIqXeplFKP/noTr+uIe9dKSOFt62UkcJbV0pu726vYTrbMnj0K5D19hptrvps3jfXQqubK9OwNXpZpV60V+AbDwoXjrw6KPDomYlo2Rwvm+OVHzzY5nWWJ4wfZea1gxOP9vlAy2k0UF09nXMZHRZk8US/D10VGfZ6wBxsdONqEbR6K/ze9TZQGO5tb4piqPCmKN64v75W+Kpvd/eH89VvPS8mdT7svh/3/vbn8+n+4tOn/x/xCX4rejw/3O9/PJ/3prT8YKR/vugXSVv9XeKrfU+nb/VrhS21Ym+jfUr2qXx9MWf+Ag==" + }, + { + "name": "has_htlc", + "is_unconstrained": true, + "custom_attributes": [ + "abi_public", + "abi_view" + ], + "abi": { + "parameters": [ + { + "name": "swap_id", + "type": { + "kind": "field" + }, + "visibility": "private" + }, + { + "name": "htlc_id", + "type": { + "kind": "field" + }, + "visibility": "private" + } + ], + "return_type": { + "abi_type": { + "kind": "boolean" + }, + "visibility": "public" + }, + "error_types": { + "459713770342432051": { + "error_kind": "string", + "string": "Not initialized" + }, + "13455385521185560676": { + "error_kind": "string", + "string": "Storage slot 0 not allowed. Storage slots must start from 1." + }, + "15764276373176857197": { + "error_kind": "string", + "string": "Stack too deep" + }, + "16190783185788596410": { + "error_kind": "string", + "string": "Function has_htlc can only be called statically" + } + } + }, + "bytecode": "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", + "debug_symbols": "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" + }, + { + "name": "lock_dst", + "is_unconstrained": true, + "custom_attributes": [ + "abi_public" + ], + "abi": { + "parameters": [ + { + "name": "swap_id", + "type": { + "kind": "field" + }, + "visibility": "private" + }, + { + "name": "htlc_id", + "type": { + "kind": "field" + }, + "visibility": "private" + }, + { + "name": "hashlock_high", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 128 + }, + "visibility": "private" + }, + { + "name": "hashlock_low", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 128 + }, + "visibility": "private" + }, + { + "name": "reward", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 128 + }, + "visibility": "private" + }, + { + "name": "reward_timelock", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 64 + }, + "visibility": "private" + }, + { + "name": "timelock", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 64 + }, + "visibility": "private" + }, + { + "name": "src_receiver", + "type": { + "kind": "struct", + "path": "aztec::protocol_types::address::aztec_address::AztecAddress", + "fields": [ + { + "name": "inner", + "type": { + "kind": "field" + } + } + ] + }, + "visibility": "private" + }, + { + "name": "token", + "type": { + "kind": "struct", + "path": "aztec::protocol_types::address::aztec_address::AztecAddress", + "fields": [ + { + "name": "inner", + "type": { + "kind": "field" + } + } + ] + }, + "visibility": "private" + }, + { + "name": "total_amount", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 128 + }, + "visibility": "private" + }, + { + "name": "src_asset", + "type": { + "kind": "string", + "length": 30 + }, + "visibility": "private" + }, + { + "name": "dst_chain", + "type": { + "kind": "string", + "length": 30 + }, + "visibility": "private" + }, + { + "name": "dst_asset", + "type": { + "kind": "string", + "length": 30 + }, + "visibility": "private" + }, + { + "name": "dst_address", + "type": { + "kind": "string", + "length": 90 + }, + "visibility": "private" + } + ], + "return_type": null, + "error_types": { + "361444214588792908": { + "error_kind": "string", + "string": "attempt to multiply with overflow" + }, + "459713770342432051": { + "error_kind": "string", + "string": "Not initialized" + }, + "1998584279744703196": { + "error_kind": "string", + "string": "attempt to subtract with overflow" + }, + "2360858009427093503": { + "error_kind": "string", + "string": "InvalidTimelock" + }, + "3380315280177356474": { + "error_kind": "string", + "string": "FundsNotSent" + }, + "4736483829072576196": { + "error_kind": "string", + "string": "HTLCAlreadyExists" + }, + "7413154743021792023": { + "error_kind": "string", + "string": "InvalidRewardAmount" + }, + "12697770001660251253": { + "error_kind": "fmtstring", + "length": 24, + "item_types": [] + }, + "13455385521185560676": { + "error_kind": "string", + "string": "Storage slot 0 not allowed. Storage slots must start from 1." + }, + "14990209321349310352": { + "error_kind": "string", + "string": "attempt to add with overflow" + }, + "15764276373176857197": { + "error_kind": "string", + "string": "Stack too deep" + }, + "16431471497789672479": { + "error_kind": "string", + "string": "Index out of bounds" + }, + "16884080922827299127": { + "error_kind": "string", + "string": "InvalidRewardTimelock" + } + } + }, + "bytecode": "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AAABAgEtDgYJLQgBBgAAAQIBLQgBCgAAAQIBLQgBDycCEQTdAAgBEQEnAw8EAQAiDwIRLQoREi0OARIAIhICEi0OAhIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhICEi0OFBIAIhIC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", + "debug_symbols": "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" + }, + { + "name": "lock_src", + "is_unconstrained": true, + "custom_attributes": [ + "abi_public" + ], + "abi": { + "parameters": [ + { + "name": "swap_id", + "type": { + "kind": "field" + }, + "visibility": "private" + }, + { + "name": "hashlock_high", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 128 + }, + "visibility": "private" + }, + { + "name": "hashlock_low", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 128 + }, + "visibility": "private" + }, + { + "name": "timelock", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 64 + }, + "visibility": "private" + }, + { + "name": "src_receiver", + "type": { + "kind": "struct", + "path": "aztec::protocol_types::address::aztec_address::AztecAddress", + "fields": [ + { + "name": "inner", + "type": { + "kind": "field" + } + } + ] + }, + "visibility": "private" + }, + { + "name": "token", + "type": { + "kind": "struct", + "path": "aztec::protocol_types::address::aztec_address::AztecAddress", + "fields": [ + { + "name": "inner", + "type": { + "kind": "field" + } + } + ] + }, + "visibility": "private" + }, + { + "name": "amount", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 128 + }, + "visibility": "private" + }, + { + "name": "src_asset", + "type": { + "kind": "string", + "length": 30 + }, + "visibility": "private" + }, + { + "name": "dst_chain", + "type": { + "kind": "string", + "length": 30 + }, + "visibility": "private" + }, + { + "name": "dst_asset", + "type": { + "kind": "string", + "length": 30 + }, + "visibility": "private" + }, + { + "name": "dst_address", + "type": { + "kind": "string", + "length": 90 + }, + "visibility": "private" + } + ], + "return_type": null, + "error_types": { + "459713770342432051": { + "error_kind": "string", + "string": "Not initialized" + }, + "1998584279744703196": { + "error_kind": "string", + "string": "attempt to subtract with overflow" + }, + "2360858009427093503": { + "error_kind": "string", + "string": "InvalidTimelock" + }, + "3380315280177356474": { + "error_kind": "string", + "string": "FundsNotSent" + }, + "12697770001660251253": { + "error_kind": "fmtstring", + "length": 24, + "item_types": [] + }, + "13455385521185560676": { + "error_kind": "string", + "string": "Storage slot 0 not allowed. Storage slots must start from 1." + }, + "14990209321349310352": { + "error_kind": "string", + "string": "attempt to add with overflow" + }, + "15764276373176857197": { + "error_kind": "string", + "string": "Stack too deep" + }, + "16431471497789672479": { + "error_kind": "string", + "string": "Index out of bounds" + }, + "17552554873437466887": { + "error_kind": "string", + "string": "SwapAlreadyInitialized" + } + } + }, + "bytecode": "JwACBAEoAAABBIEBKAAAAAQBAScCDAS7JwINBAAfCgAMAA0ARhwAR0cGHABISAYcAElJBRwATEwGHABNTQIcAE5OAhwAT08CHABQUAIcAFFRAhwAUlICHABTUwIcAFRUAhwAVVUCHABWVgIcAFdXAhwAWFgCHABZWQIcAFpaAhwAW1sCHABcXAIcAF1dAhwAXl4CHABfXwIcAGBgAhwAYWECHABiYgIcAGNjAhwAZGQCHABlZQIcAGZmAhwAZ2cCHABoaAIcAGlpAhwAamoCHABrawIcAGxsAhwAbW0CHABubgIcAG9vAhwAcHACHABxcQIcAHJyAhwAc3MCHAB0dAIcAHV1AhwAdnYCHAB3dwIcAHh4AhwAeXkCHAB6egIcAHt7AhwAfHwCHAB9fQIcAH5+AhwAf38CHACAgAIcAIGBAhwAgoICHACDgwIcAISEAhwAhYUCHACGhgIcAIeHAhwAiIgCHACJiQIcAIqKAhwAi4sCHACMjAIcAI2NAhwAjo4CHACPjwIcAJCQAhwAkZECHACSkgIcAJOTAhwAlJQCHACVlQIcAJaWAhwAl5cCHACYmAIcAJmZAhwAmpoCHACbmwIcAJycAhwAnZ0CHACengIcAJ+fAhwAoKACHAChoQIcAKKiAhwAo6MCHACkpAIcAKWlAhwApqYCHACnpwIcAKioAhwAqakCHACqqgIcAKurAhwArKwCHACtrQIcAK6uAhwAr68CHACwsAIcALGxAhwAsrICHACzswIcALS0AhwAtbUCHAC2tgIcALe3AhwAuLgCHAC5uQIcALq6AhwAu7sCHAC8vAIcAL29AhwAvr4CHAC/vwIcAMDAAhwAwcECHADCwgIcAMPDAhwAxMQCHADFxQIcAMbGAhwAx8cCHADIyAIcAMnJAhwAysoCHADLywIcAMzMAhwAzc0CHADOzgIcAM/PAhwA0NACHADR0QIcANLSAhwA09MCHADU1AIcANXVAhwA1tYCHADX1wIcANjYAhwA2dkCHADa2gIcANvbAhwA3NwCHADd3QIcAN7eAhwA398CHADg4AIcAOHhAhwA4uICHADj4wIcAOTkAhwA5eUCHADm5gIcAOfnAhwA6OgCHADp6QIcAOrqAhwA6+sCHADs7AIcAO3tAhwA7u4CHADv7wIcAPDwAhwA8fECHADy8gIcAPPzAhwA9PQCHAD19QIcAPb2AhwA9/cCHAD4+AIcAPn5AhwA+voCHAD7+wIcAPz8AhwA/f0CHAD+/gIcAP//Ah0AAQABAAItCEYBLQhHAi0ISAMtCEkELQhKBS0ISwYtCEwHJwIIBE0nAg0EHi0IAQwnAg4EHwAIAQ4BJwMMBAEAIgwCDi0CCAMtAg4ELQINBSUAAATTLQoMCCcCCQRrJwINBB4tCAEMJwIOBB8ACAEOAScDDAQBACIMAg4tAgkDLQIOBC0CDQUlAAAE0y0KDAknAgoEiScCDQQeLQgBDCcCDgQfAAgBDgEnAwwEAQAiDAIOLQIKAy0CDgQtAg0FJQAABNMtCgwKJwILBKcnAg0EWi0IAQwnAg4EWwAIAQ4BJwMMBAEAIgwCDi0CCwMtAg4ELQINBSUAAATTLQoMCyUAAAUFJQAABTkoAgABBAEBJwICBAA7DgACAAEAAAMFBy0AAwgtAAQJCgAIBwokAAAKAAAFBC0BCAYtBAYJAAAIAggAAAkCCSMAAATgJiwAAEMAMGROcuExoCm4UEW2gYFYXSgz6Eh5uXCRQ+H1k/AAAAApAABEBP////8nAEUEAyYlAABEkh4CAAwAHgIADQAtCAEOAAABAgEtDg0OLQgBDQAAAQIBJwIPAAEtDg8NLQgBEAAAAQIBJwIRAAItDhEQLQgBEQAAAQIBJwISAAMtDhIRHgIAEgAeAgATADMqABIAEwAUJwISAQEkAgAUAAAFryUAAES4JwITBgAMKhMHFCQCABQAAAXGJQAARMonAhMAAC0IARQnAhUEBAAIARUBJwMUBAEAIhQCFS0KFRYtDhMWACIWAhYtDhMWACIWAhYtDhMWKwIAFQAAAAAAAAAAAgAAAAAAAAAALQgBFicCFwQFAAgBFwEnAxYEAQAiFgIXLQoXGC0OExgAIhgCGC0OExgAIhgCGC0OExgAIhgCGC0OFRgtCAEXAAABAgEtDhQXLQgBFAAAAQIBLQ4WFC0IARgAAAECAScCGQQALQ4ZGC0IARoAAAECAScCGwEALQ4bGicCHAQBJAIAGwAABuQjAAAGnS0IAQwnAh0EBAAIAR0BJwMMBAEAIgwCHS0KHR4tDg8eACIeAh4tDhMeACIeAh4tDhMeLQ4MFy0OFhQtDhwYLQ4bGiMAAAdwLQoZDCMAAAbtDCIMRRYkAgAWAABEDCMAAAb/LQsXDC0LFBYtCxodLQsWHgAiHgIeLQ4eFi0IAR4nAh8EBQAIAR8BJwMeBAEAIhYCHycCIAQEACIeAiE/DwAfACEtAgwDJwAEBAQlAABE3C0IBRYAKhYcHy0ODx8tDhYXLQ4eFC0OHBgtDh0aIwAAB3AtCxcMLQsUFi0LGh0KKh0bHiQCAB4AAAeSJwIfBAA8Bh8BJwIdBAIkAgAbAAAH1CMAAAekLQIMAycABAQEJQAARNwtCAUeACoeHR8tDgEfLQ4eFy0OFhQtDh0YLQ4bGiMAAAhgLQoZDCMAAAfdDCIMRRYkAgAWAABDhiMAAAfvLQsXDC0LFBYtCxoeLQsWHwAiHwIfLQ4fFi0IAR8nAiAEBQAIASABJwMfBAEAIhYCICcCIQQEACIfAiI/DwAgACItAgwDJwAEBAQlAABE3C0IBRYAKhYcIC0OASAtDhYXLQ4fFC0OHBgtDh4aIwAACGAtCxoWCioWGx4kAgAeAAAIeicCHwQAPAYfAS0KGQwjAAAIgwwiDEUWJAIAFgAAQwAjAAAIlS0LFwwtCxQWLQsYHi0LFh8AIh8CHy0OHxYtCAEfJwIgBAUACAEgAScDHwQBACIWAiAnAiEEBAAiHwIiPw8AIAAiLQ4MFy0OHxQtDh4YLQ4SGgAqHxwULQsUDAoqDBMUCioUGxYkAgAWAAAJBiUAAEU7LQgBFCcCFgQEAAgBFgEnAxQEAQAiFAIWLQoWFy0OExcAIhcCFy0OExcAIhcCFy0OExctCAEWJwIXBAUACAEXAScDFgQBACIWAhctChcYLQ4TGAAiGAIYLQ4TGAAiGAIYLQ4TGAAiGAIYLQ4VGC0IARcAAAECAS0OFBctCAEUAAABAgEtDhYULQgBGAAAAQIBLQ4ZGC0IARoAAAECAS0OGxokAgAbAAAJ+yMAAAm0LQgBHicCHwQEAAgBHwEnAx4EAQAiHgIfLQofIC0ODCAAIiACIC0OEyAAIiACIC0OEyAtDh4XLQ4WFC0OHBgtDhsaIwAACoctChkWIwAACgQMIhZFHiQCAB4AAEJ6IwAAChYtCxcWLQsUHi0LGh8tCx4gACIgAiAtDiAeLQgBICcCIQQFAAgBIQEnAyAEAQAiHgIhJwIiBAQAIiACIz8PACEAIy0CFgMnAAQEBCUAAETcLQgFHgAqHhwhLQ4MIS0OHhctDiAULQ4cGC0OHxojAAAKhy0LFwwtCxQWLQsaHgoqHhsfJAIAHwAACqknAiAEADwGIAEkAgAbAAAK5iMAAAq2LQIMAycABAQEJQAARNwtCAUeACoeHR8tDhMfLQ4eFy0OFhQtDh0YLQ4bGiMAAAtyLQoZDCMAAArvDCIMRRYkAgAWAABB9CMAAAsBLQsXDC0LFBYtCxoeLQsWHwAiHwIfLQ4fFi0IAR8nAiAEBQAIASABJwMfBAEAIhYCICcCIQQEACIfAiI/DwAgACItAgwDJwAEBAQlAABE3C0IBRYAKhYcIC0OEyAtDhYXLQ4fFC0OHBgtDh4aIwAAC3ItCxoWCioWGx4kAgAeAAALjCcCHwQAPAYfAS0KGQwjAAALlQwiDEUWJAIAFgAAQW4jAAALpy0LFxYtCxQeLQsYHy0LHiAAIiACIC0OIB4tCAEgJwIhBAUACAEhAScDIAQBACIeAiEnAiIEBAAiIAIjPw8AIQAjLQ4WFy0OIBQtDh8YLQ4SGgAqIBwWLQsWFAoqFBMWCioWGxckAgAXAAAMGCUAAEU7LQgBFicCFwQNAAgBFwEnAxYEAQAiFgIXJwIYBAwAKhgXGC0KFxoOKhgaHiQCAB4AAAxZLQ4TGgAiGgIaIwAADD4tCAEXAAABAgEtDhYXJwIWBAwtChkMIwAADHQMKgwWGCQCABgAAEEoIwAADIYtCxcMJwIUBAcAKgwUGC0LGBcKKhcTDCQCAAwAAAyqJQAARU0eAgAMBigCABQFBwgAKgwUFw4qDBcYJAIAGAAADM0lAABFXwwqFwQMJAIADAAADN8lAABFcR4CAAwBCiIMQxQWChQXHAoXGAAEKhgMFycCDAJTJwIYAmUnAhoCbicCHgJkJwIfAnInAiACICcCIQJtJwIiAnUnAiMCcycCJAJ0JwIlAm8nAiYCYicCJwIhLQgBKCcCKQQZAAgBKQEnAygEAQAiKAIpLQopKi0ODCoAIioCKi0OGCoAIioCKi0OGioAIioCKi0OHioAIioCKi0OGCoAIioCKi0OHyoAIioCKi0OICoAIioCKi0OISoAIioCKi0OIioAIioCKi0OIyoAIioCKi0OJCoAIioCKi0OICoAIioCKi0OGioAIioCKi0OJSoAIioCKi0OJCoAIioCKi0OICoAIioCKi0OJioAIioCKi0OGCoAIioCKi0OICoAIioCKi0OGioAIioCKi0OJSoAIioCKi0OGioAIioCKi0OGCoAIioCKi0OJyoKKhQbDCQCAAwAAA6PJwIYBBotCAEaJwIeBBoACAEeAS0KGh4qAwAeBbA3iop0kgx1ACIeAh4AIigCHycCIAQYLQIfAy0CHgQtAiAFJQAABNMnAh8EGAAqHh8eLQ4THgAiHgIePA4YGi0LDQwtCAENJwIUBAQACAEUAScDDQQBACINAhQtChQYLQ4TGAAiGAIYLQ4TGAAiGAIYLQ4TGC0IARQnAhgEBQAIARgBJwMUBAEAIhQCGC0KGBotDhMaACIaAhotDhMaACIaAhotDhMaACIaAhotDhUaLQgBGAAAAQIBLQ4NGC0IAQ0AAAECAS0OFA0tCAEaAAABAgEtDhkaLQgBHgAAAQIBLQ4bHiQCABsAAA+IIwAAD0EtCAEfJwIgBAQACAEgAScDHwQBACIfAiAtCiAhLQ4MIQAiIQIhLQ4TIQAiIQIhLQ4TIS0OHxgtDhQNLQ4cGi0OGx4jAAAQFC0KGRQjAAAPkQwiFEUfJAIAHwAAQKIjAAAPoy0LGBQtCw0fLQseIC0LHyEAIiECIS0OIR8tCAEhJwIiBAUACAEiAScDIQQBACIfAiInAiMEBAAiIQIkPw8AIgAkLQIUAycABAQEJQAARNwtCAUfACofHCItDgwiLQ4fGC0OIQ0tDhwaLQ4gHiMAABAULQsYDC0LDRQtCx4fCiofGyAkAgAgAAAQNicCIQQAPAYhASQCABsAABBzIwAAEEMtAgwDJwAEBAQlAABE3C0IBR8AKh8dIC0OASAtDh8YLQ4UDS0OHRotDhseIwAAEP8tChkMIwAAEHwMIgxFFCQCABQAAEAcIwAAEI4tCxgMLQsNFC0LHh8tCxQgACIgAiAtDiAULQgBICcCIQQFAAgBIQEnAyAEAQAiFAIhJwIiBAQAIiACIz8PACEAIy0CDAMnAAQEBCUAAETcLQgFFAAqFBwhLQ4BIS0OFBgtDiANLQ4cGi0OHx4jAAAQ/y0LHhQKKhQbHyQCAB8AABEZJwIgBAA8BiABLQoZDCMAABEiDCIMRRQkAgAUAAA/liMAABE0LQsYDC0LDRQtCxofLQsUIAAiIAIgLQ4gFC0IASAnAiEEBQAIASEBJwMgBAEAIhQCIScCIgQEACIgAiM/DwAhACMtDgwYLQ4gDS0OHxotDhIeACogHA0tCw0MCioMEw0KKg0bFCQCABQAABGlJQAARTstCAENJwIUBAQACAEUAScDDQQBACINAhQtChQYLQ4TGAAiGAIYLQ4TGAAiGAIYLQ4TGC0IARQnAhgEBQAIARgBJwMUBAEAIhQCGC0KGBotDhMaACIaAhotDhMaACIaAhotDhMaACIaAhotDhUaLQgBGAAAAQIBLQ4NGC0IAQ0AAAECAS0OFA0tCAEaAAABAgEtDhkaLQgBHgAAAQIBLQ4bHiQCABsAABKaIwAAElMtCAEfJwIgBAQACAEgAScDHwQBACIfAiAtCiAhLQ4MIQAiIQIhLQ4TIQAiIQIhLQ4TIS0OHxgtDhQNLQ4cGi0OGx4jAAATJi0KGRQjAAASowwiFEUfJAIAHwAAPxAjAAAStS0LGBQtCw0fLQseIC0LHyEAIiECIS0OIR8tCAEhJwIiBAUACAEiAScDIQQBACIfAiInAiMEBAAiIQIkPw8AIgAkLQIUAycABAQEJQAARNwtCAUfACofHCItDgwiLQ4fGC0OIQ0tDhwaLQ4gHiMAABMmLQsYDC0LDRQtCx4fCiofGyAkAgAgAAATSCcCIQQAPAYhASQCABsAABOFIwAAE1UtAgwDJwAEBAQlAABE3C0IBR8AKh8dIC0OEyAtDh8YLQ4UDS0OHRotDhseIwAAFBEtChkMIwAAE44MIgxFFCQCABQAAD6KIwAAE6AtCxgMLQsNFC0LHh8tCxQgACIgAiAtDiAULQgBICcCIQQFAAgBIQEnAyAEAQAiFAIhJwIiBAQAIiACIz8PACEAIy0CDAMnAAQEBCUAAETcLQgFFAAqFBwhLQ4TIS0OFBgtDiANLQ4cGi0OHx4jAAAUES0LHhQKKhQbHyQCAB8AABQrJwIgBAA8BiABLQoZDCMAABQ0DCIMRRQkAgAUAAA+BCMAABRGLQsYFC0LDR8tCxogLQsfIQAiIQIhLQ4hHy0IASEnAiIEBQAIASIBJwMhBAEAIh8CIicCIwQEACIhAiQ/DwAiACQtDhQYLQ4hDS0OIBotDhIeACohHBQtCxQNCioNExQKKhQbGCQCABgAABS3JQAARTscCgcUABwKAgcAHAoDGAAcCgQaAC0IAQQnAh4EDQAIAR4BJwMEBAEAIgQCHi0KHh8tDhQfACIfAh8tDgYfACIfAh8tDgcfACIfAh8tDhgfACIfAh8tDhMfACIfAh8tDhMfACIfAh8tDhcfACIfAh8tDgUfACIfAh8tDhofACIfAh8tDg8fACIfAh8tDhMfACIfAh8tDhMfLQoZDCMAABVXDCoMFgckAgAHAAA92CMAABVpLQsOBy0IAQwnAg0EBQAIAQ0BJwMMBAEAIgwCDS0KDQ4tDhcOACIOAg4tDgcOACIOAg4tDhQOACIOAg4tDhMOLQsMBwAiBwIHLQ4HDC0IAQcAAAECASkCAA0AjJ5Uci0IAQ4nAhYEBgAIARYBJwMOBAEAIg4CFi0KFhgtDg0YACIYAhgtDhMYACIYAhgtDhMYACIYAhgtDhMYACIYAhgtDhMYLQ4OBycCDQQEJwIOBAUtChkEIwAAFiIMKgQNFiQCABYAAD2CIwAAFjQtCwcEACIEAgc5A6AARABEAAYADgAHIAIABCECAAYtCAEMACIMAhYtCxYWLQoWDicCGAQDACoMGA0iOgAGABkADS0KBg4nAwwEAQAiDAIWLQ4OFgAiFgIWLQ4OFicCGAQDACoOGBYACAEWAS0KDgcGIgcCByQCAAQAABbiIwAAFrUtCwwEACIEAgQtDgQMACIMAg0tCw0NLQoNBicCDgQDACoMDgQ8DgYEIwAAFuIKKgcZBCQCAAQAABb4JwIGBAA8BgYBLQsQBC0IAQYnAgcEBAAIAQcBJwMGBAEAIgYCBy0KBwwtDhMMACIMAgwtDhMMACIMAgwtDhMMLQgBBycCDAQFAAgBDAEnAwcEAQAiBwIMLQoMDS0OEw0AIg0CDS0OEw0AIg0CDS0OEw0AIg0CDS0OFQ0tCAEMAAABAgEtDgYMLQgBBgAAAQIBLQ4HBi0IAQ0AAAECAS0OGQ0tCAEOAAABAgEtDhsOJAIAGwAAF/EjAAAXqi0IARYnAhgEBAAIARgBJwMWBAEAIhYCGC0KGB4tDgQeACIeAh4tDhMeACIeAh4tDhMeLQ4WDC0OBwYtDhwNLQ4bDiMAABh9LQoZByMAABf6DCIHRRYkAgAWAAA8/CMAABgMLQsMBy0LBhYtCw4YLQsWHgAiHgIeLQ4eFi0IAR4nAh8EBQAIAR8BJwMeBAEAIhYCHycCIAQEACIeAiE/DwAfACEtAgcDJwAEBAQlAABE3C0IBRYAKhYcHy0OBB8tDhYMLQ4eBi0OHA0tDhgOIwAAGH0tCwwELQsGBy0LDhYKKhYbGCQCABgAABifJwIeBAA8Bh4BJAIAGwAAGNwjAAAYrC0CBAMnAAQEBCUAAETcLQgFFgAqFh0YLQ4XGC0OFgwtDgcGLQ4dDS0OGw4jAAAZaC0KGQQjAAAY5QwiBEUHJAIABwAAPHYjAAAY9y0LDAQtCwYHLQsOFi0LBxgAIhgCGC0OGActCAEYJwIeBAUACAEeAScDGAQBACIHAh4nAh8EBAAiGAIgPw8AHgAgLQIEAycABAQEJQAARNwtCAUHACoHHB4tDhceLQ4HDC0OGAYtDhwNLQ4WDiMAABloLQsOBwoqBxsWJAIAFgAAGYInAhgEADwGGAEtChkEIwAAGYsMIgRFByQCAAcAADvwIwAAGZ0tCwwELQsGBy0LDRYtCwcYACIYAhgtDhgHLQgBGCcCHgQFAAgBHgEnAxgEAQAiBwIeJwIfBAQAIhgCID8PAB4AIC0OBAwtDhgGLQ4WDS0OEg4AKhgcBi0LBgQKKgQTBgoqBhsHJAIABwAAGg4lAABFOy8KAAQABi0LEQQtCAEHJwIMBAQACAEMAScDBwQBACIHAgwtCgwNLQ4TDQAiDQINLQ4TDQAiDQINLQ4TDS0IAQwnAg0EBQAIAQ0BJwMMBAEAIgwCDS0KDQ4tDhMOACIOAg4tDhMOACIOAg4tDhMOACIOAg4tDhUOLQgBDQAAAQIBLQ4HDS0IAQcAAAECAS0ODActCAEOAAABAgEtDhkOLQgBEQAAAQIBLQ4bESQCABsAABsNIwAAGsYtCAEWJwIYBAQACAEYAScDFgQBACIWAhgtChgeLQ4EHgAiHgIeLQ4THgAiHgIeLQ4THi0OFg0tDgwHLQ4cDi0OGxEjAAAbmS0KGQwjAAAbFgwiDEUWJAIAFgAAO2ojAAAbKC0LDQwtCwcWLQsRGC0LFh4AIh4CHi0OHhYtCAEeJwIfBAUACAEfAScDHgQBACIWAh8nAiAEBAAiHgIhPw8AHwAhLQIMAycABAQEJQAARNwtCAUWACoWHB8tDgQfLQ4WDS0OHgctDhwOLQ4YESMAABuZLQsNBC0LBwwtCxEWCioWGxgkAgAYAAAbuycCHgQAPAYeASQCABsAABv4IwAAG8gtAgQDJwAEBAQlAABE3C0IBRYAKhYdGC0OFxgtDhYNLQ4MBy0OHQ4tDhsRIwAAHIQtChkEIwAAHAEMIgRFDCQCAAwAADrkIwAAHBMtCw0ELQsHDC0LERYtCwwYACIYAhgtDhgMLQgBGCcCHgQFAAgBHgEnAxgEAQAiDAIeJwIfBAQAIhgCID8PAB4AIC0CBAMnAAQEBCUAAETcLQgFDAAqDBweLQ4XHi0ODA0tDhgHLQ4cDi0OFhEjAAAchC0LEQwKKgwbFiQCABYAAByeJwIYBAA8BhgBLQoZBCMAABynDCIERQwkAgAMAAA6XiMAABy5LQsNBC0LBwwtCw4WLQsMGAAiGAIYLQ4YDC0IARgnAh4EBQAIAR4BJwMYBAEAIgwCHicCHwQEACIYAiA/DwAeACAtDgQNLQ4YBy0OFg4tDhIRACoYHActCwcECioEEwcKKgcbDCQCAAwAAB0qJQAARTstCAEHJwIMBAQACAEMAScDBwQBACIHAgwtCgwNLQ4TDQAiDQINLQ4TDQAiDQINLQ4TDS0IAQwnAg0EBQAIAQ0BJwMMBAEAIgwCDS0KDQ4tDhMOACIOAg4tDhMOACIOAg4tDhMOACIOAg4tDhUOLQgBDQAAAQIBLQ4HDS0IAQcAAAECAS0ODActCAEOAAABAgEtDhkOLQgBEQAAAQIBLQ4bESQCABsAAB4fIwAAHdgtCAEWJwIYBAQACAEYAScDFgQBACIWAhgtChgeLQ4EHgAiHgIeLQ4THgAiHgIeLQ4THi0OFg0tDgwHLQ4cDi0OGxEjAAAeqy0KGQwjAAAeKAwiDEUWJAIAFgAAOdgjAAAeOi0LDQwtCwcWLQsRGC0LFh4AIh4CHi0OHhYtCAEeJwIfBAUACAEfAScDHgQBACIWAh8nAiAEBAAiHgIhPw8AHwAhLQIMAycABAQEJQAARNwtCAUWACoWHB8tDgQfLQ4WDS0OHgctDhwOLQ4YESMAAB6rLQsNBC0LBwwtCxEWCioWGxgkAgAYAAAezScCHgQAPAYeASQCABsAAB8KIwAAHtotAgQDJwAEBAQlAABE3C0IBRYAKhYdGC0OBhgtDhYNLQ4MBy0OHQ4tDhsRIwAAH5YtChkEIwAAHxMMIgRFDCQCAAwAADlSIwAAHyUtCw0ELQsHDC0LERYtCwwYACIYAhgtDhgMLQgBGCcCHgQFAAgBHgEnAxgEAQAiDAIeJwIfBAQAIhgCID8PAB4AIC0CBAMnAAQEBCUAAETcLQgFDAAqDBweLQ4GHi0ODA0tDhgHLQ4cDi0OFhEjAAAfli0LEQwKKgwbFiQCABYAAB+wJwIYBAA8BhgBLQoZBCMAAB+5DCIERQwkAgAMAAA4zCMAAB/LLQsNBC0LBwwtCw4WLQsMGAAiGAIYLQ4YDC0IARgnAh4EBQAIAR4BJwMYBAEAIgwCHicCHwQEACIYAiA/DwAeACAtDgQNLQ4YBy0OFg4tDhIRACoYHActCwcECioEEwcKKgcbDCQCAAwAACA8JQAARTswCgABAAQtCxAELQgBBycCDAQEAAgBDAEnAwcEAQAiBwIMLQoMDS0OEw0AIg0CDS0OEw0AIg0CDS0OEw0tCAEMJwINBAUACAENAScDDAQBACIMAg0tCg0OLQ4TDgAiDgIOLQ4TDgAiDgIOLQ4TDgAiDgIOLQ4VDi0IAQ0AAAECAS0OBw0tCAEHAAABAgEtDgwHLQgBDgAAAQIBLQ4ZDi0IARAAAAECAS0OGxAkAgAbAAAhOyMAACD0LQgBEScCFQQEAAgBFQEnAxEEAQAiEQIVLQoVFi0OBBYAIhYCFi0OExYAIhYCFi0OExYtDhENLQ4MBy0OHA4tDhsQIwAAIcctChkMIwAAIUQMIgxFESQCABEAADhGIwAAIVYtCw0MLQsHES0LEBUtCxEWACIWAhYtDhYRLQgBFicCGAQFAAgBGAEnAxYEAQAiEQIYJwIeBAQAIhYCHz8PABgAHy0CDAMnAAQEBCUAAETcLQgFEQAqERwYLQ4EGC0OEQ0tDhYHLQ4cDi0OFRAjAAAhxy0LDQQtCwcMLQsQEQoqERsVJAIAFQAAIeknAhYEADwGFgEkAgAbAAAiJiMAACH2LQIEAycABAQEJQAARNwtCAURACoRHRUtDhcVLQ4RDS0ODActDh0OLQ4bECMAACKyLQoZBCMAACIvDCIERQwkAgAMAAA3wCMAACJBLQsNBC0LBwwtCxARLQsMFQAiFQIVLQ4VDC0IARUnAhYEBQAIARYBJwMVBAEAIgwCFicCGAQEACIVAh0/DwAWAB0tAgQDJwAEBAQlAABE3C0IBQwAKgwcFi0OFxYtDgwNLQ4VBy0OHA4tDhEQIwAAIrItCxAMCioMGxEkAgARAAAizCcCFQQAPAYVAS0KGQQjAAAi1QwiBEUMJAIADAAANzojAAAi5y0LDQwtCwcRLQsOFS0LERYAIhYCFi0OFhEtCAEWJwIYBAUACAEYAScDFgQBACIRAhgnAh0EBAAiFgIePw8AGAAeLQ4MDS0OFgctDhUOLQ4SEAAqFhwMLQsMBwoqBxMMCioMGw0kAgANAAAjWCUAAEU7ACoGDwwwCgAMAAcnAgYCAC0IAQcnAgwEIQAIAQwBJwMHBAEAIgcCDCcCDQQgACoNDA0tCgwODioNDg8kAgAPAAAjqS0OBg4AIg4CDiMAACOOLQgBBgAAAQIBLQ4HBi0IAQcAAAECAS0OAgcnAgIEECcCDAQPJwINBCAnAg4GCC0KGQQjAAAj4AwqBAIPJAIADwAANr8jAAAj8i0OAwcnAgMEHy0KGQQjAAAkBAwqBAIMJAIADAAANlYjAAAkFi0LBgMtCAEEJwIGBNsACAEGAScDBAQBACIEAgYnAgcE2gAqBwYHLQoGDA4qBwwOJAIADgAAJFstDhMMACIMAgwjAAAkQC0IAQYAAAECAS0OBAYtCAEEAAABAgEtCAEHAAABAgEtCAEMJwIOBNoACAEOAScDDAQBACIMAg4tCg4PLQ4BDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4TDwAiDwIPLQ4T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", + "debug_symbols": "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" + }, + { + "name": "redeem", + "is_unconstrained": true, + "custom_attributes": [ + "abi_public" + ], + "abi": { + "parameters": [ + { + "name": "swap_id", + "type": { + "kind": "field" + }, + "visibility": "private" + }, + { + "name": "htlc_id", + "type": { + "kind": "field" + }, + "visibility": "private" + }, + { + "name": "secret_high", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 128 + }, + "visibility": "private" + }, + { + "name": "secret_low", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 128 + }, + "visibility": "private" + } + ], + "return_type": null, + "error_types": { + "361444214588792908": { + "error_kind": "string", + "string": "attempt to multiply with overflow" + }, + "459713770342432051": { + "error_kind": "string", + "string": "Not initialized" + }, + "1998584279744703196": { + "error_kind": "string", + "string": "attempt to subtract with overflow" + }, + "2369193878689457446": { + "error_kind": "string", + "string": "HTLCNotExists" + }, + "4493654309393309420": { + "error_kind": "string", + "string": "AlreadyClaimed" + }, + "12697770001660251253": { + "error_kind": "fmtstring", + "length": 24, + "item_types": [] + }, + "13455385521185560676": { + "error_kind": "string", + "string": "Storage slot 0 not allowed. Storage slots must start from 1." + }, + "14924807131364042204": { + "error_kind": "string", + "string": "HashlockNotMatch" + }, + "14990209321349310352": { + "error_kind": "string", + "string": "attempt to add with overflow" + }, + "15764276373176857197": { + "error_kind": "string", + "string": "Stack too deep" + }, + "16431471497789672479": { + "error_kind": "string", + "string": "Index out of bounds" + } + } + }, + "bytecode": "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LCQCACwAACo+IwAAKpQAIikCLQAqLR8uLQsuLAAiKAIuACouHy8tCy8tACosLS4tAikDJwAEBAUlAAAytC0IBSwAIiwCLQAqLR8vLQ4uLy0OKCItDiwHLQ4qJi0OKycjAAAqlAAiH1IoLQooHyMAAA+0LQsfIhgqIg8mACIFAicAKicLKC0LKCIcCiInBgAqJiciDiomIigkAgAoAAAq1SUAADNtLQ4iHwAiC1IiLQoiCyMAAA6YLQscIhgqIg8mACIFAicAKicLKC0LKCIcCiInBgAqJiciDiomIigkAgAoAAArGiUAADNtLQ4iHAAiC1IiLQoiCyMAAA59LQsmJxgqJw8oACIcAikAKikLKi0LKiccCicpBgAqKCknDiooJyokAgAqAAArXyUAADNtLQ4nJgAiC1InLQonCyMAAA4FLQsfJxgqJw8oACIcAikAKikLKi0LKiccCicpBgAqKCknDiooJyokAgAqAAArpCUAADNtLQ4nHwAiC1InLQonCyMAAA3qLQsmJwAiJwIqACoqCystCysoHAooJwAnAioBAC0IASgnAisEBQAIASsBJwMoBAEAIigCKycCLAQEQwOiACcATwAsACoAKwQoTgsnLQoDHyMAACwKDCIfTiokAgAqAAAsKiMAACwcACILUh8tCh8LIwAADbEAKicfKg4qJyorJAIAKwAALEElAAAzbQAiKAIsACosHy0tCy0rLQspLAwqKg4tJAIALQAALGUlAAAzWy0CLAMnAAQEISUAADK0LQgFLQAiLQIuACouKi8tDisvLQ4tKQAiH1IqLQoqHyMAACwKLQsmHwwiC00oJAIAKAAALK0lAAAzWy0CHwMnAAQEESUAADK0LQgFKAAiKAIpACopCyotDgMqLQ4oJgAiC1IfLQofCyMAAAzGLQgBKQAAAQIBLQ4DKQQiC04qBiIqTiwKKiwLKyQCACsAAC0IJQAAM5EtCgMnIwAALREMIidOKyQCACsAAC1vIwAALSMtCyknLQsoKQwiC00qJAIAKgAALT0lAAAzWy0CKQMnAAQEESUAADK0LQgFKgAiKgIrACorCywtDicsLQ4qKAAiC1InLQonCyMAAAwwACoqJywOKiosLSQCAC0AAC2GJQAAM20MKiwOLSQCAC0AAC2hIwAALZgtCgorIwAALcUkAgAtAAAtriUAADNbACIFAi4A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", + "debug_symbols": "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" + }, + { + "name": "refund", + "is_unconstrained": true, + "custom_attributes": [ + "abi_public" + ], + "abi": { + "parameters": [ + { + "name": "swap_id", + "type": { + "kind": "field" + }, + "visibility": "private" + }, + { + "name": "htlc_id", + "type": { + "kind": "field" + }, + "visibility": "private" + } + ], + "return_type": null, + "error_types": { + "459713770342432051": { + "error_kind": "string", + "string": "Not initialized" + }, + "4493654309393309420": { + "error_kind": "string", + "string": "AlreadyClaimed" + }, + "5029608433027800177": { + "error_kind": "string", + "string": "NotPassedTimelock" + }, + "13455385521185560676": { + "error_kind": "string", + "string": "Storage slot 0 not allowed. Storage slots must start from 1." + }, + "14990209321349310352": { + "error_kind": "string", + "string": "attempt to add with overflow" + }, + "15764276373176857197": { + "error_kind": "string", + "string": "Stack too deep" + }, + "16431471497789672479": { + "error_kind": "string", + "string": "Index out of bounds" + } + } + }, + "bytecode": "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", + "debug_symbols": "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" + }, + { + "name": "process_message", + "is_unconstrained": true, + "custom_attributes": [ + "abi_utility" + ], + "abi": { + "parameters": [ + { + "name": "message_ciphertext", + "type": { + "kind": "struct", + "path": "std::collections::bounded_vec::BoundedVec", + "fields": [ + { + "name": "storage", + "type": { + "kind": "array", + "length": 17, + "type": { + "kind": "field" + } + } + }, + { + "name": "len", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 32 + } + } + ] + }, + "visibility": "private" + }, + { + "name": "message_context", + "type": { + "kind": "struct", + "path": "aztec::messages::processing::message_context::MessageContext", + "fields": [ + { + "name": "tx_hash", + "type": { + "kind": "field" + } + }, + { + "name": "unique_note_hashes_in_tx", + "type": { + "kind": "struct", + "path": "std::collections::bounded_vec::BoundedVec", + "fields": [ + { + "name": "storage", + "type": { + "kind": "array", + "length": 64, + "type": { + "kind": "field" + } + } + }, + { + "name": "len", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 32 + } + } + ] + } + }, + { + "name": "first_nullifier_in_tx", + "type": { + "kind": "field" + } + }, + { + "name": "recipient", + "type": { + "kind": "struct", + "path": "aztec::protocol_types::address::aztec_address::AztecAddress", + "fields": [ + { + "name": "inner", + "type": { + "kind": "field" + } + } + ] + } + } + ] + }, + "visibility": "private" + } + ], + "return_type": null, + "error_types": { + "344423948968719440": { + "error_kind": "fmtstring", + "length": 98, + "item_types": [ + { + "kind": "integer", + "sign": "unsigned", + "width": 32 + }, + { + "kind": "integer", + "sign": "unsigned", + "width": 32 + }, + { + "kind": "field" + } + ] + }, + "361444214588792908": { + "error_kind": "string", + "string": "attempt to multiply with overflow" + }, + "992401946138144806": { + "error_kind": "string", + "string": "Attempted to read past end of BoundedVec" + }, + "1998584279744703196": { + "error_kind": "string", + "string": "attempt to subtract with overflow" + }, + "3080037330898348111": { + "error_kind": "fmtstring", + "length": 132, + "item_types": [ + { + "kind": "integer", + "sign": "unsigned", + "width": 32 + } + ] + }, + "4261968856572588300": { + "error_kind": "string", + "string": "Value does not fit in field" + }, + "4440399188109668273": { + "error_kind": "string", + "string": "Input length must be a multiple of 32" + }, + "7564993426627941149": { + "error_kind": "fmtstring", + "length": 48, + "item_types": [ + { + "kind": "field" + }, + { + "kind": "field" + } + ] + }, + "7995966536718645961": { + "error_kind": "fmtstring", + "length": 61, + "item_types": [ + { + "kind": "field" + }, + { + "kind": "field" + } + ] + }, + "8556029555939094797": { + "error_kind": "fmtstring", + "length": 75, + "item_types": [] + }, + "8992688621799713766": { + "error_kind": "string", + "string": "Invalid public keys hint for address" + }, + "9791669845391776238": { + "error_kind": "string", + "string": "0 has a square root; you cannot claim it is not square" + }, + "9885968605480832328": { + "error_kind": "string", + "string": "Attempted to read past the length of a CapsuleArray" + }, + "10522114655416116165": { + "error_kind": "string", + "string": "Can't read a transient note with a zero contract address" + }, + "10791800398362570014": { + "error_kind": "string", + "string": "extend_from_bounded_vec out of bounds" + }, + "11021520179822076911": { + "error_kind": "string", + "string": "Attempted to delete past the length of a CapsuleArray" + }, + "12469291177396340830": { + "error_kind": "string", + "string": "call to assert_max_bit_size" + }, + "12913276134398371456": { + "error_kind": "string", + "string": "push out of bounds" + }, + "13060541637244024094": { + "error_kind": "fmtstring", + "length": 98, + "item_types": [] + }, + "13450089406971132036": { + "error_kind": "fmtstring", + "length": 144, + "item_types": [ + { + "kind": "integer", + "sign": "unsigned", + "width": 32 + } + ] + }, + "14990209321349310352": { + "error_kind": "string", + "string": "attempt to add with overflow" + }, + "15764276373176857197": { + "error_kind": "string", + "string": "Stack too deep" + }, + "16431471497789672479": { + "error_kind": "string", + "string": "Index out of bounds" + }, + "16792019527863081935": { + "error_kind": "fmtstring", + "length": 77, + "item_types": [ + { + "kind": "integer", + "sign": "unsigned", + "width": 32 + } + ] + }, + "17154023812102399658": { + "error_kind": "fmtstring", + "length": 128, + "item_types": [ + { + "kind": "integer", + "sign": "unsigned", + "width": 32 + } + ] + }, + "17803644318014042523": { + "error_kind": "fmtstring", + "length": 58, + "item_types": [ + { + "kind": "field" + } + ] + } + } + }, + "bytecode": "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", + "debug_symbols": "TJ3LsjS7bpzf5Yw9aIIECfpVPHBYvigUoZAifBnp5b0KSSBz4vOltX8milXIrq5G9/qPf/yP//lP/++f/+u//Nv/+vf/84///F/+4x//9L//5V//9V/++b/+67//9//2f//l3//t7//3P/7x+/6f+Pt/53/6R4x//Gf/+x/D/0z8z8L/OP5n438O/ifwPzf/5/7wP1jlYpWLVS5WuVjlYpWLVS5WuVhl/H7vf8f7X3v/O9//rve//v53v/8973/j/e9bb7z1xltvvPXGW2+89cZbb7z1xltvvPXGW8/eevbWs7eevfXsrWdvPXvr2VvP3nr21ptvvfnWm2+9+dabb7351ptvvfnWm2+9+dZbb7311ltvvfXWW2+99dZbb7311ltvvfXW87eev/X8redvPX/r+VvP33r+1vO/9c73vxf/u3/vf8f737/1xu+DWbAK/pYc84O/NUf+x6cgCu6D8ysYBX8r2/hgFqwCL/hb2eyDUxAF38rfEXztARgF38rxwSxYBV6wC05BFNwHX8sARkGtfGvlWyt/zTO/bfnaB3AKouAC7OsiwCiwglmwCrxgF5yCKKiVR608auVRK49aedTKo1YetfKolUetPGplq5W/1pr2gRXMglXgBbvgFETBffD1GKBWnrXyrJVnrTxr5Vkrz1p51sqzVl618qqVV628auVVK69aedXKq1ZetfKqlb1W9lrZa2Wvlb1W9lrZa2Wvlb1W9lp518q7Vt618q6Vd628a+VdK+9aedfKu1Y+tfKplU+tfGrlUyufWvnUyqdWPrXyqZWjVo5aOWrlqJWjVo5aOWrlrwenfxAF98HXg4BRYAWzYBV4wS6olW+tfN/KM3swPhgFVvC38pofrAIv2AWnIArug68HAaPACmrlUSuPWnm8RJrjFETBS6Rpv4JRYAWzYBV4Qa1stbLVyl8Prv0HXw8CRoEVzIJV4AW74BREQa28auVVK69a+evBdT5YBV6wC05BFNwHXw8CRoEV1MpeK3utnK+A64NTEAX3wdeDgFFgBbNgFXhBrbxr5V0r71r51MqnVj618qmVT618auVTK59a+dTKp1aOWjlq5aiVo1aOWjlq5aiVo1aOWjlq5Vsr31r51sq3Vr618q2Vb618a+VbK9+38vr9CkaBFcyCVeAFu+AUREGtPGrlUSuPWnnUyqNWHrXyqJVHrTxq5VErW61stbLVylYrW61stbLVylYrW61stfKslWetPGvlWSvPWnnWyrNWnrXyrJVnrbxq5VUrr1p51cqrVl618qqVV628auVVK3ut7LWy18peK3ut7LVy9eCqHlzVg6t6cFUPrurBVT24qgdX9eCqHlzVg6t6cFUPrurBVT24qgdX9eCqHlzVg6t6cFUPrurBVT24qgdX9eCqHlzVg6t6cFUPrurBVT24qgdX9eCqHlzVg6t6cFUPrurBVT24qgdX9eCqHlzVg6t60KsHvXrQqwe9etCrB7160KsHvXrQqwe9etCrB7160KsHvXrQqwe9etCrB7160KsHvXrQqwe9etCrB7160KsHvXrQqwe9etCrB7160KsHvXrQqwe9etCrB7160KsHvXrQqwe9etCrB7160KsHvXrQqwe9etCrB7160KsHvXrQqwe9etCrB7160KsHvXrQqwe9etCrB7160KsHvXrQqwe9etCrB7160KsHvXrQqwe9etCrB7160KsHvXrQqwe9etCrB7160KsHvXrQqwe9etCrB7160KsHvXrQqwe9etCrB7160KsHvXrQqwe9etCrB7160KsHvXrQqwe9enBXD+7qwV09uKsHd/Xgrh7c1YO7enBXD+7qwV09uKsHd/Xgrh7c1YO7enBXD+7qwV09uKsHd/Xgrh7c1YO7enBXD+7qwV09uKsHd/Xgrh7c1YO7enBXD+7qwV09uKsHd/Xgrh7c1YO7enBXD+7qwV09uKsHd/Xgrh7c1YO7enBXD+7qwV09uKsHd/Xgrh7c1YO7enBXD+7qwV09uKsHd/Xgrh7c1YO7enBXD+7qwV09uKsHd/Xgrh7c1YO7enBXD+7qwV09uKsHd/Xgrh7c1YO7enBXD+7qwV09uKsHd/Xgrh7c1YO7enBXD+7qwV09uKsHd/Xgrh7c1YO7enBXD+7qwV09uKsHT/XgqR481YOnevBUD57qwVM9eKoHT/XgqR481YOnevBUD57qwVM9eKoHT/XgqR481YOnevBUD57qwVM9eKoHT/XgqR481YOnevBUD57qwVM9eKoHT/XgqR481YOnevBUD57qwVM9eKoHT/XgqR481YOnevBUD57qwVM9eKoHT/XgqR481YOnevBUD57qwVM9eKoHT/XgqR481YOnevBUD57qwVM9eKoHT/XgqR481YOnevBUD57qwVM9eKoHT/XgqR481YOnevBUD57qwVM9eKoHT/XgqR481YOnevBUD57qwVM9eKoHT/XgqR481YOnevBUD57qwVM9eKoHT/XgqR481YOnejCqB6N6MKoHo3owqgejejCqB6N6MKoHo3owqgejejCqB6N6MKoHo3owqgejejCqB6N6MKoHo3owqgejejCqB6N6MKoHo3owqgejejCqB6N6MKoHo3owqgejejCqB6N6MKoHo3owqgejejCqB6N6MKoHo3owqgejejCqB6N6MKoHo3owqgejejCqB6N6MKoHo3owqgejejCqB6N6MKoHo3owqgejejCqB6N6MKoHo3owqgcje/B8YAWz4G/lPT7wgl1wCqLgPvh6EDAKrGAW1MpRK0etHLVy1MpRK99a+dbKt1a+tfKtlW+tfGvlWyvfWvm+le/vVzAKrGAWrAIv2AWnIApq5VErj1p51MqjVh618qiVR608auVRK49a2Wplq5WtVrZa2Wplq5WtVrZa2Wplq5VnrTxr5Vkrz1p51sqzVp618qyVZ608a+VVK69aedXKq1ZetfKqlVetvGrlVSuvWtlrZa+VvVb2WtlrZa+VvVb2WtlrZa+Vd628a+VdK+9aedfKu1betfKulXetvGvlUyufWvnUyqdWrh681YO3evBWD97qwVs9eKsHb/XgrR681YO3evBWD97qwVs9eKsHb/XgrR681YO3evBWD97qwVs9eKsHb/XgrR681YN/n7L/mkaTNc2m1eRNu+k0RVN7jPYY7THaY7THaI/RHqM9RnuM9hjtYe1h7WHtYe1h7WHtYe1h7WHtYe0x22O2x2yP2R6zPWZ7zPaY7THbY7bHao/VHqs9Vnus9ljtsdpjtcdqj9Ue3h7eHt4e3h7eHt4e3h7eHt4e3h67PXZ77PbY7bHbY7fHbo/dHrs9dnuc9jjtcdrjtMdpj9Mepz1Oe5z2OO0R7RHtEe0R7RHtEe0R7RHtEe0R7XHb47bHbY/bHrc9bnvc9rjtcduj+3x0n4/u89F9PrrPR/f56D4f3eej+3x0n4/u89F9PrrPR/f56D4f3eej+3x0n4/u89F9PrrPR/f56D4f3eej+3x0n4/u89F9PrrPR/f56D4f3eej+3x0n4/u89F9PrrPR/f56D4f3eej+3x0n4/u89F9PrrPR/f56D4f3eej+3x0n4/u89F9PrrPR/f56D4f3eej+3x0n4/u89F9PrrPR/f56D4f3eej+3x0n4/u89F9PrrPR/f56D4f3eej+3x0n4/u89F9PrrPR/f56D4f3eej+3x0n4/u89F9PrrPR/f56D4f3eej+3x0n4/u89F9PrrPR/f56D4f3eej+3x0n4/u89F9PrrPrfvcus+t+9y6z6373LrPrfvcus+t+9y6z6373LrPrfvcus+t+9y6z6373LrPrfvcus+t+9y6z6373LrPrfvcus+t+9y6z6373LrPrfvcus+t+9y6z6373LrPrfvcus+t+9y6z6373LrPrfvcus+t+9y6z6373LrPrfvcus+t+9y6z6373LrPrfvcus+t+9y6z6373LrPrfvcus+t+9y6z6373LrPrfvcus+t+9y6z6373LrPrfvcus+t+9y6z6373LrPrfvcus+t+9y6z6373LrPrfvcus+t+9y6z6373LrPrfvcus+t+9y6z6373LrPrfvcus+t+9y6z2f3+ew+n93ns/t8dp/P7vPZfT67z2f3+ew+n93ns/t8dp/P7vPZfT67z2f3+ew+n93ns/t8dp/P7vPZfT67z2f3+ew+n93ns/t8dp/P7vPZfT67z2f3+ew+n93ns/t8dp/P7vPZfT67z2f3+ew+n93ns/t8dp/P7vPZfT67z2f3+ew+n93ns/t8dp/P7vPZfT67z2f3+ew+n93ns/t8dp/P7vPZfT67z2f3+ew+n93ns/t8dp/P7vPZfT67z2f3+ew+n93ns/t8dp/P7vPZfT67z2f3+ew+n93ns/t8dp/P7vPZfZ6zShvT1dF0i7LPT9JosqbZtJq8aTedpmi6j3Jw6dFosqbZtJq8aTedpmhqj9Eeoz1Ge4z2GO0x2mO0x2iP0R6jPaw9rD2sPaw9rD2sPaw9rD2sPaw9ZnvM9pjtMdtjtsdsj9kesz1me8z2WO2x2mO1x2qP1R6rPVZ7rPZY7bHaw9vD28Pbw9vD28Pbw9vD28Pbw9tjt8duj90euz12e+z22O2x22O3x26P0x6nPU57nPY47XHa47THaY/THqc9oj2iPaI9oj2iPaI9oj2iPaI9oj26z1f3+eo+X93nq/s856L2TdpNpyma7qMcjno0mqxpNq0mb9pNpyma2mO0x2iP0R6jPUZ7jPYY7THaY7THaA9rD2sPaw9rD2sPaw9rD2sPaw9rj9kesz1me8z2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TLdInMRFdOImHmIQbyOyBDiIdDt0O3Q7dDt0O3Q7dDt0C7oF3YJuQbegW9At6BZ0C7oF3S7dLt0u3S7dLt0u3S7dLt0u3W67rd+POIhGnMRFdOImHmIQ6TboNug26DboNug26DboNug26DboZnQzuhndjG5GN6Ob0c3oZnQzuk26TbpNuk26TbpNuk26ZZZ8v3trOYBYeBszS77fw7WcQSw04iQuohM38RCDeBudbk43p5vTzenmdHO6Od2cbk63TbdNt023TbdNt023TbdNt023TbdDt0O3Q7dDt0O3Q7dDt0O3Q7dDt6Bb0C3oFnQLugXdgm5Bt6Bb0O3S7dLt0u3S7dLt0u3S7dLt0u22W44vFg6iESdxEZ24iYcYRLoNug26DboNug26DboNug26DboNuhndjG5GN6Ob0c3oZnQzuhndjG6TbpNuk26TbpNuk26TbpNuk26TbswSZ5Y4s8SZJc4scWaJM0ucWeLMEmeWOLPEmSXOLHFmiTNLnFnizBJnljizxJklzixxZokzS5xZ4swSZ5Y4s8SZJc4scWaJM0ucWeLMEmeWOLPEmSXOLHFmiTNLnFnizBJnljizxJklzixxZokzS5xZ4swSZ5Y4s8SZJc4scWaJM0ucWeLMEmeWOLPEmSWbWbKZJZtZspklm1mymSWbWbKZJZtZspklm1mymSWbWbKZJZtZspklm1mymSWbWbKZJZtZspklm1mymSWbWbKZJZtZspklm1mymSWbWbKZJZtZspklm1mymSWbWbKZJZtZspklm1mymSWbWbKZJZtZspklm1mymSWbWbKZJZtZspklm1mymSWbWbKZJZtZspklm1mymSWbWbKZJZtZspklm1mymSWbWbKZJZtZspklm1mymSWbWbKZJZtZspklm1mymSWbWbKZJZtZspklm1mymSWbWbKZJZtZspklm1mymSWbWbKZJZtZspklm1mymSWbWbKZJZtZspklh1lymCWHWXKYJYdZcpglh1lymCWHWXKYJYdZcpglh1lymCWHWXKYJYdZcpglh1lymCWHWXKYJYdZcpglh1lymCWHWXKYJYdZcpglh1lymCWHWXKQJTtxEZ24iYcYxNuILAEOohHptui26Lbotui26Lbo5nRzujndnG5ON6dbZonhzxkcYhA/N8uNyix5OIifm53ESVxEJ27iIQbxNmaWPBxEuh26Hboduh26Hboduh26Bd0ySyx3J7Pk4SQuohM38RCDeBszSx7S7dLt0u3S7dLt0u3S7dLttluOehYOohEncRGduImHGES6DboNug26DboNug26DboNug26DboZ3YxuRjejm9HN6GZ0M7oZ3Yxuk26TbpNuk26TbpNuk26TbpNuk26Lbotui26Lbotui26Lbotui26Lbk43p5vTzenmdHO6Od2cbk43p9um26bbptum26bbptum26bbptum26Hboduh26Hboduh26Hboduh26Fb0I1ZEsySYJYEsySYJcEsCWZJMEuCWRLMkmCWBLMkmCXBLAlmSTBLglkSzJJgllxmyWWWXGbJZZZcZsllllxmyWWWXGbJZZZcZsllllxmyWWWXGbJZZZcZsllllxmyWWWXGbJZZZcZsllllxmyWWWXGbJZZZcZsllllxmyWWWXGbJZZZcZsllllxmyWWWXGbJZZZcZsllllxmyWWWXGbJZZZcZsllllxmyWWWXGbJZZZcZsllllxmyWWWXGbJZZZcZsllllxkSSQOohEncRGduImHGMTbeOh26Hboduh26Hboduh26HbodugWdAu6Bd2CbkG3oFvQLegWdAu6Xbpdul26Xbpdul26Xbpdul263XKbv9+POIhGnMRFdOImHmIQ6TboNug26DboNug26DboNug26DboZnTLLPn+LtzMQdbCSfzcvj/zNXOWtXATDzGItzGz5OEgGnES6TbpNuk26TbpNum26Lbotui26Lbotui26Lbotui26OZ0c7o53ZxuTjenm9PN6eZ0c7ptum26bbptum26bbptum26bbptuh26Hboduh26Hboduh26Hboduh26Bd2CbkG3oFvQLegWdAu6Bd2Cbpdul26Xbpdul26Xbpdul26XbrfdMPf6cBCNOImL6MRNPMQg0m3QbdBt0G3QbdBt0G3QbdBt0G3QzehmdDO6Gd2YJYNZMpglg1kymCWDWTKYJYNZMpglg1kymCWDWTKYJYNZMpglg1kymCWDWTKYJYNZMpglg1kymCWDWTKYJYNZMpglg1kymCWDWTKYJYNZMpglg1kymCWDWTKYJYNZMpglg1kymCWDWTKYJYNZMpglg1kymCWDWTKYJYNZMpglg1kymCWDWTKYJYNZMpglg1kymCWDWTKYJYNZMpglg1kymCWDWTKYJYNZMpglg1kymCWDWTKYJYNZMpglg1lizBJjlhizxJglxiwxZokxS4xZYswSY5YYs8SYJcYsMWaJMUuMWWLMEmOWGLPEmCXGLDFmiTFLjFlizBJjlhizxJglxiwxZokxS4xZYswSY5YYs8SYJcYsMWaJMUuMWWLMEmOWGLPEmCXGLDFmiTFLjFlizBJjlhizxJglxiwxZokxS4xZYswSY5YYs8SYJcYsMWaJMUuMWWLMEmOWGLPEmCXGLDFmiTFLjFlizBJjlhizxJglxiwxZokxS4xZYswSY5YYs8SYJcYsMWaJMUuMWWLMEmOWGLPEmCXGLMHca/4BXMy9PnRiup3EQwziLcTc68NBNOIkLqITN/EQ020k3kZkCXAQjTiJi+jETTxEug26Gd2MbkY3o5vRzehmdDO6Gd2MbpNuk26TbpNuk26TbpNuk26TbpNui26Lbotui26Lbotui26Lbotui25ON6eb083p5nRzujndnG5ON6fbphuy5CYacRIX0YmbeIhBvI3IEiDdDt0O3TJLViQ6cRM/t4X/Noi3MbNk/RIH0YiTuIhO3MRDDOJtvHS7dLt0u3S7dLt0u3S7dLt0u+2GudeHg2jESVxEJ27iIQaRboNug26DboNug26DboNug26DboNuRjejm9HN6GZ0M7oZ3YxuRjej26TbpNuk26TbpNuk26TbpNuk26Tbotui26Lbotui26Lbotui26LbopvTzenmdHO6Od2cbk43p5vTzem26bbptum26bbptum26bbptum26XbohmevnmjESVxEJ27iIQbxNuLZK5BuQbegW9At6BZ0C7oF3YJul26Xbpdul26Xbpdul26Xbpdut90w9/pwEI04iYvoxE08xCDSbdBt0G3QbdBt0G3QbdBt0G3QbdDN6GZ0M7oZ3YxuRjejm9HN6GZ0m3SbdJt0m3SbdJt0m3SbdJt0m3RbdFt0W3RbdFt0W3RbdFt0W3RbdHO6Od2cbk43p5vTzenmdHO6Od023TbdMkv8lziJi/i5+UzcxEP83L4/Xzcx9wrMLHk4iEacxEV04iYeIt0O3YJuQbegW9At6BZ0C7oF3YJuQbdLt0u3S7dLt0u3S7dLt0u3S7fbbph7fTiIRpzERXTiJh5iEOk26DboNug26DboNug26DboNug26GZ0M7oZ3YxuRjejm9HN6GZ0M7pNuk26TbpNuk26TbpNuk26TbpNui26Lbotui26Lbotui26Lbotui26Od2cbk43p5vTzenmdHO6Od2cbpklfhMH0Yif27bERXTiJh5iEG9jZsnDQTQi3Q7dDt0yS3aWnlnyMIi3MbPk4SAacRIX0Yl0C7oF3YJul26Xbpdul26Xbpdul26Xbpdut90w9/pwEI04iYvoxE08xCDSbdBt0G3QbdBt0G3QbdBt0G3QbdDN6GZ0M7oZ3YxuRjejm9HN6GZ0m3SbdJt0m3SbdJt0m3SbdJt0m3RbdFt0W3RbdFt0W3RbdFt0W3RbdHO6Od2cbk43p5vTzenmdHO6Od023TbdNt023TbdNt023TbdNt023Q7dDt0O3Q7dDt0O3Zglh1lymCWHWXKYJYdZcpglh1lymCWHWXKYJYdZcpglh1lymCWHWXKYJYdZcpglh1lymCWHWXKYJYdZEsySYJYEsySYJcEsCWZJMEuCWRLMkmCWBLMkmCXBLAlmSTBLglkSzJJglgSzJJglwSwJZkkwS4JZEsySYJYEsySYJcEsCWZJMEuCWRLMkmCWBLMkmCXBLAlmSTBLglkSzJJglgSzJJglwSwJZkkwS4JZEsySYJYEsySYJcEsCWZJMEuCWRLMkmCWBLMkmCXBLAlmSTBLglkSzJJglgSzJJglwSwJZkkwS4JZEsySYJYEsySYJcEsCWYJ5l6/X8yfmHsFIkuAg2jESVxEJ27iIdIt6HbpdumWWXJO4iQuohM38RCDeAsx9/pwEI04iYuYxzYTN/EQg3gbkSXAQTTiJC4i3QbdBt0G3QbdjG5GN6Ob0c3oZnQzuhndjG5Gt0m3SbdJt0m3SbdJt0m3SbdJt0m3RbdFt0W3RbdFt0W3RbdFt0W3RTenm9PN6eZ0c7o53ZxuTjenm9Nt023TbdNt023TbdNt023TbdNt0+3Q7dDt0O3Q7dDt0O3Q7dDt0O3QLegWdAu6Bd2CbkG3oFvQLegWdLt0u3S7dLt0u3S7dLt0u3S7dLvltjD3+nAQjTiJi+jETTzEINJt0G3QbdBt0G3QbdBt0G3QbdBt0M3oZnQzuhndjG5Gt8ySWImHGMTP7fvTDgtzrw8H8XP7fht7Ye714SJ+bnckbuIhBvE2ZpY8HEQjTuIi0m3RbdFt0S2z5J4PM0seDuKfm/1yH74sKVxE/zD34cuSwkP8c7Nhibfxy5LC8WGeiy9LCifxcxtZzpclhZt4iEG8jedHHEQjTiLdDt0O3Q7dDt0O3YJuQbegW9At6BZ0C7oF3YJuQbdLt0u3S7dLt0u3S7dLt0u3S7fbbjn3WjiIRpzERXTiJh5iEOk26DboNug26DboNug26DboNug26GZ0M7oZ3YxuRjejm9HN6GZ0M7pNuk26TbpNuk26TbpNuk26TbpNui26Lbotui26Lbotui26Lbotui26Od2cbk43p5vTzenmdHO6Od2cbptum26bbptuzJLBLBnMksEsGcySwSwZzJLBLBnMksEsGcySwSwZzJLBLBnMksEsGcySwSwZzJLBLBnMksEsGcySwSwZzJLBLBnMksEsGcySwSwZzJLBLBnMksEsGcySwSwxZokxS4xZYswSY5YYs8SYJcYsMWaJMUuMWWLMEmOWGLPEmCXGLDFmiTFLjFlizBJjluTcq9lKNOIkfm52E524iZ/b992dlXOvhbcxs2SmW2bJQyN+bjMSF9GJn9vyxEMM4ue29oeZJQ8H8XPzPKDMkoeL+Ll5LpZZ8vAQP7fv7wmvnHt9mFny8HPbWW9mycNJ/Nx27llmycNN/NxO1ptZ8vA2Zpac3LPMkodG/Nwidz2z5KETN/EQg3gbM0seDqIR6Xboduh26Hboduh26BZ0C7oF3YJuQbegW9At6BZ0C7pdul26Xbpdul26ZZbkfXXOvRYeYrrlycosScy518JBNOIkLqITN/EQg0i3QbdBt8ySa4mTuIif2/cnbFbOvRYe4uf2/Y2MlXOvDzNLHg6iESdxEZ24iYdIN6PblyV/G5c4iEacH2a9X5YUOnF/eBMPMYh/bvP7jcaVc6+FoxFjCEnfWmMk5r9Kh/sjDqIRJ3ERnbiJhxjEdss5yMJBNOIkLqITN/EQg0i3QbdBt0G3QbdBt0G3QbdBt0G3QTejm9HN6GZ0M7oZ3YxuRjejm9Ft0m3SbdJt0m3SbdJt0m3SbdJt0m3RbdFtpdtOnMRFdOImHuLnZr/E2/i9ThUO4udmI3ESP7fv925WzkEWbuIhBvE27h8x3TzRiJOYbifRiZv4ueWdRM5BFt7G73WqcBCN+LnNlbiITtzEdMvKThBv4/c69ZcGiYNoxM9t5WLf61ShE3PPIvFbN29hcrZxrjzizAfP0jMfHjpxEw8xiN+6eWOTs42Fg2jEdPPERUy3SNzEQwzibcx8ePi5ffMcK2cbCydxET+3fOKVs42Fn9vOIjMfHt7GzIeH6ZbGmQ8PJ3ERnbiJn9vJcjIfHt7GzIeHn9vJIjMfHk5iuu1EJ+7G7PmHuUIeRXZ33srlZOLMu46cTCwM4ldZZDnZ3Q8H8Vs3nxLmZGLhV1neEuRkYuEmpltuSXb3w9uY3f1wEI2Y697Eb4V8zpjThjMf7OW0YeEgGvGrN+86ctqw0ImbeIjplkeRHQvMjn2YbnmBZ8c+nMRFdOImplueoezjh7cx+/hhrpBbkh37MFfIc5Ed+/AW5gTh38t64iAacX5oiYvoH87ETTwfemJ8uBPvh1+ROUG48llnThAWGvFzG1nZ17GFTvzWzRuinApc+TqUU4Er32PmVODfK3xirnATvxXyFSfn/1a+3cz5v4dfvxV+61qu+/Vb4SR+R5yvFznTtzJec6ZvWe7DGsRcIWv4XmNXvkjkTF+hEzfx28mZ9X5dWHgbvy4sHEQjTuIi5rq51TtXyCJ3/gd58DvLyf3dm3iI0XgGMVfI3TlOzBVyo06WnhsV+d/mloQTN/FzW7kP32VfeBvvr9f9bnrr/9eIk7iI3kd8N/EQozBH4HBsOQKHA8oRuMJFPHU95LDbypfmHHb7u8X6MC/7h4NoxElcRCd+9a6sbBxiENPtO4U57LbydT6H3VY+lMhht5Uv+Tnshos2h90Knfitmy/uOdb2MFvk4beuZ2XZIg8n8avXs7JskXz1z1G19X1bbOWoWmGukPVmi3jWmy3y0Imb+O2D5wFlizy8jdkiDwfRiJO4iLlu7kO2iGeR2SL57CXnyFbeSuQcWeFt/F5xCj/jvMHIObLCSVxEJ27iIQbxNsaPSLegW9At6BZ0C7oF3YJuQbdLt0u3S7dLt0u3S7dLt9tuOSa28u4qx8QKJ3ERnbiJhxjE25hd+JBug26DboNug26DboNug26DbkY3o5vRzehmdDO6Gd2Mbt8bvL92T0y376LNwa2Vt4s5orXyxjDnp1Z+OJnzU4VOzMV24m3My/7h99+eSNzEQ/xWyHvEnH76K+rD7ICHg2jESVxEJ27iIQaRbkG37IC8G8zpp8JJ/NzyHjGnnwo38XPLG7icfiq8jdkBec+V00+FRvzc8vYrp58KnbiJhxjEW5jTT4WDaMRJXEQn5rrfwedEk+dtXU40ed7L5URT4SI6cRMPMYi38bvsCweRbkY3o5vRzehmdDO6Gd1mus3EQTTiJC6iEzfxEIN4GxfdFt0W3Va6rcRFdGKu+73U5ZSS5w1yTil53iDnlFLhIjpxEw8xiLdx/4iDSLdNt023nW557exNPMQg3sbzIw6iESdxEel26Hboduj29bznc9GcUiocRCNO4iJ+6+ZD1Jw88nzXkZNHnm8qcvKocBIX0YmbeIhBvA89J48KB9GIk5huK9GJm3iIQbyN2d3f+yHPaSL/3g95ThMVHmKucBNvY/bxw0E04iQuohM38RDpZnTLPv7ennlOExUa8XP73lF5ThMVfm6WR5x9bLl92ceWB599/PA2Zh9bGmcfP/zcvndfntNEPtM4+/h7w+Q5TeQz3b7b0MJDDOJt/G5DC3PdLDL7+Hv74Dkh5DPPRfbxw9uYfTyzyOzjh0acxEX81l15QNmbKw8oe3PlAWVvPpzERXTiJh5iEG9j9ubKI87efGjEdMt9yN586MRNTLfcqAjibcw+XrlR2ccPjZhueeazjx86cRMPMYjp9m1qTv0UDuLn9r018pz6KVxEJ0Zjvh77SDRiPhvMdfNJ5MPbmF34vc/ynMMpXEQnbuIhBvE2Zhc+HMR088RJXMS0OImHGMS0yNKz9R4O4mexc0uy9R4uohM38RCDeBuz9R4OIt2cbk43p5vTzenmdHO6bbptum26bbptum26bbptuuXL7c5LI19ugdnSD9NtJhpxEtMtT1a29MN0i8RDDOJtzJZ+mG553rKlH35uJ+vNlj5ZWbb0ycsoW/rhIX5u3+Noz+Gbh9nSDz+3772I5/BN4SQuohM3Mdf9LsQcqPHvfYvnQI1nO+VATaETN/GrN0ZiEG/j986ycBA/t+/puOdAjX8f2nsO1Pw92E383CIt8qX54ed2scLn9j1t9hyoeZgvzTcXy5fmm4tlKDz81r15mNnoN9f9Wnp/N/+e4zCFk7g+TOPvhbVwEw8xiLfx6+7CdFuJRpxE78qypR8eYlrsxNvoP2Ja5H/rRpzE74BGlvO1dOF3QCOP+GvpwiB+biPP29fShYNoxElcRCdu4iEGkW6Hboduh26Hboduh26Hboduh26HbkG3oFvQLdItL7lYRCemW16IcYhBTLc8WfdHHEQjpltevzfd8vr9WnpbnpavpQsP8XPLe8ScgQHmDEzhIBpxEhfRiZt4iEGk26DbyGO7iUacxEV04iYeYhDT7dv1nIEpHMQ8tpU4iYvoxDw2TzzEaMyoeJgrnMRcIRI38RCjMds/b6bzN9p23kznb7QVbuIhBvE2Zs/PPMzs+YdGnMRFdOImHmLWm/ubPQ/Mnn84iOmW25c9/zDddqITNzHdckuy5x/exuz5h4NoxFw3a8g+zhv6/N21nTf0+btrhYNoxK/elUecffzQiZt4iOmWNWQfA7OPHw6iESfxc8ubyJw3KtzEQ/zcPI2zjxNz3qjwc8sbzpw32t8Tes95o8J0u4lO/NzyPirnjQqDeBuzjx8OohEncRGdSLdBt0G3QTejm9HN6GZ0M7oZ3YxuRjejm9Ft0m3SbdJt0m3SbdJt0m3SbdJt0m3RbdFt0W3RbdFt0W3RbdEt8yFvenPe6GHmw8NBTLe8djIfHi6iEzfxEIN4GzMfHg4i3TbdNt023TbdNt023TbdDt3y1f/7EMBzhmjnXXzOEBXmCjvxNmY+PBxEI07iIua6X/Dn76O9E3C5v9nzDydxEfOIszez5x8eYhD72skZosJBNOIkLqITd9Xg6HlgEPvacfR8JA6iEenGnnf2vLPnnT3v7Hlnz7v1leo2iEacxNU1mBM3kW7seWfPO3ve2fPOnnf2vLPnHT2fNUzu5OROTu7k5E6i52/iIH5u+b4wfx+tcBGd+Ll9n1x5TiEVBvE2Zs8/HEQjTmK6rUQn9gWeo0f7eOJtzEZ/OIi8NNDoQJ6szZO1ebL2IQaRJ+vwZB2erMOTdXiyDk/W4YV4eCEeXhrZ/vlOOAeSCo2YG5X7kO2f749zIKlwEw8xiLcxo+LhIBox181LI0Ph4SEG8Vv3+2zRc0ypcBCNmLcdwEV04iYeYhBvY4bCw7zZAy6iEzfxWzff++ePl+HuNceUCo34rZsPB3JMqdCJ37rfh5qeP15W/yyIfYOcw0uFdJt0y0Z/uIhO3ES6TVpkH+dbgpxjKlzELB24ibklJzGItzH7+Jvk85xjKjTi53Zzf7OPHzpxEz+3fHSSv01WeBuzpR9+bje3Ops3n63k+FPhJua6KzGItzGb9+EgGnES0y13J5v34SYeYhBvY7b0w0HMxXJTszfzAVBOTT3M3nw4iEacxL8iTz4Wyqmpwk08xCDewvw5scJBtA9H4iQuohM38RCjTktOWD3Mjn04iNlkN3HX7uQAVWEQb6Nl6ZbYW5KjUoVOzCLTzQ4xiLkl35nPAar3z+YgGpFuk26TbtmmDw8xiH26c9iqkBarnw0ePHYDHmKWvhNvo/+IeTZzU92Ik/idzXyElD/7VbiJ30blI6T82a/C2/i1aeEgGnESF9GJm0i3TbdNt0O3Q7dDt0O3Q7dDt0O3Q7dDt0O3oFvQLegW6ZYXTCyiE9Mtz0UcYrrl9Ru38f6I6ZZn6Box3fLMZ88/dOLnlg+3clyr8HPLJ3D5s1/A/Nmvws8tH03lPFfh55avFznPVfi55TOmnOcqPMR0u4m3cfyIg2jESfzWzVfpnNE6+aKWM1onP9zNGa1CI07iV28+9ckZrcJNPMQgptu3k/lTXoWDaMRJXMTPLT9YzZ/yKjzEIH5u+fgmJ8IKB/Fzyw9Wc07s5IOa/CmvwnTLPVub+LnlZ5b5U16FtzHz4eEgGnESF9GJm0g3p5vTbdNt023TbdNt023TbdNt023TbdPt0O3Q7dDt0O3Q7dDt0O3Q7dDt0C3oFnQLugXdgm6ZD/n5cQ6zFR5iENMtr4fMh4eDaMRJXEQnbuIpzLG18w39eg6onXxwlwNqhbnCTtzEQwzibcyefziIue5J7P3NATUccQ6oPcyefziIecSROImL6MQ+mzmgVhjEPps5oFY4iEacxNXlTCdu4iHy2LLn82FnDqgVfm75DjAH1AoncRE/t3zGlD+5VXiIQbyN2fMPB9GI6ZYXQfb8w90nKxs9n13lBFvhbcxGfzj6BGyerM2TtXmyNk8WGh14iDxZbPTLRr9s9MtGv2z0y0a/bPTLRs9ZtZOP0nJWrXAQc6NyH7Kl84lAzqoVOnETDzGItzFb+uEg5rp5aWTzPtzEQ/zWzUcyOcGWuHOCrXAQ8+VrJE7iIjpxEw8xiLcxG/3hfJ+j7x8+PAc68Vv3AA8xiHkU/mG2/8NB/I7ipFu2/8NF/I7ie16yc66t8BDjfcK/MdcGzImah4NoxElcRCdu4iHSbdJt0W3RbdFt0W3RbdFt0W3RbdFt0c3p5nTL9v+eJu2cditcRH/zDxszcA9zJyMxiLcxh2tunoscrnmYQw95IeZwzcNF9DcrsfNXsgo/t8B/EMTbmEmAiyuT4KERJ3ERnbiJhxjE2xh0C7oF3YJuQbegW9At6BZ0C7pdul26Xbpdul26Xbpdut12y8m48z2w2jkDd75vgO6cgTt5aeQMXOEmHmLWexJvYybBw0E0YrrdxEV04ud2s8jMh4dB/NzyispfviocRCNO4iI6cRMPMYh0m3TL24Ob25e3Bze3L28PHi6iEzfxEIN4G/P24OEg0i1vD25uat4ePHRiuuXJytuDh0FMt9z1vD14OIh/bvHLxb58KFxE/zASN/EQ/9zim9TZOXz38MuHwvFhlvPlQ+EkpluWs524iZ+b5aXx5UPhbfzyISxP1pcPhUb83Czr/fKh0Imfm6XbOcQgfm7fEMHO4bvCQfzcZu7Zlw+Fi/i5rTyxXz4UHuLntnJLvnx4+OVD4ee2spwvHwon8XPzLOfLh8JN/Nx2XuDfXUXhLcxfvorvu3I7f/mq0Iif23dfsnNQr9CJn1vejOSgXmEQP7d88clBvcJB/NzyZSYH9QoX8XP7vrC+c1Cv8BA/t8Bit/HLksLPLbs7B/UKJ3ERnbiJhxjE2/hlSSHdJt0m3b4sub/cnS9LCjfxfJhn6MuSwtv4ZcnNhsxRv0Ijzg/zDK1FdOLnNvIcf1lSGMTPbeT2fVlSOIif20i3L0sKF/Fz+2aedk79FR7i5/Y9hNo59ffwy5LCz83S7cuSwkn83GYu9mVJ4SZ+bhOLBfE2fllyV27qlyWFRvzcVm7JlyWFToyK15zkOzcPPu8fHk7iIjpxEw8xiF+9K6+d+yMOohEncRGduInf7qzsoS8fCm9hTvLdjKuc5Cs0Yh7bL3ERnbiJhxjEdPvOZk7yFQ7i5+b53375ULiIeWyRuImH+B3bN+i0c5Lv4ZcPhZ/b98595yRf4SR+bjvdviR4/2wacRIX0YmbKCt8lW3gbczufvhV9r2f3/k3WAsncRGduImHGMTbmN39kG5Ot+zunddDdvdDJ27iIQbxc8uXg5zvKxxEI35u+bYv5/sKnfi5nawsu/vkhZjd/TDdvu7O+b7CdMtysrsfTuIiOnETDzGItzF+RLoF3YJuQbegW9At6BZ0C7pdul26Xbpdul26Xbpdul26XbrddstZwMJBNOIkLqITN/EQg0i3QbdBt0G3QbdBt0G3QbdMgrzXyFnAwtuYSfCwk2AxCRaTIGcBC524iYcYxNuYqZF3Njnfh1jJ+b578B8cYhBvY+bDw0E04rduvpfOmb23D4tH7Dzi7PmHRvyO+Bum2DmzV+jETeTZdLo5z+bm2dw8m5tnc/NsouezBvQ8cBN5NrPnUUP2PDB7/iHd2POLPb/Y84s9v9jziz2/Dq+dw50M7mRwJ7PnUUNwJ4M7yZ5f7PnFnl/s+cWeX+z5xZ5fl+cNPQ/kTl7u5OV5y55/yJ1kzzt73tnzzp539ryz55097+x5//V5818Qeyd9/IiDmDtpiZOYOzkTnbiJh5jHljVkzwOz5x8OohEncRGdmG5ZZPb8w+z5NJ6jujCn/u43UbNz6q9wEZ3YZyin/gqD2Nd6Tv0VDqIReYYWz9DiGVo8Q+sQg8jrwXk9OK8H5MNNdOImfuvmzV6O+t184pKjfg8zHx4OohEncRGduIn9DCSH+goH0YiTuIi5bp7CTIKHh5hHsRJvYybBwzwKTzTiJC6iEzfxEIN4GzMJHtLt0u3S7dLt0u3S7dLt0u22Ww4AFg6iESdxEZ24iYeYbjsx3b4OyAHAwkE04iQuohM38RCDSLd8TpBPv3JYsNCIs55+5bBgoRPz2VUeRT4neBjE25jPCR4OohEncRGdSLdJt0yCvH7x10t/+aAAf770901Tbfz90uItfMj5xzd+38DUxt8l/f3yRPkSduEtfIRD+CbnXu6f8BA24Sm8hF14C8N3JofwJZ+fMHzz1B0Tzp3Pbcunhg+duImHGMTbGDDME5J/hueXj0fxt0aLL/n2E9QcDyw04iQuohM38RCD2M9rczywcBCNOImL6MRNPMQg0m3QbdBt0G3QbdBt0G3QbdBt0G1gK79rGH9utDjPdT54xh8cLc5r7Jvd2viTo8UuvIWPcAhf8vwJD2ETFt8J35PswnmwWWY2+MMg3saFtSMZa9zkXc+6c7qwMIi3nnXndGHhIObj9CwoPyp4uIhO3MRDDOJtzI8KHg4i3Tbd0OWWZxjdnB8A4E+F/vJZP/5WaLEJT2Gskzt2sE6eATTp4yFswlN4CeduYzNjCx/hEL7k+xMewiYM35W8hF14C8M3z90N4fTNz/Lxh0GLh7AJT+El7MJb+AiHsPhmAOQDw5wVLDRifqjhiYvoxPwIZSYeYhBvY76gPxxEI07iIjqRbkY39Pc3j7jxdz9/+YwZf/jzl4+T8Zc/i7fwIS+sc5KxTiQvYRfewkc4hHO3vy9NbPxhz+IhbMJTeAm78BaG704O4UvGa/tj+ObZx2v74/70Cn+u85fP0PH3OouHMP5pbj8a+nF/8pWDfoWbeBrR5LjO0My4pPKzuvwYLMf3CjcxPz3LOvKzuoe3MV+z8/FNju8VGnESF9GJm3iIQbyF9/cjDiJO3k7Ok5TPvPH3NX+50/gDm4/HT3gI5zrfTNvGH8785RNq/OXM4kvGi+zjIWzCudvfHOLG388sduEtfIRD+JLRhI/hm/uAF9nHU3gJw9eTtzB8T3IIXzKa9vEQNuEpvIRdeAuLb74050eqOeT3MF+aH+Ynpnkc+dL8cBLzCsuTny/NDzfxEIN4G/Ol+eEgGnES6bbphttvT0Yf4ypFH2db4c9lFi9hF8518uMH/BnM384zjhfmx1N4CbvwFs7dzg8k8Ncwiy8ZL8yPh7AJT+ElDN+88vHC/PgIhzB8/87+wV/GLIbvTc71vzG6gz+D+fs++Dj4O5jFh5x/3fL3feBx8Octi5ewC2/hIxzCl4yufzyExTdfXU8eSr66PnRijgxE4iEGMUcG9of5dvnhIBpxEhfRiZt4iEGk26IbevkxdilrQ8+ePDt4AX58yXgBfpzrfA/jzg8vqJFnEy+oj0P4kvGC+ngI525/E17nhzfLj5ewC2/hIxzCl4xX4+/J5fmhix+b8BSGb559dPFj+OZJP0c4hC8Zr9SR+4auf2zCU3gJu/AWPsIhfMlXfPNh2i8PKx+mPZzEHKfI85kP0x5uYo6KYLEg3sIc1SscRCNO4iI6cRMPsd0GXtm/Z65noPe/Ubsz0PvfU8wz0PuPj3CQ0ePfs7oz8Ar+Paw7A6/gj7fwEQ7hS8Yr+Pfs7Qy8gj824Sm8hF14Cx9h+K7kS8Yr+OMhDN/cN3T942+dkec0h+X+OPckb5eLXXgn515ldxeH8CVndxcPYROewkvYhcV311DUwejcw9t4aijqYHTuoRG/ay/bF6NzD524iYcYxNuYo3MPB9GIdAu6BXYvC77YpTyzF7uUZ+ea8BRewrnO97tjJyfd/tCSh7AJT+El7MK5299XAU8OvDWH8CWPn/AQNuEpDN9fsgtv4SMMX0++ZIPvSR7CJjyF4XuTXXgLH+EQvuT5Ex7CJjyFxRfDcJG4iYeYw3D4b28jhuGAmd55QBiGA07iIjpxEw8xiLcxPwR7SDenGzLB8uyg9y2vHPT+90DqGHr/8RA2YayTZ3NjnZ18yecnPIRNeArnbltu5nHhLXyEQ/iS4yc8hOGbV3JM4SXswvDNc4euB6PrZ3Yuuv6xCU/hJezCuf7M/UcaPM7jmrnPeR8OnkiJ77HOmUiJx/D15CkM353swvA9yUcYvpF8yUiJ73fGzkRKPE7f7xHMmUiJx+n7PVI5EynxOH2/ZydnIiUep+/KY0RKgJESK48RKfEYvnmMSInH8M1jREo8hm8eI1LiMXzzGJES4J6WPbOnZc/sadkze1r25DxdoRPhmLs0j3AIp6PnDuSrf/EQNuEpvIRdeAsf4RAWXxdf3EV41o+7Bc/dxt2C5w4jMR5fMhLj8RCW+rfUv6X+LfVvqX9L/Vvq31L/kfqP7NsR3yO+SBIcIxIDxxhSf0j9SIzHU3gJS/0h9YfUH1J/SP1X6r9S/5X6r9R/Zd+u+F7xRWLkMS4kQx7j+rH+9VvCLryFjzDrXz/Wv8ZPeAib8BRewi68hY+w+A7xRQLgGNHpOEaT+k3qtxDmdbvmT3gIY/2dPIVzfjxLyNuBh5t4Gl9Pn2SsEcm5Bv6/nbiJuQb+2yDeRky8Z0GYeAcacRIX0YmbeIhBvI2bbptur4Nvcu7092zsLHTqzh1Ap4LRqY+HcK6z8+zhtX3nGcBr++NLRqc+HsImnLudz6sWOvWxC2/hIxzCl4xOfQzfvPrQqY+n8BKGb547dOrj9P2ej56F1/zHt9nxmv94CJvwFF7CLryFj3B+y2El3saccXmY33LwRCNO4neF5U0hpt0ebuIhBvE25rTbw0E04iTSzeiG/v4msI+jj/OJo6OPTx4I+vjxEnZhrPNd4Y7X4Xwo6HgdfjyFl7ALb2Hs9k0O4UvG6/DjIWzCU3gJwzfPBV63Hx/hEE7ffDbmeN1+nL75jM3xuv04ffO9r6Pr8806BtwsDzEH3B4eYhBvYw7APhxEI07iItLt0A2J8U0mHkdiPL5kJMbjIWzCU3gJu/AWhm/uPxLj8SUjMR4PYRPO/z7vGTc6/fEQNuEpvISzznxitNHpYLz25hOyjdfexy6M//4kH+EQzq8k5ZLZrA8H8Tt/+a4jB9IKFzG/AJXF5mjqw0MM4m2cP+IgGnESF5Fuk264487ncPmbdX9vg3/JM3kkL2EX3sI3Odd0rJOb4FN4CbvwFj7CkbyTLzk7tHgIm/AUXsIuDF9LPsIhfMkHvnn2zxBO33y6kyNpf4z/fgm78BY+wiF8ydmtxUPYhMU3Z1Xz7WX+yF3hJuY3rfDfBvE24jtreUD4zhrQiJO4iE7cxEMM4i08vx9xELF7Mxm75MnYpZ18yeMnPISxTiRjnZscwpdsP+EhbMK5299Pex0MoxW78BY+wiF8yXnfXQzfk2zCU3gJw9eSN3nlwGqWvIw4iYuINVbyFj7CIXzJ/hMewiY8hZew+Lr4uvi6+Lr4bvHd4rvFd4vvFt8tvkiCvG86SIJ8+naQBI8vGUnweAib8BRewi68hcUX32vPU5gP54H5cP5hDuJlvflw/uEk5thfXkw5K/NwEw8xiLcxZ2UeDqIRJ5Ful24Xu/ddoRhes3xWiOE1+35d7mB4rXgJu3Cuk88BA52dr105jtY8hZewC2/h3O18HQ4kweNLRhI8HsImPIWXMHxH8hY+wiEM3+/sY2ytGL6RbMJTeAm78BY+wiF8yesnLL4ZHSgno+PhIn7nPJ+X5uhb4SF+Vxg2JmdlgDkr83AQjTiJi+jETTxEujndkAn5lDbQ+/liGOj9fN0L9P7jEL5k9Hg+dQ30cj5pDfTy4yMcwpeMV/XHudv5BDbwqv54Ci9hF97CRziE4ZtX/v0JD2EThm+e/buE4Zt7iO5+fJtz6u3vQ5CRPIRz/XxWddH1j5dwrp/PsPJn7pqPcAhfMl7/Hw9hE57CS1h8h/gO8R3iO8TXxNfE18TXxNfE18TXxNfE18QXKZHP9TBXVzyETXgKL+H8XsQv8fbljJG54iFswljSk3nJYzSuOIRR8pcTF7cJj4cwSj7Jk/8WtwmPXVh8XXxdfJ2tdvdPeAibsPhu8UIM5GPKixgA4xbgca65cz8RD4+n8BLO9fPh4EVsPD7CIZy++XAQA3WWD9EwUFe8hLF+ni/Ew+MjHMKXjHh4PIThm3uCeHi8hF14Cx/hEL7F8UMkfA8TA8Ny9j0QDAzLFYfwJaP1Hw/hrPl7qBcYritewi68hY9wCF8yWv97xBYYris24Sm8hF1417mLH1r/cQhf8mv3m7y4b3jxf7yFjzCOxT5eslfo8cdTGDWnL94iPN7C2KuVLOdoyTlyOUcuvi6+Lr7o/ccuLNeGy7Xh4rvFC30983hx+//YhbcwjiWvSfT4zGM8Q9iEcX538hJ2YexV7j96/P3bEL7kEN8Q3xDfmMJL2IW3sPiGeKGvT+4V+vrxEs41I6959PXjIxzCuf43QhkDtwOPh7AJp+83KhkDvf99ETwGev9xCGP973ob6P3HQ9iEp/ASdmH4evIRDuFLRu8/HsImPIWx5ncNYKDOvsemgYG6YhOewkvYhbPmb2gwMFBXHMKXjNf3x0PYhKdw+t48R+j9x1v4CIfwJaP3ce7Q+49NeAqjd25ycN/wmg5Gjz8ewjiWvJa27BV6/PERRs3pi9d3MHr/MfYqr5Mj5+jIOTpyjo74HvE94ovef3zJIddGyLUR4hvihb4e4BC+ZLymP8ax5DWJHh+5z+jxx1sY53cnh/BtxqiefY/FA6N6+LcY1SuewkvYhbfwEQ7hSx4/YfEd4oW+/h5wB8bwikP4W3N+98OBMbziIWzCM3kkL2EX3sIn+bsmMW43vwflgXG7YhPG+it5CbvwFj7CIXzJC76ePIRNeAovYRfewofsWDOvAce/zb11F97CRziELzl7fI7c8+zxYhOewkvYhbfwEU7fkecoe//x+QkPYROewovn7rjwFj7C6J28PsO4bzGFl7AL41jyWgrZq/sTHsKoOX3vFF7C2Ku8Tq6coyvn6Mo5uvTFAF7xEDbhKbyEXXgL0wvDdfnBUmC4rngKL2Eciyfjg5yVfMl47X6M87uTTXgKY69Ossu/3cJHWHxNfKf44nX/sQlP4SUsvlO80NeZ7RiTKzbhPJZvwDUwJlfswls4z/v3EDcwJld8yfmaXpy+35PpmOh9y3OB3n+8hbF+1o/ef3zJ6P3HQ9iEpzB887yj9x9v4SMcwpeM3n88hLFmXgMH/zb39lxy/ISHsAlP4ax55p6jxx9v4SMcwpeM3n88hNN35jlC7z9ewi68hY9w8Nyh95MXev/xEEbv3OTd+4bxueIQvuSBY7Fk7hXG5IpdGDWn7zjCIYy9+q6TZTxHy4awCYuvia+JL17fHx/hEOa1gbG6YvF6ozY7eQsf4RDGsXzX5OIITiyO4MTiCE4s9PjMf4sef3yEsVf47y//7RvBAQ9h8XXxdfF1F97CRziExXeLF/p65l6hrx9v4TyW72PjwLBd8SWjrx/nef8e/8fCa/rjKbyE03flNYneX3ldoffB6P3HWD+vN/T+4ym8hF14Cx9h+OZ5R++D0fuPh7AJT+El7MJY89tzDNLN75F/YJCueAm78BY+wlnz91XucPQ4GD3+eAib8BRewi6cvt/HC+Ho/cchfMno/cdD2PrcOXr/8RJ2YfTOl2+Ovsa+4X7+sQlPYRyLJcte4b798SXj9d3TF6/vj00Ye7WS5RwtOUdLztES3yW+S3zx+v54CMu14XJtuPi6eKGvd9aG0brHQ9iEcSyejMFQ8BEOYZzfL8ccPf54CGOvcv8x+o5/+wZtwS4svkd8j/hyADecA7jhHMAN5wBuvHG6x+KFvvbcK/Q1GH39OI9l5zWPvn48hZdwnved1zZe0x8f4RBO3+/zhcBo3cznzBitK17CWH8lb+EjHMKXjN5/PITh68lTeAm78BY+wiF8yejrfAa+8dqdz4c3evlxCF8yevzxEM6a87OAjR5/vIRdeAsf4RC+ZPR+fkaw0fuPTXgKL2EX3jx36P3HIXzJ6Pf8fAFDe2/fcD//eAsfYRxLXktb9gr37Y+nMGpOX7y+P97C2Ku8Tracoy3n6Mg5OuJ7xPeIL17fH7uwXBtHro0jviFeeE3Pzws2XtPzPm3jNf3xFj7CIXzJ6P3H+ApGer2vwICn8BJ24S18hKP5YKw2X0cOej/vuw56//ESdmEcF9Y5wiF8yej9x0PYhHFcK3kJu/AWPsIhfMn40tzjIbx47CbHhXx4fIRDWI5rynFNOa4px/XyAbyEXViOa8pxTTmuKce15LiWHNcyYdnPJfv5vgqXx77kuJADYNwDPB7Cclwux+VyXC7H5XKduFwnLteJy3FtOa4tx7XluLYc15bj2nKdbNnPLfv5viKXx37kuI5c/0eu/yPX/5HjOnJcR47ryHEduU5CrpOQ6yTkuEKOK+S4Qo4r5LhCjivkOgnZzyv7idzIZxr4lbpiF97COK7vtQC/RpdfTA4M9BWbcO5bfg6Igb5iF859y8/+8Gt09W9D+JKH+A7xHeKL3Hi8hF14C4vvEC+8F8jPIjHcV7yEcSwreQsf4RDOayA/B8RwX/EQNmH4Zj24Z8jPtjDEVxzCWP+7ljDEVzyETXgKL2EXhm+ed9wzPA7hS0ZWPB7CJjyFc838fBC/QzfzMzv8Dl2xCU/hJezCWXN+TodRvuIQvmTcMzwewiY8heGb5wg58HgLH+EQvmTkAM4dcuCxCU9hnJeZHNw33DOAcc/weAjjWPJaurJXeF/w+Ahj/fTF+4JkjPUVY/1I5jnCWF/xEnbhLXyEQ/iSx094CIvvEK/3UxsjOYQv+f3UBhhr3uTMjfxs5b6f1ABv4W/9lZ8DYjSv+JKzx1d+9nffT2rkv30/qQGewuI7xXeKL+4HHofwJeN+4LH4LvHKvl4/8BEOYRzLd81jZq94CJvwTPbkJezCWxi+3zWJ2byVn21hNq/YhLF+Xm97CbvwFj7CIXzJB7553s8QNuEpvIRdeAsfcvb1wjWWr+ML+5+9XLyFj3AIX3L2+MrP6TCbV2zCU3gJu/AWPsLwzXN0b/HFj90VD2ETnsKrzt3Fj+AVb+EjjPMyPx5W+3Yxs1e8hF0Yx7KTe68uZvOKhzDWT1+bwksY60fyln97hENYfKf4TvGdJjyFl7ALi+8Ur/dDWLnP74ewwFN4CWPNmxz/eD/qdd/P34Hx83ePs+bvc8CL2bziKZw1W+4/fn/2/dstfITF18V3iy9+Lu+xCU/hJSy+W7zQ15Z7hb5+bMI4lpW8hF14C+d5t9zPfE0vvuT4CcM360HvW15X6P3HWxjr5/WG3n98yej9x0PYhKcwfPO8o/cfb+EjHMK3GfN7xUM41/w+H7yYzVvfZ3YXs3mP87W7eAib8BTOmr/P6S5m84q38BEO4UtG7z8ewvD15Cm8hF14Cx/h6HOHH8p7jN5/PIRxXmby5r7NIxzCl7xwLDtZ9motYRfG+umL1/fHIYz1v+sEs3nv37qcI5dz5OLr4uvii9f3x0dYrg2Xa2OL7xav9zOYeezvZzDBRziEsWZek+/nLnOd93OX4CWcNX+fA17M5hUf4ax55frv5y7z376fuwQPYfEN8Q3xfT93Cd7CRziExfeKF/p6gV14C+NY8ppHXz++zZjZK87z/n0OeDGzVzyFlzB8dzLWP8mXjN5/jPUj2YSn8BJ24S18hOF7ky8Zvf94CJvwFF7CLpxrfp8PXszmre8zu4vZvOIl7MJb+AhnzZ57jh4Ho8cfD2ETnsJL2IXhm+cIvf84hC8Zvf94CBvPHXr/8RJ2YZyXL98ws/f2Dffzj014CuNY8lrasle4b398yXh99/TF6/tjE8b6eZ0cOUdHztGRc3TE94jvEV+8vj8ewnJthFwbIb4hXu/Hq3Ov3o9Xg4ewCWPNvCbfj1TnuX4/Ug0O4az5+xzwYjaveAhnzd9nfxezefi3mM0rduEtfIRD+JLxk/WPh7AJi+8QL/T191nkxczeY/T1YxxL/vfo68dTeAnnef8+B7yY2Ss+wiEM3++axGze+j7bupjNK17CWD+St/ARDuFLRu8/HsLwvclTeAm78BY+wiF8yejrk9cAXrtP7i16+XEIXzJ6/PEQzppP7jl6/PESduEtfIRD+JLR+yfPEXr/sQlP4SXswpvnDr3/OIQvGf2e/YiZvbdvuJ9/vIWPMI4lr6Ure4X79sdTGOunL17fH29hrJ/XyZVzdHmOMJtXPIRNeAovYRfewkeYvpjZK86+zmxf/BMVFzN7xVsYa37X5OKfqLiLf6LiLv6JiovZvPV9jnAxm1fswllz3h+u9ycq8G9D+JKn+E7xneL7/kQFeAm78BYW3yle6OsAT+EljGNZyVv4CIdwnvfvs4OLmb3iIWzC8N3JWP8kH+EQxvrf9bbQ+4+HsAlP4SXswvDN847efxzCl4zefzyETXgK55o3rwG8dt/cW/TyYxOewkvYhbPmm3uOHn8cwpeM9+yPh7AJT2H45jlC7z/ewkc4hG8zfiAP5w4/kFdswlMY52UmR+8bZvYeo8cfD2Ecy07mXmE2r/gIY/30xes7GK/vj7F+JPMcYTaveAmLr4mviS9e3x9f8vwJD2HxneKF1/Tv84KLmT3/nvlfzOw9ztf04iFswlN4CWee5PsszOwVH+EQvuT3d6TAQ9iE/9bPv+d0c0yv8BBxUHmwfsn7JzyETXgKL2EX3sJHWHy3+B7xPeJ7xPeI7xHfI75HfI/44m9b5IMRDPU9xpv9x0MYvtkseFOfD1LwW3jFRxjHtZIv+f6EcVx5gnDzj3+Lv1zzeAmL7xXfK754U/D4Nu/3J+XAQ9iElzD2aieH8CUPHEv+92MIm/AUxjm6yS68hY9w+n5f2rr5C3t/PJJNeArn+vnAPH9lr3kLH+EQvuQMh2L4zmQTnsJL2IW38BEOMsIhP0DB8J7nhxoY3is+wiF8yf4TRs25527CU3gJu/AWPsIhDN88R8iHx0PYhKfwEnaeO+TD4yMc5JcJJ3ly39D7j114C+ea+UEGBvneXsUQNuFcPz/swIBfsQvn+vnhAgb86t/KOQo5R1d8r/he8b1TeAnLtXHl2rjie+mFob78U5oXQ33FS9iFcSwzOXMjP8jA8F7xEM6a84MSDO8VL2HsVa6Pm//3b49wCIuvia+JL94UPJ7CS9iFxdfEC3392ISnMI4lkl14Cx/hPO/5QQkG9h7jxuDxEE7f70tbF7/D5/nwH7/DV3yEc/18YI6Bvcfo/cdD2ISn8BKGb5539P7jIxzCl4zefzyETRhr5jWA1/f8UAPDeMVD2ISn8BJGzbnn6PHHRziELxm9/3gImzB88xyh9x+78BY+wiF8ee7Q+4+HsAnjejvJh/t2Q/g2YzCvONfMDzIwgIe9wgBe8RbO9fPDDgzgFV8yXt/zwwUM4L1/O0x4CovvEN8hvnh9fxzCvDbwC3zF4mvihdf0fPiMATzPDzUwgFd8yXhNfzyETXgKZ57k69T7Y7GPt/ARDuFLxl+zejyEc/28D3x/RPbxFj7COK4817jJ/4FNeArnucgPa/DHYou3MPbtJIf820t+fwgeLL5bfLf4vj8ED3bhLXyExfeIF3o/P/TBAF6xC+exeF7z6P3HIXzJ6P18AIUBvGITnsLpmw9w8Bt77nm9occfXzJ6PD+UwTBesQlP4SXswlsYvrknyIHHtxlDesVD2ISn8BLGmt81gEE7zw9QMGhXPIWXsAtv4aw5P3TAMF7xJaPHHw9hE57CSzh984MMDOkVH+EQvmTkwOPR5w5DesVTeAmjd27y5b7h9f3xEDZhHIsly17h9f1xCKPm9MXr++MhjL1ayXKOXM6Ryzly8XXxdfHF6zsYr++P5drYcm1s8d3ihfv2/GAFA3iP8br/eAjjWHbyFF7CLvx3LCefg+b8XWEQb+PX94WDaMRJXERcTnn60PKPLxkt/xiHk4ePln88hZfw3+H4AW7iIQbxPvzLx6/dm4ewCWOrLsRWcVSEiisCr/0l8gi+b6d9Ilf7Pub4RK72fQbwiVBxRaDbv691fWKoyI36Puj5xFSxVOTxfJ/jfGKrOCpCxRWBvi8xVKCCDTFVLBWuYqs4Kr5z5tgcZMHbNoRBCd1QPAf8PuP5hKvYKo6KUIEDxZlHWJQYKkxFVhCoAIFRwlVkBYGziMwoESqygsApRWyUGCpQAS4qJEfg/OKxQOCMIEcCG4o3ECWOCERJYA+QJSVMxVQBH+wB7hnelYybhhJXBG4bSpiKr4MXdup7Q9B8hL8LYr3//pK/5GgewiY8hZewC29hnIbcX4zwtRgqTEVuz/1BLBWuYqv4jm9ucAhf8hcgzUPYhKfwEnbhb/1xwJeMSLkDYqgwFVMFDs8gXMVWcVSEiivii5R8IvbxEDbhKbyEXXgLH+EQvmQkyZ0QU8VS4SpwfAviqAgVV4Tn8eFYfQib8BRewi68hQ8ZOXEdYqgwFVPFUuEqPpcfjvaLieYQvuQvPZqH8Hd0P+zAFx3NS9iFt/AhIzUuLmK8q7i4cvG2ooSryLXePznCIXzJmSHFQ9iEp/ASdmHxveJ7xffSN6cIm4ewCU9hXH0BcVSEiisCNyD3QgwVpmKqWCpcxVZxVHwV7N8P4orIhGkxVFiKATFVLBWuYvNE20uYJ0LFFYGblhJDhamYKpaKkxUYRKi4IhaOdELgSBeEqZgqlgocqUNsFUdFqEAFKNRRAU6JDxWmYqpYKlzFVnFUhIorYmsFXxqteGzCU/jPfuEFMX92sHkLn++/xwX9BVHzJX9B1DyETXgKL2EX3sLie8Q3n3rsgeIyhzbCGD82uAcugXy42eKoCBEXq+F0XqyGhr+uYqs4KkLFpcAM48YLHoYYW5iKqWKpcBVbxVGBChbEFTF+KoYKVHAhpoqswAZEVmATYqs4KkLFFYH8KTFUmIqpYqnQCiwvS+zuFz/NIfxdloiO/NXC5iH8XZZ4zc3JyOYl7MJb+AiH8CWvn/AQFt8lvkgbw6lBphiOBpliKBuZUsJUTBVYDacT+TCzWzD92GKoMBVTxVKRZ2MaxFZxVISKK+L8VAwVpgLHg+v7LBWuYqtABbhSTqhABdjR+KkYKkzFVLFUuIqtAhVg45EyJa6I+1MxVJiKqWKpyEsTR3238BEO4ducw5XN6YD3eJiW3HgThnHJFnkH9f6rS853R8VD2ISn8BJ24S2cG7XyKsBQ5V4TYqgwFVPFUuEqtgoc4IIIFVfE/KlABQ5hKqaKpcJVbBVHBSrYEKggmxl/d7jFUGEqpoqlwuVULj3JS08ybmtKXBGIoBJDhamYKiSCMJvZIlRcEQinhUtTI2hpBK0XQU/geN4CR0WoSB/HvzkSgusMFaZCKzhawdEKEEEljopQITG8QisINUW24NEbZjZbHBW5tONSRrY8gWwpMVSkj+NSRraUWCpcBSrANYp7G89rFHOaLYYK+ByIqWKpcBVbxVERKlBBXiGY6mwxVJiKqWKpcBVbBHJn/yBygT0glgpXsVUcFaEiD2HnKcEAZ4uhwlRMFUuFq9gqUMGCCBVXBNKlxFBhKqacYKRLCVexVeDMZZJjpLN2FLFRYqpYKnBwDqGbiNh4ArFRAj6oAPc0JaYK+OCq2noat57GradxawVbKzhaAQKlhKnQC+nohXS0gqOmSAq8O/EYKkzFVIGlcSmHvFXxCBXyVgUTnRuflGCks4WpSB888nd9s+T6Zsn1zZLrmyXXN0uub5b2e7P0xFBhKqaKpWKryKXxhBsjni2Gilwan+JgyrPFUuEq0gcf6WDSs0WouCIQKPisBtOeGx+1YNyzhauAz4E4KkLFFYFAKTFUmApUEBBLhavYKo6KUHFFIFBK5NL4FAYDoDuw8QiHElcE7jZKDBWmIg8BH8lgDrSFq9gqjopQcUUgUEqgApxGBEqJqWKpcBVbxZETjEApcUUgUErgzBmEy47i1qPEUREqcHC4+EI3EbFRYqmADyrAfUiJowI+uKpCT+PV03j1NF6t4GoFVytAoJTYKvRCunohXakAvw7ZAksHBJa+EFvFUREiEBslcjU8HsOAaItcDZ/UYBR044MWzHZufJKB4c4WW0VWgA8vMOvZ4opAoz8fNHr9X0zFVLFUfG8hHYeTTzeKj3CQlx4/7g3eIePeoITuzMq1cFxoeDzuwNznxvMaDH62GCpMxVSxVLgKbOaBOCpCBSrA9YCGx6N0zIAevBvFEOjBw+/82caFG+P82cZmF/62DK/DmBQ9eDqNUdGDp9OYFW1hKqaKpcJVbBUnBQrIzm9xRQQqQG2BCrBngQqwM4EKsDNfJqzx/isX3sJ/JvNt69f1zUM4HfDIFj/j2CKPEc9v8UOOLbaKPEY8ssUoaYtLgWHSg/3HNGkLUzFVLBWoICC2iqMiVFwR46diqDAV8LkQ8e0U/g/5lOPYD8JUTBVZNB7S4jcdW2TRZhBHRajIovFYFXOlLYYKUzFVLBWuAhUsiKMiVFwR66diqDBuzoINTtXaKo6KUAGbvFbxS48thgpTMT9P7PQXNc0uvIWPcAhf8v4JYyMPxFLhKraKoyKPcOKMI2eeQM6UGCpMxVSRFUzsF3KmxFZxVKAC7Bdy5gnkTAlUgKqRMyWmClSAdsh7j4OnkvgT0QfPAzG/2iJUXBF579FiqEgfPHPDtGqLreKoCBWXAr/1ePDACj/22AKmFyJN8eQG46YttoqjIlRcEehivK3GUGgJdHGJocJUTBVLhavYKo4KrWBqBUsrWFrB0gqWVoA2xl0CBkYPXksxMXrwNAEjoy1MBVY7EEuFq9gqjooQgZd/PAfCDzYe3AFhMPRsVI3WLHFU5Gp4+46h0RJozRJDhamYKrICPNPB6GgLVICtQmuWCBFoQDxEwY85HjwDwa85tsBqPwishg1Bm5W4ItBmJeCDfcPLfYmpAhVgR9GAJbYKreBqBZcVDPy4Y4uhwvqcDvy+Y4ulwlVsFUcEejsvioE5UlwUAz/tiFM/8NuOLbaK0+d0YMK0xRVhPxVDhamYfR0MTJi28D71AxOmLY4IJEVeFAPTorgOBqZFW3hfFAPTorW986gIFXp+kAcb+7aGClMx+9QPDJK2cBVawdIKllawtALXKwStebCJaM0n0JolstCDHUVrlpgqlgpXsVUcFaHiisCr5kGhaNoSpmKqWCpcRVYQOB60c4lQcUWgnQMXLNq5hKnICgJVo51LuApUgOsN7VwiVFwKDHuefFAxMNJ58jnDwEhnC1exVcAnIOBzIdInb78GftuxxVBhKrKCfI898PuOLVzFVpEV5Hv5gd91PBfHg96+KBS9fVFo9nb8sED2doulwlVsFUdFqLgp8szhJx5bjBQoZ5qKqWKpcBVbRVYwsG+ZBy2uiMyDFlnBQKGZBy2miqxgoOrMgxZbBSrAhbRQAWpbV4T/VAwVpmKqyAoMPnlP0WKrOCpCxRWRDxtaDBWmYqrQCrZWsLWCrRVsrWBrBUcrOFrB0QqOVnC0gqMVHK3gwAdnIX4qhogLHzTGnSrgg42/rmKrOCpCxaXAD0W2GCpMxVSBCg4EKgiIreKoCBVXxPipGCpMxVSxVGgFQysYWsHQCoZWYFqBaQWmFZhWYFqBaQWmFZhWYFqBaQVTK5hawdQKkC45CzAw5hn5ofjAmOe7xDDm2WKowGoDYqpYKlzFVnFUoIInrghkyIQpMqSEqUifnEAaGNmMuSCuiJcHONKXB7j4Xh48MVXoNYo8yLflA38uusVRIV1iW7vkaJccreBoBUcrOFrBywOIQAVPHBWhAq9M2J37UzFUmIqpYqnAHuBCQlKUOCpCxaXAqGaLoSJ98tHEwEBmi63iqAgVVwTyoMRQYSqmCq1gaAVDKxhawdAKhlZgWoFpBaYVmFZgWoFpBaYVmFZgWoFpBVMrmFrB1AqmVjC1gqkVTK1gagVTK5hawdIKllawtIKlFSytYGkFSytYWsHSCpZW4FqBawWuFbhW4FqBawWuFbhW4FqBawVbK9hawdYKtlawtYKtFWytYGsFWyvYWsHRCo5WcLSCoxUcreBoBUcrOFrB0QqOVhBaQWgFoRWEVhBaQWgFoRWEVhBaQWgFVyu4WsHVCq5WcLWCqxVcreBqBVcruFLB+v1UDBWmYqpYKlzFVnFUhAqtQDNxaSYuzcSlmbg0E5dm4tJMXJqJ+LPakQOKA3OmJZCJJYzpv14MPrFUuIqt4qgIFfKSs+ZPxVChFUytYGoFUyuYWsHUCqZWMLWCpRUsrWBpBUsrWFrB0gqWVrC0gqUVLK3AtQLXClwrcK3AtQLXClwrcK3AtQLXCrZWsLWCrRVsrWBrBVsr2FrB1gq2VrC1gqMVHK3gaAVHKzhawdEKjlZwtIKjFRytILSC0ApCKwitILSC0ApCKwitILSC0AquVnC1gqsVXK3gagV6A7j0BnDpDeDSG8ClN4CuN4CuN4D+MxVTxVLhKraKoyJUaAVDKxhawdAKhlYwtIKhFQytYGgFQysYWoFpBaYVaCa6ZqJrJrpmomsmumYiBmIjh+oHBmJLIBNLZAU5Ez8wENtiqsgK8iO5gYHYFlvFUREqrghkYn5yNzAQ28JUTBVLhavYKo6KUHFFuFbgWoFrBa4VuFbgWoFrBa4VuFbgWsHWCrZWsLWCrRVsrQCZuHC2kYkljopQcUUgE0tkBfnx58BEbYupIivITxUHJmpbbBVHBJIvP3wcGKKt1ZBvJVwFVsPlgnwrESryeBzXKPKtxFBhKlDBgVgqXMVWAZ/cKozKBj6bwqhsi6UC5+dAbBVHRai4IpBVJYaKrAAfe2GitsVS4Sq2iqMiVFwRyKoSQ4VWYFqBaQWmFZhWYFqBaQWmFUytAFmFz+cwa9tiqlgqXMVWcVSEiisCWVVCK1haAbIKnxBiJDfwOSB+q7XFVnFUhIorAllVYqgwFVOFVoCswudzGNZtcVSgAoe4IpBVJVABLnJkVYmpIivAR2UY1m2xVRwVoeKKQFaVGCpMxVShFSCrDjoYWVXiqAgVVwRSrMRQYSqmiqVCKwitILQC5FtOFQ9M+5ZAvpXICvAxHqZ9W0wVS4Wr2CqOilBxKQ7u30oMFaZiqsAeXAhXsVVkBTnGOzAU3OKKQCbioz+MC7cwFVkBPvrDIHELV5EVXFSATCwRKq4IZGKJocJUTBVLhavQCkwrMK0gM/Hic0CMJbcYKizFgZgqloqvgouP8fATtS2OikiB05iZWCIzsUVWMFBoZmKLqSIrwANw/IZti60iK8CHAJhnbnFFZCZefAiAeeYWpiIrwKMJzDO3cBVZQQ7DDcwztwgVWQFegzHP3GKoyApwX4U/Q99iqcgKcFOCH79tcVRkBf6WviIyE1tkBXj9wbRzi6liqXAVW8VRESquiMzEFlpBaAWhFWQm3oMdzUxssVVkBRgWwU/ltrgiMhMvohO/ltvCVGQFL2ruUuEqsgLMYGAaukWouBSYhm4xVJiKqWKpcBVbxVERKrSCoRUMrWBoBUMrGFrB0AqGVjC0gqEVDK3AtALTCkwrMK3AtALTCkwrMFRwIELFFYFMxFAKhqtbmIqpYqlwFVvFUREqroilFSytYGkFyMT8fsjAT/u2cBVZAaZaMHfdIlRkBRd7gEwsMVT8VWD588CfmCqWCk+Bpb9MpDgq4hOYHMnp6xZfJlKMFDiN21RMFbgfvRC468RW4Z6vxFBhKqaKpcJVbBV5PPl9hpFT1hRXRPxUDBWmYqpYKnJHMeKSU9YURwUqwFmIK+L+VGAPfhCmYqpABTj1Fz447BsqLkX+MDDFUGEqpoqlwlVsFUdFqNAKhlYwtIKhFQytYGgFQysYWsHQCoZWMLQC0wpMKzCtwLQC0wpMKzCtwLQC0wpMK5hawdQKplYwtYKpFUytYGoFUyuYWsHUCpZWsLSCpRUsrWBpBUsrWFrB0gqWVrC0AtcKXCtwrcC1AtcKXCtwrcC1AtcKXCvYWsHWCrZWsLWCrRVsrWBrBVsr2FrB1gqOVnC0gqMVHK3gaAVHKzhawdEKjlZwtILQCkIrCK0gtILQCkIrCK0gtILQCkIruFrB1QquVnC1gqsVXK3gagWaiVcz8Uom2k8y0X6SifaTTLSfZKL9JBPt9zLxQmwVR0WouCJeJj4xVJiKqSIryGkt+yETS2wVWUFORNkPmVjiikAmlhgqTMVUsVS4iq1CKzCtwLQCZGLONNoPmVjCVGQF+e7QfsjEEq5iqzgqQsUVgUwsMVSYCq1gaQVLK0AmTpwFJN87BORbfr/Pfsi3ElhtQ7iKreKoCBVXBPJtYXuRbyVMxVSRFSwcAvKtxFaRFSwcHPKtxBWBfFs4OORbCVMxVaACbBXybeF4kGL55tt+SLEnkGIlhgr4oGWQYo4jRYo5CkWKOSpAipU4KkJFVuAoFClWYqgwFagAx4PgchSK4HIECoJro1AE14YpggtiILhKDBWmYqpYKrKCfHpsA8FVInjBjp9cvWP8VAwVpmKqWCpcxVZxVGgFQyswrcC0AtMKkFX57RsbyKoSrgKHfSCOilBxRSCrSgwVpmKqWCpchVYwtQJkVT4psYGsegJZVWKoMBVTRVZwsDvIqhJbxVGBChziisD9WwlUgKqRb/lExgbyrQQquBCuIisIFIp8KxEqrgjkW4mhwlRMFUuFq9AKtlawtYKtFRyt4GgFRys4WsHRCo5WcLSCoxUcreBoBaEVhFYQWkFoBaEVhFYQWkFoBaEVhFZwtYKrFVyt4GoFVyu4WsHVCq5WcLWCKxXY76diqEAFA2KqWCpchdw52O+oCBVy52Djp2KoMBVTxVKBI80XI0O+zSdwPBPCVEwVS4Wr2CqOCKRYfl3MbMr5sam7M3V3kFUljgqcH4e4IpBVJYYKuUJsaQVrqXAVW8VRESqu1IasKjFU6BWCrHq1IatKuAqtQLPKNKtMs8o0q0yzyjSrbOs1uvUsbD0LW8/CyyrUtvUsbD0LmlWmWWWaVaZZZZpVplllmlV29Dp4WfWEnoXQsxB6HbysekLPgmaVaVaZZpVpVplmlWlWmWaVaVbZ1evg6lm4ehaunoWrZ+Fl1YYIFaggXxvny6onhgpTkRXkVydtIqtKuIqt4qgIFVcEsqpEVpBft7SJrCqB+zeH2EyKiazKz2lt4i6txBWBFCshZ3uaqZgqlgpXsVUcFXK2p8nZnvOnYqgwFVPFUuEqtgocaeboRL6VGCqwo9g35NtF1ci3Eq5iqzgqQsUVgXwrMVTwGbHN98Tsia3iqAgVV8R7YvbEUGEqpgqtYGsFWyvYWsHWCrZWcLSCoxUcreBoBUcrOFrB0QqOVnC0gqMVhFYQWkFoBaEVhFYQWkFoBaEVhFYQWsHVCq5WcLWCqxVcreBqBVcruFrB1QquVLB+PxVDhamYKpYKV7FVHBWhQisYWsHQCoZWMLSCoRUMrWBoBUMrGFrB0ApMKzCtwLQC0wpMKzCtwLQC0wpMKzCtYGoFUyuYWsHUCqZWMLWCqRVMrWBqBVMrWFrB0gqWVrC0gqUVLK1gaQVLK1hawdIKXCtwrcC1AtcKNBOXZuLSTFyaiUszcWkmLs3EpZm4NBOXZuLSTFyaiUszcWkmLs3EpZm4NBOXZuLSTFyaiUszcWkmLs3EpZm4NBOXZuLSTFyaiUszcWkmLs3EpZm4NBOXZuLSTFyaiUszcWkmLs3EpZm4NBOXZuLSTFyaiUszcWkmumaiaya6ZqJrJrpmomsmumaiaya6ZqJrJrpmomsmumaiaya6ZqJrJrpmomsmumaiaya6ZqJrJrpmomsmumaiaya6ZqJrJrpmomsmumaiaya6ZqJrJrpmomsmumaiaya6ZqJrJrpmomsmumaiaya6ZqJrJrpmomsmumaiaya6ZqJrJrpmomsmumaiayY6MjF/asUcmVgiVFwRyMQSQ4WpmCqWClehFWytYGsFWys4WsHRCo5WcLSCoxUcreBwdsXedx5KhIorAnPEJYYKVBAQU8VSgQrev9kqjopvD0b+xKrl9yRaZCa2GCpMxVSxVLiKreKo0AquVJA/Q04xVJiKqWKpcBVbxVERKrSCoRUMrWBoBUMrGFrBQAUDAhVMiKMiVFwR9lMxVJiKqWKpcBVagXGm3t53K0pcEZMT7fa+W1HCVGCifUMsFa5iqzgqQsUVge9WlBgqTIVWsLSChb3ON9L5PYnv4yoI7CiO1E3FVLFUYLXsn/zOw/epFsRQYSqmiqXCVeT5yZE3y+88UISKK+L8VAwVpmKqwPHgzB1XsVUcFagA1865It53HnCRv+88PGEqpoqlwlVsFdgDnDmkS86T20a6lNgq8C0F7OgNFfyehNW3FJ4YKkzFVLFUuIqt4qgIFVrB0AqGVjC0gqEVDK1gaAVDKxhawdAKhlZgWoFpBaYVmFZgWoFpBUgXvPDntxQo8tqx959dEXnHNfJ3fiy/pUBhKqaKpcJVbBVHRai4IpZWsFCBQZgKflvF8C2FFq5iq4BPdslBuuDTZXzjAN8vMXzjoIWr4Pc+DN84aBEq8M0T7DW+hVViqDAVU8VS4Sq2iqMiVGgFRytA7uBJ8EG62Pu/4PzgSJEuJa6I+KnI1SaunbyrGfgM7CApSoSKKwJ3NSWGijw/EycLdzUllgpXsVUcFaHiUgTuavK3tSxwV1PCVEwVqGBBuApUsCGOilBxReCupsRQYSqmiqXCVWgFg98MsvdNgBJXhPGbQfa+CVDCVOCbQdg3fBOghKvYKo6KUHFF4JsAJYYKU6EVTK0A6ZK/oGWBDJk4WcgQTEQFMqTEVLFU5GqYewrcoWCgKXCHUsJUTBVLhavI87Owo7h3KREqrgjc1ZQYKkzFVIEKBoSr2CqOClSAawd3NU/gW0sYVgzEBmayMJTfIlRggUwKDOW3yBNsWBpfOioxVSwV8EEFiA3MfmHAHl8xMwzYt5gq8EUynFN8gajEVoGvsr2lQ8WluPgCUYmhwlRMFUuFq9gqjgqpAAP2I79sbxijHxhfwxj9wFwaxuhbHBUhAm9fML6GkfiB8TWMxLfYKo6KUHFF4DYiv1JvGIlvYSqmiqXCVWwVRwUqcIgrAhFQYqjICjCOh5H4FllBfm3dMBLfYqs4KkLFFYHYKDFUmIqpQiuQLzsafqO9xVHBLzvafV92hHhfdnwC12hAmIqpYqlwFVvFUREqrgjERgmt4GgFeMuDMUaMt4+Nk4UMwXAfxttbDBWmAqthadx64FkNRtVLIENKDBWmYqrI84M3QxhVb7FVHBWh4raYGFVvMVSgggMxVSwVrgIVGMRRgQpWCmTIwb/BDUY+MpgYSG+xVGTV+bZiYri8xVBhKqaKpcJVbBVHRajQCia/xDt/c6gwFfwS78Svt7dwFfga8YY4KkLFFYGvDZYYKkzFVLFUuAqtYGkFyJDARYGkyHGvieHyETinuMEosVUcEbiNCCyNm4XAVuFmoYSr2CqOilCB83NT4BFIiaHCVEwVS4Wr2CpQgUOEiisCSVEiK7i4dpAUJbKCiy7Jx7UtXMVWkRVc7CjSpcQVgXQpMVSYiqliqXAVW4VWgDuUg+PBHQoEfjK+Bb5kPSBMxVSBL5pfCFexVRwVoeKKwFecSwwVpmKq0AqGVoB7l5yEmRgUH/medmJQfOR79IlB8RZLhav4VrMfdifvUOyHPcg7lBZTxVLhKraKk2JChIorIu9QWgwVpmKqWCpwPNgd3KGUOCpCBSrIawdD3y1wPBkOGMa2H7ZqDxWmImsb2MTMkBauYqs4KkLFFZEZ0mKoMBVaAX4mwXEIx1VsFXn1Oq6dEyquCPxMguN6wzuWEqZiqlgqXMVWcVSEiiviagVXK7jYa1xvFzuKi+JiR3FO76XAYHWLoQKrbQisdiBCxRUxfiqGClOB83MhlgpXsVUcFaHiirCfClTgEKZiqlgqsoJ88DkxWN0iK8gnjdOQFCWuiHyX0yIrMOwoMqTEVLFUuIqt4qgIFVcEMqSEVoD7ENy/4RffWywVeY0ebCLuQ0ocFXiVwTnFzxc8gZ8vKDFUmIqpYqlwFVvFUaEVuFaARDKcU+SOvf8LdhRHitwpESquCKTLxHWQ9yGWzw8mhqRbHBWh4orI+5AWeX7ysePEkHSLqWKpcBVbxVERKnA8OHP3p2KoMBWoANcO0qUEfBAOSJcSlwKj0C2GClMBnwOxVOBIA2KrQAUXIlRkBfkGd2IUukVWkI+1JkahW2QF+WhvTiRSiawgH9NNDEm3yAryW4wTQ9ItUEFefBiSboEKcNhIpBKoAIeNRCqBCnDYSKQSqACHjUQqkRU4DhuJVCIrcBw2EqlEVuA4bCRSiazAcdhIpBK453siVFwReGdUYqgwFagAm4i7mhKuAhVgd/KupkWouCJwV1NiqDAVU8VS4Sq0AtcKcI/kOD+4E3KcEtwJbZwFJFKJreKoCBV6PEeP5+jxHD2eo8dz9HiOHs/R4zl6PEd39GgFoRUgq95hI5HeYYceT+jxIJGeQCKVGCr0eK4ez9XjuXo8V4/n6vFcPZ4rx4OB5xZDhamYKjYPG8PL77AxvPwOAcPLLUzFVLFUyPFgeLnFUREq9HhMj8f0eEyPx/R4bKnQCkwreOmCw34ZgsOeejxTj2e6iq3iqAgVuEIynjCI3CIzJL9MN9f7UaYnpoqlAj4QyAPkDn5IHT8/NfFD6i2mCqyGw8YdSomtIjMRD1TwQ+otrgg8hy0xVJiKqWKpcBVbhVawtQIkRX4BfGJA2Pb7v+D84EiRByWOihCBexe8E8ewr+HJAoZ9W2wVR0WouCKQB3hUiWHfFqZiqlgqXMVWcVTgeHDmkAcQGPZtMVSgggkxVaACh3AVW8VRESquCGRIiaHCVEwVWgGelOCZEH7gvMVRkVfIff/misBHwCXyGr04UnwEXGKqWCpcxVZxVISKKwJPdUtoBVMrQLrkJNnE4K7hvQwGdw3vWDC422KoMBW5Gh6wYgjXkCEYwi2BDCkxVJiKqSLPDx69Ygi3xVZxVISKKwJ3GyWGClTwg5gqlgpXgQpwtnEfUgIVYHdwH/IE7kPw5BRDuHaxb/gsBw/j8MPjLZYKV7FVHBWh4orAE5kSQ4VWEFoBsupdO8iqElvFUREqrghkVYmhwlRMFagAJwtZVWKrOCpCxaXA2KzhISbGZluEiisC6VJiqEDVF2KKyHuKieejGHRtYSpmCoNYKlxFDjzjSePG8H+JUJFD3/mDhXNj+L/EUJEj13gKujH8X2KpcBVbxVERKq4IDP+XGCq0gqUV5DuWWeKmQNWOHd0QQ4WpmCqwGk6WYzWcn/1TMVSYiqliqcjzg0eIGHRtcVSEiisi86DFUGEqUMGBWCpcxVaBCnDtnFCBCrCjgQrwb2KoMBVTxVLhKraKoyJUXBFXK3hfVMJhvy8qPTFV4MsZOJ73RaUntgp8PQRt9r6o9MSlOO+LSk8MFaZiqlgqXMVWcVRIBTkc+31bHCJ31N7/JXc0pzdnjsBSHBUhAumSY5nzIEPwEPMgQ0psFUdFqLgiMkNmThBNjLO2MBVTxVLhKraKowIVGMQVsX4qhgpUcCCmCozeX4grAn9UoMRQgdWemCqWClexVRwVoeKKQO6UGCq0gq0VbK1gawVbK9hawdYKtlZwtIKjFRytALmDp7oHuYPnsAe5U2KrOCpCxRWB3CkxVJiKqUIrwIA9PlDGD2i3OCow0ovGwB8VeAJ/VKAEhoqxNH5gtsRUsVS4iq3iqAgVlwI/oN1iqDAV2GuDwI4uCOxoJjlGYFsMFaYCqx0IrBYQVwTuXUoMFaZiqsjzg6fHgdwpsVUcFaHiikDulBgqUMGGmCqWCleBCrCjyJ0SqGBCXBHInRJDhamYKpYKV7FVHBVaAT4Zwr3L+2HrEkNF3q3jtT7w3KXEUpHvF3D3FHjuUuKoCBVXBJ67lBgqTMVUsVRoBVsrQCLhQ4BA7uDpfiB38EA/kDslXMVWgdUyuPAj1RPP8PEj1S2WClexVRwVeX7wdB8/Ul0C9y4lhgpTMVUsFa4Cx4NmukdFqLgU+Pnqic8X8PPVLVDBgnAVWwWOdEOEChxpbi9+pLrFUAEflDOmiqXCVWwVR0WouCKQSCWGCq3AtALTCkwrMK3AtALTCkwrmFrB1AqmVjC1gqkVTK0AiYQnwZjIbREqrggkUomhAt9E+0Fs9sJ9UfNEqJCWwajtxKNkDNS+yx8DtS1cRfrgITN+Y7pFqEgfPErGb0zXArj5KWEqtIKtFWytYG8VR0WouCKOVnDUFOmCx9z48egWRwUOziGuCNzVlBgq0gdPj/Hj0S2WCleBCtBmyB08U8XcbYuhAj44p8idEkuFq9gqjopQkRXkJbYwd9tiqDAVU8VS4Sq2CERNPnFeGKid+cB4YaC2havYKo6KUIFD8BQIlBJDhamYKpYKV7FVoIINESquCARKiaHCVMw+wQu/8NzCVWwVOHMrBZLi7SjuXUpMFUsFDu5A6CYiNp5AbJSADyrAu6kSUwV8LoSeRtfT6HoaXStwrWBrBQiUEqZCL6StF9LWCraaIikm9gBvk0qYiqkilw5cyu/NEA77hIorArGRT9AXRm1bmIr0CZyf92boLeAqtgqtILSC0AruT8VQYSqmCq3gqimSIqesF36TucVQgYNziKliqXAV6ZOfz62Be5cSoeKKQKDkx5ILP8M888PHhZ9hbuEq4HMhjopQcUUgUEoMFaYiK8gPARama1u4iq3iqAgVVwQCpQSWNggsgI1HOJS4InCDUWKoMBU4BJwSxEYJV7FVHBWh4opAoJRABTiNCJQSU8VS4Sq2iiMnGIFS4opAoJTAmVsQLjuKW48SR0WowMHh4ju6iYiNEksFfFAB7kNKHBXwwVV19DSGnsbQ0xhaQWgFoRUgUEpsFXohhV5IoRVcNUVS2BOuYqs4Kr6lV35EsjBqiweSC79h3GKqWPlvBoSr2CpOCoMIXeCKQGyU0AqGVjC0grFUuIqt4qjQCkxNMylWfhCyMHfbwlXg4BziqAgVV0QmxcqHCQtzty1MxVSBCg4EfAIiVFwRCz4XYqgwFVPFUuEqtoqsYOAKyUBpcUVkoLQYKkzFVLFUYGlcLhsLYOO3qZgqlgpXsVXgEHBKdqi4Is5PxVBhKqaKpQIV4DSereKoCBVXRPxUDDnBYSqmiqUCZw7XdVzZ0ftTMVSYChwcLr6rm3iPilABn6wA07Uthgr4XAg5jZiubeEqtoqjIlRcEeOnYqgwFVrBUFMkBXYUY7Ml3kfNTwwVuXR+tLTm+0AZR4objBJHRR5CfrS0MBxbArFRIg8hP4pZGI6tBeZUsVRoBVMrmFoB7lBKXBHrp2Ko0AqWmiIp8MKCqdcWVwSSIqfgF6ZeW5iKqSKvkPwIa2HqtcVWcVSggryU8aPBy3CyECglpgr44HgQKCW2iqMiVFwRCJQSWcHEFYJAKTFVLBWuYqs4KkIEkmLicgksgI1HOJQ4KkLFFYHYKIFDwClBbJSYKpYKV7FVHBWhAhXkacQIbIuhwlRMFUuF8wRjOLbFUREikCG4P8A87NtRzMO2cBVbBQ4uLz5Mvb5NxNRrC1MBH1SA+5ASrgI+F+LoAqFCTiN+sreFVjC1AtyHlFgqXMVWoRVMNcX4Gt5V47d4WywVriKXzk+g1pLBtrVksG0tGWxb+MXdtbAAYqPEUpGHsN6/2brAUREqtIKtFWytYJuKqWKpcBVawVZTJMXCJiIpSkwVODiHcBVbxVGRV8hCY+DW4wncepQYKlABLmUEysKViEApcVTAB9coAuUJBEqJocJUTBVLRVbguEIQKCWOilBxKTBD22KoMBVY2iCwQG48RmBbDBWmYqpYKnAIDrFVHBWh4opAoJQYKkwFKtgQS4Wr2CqOilBxeYLxe7cthgpTgTO3II7sKN7LlLgi8F6mBA7uQOgm4h1Lia0CPqgA9yElrgjch+QHOwuTsrWA62l0PY2uFbhW4FoB7kNKhAq9kLZeSFsr2Gr6voqDQt9XcZ4IFVcEbj02LmV84eY8sVS4ijyE/DRpOWKjRKjIQ9g4P/jCzVsAo/clTIVWEFpBaAUylL9chvKXy1D+chnKX2/QtYSaIik2NhFJUeKowMGhZZAUEPgZ2RZDRV4h+QHSws/ItlgqXAUqOBDwySsRU68thgr4XIipYqlwFVvFUREqsgJsFWZoWwwVpmKqWCpcxRaBpMDHHRiBXXjujxHYFq5iqzgqQgUOAacEsVFiqDAVU8VS4Sq2ClSA04hAKXFFIFBKDBWmYsoJRqCUcBVbBc5c5ihmaGtH8V6mxFSxVODgcPFt3US8Y3kCsVECPqgA9yElpgr44Ko6ehqPnsajp/FoBUcrCK0A9yElTIVeSKEXUmgFoaa49cBnRhiBXbjrxAhsi6liqXAVW8VRgVR+ppfivK/vPDFUmIqpYqlwFfiaXUDkJuIO8iBQSgwVpgJHitUQKCVcxVZxVISKK+J90e9CDBWmYqpYKlzFVnFUhIj3NWJsyNQjRe6UWCpchR7p1COdeqRTjxS5U2KoMBV6pEuPdOmRLj3SpUe69Ejf14ghXPfada/fl4WxIa5HinQpcVSECj3SrUe69Ui3HunWq2rrVbX1qtp6pFuPdOuRbj3So0d69EiPXlVH9/roXr+vEWNDjh7p0f4J7Z/Q/gk90tAjDT3S0CMNvapCr6rQqyr0SK8e6dUjvXqkV4/06pFevaqu7vWVvY73Ywg/iKHCVEwVONIFwZ+XWPF+8uCJK+IlkkMMFaYCO7ohli7gKrYKrWBoBUMrQCKVGCpMxVShFZia4s0QPuzGDG2LoQIHh71+IfTEUuEq8nLBp8uYoW0RKq4IhNBFbbjFwQejmJRt4SrgMyGOilBxReAWp8RQYSpQAa4Q3OKUcBVbxVERKq4IhFAJLI3LBQ9l8REwfh+2xRWBW5wSQ4WpwCHglOAWp4Sr2CqOilBxRSBdSnwVOD6AxUBti6liqfj/vL1LjjQ7kKW3lxr3wPk2661oIBSkEiCgUBL6oUmj9y4PHid5MvKGhUU4s0eX380/zI2v43TSSBaGytCogqEuA5QAI6EBaKMCKFSiGOIMaAzCoN2D3vgQD3sVouLLaEBmQBYioDI0BumQAFSNiJSdEBjYg8AeBPYAQ5wBlaExCAN7EPmh13FNFVAYKkNjQOZ6U0agK86iygh0nZAY0A4KoDBUBhQinoOtx8OAEmDr8QD2ILMHmT3A2GVAYagMjYE9KPzQgkZ+QWYoDMicAhqDMChBV4qC1WWEwE6IDImhexDQlLugFCyMItB1ghI0PAdttAWGyJAYMkNhqAzwAC2kCYMSyMEQGCJDYsgMMI3mojCAgtfIkBgyQ2GoDMgCqkSFQScUBLpOCAyRITFkhu5BX4AtCHSd0BiEQQm6oEwIs4ILjp6dkBgyA9qoAHSWaEEI7ITAEBm66b7qWxDoikIsCHSdIAzIAjxIB0Ng6M/pC7AFga7DQMoMhYE9SOxBYg+SEuSDITBEBvYg80OhFAdq4ToCEnAdAXlBYEDmMqAr0oFCxCrPgMaAdlAASgDZGIBCRP1cB0rCAFZ5BmQG9qCyB5U9wFfOACXAV86AwMAeNH4olCKiEKEUA5QAShHRZaAUAyJDYugtJKGsMfQYUBkaQ/cgwTcISkJLhKAMSAx4DtooBGVAZWgMwqALEA87AR5kQGRIDJmhMFSGxiAEUIq+7lwQ6Fr6EnBBoOuExiAMSgDZGIAsKCAyJIbMUBgqQ2MQhu5BX4AtCHSdEBgiQ2LIDGVVMI6endAYhAAa0hfiC0JgR4nmzFAYKkM33Vd9CwJdRyGWwBAZkAV4gHHIgMLQn5PRqgpXY+FqLFyNlT2o7EFlDzAOGZAZuCFVbkiVPaj80Ov4ahTIdXz1BZmhMCBzaMrXIdWwdh1SfUFgQDsogMSQGVCIeA4OqR4GGoMwsAfKHih7gEOqBySGzFAY2AOlhyIEtuQLIkNiQOYUUBgqQ2PoLaSvLheEwA7A0GNAYOge9LMQCwJdS18YLQh0ndAY8JwEUAIIyoDAEBkSQ2aABxlQGRqDMCgBBGVAYIgMMF0BMICChzgMCAyRITFkBmQBVQLZGNAYhEEJICgDAkNk6B5UVCMEZUBhqAyNQRiUKhiCMiAwRAa0UQE0KlF8ywxQAnzLDOimKxpf40LEF8uAyoAswAOMQwYoAcYhFa1KuBqFq1G4GoU9EPZA2AOMQwYIAzck5Yak7IHyQ6EUFYWI4+wHCIMuQAhs6Yt1JV1XYiggMxQGtIMCaAzCgELs9YNA12EAl2UMiAzsQWAPAnuAq3gGNAZhUILIHkR+KJSiL3YXhMBOaAzI3PUbJYBSDAgMvYX01eWCENgJmaEwdA/61QEFga6lL4wWBLpOCAx4TgIkhsxQGCpDYxAGeIAWAkEZEBgiQ2LIDIWhEkApGpoLBhgNBQ9xGFAYKkNjEAZkAVUC2RgQGCJDYsgMhaEydA8E1QhBGaAEEJQBgSEyJKpgCMqAwlAZ0EbRt6EUV4niW2ZAYsgM3bSg8SkXIr5YAAh0nYAsREBkSAz9OX0BqSDQdRqoDI1BGNiDwB5gHDIgMiSGzMAeBH4olAIvlkzXeRWEwE5IDMhcBnRFKpc1YVACyEZfTSoIdJ0QGVCIeM51nddloDBUBvYgsQeJPbiu87ogMESGxMAeZH4olAKDU4TATggMyJwCEkNmKAy9hfQFpIIQ2AnCoAQQlL7OVBDoWhQtEYIyoDDgOWijEJQBwqAEEJQBgSEywAO0EAjKgMJQGRqDMCgBBGUATKO5YIChKHiIwwAlwABjQGCIDMgCqgSyMaAwVIbGIAy6AIGuEx4eVMyYIdB1QmLIDIWhMrRVwTgsdoISQFAGoI0KoKwSRQjshMYgDNo96I0Pga5XISLQdUJmQBbgQawMjUE6JABVIwJdJwQG9iCxB4k9wDhkQGVoDMLAHmR+aEb9ZAAyVwCVoTEIgxJ0QZkQGKBVqG1c5zUgMxSGytAYhEEJcLwR5vALjjcakBmQU5RBrQyNQRiUoB0MgSEyJIbMwB409qCxB409aOyBsAfCHgh7IOyBsAe46AsTUYiUndAYhAEeoM9hpgSTVzj4dUJmQE5R8FoZGkPPaUA14vsHBhA2OyEwRIbEkBkKQ2VoDMLAHgR+aB+h1L6mVxApO6Ey9MyF6zfCoAR9IDOhV2NfRCuIlJ2QGDIDPCgAPKcClCAdDHhOA0SGxJAZCkNlaAzwQABKkA+GwBAZEkNmKAzdNJbXEA9bsdKFeNgJmaEwVIbG0LOAxS0cPTugD1cmBIbIkBgyQ2GAB6hG6M4AYVAC6M6AwBCpgqE7AzJDYUDN9b6NSNlRohCUAZEhMSBzaHzChSjCoASK58ADDQyRAc9Bq1KuRuVqVK5GZQ+UPVDyAGGzEwJDZEgMmaEydKXAQlW7bjS/IDBEBpgWQFckLG4hHnaCMCALXS0RDzshMPQsXM/B989lAFcCDigM7EFkDyJ7gC+jC3DR8YDAEBnYg8QPhVIMUAIoxYCeOSy8IQR2QmLIDL2FYBENIbATGoMwwIPelHGmbMX6D86UnZAZ8JwGqAyNQRiUAIIyIDDAA7QQCMqAzFAYKkNjEAYlgFJgeQ1HwlasdCG2dYIwKAFkY0Bg6FnAWxOxrRMyQ2GoDI1BGJQAgoJ1JsS2TogMiSEzFIZKFQxBGSAMugCBrhXrjQhnvUoUp8BOqAyNAZnrjQ/hrFchIpx1QmLAc+ABxiEDKgOe0wDCBqgaEc46gT2I7EFkDzAOGVAYKkNjYA8SPxRDD6wvIJy1YqUL4awTKkNjEAYlgKAM6FqFtyaOhJ2QGDJDYagMjUEIcPE5RrcIZ52QGDJDzym+ZRC0GsIFSoDrjAf0ysKankA2BiSGXqJYyxFcdDwMVIbGwB5U9qCxB7joeEBkSAyZgT1o/FAIClYIEc46ITIgc+gyEJQBhaEy9OaC6UCEs05QAgjKAHiA/gPZKGijkI0BlQHPQZ1CNgboApwCOyEwRIbE0D3AMh6iXidUhsYgDErQhysTAgNMRwAMJIASQDYGBIbIkBiQhQIoDJWhMQiDEkBDBgQGeFABiSEzFIbK0BhkVTCiXgdAXQYEBtRcBlQqUYxDBgiDEmBCBYtbiG0dhYhxyIDCgOfAA4xDBggDnoNWVbkaK1dj5Wqs7EFlDyp7gHHIgMbADalyQ2rsQeOH9stz5CrRfnnOhG4aS3IIZ52gBBCUAYEhMiSGnjms2OB41wmVAR7AUQjKACWAoGC5EPGwEyJD6plDleDQ+gGFoTI0BmHQCfXAofUDAkNkwHMSoDIgpxkgDEoAQRkQGCJDYkBZV0BhqAzwoAGEQQmgSH2nbUVw7ITIgLIOgMxQGCpDYxAGJUgHQ2CIDMipACpDY0BOUT/QnQugOwN6TvuyZEVw7IRe1oKH4jNpQGHoHvR1wBMagzAoAeRpQGCIDPAADQnCNaAwVIbGIAy9rBPaTp/vlYgy6PO9klDBfb53QmGoDI1BGJSg9TqNaIktMESGxAAPUAtQsQGVoTEIgxL0K8AmBIbIgBJF6UCrBjQGlCgyB626AFo1AHWK/ECrBqBO0ecwLBpQGOABmjKGRQOEQRcg1HZCYIgM8EABmaEwVIbGIAyPsm79XV973G1oBc95aNX5lwsyQ2GoDI1BGJSgXz3YKjzoVw9OiAyJoXtQLigMlaExCIMSdK2aEBgiA7UqxN1OaAzUqnBC7YB8MFCrCjkyUKsKOTMUBmpVITcGYeBWVbhVFW5VhVtV4VZVuFUVblWFW1XhVlW4VRVuVZVbVeVWVblVVW5VlVtV5VZVuVVVblWNW1XjVtW4VTVuVY1bVeNW1bhVNW5VjVtV41Yl3KqEW5Vwq4JW9VCAiijeCY1BGHqd9oiBiijeCYEhMvScFrRRzQyFoTI0BmHQBfE4GAJDbzt6QWGoDI1BGJQA46p+gnBFSO+EyJAY4IECCkNleHjQ+kJ8RbDvBCXo46rW17crgn1bX9+uCPZtBxztX3oTMkNhqAyNIMFAAWQGGKiAygADDXBmAbcE1R7rO9IPCZrpQOlI6URpPAFlmVEUKLHSLcHdEigdKd0toYAeMjLThdKV0o3SQun+4IA66J9pE3odBDjbP9MmJIaejYB6q708kG4HFVoLDJEhMfT6CHCtT+FMqAxcH00YlEDYA2EPBKZR71IZGkM3HVArogR6MASGyJAYeuYistBHMRMqQ2PoHkTUeR/FXICo3QndA4wLcXBtw5gV8bwTMkNhqAyNQRiUIBwM3QMMEhHPO6F70FdbKuJ5JxSGytA9wBgc8bwTlACaMSAwRIbEkBngQQFUBrQDlGiEBxcoQToYAkNkwEMboDBUBmRbAMKgBH2w0zKKtw92JvSHQmAQAzwhM3QP0E8RAzyhMQiDEpSDITDAgwRIDJmhMFSGxoAyQBODIEEw0yVI+GeXIF2QGQpDZWgMwqBL+tOlYhcEhsgAFYOjULEBhaEyNAZhoLdBulTsgsCAEkVThqQNqAyNQRhQp2h8kLQBgSEyJIbM0D3A7AOOzp3QGIShe9BXDSoiiicEhu4BpooQUTwhM8CDAoAHFQAPGkAYlACSNiAwRIbHS/ZAsq5kW0lZSZ3Jh1xdSegGxuqI+50QGR5ZvZJ5JctK1pVsKykzCXnAgBhxu63ChYcIpOsf1ZVsK/nIBDL86PxXsg9OrmRYybiSaSXxvAAoDL1yKmoXXX6AEKDLV9QuOnbfp1IRsjvh4T8qGt26ogmgWw9QAnTrAYEhzrJrq/TbKv22Sr+t0m+r9NFhryLvs76jyNFh8bmGo2knoDxQbOiwA5CHy/SZB/S2Hq87kmEl40qmlcwrCdvdOUTctj4lXXvELdp3j7cdybSSpxV0px5pO5J1JdtKykrqTKJ79dnoipNoJ/RW32e9K06inZAZuvd91rviVNmGSV6cKjvh4X9BMq3iQ6jthMJQGfCUy4AwKAH6MKoJobYTIgN7kNiDxB4k9iCxB4k9SOxBZg8ye5DZg8weZPYgsweZPcBAYICM/oV43KuvIB53QmCIDIkA72pMphd06QGF4dGlUemPLj2SspI6k4/OPJJhJeNKppXMK1lWcj2trae19bS2nibraXgbY4YcYbETEkPPJebBERY7oRc5ZuIRFjtBGJQA7+kBgSEydA8wcYaA2QmFoXuAiXQEzE4Qhu4B5tcQMDshMDzK/EqmlcwrWVayrmSbSUgEputwgmzDpBziYhum0RAXO6EyNIaeB0ztIC52AMRjQGCIDI9cJCT78zHlg6jYCZWhP1+v3wiDEkA8FJmGeAzA81ECEI8BmeH0IF+26kq2lZSV1Jl8SMZIwjZKF50fMzs4QLZh/gYHyE5QAnT/AY88yIFC6N1/QmLIDIXhkQvk7TEgGElZyUcuUEaPiYqRDCsZVzKtZF5JPC8CKkMj6IODCfAeRYZhwIBHDWQk60q2lezDMMwu4dTYAXIwoORQDxIZ8GxUimQG5ARF31VEMG2DKFnB5AyiZAWTM4iSHdBVZMLj1Q+fHxoykmkl8QTkW2Gn/wWxroL5EsS6Cj6aEesqPWy7ItZVemx1RXirYFakHY1BGM7n4KXRw15HMqxkL5EeKlwR2Co9Zrb2wFaMGntY65XsfV76EUMVQa0Sr79EhsSQGXqpY84FQa0TGoMwKEE6GAJDZMBzkEsM5jG3gwBViSjUDEdRqDkzFIbKoAToppjBQRjqhG4NHysINhVMzSBwVPACRODohMzQPYB0InB0QmMQek4foY+/oBMOCAyRIVHpoHsOKAyVgcsAXfHKNrriAC4ddLirraHDYQ4JUaTXOi6iSCcoATrcgMAQGRIDShRea2GoDPAAjULhATKHror5E5ydKpgpQkjp1V1wduqExNCfky9oDMLw6GRI9q56JcNK9pxgjggho4K3UA8ZxbdSDxi9kuiq0FGEiwo0HOGiExJDZuilhTcHwkUnNAZhUAJ01QGBITLgOQ0Aa73sEfopGflBhywoe3TIAY1BGB6Fip8/3rQjGVYyrmRaybySZSXrSraVlJVcT6vraXU9ra6n1fW0up5W19PqelpdT6vraXU9ra2ntfW0tp7W1tPaelpbT3v0Z3zq9ODOkQwrGVcyrWReybKSdSXbSspKrqfpepqup+l6mq6n6Xqarqfpepqup+l6ms6n9XDOkQwrGVcyrWReyfk0HBsq5QI0vARAw+stF3GWV8hWD3lEi+4BjyOZVvI0ihCqHtA4kjKTeE1hCgTHcU4oDN05TPz0+EV8zPfoxZHUmXz0iJEMKxlXMq1kXsmyknUl19PKelqffBKMHRCNKPX6y2kFXzw9FnEk20rKSupMPlr6SIaVjCuZVjKv5HpaW09r62ltPa2tp8l6mqynyXraoyvgQ6uHI45kWcnH09BYHl1hJGUm8RrDaAwHbArms3DAplzNDi+rAY1BGHRCwwGbEwJDZEgMmaEwVIbGAA8EoAThYAgMkSExZIbCUBkaA3sQ2IPIHkT24PES7J+LrQcajmReybKSdSXbTOL11gW04YRN6fOArZ+wGQ6UzuPtNtOV0o/ohb700XoA4UzrSj++NGc6UDpSuhdRn9xriAOUPrnXEAc4oH9oTugF0ftoQxzghMSQGQpDZWgMwqAE9WBgDyp7gPFwQ+YgGQMKAzxAXWI8PAAeoFowHhZUC8bDgqLCeHhAZOgeCNzBeHhA90BQ/RgPC9zB3LWganvUTYIDPejmSveYm5EOlI6UTpTGE5AtjIQFf8FIuE+XNEQATogMPSeKbEFcBhSGytAWIM5P+nxLQzSf9GiXhmg+QU9ANN+EytAYhEEJIBQDAkNkgAcVkBkKAzxogMYgDEoAoeiTNw0nb06IDI/qKSiPHuY30oXSj15eUIA9xm+khdK60j3Ab6QDpR/NoqC4U6J0pjTyrYDK0BiEIAeGRylqDyBqiOAb8FCMfCXDSsaVfLzmUCwPPRjJtpKykjqTDx0YybCScSXTSuaVhG8o4t77JzQG7YD20jv8hMAQO6C99A4/ITM83gHI7aO7j2RbSVlJnclHRx/JsJJxJdNK5pVcT5P1NFlPk/U0WU/T9TRdT9P1NF1P0/U0XU/T9TRdT9P1NJ1P6+F0I4kSbYDIkBhQogooDJWhV2OfdWsIs5vQ67TPljWE2U0IDJEhMXQP+gxbQ5jdhO5Bn25rCLPTAK8DPBCAEsSDAR4gCzEyJIZHuScky0rWlWwrKSupM9k/mTWi5Hu314ji6d1e+5xcQ5zdBGFQgr7spRHF0wVhQmRIDJnhkQsUW+6jGviS8fjrD3g8CiorQR+NaEJm+mhEExzro5EJ/fEJT+yjEU0w3UcjE/rwCZYfkhKup/SY3QTHesjuSFdKd4cT6rwPHSYoAZRkQGCIDImhOwyxRCTehMogy+M+WrjSfbQw0n20gH+P0cKVTpTG49BapDBUhp7hjObf59om9AxnlHYfYUwIDP35qKAetjvSmdKF0pXSjdJCaZ3pHpU304HSkdKJ0pnShdKV0o3SQml6bqDnBnpuoOcGem6g5wZ6LiSlz201ROFNEAaUdm8qiMKbEBh68+rzBA1ReBMyQ2GABwroHvT5sNaj8EKfGW09CG+k+xBkpPvje3BRQwjehMSQGQpDZWgMwqAE0KMB7EFmDzJ7kHsFZKQLpSulG6WF0rrS5aB0oHSveFRDSZTOlEbGUfOlMjQGYUDGe3fEeZ0TAkNmgDXUEGSqoB1Bpi6ATA0IDLCGBtJgDQ2kCYMSyMEQGCJDr5SKSoEKDSgMlaExCIMSQIUGwAMUvEaGxJAZ4AEKXisDPEDxqjDogh5QF/CTHk8305HSidKZ0oXSeEJvWQiL0z7p0xAWp33Sp+GgzQmZoTAgJwJoDMKgBNCYAd2DHjnUcB7nhMSQGQpDZegeNOSnrwdMUII+YTIBHiA/kJkBiQEewGvIDD7tEbc3oXuA73zE7k3oHggchcwMCAyRITFkhsJQGRqDMLAHhT0o7EFhDwp7UNiDwh4U9qCwB4U9KOxBZQ8qe1DZg8oeVPagsgeVPajsQWUPKnvQ2IPGHjT2oLEHjT1o7EFjDxp70NiDxh4IewBlw+QPrr6fkBgyw6NrY+qgBx7OdKO0UFpX+iFqMx0oHSmdKI0MQo8gTpiPQvDhBGSjACJDYsgMhaEyNAJ8c2GqC6GFV9khtPAqFJzwOaEyNAZUSwMoASRqQGCghoGAxAmZoTBUhsYgDEq+QaIGBIbIkMg3SNSAwsAeJPYgsQcsUYUlqrBEFZaokqlplsy1kLkWMtfCJVHwLXMtZK4FlqjCElVYogpLVGGJKixRhSWqsESVS6LgW+FaqFwLlWuhci1cEiWAzAAPFFAZGoMwdA8w8YnDQycEhsiQGDJDYagM3QN81ePw0AHC3QyqhNlWBEZOSAyZgRsfxlsDuOqFq1646pU7oHIHVK565apXrnrlqleueuWqV27+Ss2/HgcDcloAmaEwoHgrAMXbAMKgBJC0AYEhMiSGzFAY8BwBKAEkbUBgwHMUkBgyQ2HAuA/ZhqQNEAYlgKQNCAyRITHgSwaOXp9wFwiDEvTNmwcmj+v1oQavIU8DCkPf+oG5ox4yuUAY+gaQHk3YEDI5DJTAEBnYg8IeFPbg+ma7oDEIA30X1coeVH4odAffbIiOnNAYkLkMUIKGQkRT7pHYEyJD6oDG1+OxJxQGFC98a41BGJSgx2YfAdUogSEyJIbuAWZre/TkCagsEQYlUDwHBaKBITIkhsxQGCoDPECJqjDogh53uSAwRIbEkBlguldJD6o8oQEiQ2LIDIWhMiALChAGJcB2qAGBITIkhszQPcCscg/HXNAYhEEJ0sEQVgX3cMwFiSEzoI0KQKlEISgDAkNk6KYxF94yFyIEZYAwIAvwoBwMgaE/p0euth7cOQ0UrsbC1VjYg8IeFPagKEE9GLghVW5IlT2o/NC6ZsB7COhI93MmRvrxqYEO2+M/ZzpRumcL0/cNUjKgMqBt4NmQkgFK0Gew0Sd7WOhMR0onSmdKF0pXSjdKC6V1pZWeq/RcpecqPVfpuUrPVXqu0nOVnqvruT06dKYDpSOlE6UzpQulUdYCaAzC0Msas/89ZnRBb0JY4RBo0YDE0Gs74aHQogHdA0xoC7RogDDAgz5mEGjRAHiQAZEhMcCDBigM8EABjaF7gMUTgRZdAC0a0CugIh0pnSidKV0oXSmNJ6DEIDwZuYfwYFmln0W6oDBUhp4TLLgIJGmAEkCSBgQGeIAWAEkakBkKQ2VoDN0DzEsLJOkCSNKAwNA9wEhGIEkDMkP3ADPWPZj1BJRo34w2AR6g0jEUugBDIQwuBUOhAZEhMWSGwlAZGoMwKIGwB8IeCHsg7IGwB8IeCHsg7IGwB8IeKHug7IGyB8oeKHug7IGyB8oeKHug5IEeB0NgiAyJITMUhsrQGOCBApQAyjYgMPQAmSudKJ0pXShdKd0oLZTWle5nf410z2CPs20KccKyhEKcBvRsYM5fIU4XQJwGBIbIkBgyA57Te5dmrpbMhQKJGpAYMkOvFqxHKCRqQGMQBm4YhT0o3DAKN4zCDaNwwyjcMAo3DEjU5WjhhlG4YVRuGJXLABKFb1mFRA1AiVZAYagMjQFlcJlWAkjUgMAQGRJDZigM3QOEkCokaoBS1UOVsPKiUKUBkSExZKpG4aoXrnrhqheueqjSBVClAVz1rErKqqSsSsqqpKxKyqqkrEpKqiQHtKcHvcoB7RmQGfpzetCrHNCeHmUqB7RngDAoAbRnQGCIDIkhM+A5BSAMSoCx0wA8pwIiQ2LIDHjfI9uQpwGNQRiU4Bo7XRAYIkNiqFcMkPRo5pGUlXyEL6HGHoI1kmElkTsFJIbM8Ag2akjWlWwr2fPVV/zkgExdAJkaEEakkvSw55lOlM6ULpSulG6UFkrrSteD0vTcSs+t9NxKz6303ErPrfTcSs+t9NxGz2303EbPbfTcRs+FHMkFlaExIK4LdYx1tQugTYLmAW0aEBkQJoVKwQz2AAS2odoxgz2gMSBQC30MM9gXQJsEXR7aNCAy9BK4fpIpXShdKd0oLTMdMCKSC3qb7WtmEqA9fTJfArRnQGMQBrTc3jcCtGdAYIgMiQEeKKAwVIZHbvpHuuDo05HWle6DH1Qrzj0d6UjpROlM6ULpSulGaaG0rnSi5yZ6LmSoR55KgAz1KHcJGCUNKAyVoTEIgxJgZDUgMEQG9gBipWgFGFkNqAzwIAKEQQkgWYpmhJHVgMhQGB6lmVE4XYWudFehkQ6UjpROlM6ULpRGPlAVGB0NEAYlwOhoQGCIDIkBJYlmCjkaUBngAVoqPuAGKAFCKFFCfQJqpCOlE6UzpQulH88OB4qiD5ImCIN26ArTo7IXBIbYAU2nD5ImZIbSAU1HK0NjgAfd0R6RPf7SQ637nIn0QOuRxI8vEAYlCAdDYIgM3f0+byU9zHpBYagM3YMAJ/uYaIIS9DFRCMhYHxNNiAzwoAIyQ2GoDPCgAeAB8tNHPqFPZ0sPuV6QGDJDf06fMpYejH0Cctol52pEOPT0UjOcejqgS86EwAAP4GhODJmhMMAD5KerDCKEpYdgJwQ+C05IDQmOdpUJCQ/tKjMhMWSGwlAZGgM8gG9FCSo31hoZEkNmKAyVAQ9FtqswKEEXpUvVeiD3gsiQGDJDYagMjUEYlEDYA2EPBB6gSiQxZIbCUBkaAzxAWUOaLoA0DQgM8EAAiSEzdA8KvIY0FbQqSNOA7kFBx+jfbxf0GO+E/VKSIFoDIkNiyAyFoTI0BmFQgsAeBPYgsAeBPQjsQWAPAnsQ2IPAHgT2ILIHkT2I7EFkDyJ7ENmDyB5E9iCyB5E9SOxBYg8Se5DYg8QeJPYgsQeJPUjsQWIPMnuQ2YPMHmT2ILMHmT2A8vWdcdIjvxcIgxL04O9+YJog+HukI6UTpTOlC6UrpRulZaUheH1KXNIlaxcgGxVQGRqDMCgBZG1AYEBxwYPG1dK4UBoXCiRqQGBAtQggMWSGwsANQ9gD4YYh3DCUG4Zyw1BuGJCoyzdI1IDCwA3jkij4dknUBbogs0RllqjMEpVZojJLVGaJyixR+aCmmQ9hoFrI4WAI5FuIDImBPWCJyixRmSUqs0RllqjMEpUjtYN8SdQFiSEzUDvIl0Rd0BjYA5aozBKVWaIyS1RmicosUZklKidqBzlxLSSuhcS1kLkWLolSQGToHvT1AcmQqAGFoTJ0Dyp8g0QNUAKM1AYEhsiQGDIDPEAWMFIb0JWqv617XPgQigyp6pPmkjE2G5AYMgNXduXKrlzZVRi4y10idgE3+MaV3biyG1d248pu3OBZ+HLj5ta4uQk3N8hbXwSQDHkbUBhQoCg3yFuF15C3AUoAeRsQGCJDYsgMhQEfwKgFzJMDynEwBIbIkBj6c/rKgxSI2IDK0HOKtlMgYgOUACKG+fgCERsQGRJDZigMlaExCIMSRPYgsgeRPYjsQWQPInsQ2YPIHkT2ILIHiT1I7EFiDxJ7kNiDxB4k9gAihhWOAhHDKkKBiF0AERsQGCJDYsgMhaEyNAb2oO+xwxdDjymf6UDpPg+lSCdKZ0r3eaiGdKV0o7RQWlca819XOlA6UjpROlOanlvpudAsLLzgiNzQkBsoExYtcEzuhMJQGbo1zKwXDK8wS16gPwMyQ2GoDI2h1wYmpwv05wLoz4DAEBkSQ2YoDPAAuoDh1QBh0AUVwyvMlVcMrwb0qolIJ0pnShdKV0o3Sgul8eheZRUi0uPapUJEBgjDoxnhPdmjuGc6UDpSOlE6U7pQulK6UVooTc9N9NxEz0303ETPTfTcRM9N9NxEz0303ETPzfTcTM/N9NxMz8303EzPzfTcTM+FTmA1AtHdAzDYwUx4xWBnQG+ZfauEVAx2BmSGwlAZGoMwKAHGQQMCA3uAcRBm9ivGQQN6ASA7XTdGulFaVhojHbx9EcwdMBveg7kDljx6LPdMN0r3XWYBaV3pPvc90o8qvAoYVxFe6UTpTOlC6UrpRmmhtK50D74caXqu0nOhHpikR4B20Osvj5qImE9HgPaEwBAZSocIkA4JoAThYAgMkSEx5A4FUBgqQ2MQBiWIB0NggAcBkBgyQ2GABxXQGOCBAJQgHQyBITIkhsxQGCpDY2AP+i6RgOrpu9tGOlD6sYsC6wM4k3ekM6XLI43M44L3K90oLZTWle6bRkY6UDpSOlE6U5qeW+i5BSXbGy4CtcdfujaMrHVtmFAYKkO3hrWPhoP3scLRcPT+gMxQGCpDY+i1geUORGgPwEH8AwJDZEgMmaEwwAPUljQGYVAChQdoKRoYetXAsuL3KGpoBECgEQP677EsI9CIAY+67UfXSA+7nulC6Urp/oy+qUAQQR2xwNMjqCNWV3Ak70gXSj8sYdEFJ/WOtFD60Tp7JLfgqN6RDpSOlE6UzpQulK6UbpQWStNzEz0XfR4LV4KejYUrQc/GipSgZw9Qgv6NMQHWYDrDGsomNwZhUIJyMASGXhtYxUIE9ITMUBgqQ2MQBiWo8KABAkNkSAzwAC0FfX0APEDrwnUcA4RBCXApx4DAEBkSQ2YoDOxB34SKdbgeAD3TutJ9O2pCFfbdqCMdKf1olVjp66HPM10oXSndKC2U1pXum1BHOlA6Upqeq/RcRcn2hovY5Ss3iF2+3Ebs8oTEkBm6NazOIQ459o0AgjjkCZEhMWSGwtBrA0t1ivHDAGFQAowfBgSGyJAYkB8FFIbK0BjgQQYoAcYP/QQjQahyxEc6QpUjlgQVo4QBlaDPPUSsAiJUeUJiyAyFoTI0BmFQAmjJAPagv/4zWkt//Y90pvSjKV9Z7q//kW6UfjTlq4z6VtEr3XeKjnSgdKR0onSmdKF0pXSjND230nOhD5jHRJBxxLITgowj1oYQZDxBGJQAYwFMxSJ6OGLWG9HDExqDMCgB3vgDem1U9Ik+9zAhMWSGwlAZGoMwwIOHFOgBXRgQGCIDPIiAzAAPMqAyNAZh6B70OWNFXPGEwBAZEkNmKAyVoTEIA3vQhxx9/lhxLvJIR0o/Wmb/SNUebTzThdKPlllRYH3IMdJCaV3pPuQY6UDpSOlE6UzpQml6bqLnYhQyAOUHT6EpffZaD2jKgMrQCKAcDbWOsUafa9UDY40BhaEyNAZh6LXRp0r1wFhjQGCIDIkhMxSGygAPAkAYlABjjQHwAC0FWjIA1tA+oAuCosI3woDM0H0TFCIUY0BjEAYlgGIMCAyRITFkBvagn0pR0Cn7oRQjLZR+tNiumIozkEc6UPrRYrvEKo5GHulM6ULpSulGaaG0rnQ/oWKkA6XpuYGeCxWQC1B+8BTjhj77qQHjhgGRITHAmgBgrfejgDHAgMAQGRJDZui10aemFCG6ExqDMCgB+viAwBAZ4EEDZIbCUBngQQQIAzzo7QMhuhMCQ2ToHihKFIoxoDBUhsYgDEoAxRgQGCIDe3Dd/ol0oXSl9KNlNhQG7v680rrSuPkTbQsXf17pSOlE6UzpQulK6UZpobSutNBzhZ4LtVE4B01RNLWuKanPEyrCcwd0TZkQGHIH1HofUaQDnUqFQRf0Q5EXBIbIkDoUQGYoDJWhMQiDEoSDAR4EQGRIDJkBHlRAZcBzuhQgKndCYIgMiSEz4DkKqAw9p/0kAkVU7oTuQYCjXX8mdA/6FJoiXndC9yCg4Lv+TOge9Jk2RbzuBHiAQkzCAA9QIPlggAcNEBngAbKdMwM8QLZzZegeRGS768+E7kFEtrv+TOgeRGS768+E7kFEtrv+TOgeRGS7688EeIBsF2Howzg8s3/YjHSgdKR0onSmNJ6N4quVoTHg2SiXqgTtYAgMkSExZIbCUBkaA3vQ2IM+8kkJNdPHNykhc318kxLKv2vRBGFQAmjRAM6Pcn6U86OcH+X8KOdHOT/K+VHKD+JxJwSGyFBWthFbe2UbsbVXFhBbOyEwRIbEQPlJoTBUhsYgDJyfyPmJnJ/I+YmJgT2I7AG06Mo2FOfKduL8JM4PFGdAYagMnJ/E+Umcn8z5yZyfzPnJnJ/M+cmcn8wlmtmDzB5AV65sQz2ubBfOT+H8lMYgDNxCKreQiuckQGR4KAi+InAc8kgXSldK4xldyBK0oE8FntAtXelM6ULpbqki3SgtlH5ooOABuPbwSgdKR0onSmdKF0pXSjdKC6XpuUrPhSYkOIee3+cuFWGuKaEq0fMH6AKEuU7o1voMpSJkNfUACkXI6gRhUAL0/AGBoddGn55ShKxOyAyFoTI0BmFQAvT8PmWrCFmdEBkSAzwogMIADxqgMQiDEmB8MiAwRIbEkBkKA3twXe6AtFBaVxrnhyakA6Ujpfv+W1QzDue70oXSldKN0kJpXWkcy3elA6Ujpem5hZ4L1eghYYo41FRQNdCGgn8GbRiQGDJDt4avYsSUJnzWI6Z0QmRIDJmhMPTa6NOiipjSCcKgBHIwBIbIkBjgAWoU44sBlaExwAO0FIwvLsD4AqMvRJtO6B5gVhPRpqmi3K5T1JEulK6UbpQWSutMX0cUX+lA6UjpROlM6ULpnu96QWMQBiWAGg0IDJEhMWSGwgAPKqAxCIMSQI0GBIb+G0wzIlp0APRjQGCIDImhe43ZO0SLDsD4ADOYiO+ckBnwmwyoDI2hRxpfP9GVvo7QQ7qHGSekI6UTpfs2X3h4nZ6HdKV0o7RQWlf6OjgP6UDpSOlEaXpupefiWwPTCQUqgbkOxHcmTHgivnNCZigM3RrGJAU9XvAc9PgBiSEzFIbK0GsDk3yI75ygBOjxAwJDZEgMmQH5UUBlaAzCAA96S0F85wR40ADwQAGJITMUhsrQGIRBCdD7BwQG9gDnJ1zpTOlCaWw0RbpRWijdm2VvABXHuVzpQOlI6UTpTOlC6UrpRmmhND030XOhDwrnMIrACKHimwNDgYpvjgFKgG+OAbBWALBWAY1BGJQAMxYDAkOvDYXXmLEYkBkKQ2VoDMKgBBhXYGYWcZ0TIkNigAdoBZi3uKAfs4J3ZQ/gnOlI6UTph6UMucEhvRMqQ2MQBiXoY4oJgSEyJAb2QNgDYQ+EPRD2QNgDZQ+UPVD2QNkDZQ8UHqB9KjxAUWljEAZdgOjQCYEhMiSGzFAYKkOPc81IC6V1pft1Ufhy7NGkMx0p3eNrYbMfSjfShdKV0o3SQmld6R6KPtKB0pHS9NxIz40oWWQgofwqAOXXAJEhMWQGWOv9AYf1ZmghDuudEBkSQ2YoDL02MJOLY3wnCIMSlIMhMESGxID8CKAwVIbGAA9QokUJKjxA3dfAEBkSQ2YoDJWhMQiDEjT2oC/NXJXdl2ZGOlH6Mdw+rn9fKF0p/RjmXz2jz4WMtK50nwsZ6UDpSOlE6UzpQulKaXqu0HOhNph+b9AUzKs3aAqm0hs0ZUBjkAWIGc2YShfoA2bPBfowoDI0BmFQgj4CyZhXx5m8EyJDYsgMhaEyNAZ4cACUIB4MgQEeFEBigAcV0BiEAc/pBY+TdyfgOSheaMmAxNCfg+nFfvrugsrQGIRBCaA/AwJDZEgM7EFmDzJ7kNmDzB5k9qCwB4U9KOxBYQ8Ke1DYg8IeFPYA+oOZWESsDoD+DAgMkSEx9J1UV1qoK0BXLoCuDOAe02AZDb5xj2ncYxr3GIxrMMeLE3cHYFwzADlAG8e45jKAcc0A7rPCHgh7IOyBcJ8V7rMY1wwIDOyB8kMhLphpxlG6E3QBwlFzD0dVhKNOiAyJAQ1EAIWhMjQGeNB7GQJVMyY6Eag6ITH056AdIFB1QmVoDMKgBJCdAfAgAiJDYsgMhaEyNAYhgNJgGhgRqBmzuIhAndAYhEEJoCcDkAVUCfRkQGLIDIWhMjQGYYAHqEboyYDAEBkSQ2YoVMHQkwGNQQguCamARCWKgcqAwlAZYBqNr3EhQjYGRIb+HMz44nzcCYWhPweTvAhdnQa4GhtXo7AHwh4IewBBGZAZuCEJNyRhD4Qfen0BoQyuL6ALMkNhQObQlCEbj7FwPBCtOiEw9Oc8JrofkBgyAwoxAyobaAzCwB4E9iCwByEyJIbMUBjYg8APhVI8wuseEBkSAzLXAIWhMjSG/pxHCPMDlABDlwGBAR4ooD+nwlEIyoDG0J/zmF1/gBJAUAYEhsiQGDIDPIiAytAYhEEJICgDAkNkgGk0F4wvKgoe4jAgMESGxJAZkAVUCWRjQGMQBiWAoAwIDJEBHqAaISgDCkNlaAzCoFTBEJQBgSEyoI1WQKMSxdBjgBJg6DEAptH4lAsRsjGgMvTnNHiAccgAXRAgKC0AqBrDERkSQ2YoDJWhMQgDNSQcbTuBPQj8UKy46AWNQRiUAEOPFgGYy6uAzFAYehZaAjQGYUAh9vpBFOwwkAJDZGAPEnuQ2INUGRqDMChBZg8yPxRK0VAgUIoBjQGZawAlgFIMCAy9hTQBJIbMUBjggQL6cwQtEYIyIDD05wjaKARlQGYoDJWhMQgDPEALgaAMCAyRITFkhsJQCaAUguaCAYag4CEOAwpDZWgMwoAsoEogGwMCQ2RIDJmhMFQGeIBqhKAM0AWIfp0QGCJDWhWM6NcJhaEyoI32do2w1qtEEdY6ITFkBphWABUiwloHQDYG9OcoPMA4ZEBi6M/RAChsoDI0BvYgsgeJPcA4ZEBkSAyZgT1I/FAoxVWiiB4bEBkSAzIXAVhxQ06xxjNACSAbmgCBITKgEFE/JbOBwlAZ2IPCHhT2AGs8AwJDZEgM7EHlh0Ip8GJB0OmEwIDMNUBiyAyFobcQRcfA0GOAMCgBBEXRlLuglAOV1QVlQmGoHZCfLigThEEJuqBMCAyRAR6ghWhmKAyVoTEIgy5AOOoEmM4AGCgAYVCCcDAEhsiALDRAZigMlaExCIMSxIMBHgggMiSGzFAYKkNbFYzY1AlKkA4GtNEKKFSiqTI0BmGA6d74EHQ6CjEnhszQn4OPOwSdTmgM/TkhALgaC1dj4Wos7EFhDwp7UApDZeCGVLghFfag8kOvKLMEKAyVoTEgc2jKK/7sAZEhMfQsBBhohaEyoBCv3wgbUAI5GNgDYQ+EPZDMUBgqQ2NgD5QfCqUIKEQoxYDCgMyhy0ApBgiDLkD4agkCCAyRITHAAwX058QDIAxKAEGJARAYIkNiyAyFoTLAgwgQBiWAoAwIDJEhMWQGmO5VgrjUEgsgMiSGzFAYKgOygCqBbAxQgnwwBIbIkBgyAzxANUJQBjQGYVACCMqAQBUMQRmQGDID2mgFKJVoPRgCQ2SAaTS+yoVYG4Mw9OckeNDHIRMCQ39OQqtqXI2Nq7FxNTb2oLEHjT1oSiAHAzck4YYk7IHwQ6EUGY4ibu0CyMaAwIDMoSkjOi1fUBkaQ89CSgBdgHNRJ6AQMyAuA+WKh78gMxSGytAYhEEJVqT8AwIDexD4oVCKVADCoARQitQAgSEyJIbeQpIACkNlaAzwoDdlBKqWfAAiQ2Loz0GdIlB1QmVoDMKgBBCUAfAARQVBGZAYMkNhqAyNQQigFBnNBQOMjIKHOAxoDMKgBJCNAcgCqgSyMSAxZIbCUBkagzDAA1QjBGVAYIgMiSEzFKpgCMqAxiAE0JBUAYlKFN8yAwpDZYBpND7lQsQXy4DI0J9T4AHGIQMKQ39OQatSrkblalSqRoS7TggMkSExZIbCUBkaAz8UQ48SAchcAmSGwlAZGoMwKAGi2KEuiGedEBkSQ2YoDJWhEWBOFW+zCkHBCLJCUAYkhsyAnF7WKkNjEAYlgKAMCAzIaQAkhsxQGCpDYxAGJUCc7IBEBVI4p9CdAZWhMXBOC+e0ck4r5xS6MyAxZAbOaeWcVs5p5ZxWzmnjnLbAwGXduKyx/+YqkMY5hboMUAJIzQDOqXBOhXMqnFPhViXcqoRblXBOhXOqnFPlnCrnVDmnyq1KuayVy/ray9cLBBGxV04RETshMiQGyikiYidUhsYgDNSqcMbqBMppC5EhMWSGwlAZGoMwUFm36xSCCEgMmaEwIKcVMM91OAGKNCAwoEQbIDFkBpSoACobaAzCwB5k9iCzB1CkAYkhMxQG9iDzQ/ExhMVuBMxOSAw9c1iRRsDshMrQGHpzweoyAmYHQIQGBIbuQYVvGOJgYRRhsRMaA56DxochzgUY4gwIDJEhMWQGeIAWgiHOgMYgDEoAERoQGCIDTKO5YFIWS8A4J3VCYIgMiSEz9Cxg1RexsRMagzDoApy0OiEwRIbuARZgEU87oTBUhsYgDLoqGPG0EwJDZEC2D0BbJYpA2QlKgG+mAchcAlAhCr6MBlQGZAEe4MtogBJgUhYLsAiUHQZSZEgM7EFiDxJ7gCHOAGGghoRA2QnsQeaHXqcioUBwKtIAYVACzK5gse46mRULb9fJrAMKA9pBAzQGYUAh4jk4++gygLOPBkQG9qCyB5U9wGlpAxqDMChBYw8aPxRK0S6oDI2hZw7rTAiBHQClGBAYegvB6jJCYCdkhsLQPRA0ZQgKFkYR6DohMOA5aKMQlAGZoTBUhsYgDPCgtxDEw04IDJEhMWSGwlAJoBRolgh0LagfBLpOKAyVoTEIQ88CVn0R6DohMESGxJAZCkNl6B5gARaBrhOUAIIyIDBEhrQqGGe1TigMlQHZ7jqKENhRophdGZAYMgMylwBciJiUvQCyMQBZgAcYhwxIDCjEAuBqLFyNhauxsAeFPajsAcYhAyIDN6TKDamyB5Ufep2riFq4zlW8IDIkBmQOTfk6cRGFiDNaBygBZAOrywh0nRAZUIioH5ybNgwUhsrAHgh7IOwBTmkcEBgiQ2JgD5QfCqXoi90BIbATAsPDdO0r0gEhsBMyQ2GoHSKgMQiDEnRBqX2sHBDoWvvCaECg64TCgOcUQGMQBiWIB0NgiAzwoAIyQ2GoDI1BGJQgHQwwLQAYQMEnYVCCfDAEhsjQsxBQJV02JhSGytAYhEEJuqBM6B4EVGMXlAmJITMUhsrQqIKLMChBPRiQ7QNQqERrZWgMwoDMofE1LsSWGDIDsgAPWmVoDChEtKrG1ShcjcLVKOyBsAfCHkhhqAzckIQbkrAHyg+FUhQUCM5zHVAZGgMy15tyuM55VkBkSAxoBw1QGCoDClEAwgaUAOc8D2APAnsQ2AOc8zygMFSGxsAeRH4olCJckBkKQ89cX5EOCIGdIAxKAKXoq8sBIbATIkNi6B7EBMBzMkAYlACC0tcOA457nRAZEkNmKAyVAR6ghUBQBigBBGVAYIgMiSEzwDSaS4UBFDzEYUBiyAyFoTL0LCRUCWRjgBL0cciEwBAZEkNm6B4kVCMEZUBjEAYlgKAMCFTBEJQBiSEzINsHQKlE9WAIDJEBmUPjUy5EbQzCgCx0DxDoOiEwoBALgKoRga4TCkNlaAzCoAQYhwwIDJGBPQj80Ot2iQOgBNftEhcEBmSuAroi9TXXgEDXCY0B7aABlACyMQCFKIBIBq7bJS7IDOxBYg8Se4DzowcoAc6PHhAY2IPMD4VSJBQilGKAEkAprt9AKQZEhsTQW0hfXQ4IgZ1QGRpD9yD3poxA15rREiEoAxIDnoM2CkEZUBkagzAoAQRlADxAC4GgDEgMmaEwVIbGIARQiozmggFGRsFDHAY0BmFQAsjGgJ6FgiqBbAxIDJmhMFSGxiAM3YO+aBsQ6DohMESGxJAZyqrgBEEZ0BiEABqCvo0Q2KtEEQI7oTBUBmSuNz4Eul6FiEDXCZEBWYAHGIcMKAwoxAJobEAYqBoR6DqBPUjsAcYhAzJDYagM7EHih0Ip8GJJ67arB2SGwoDMVUBXJKhyWrddPSAwoB00QGLIDChEPAfnyQ8DjUEY2IPKHlT24Lrt6oLEkBkKA3tQ+aFQinJBZEgMPXN9ASkgBHZCZWgMvYVUdAwMPS7A0GNAYOgeVDRlCEpFS4SgDGgMeA7aKATlAgjKgMAQGRJDZoAHaCEQlAGNQRh0AeJhJwSGyADTAoCBXvAIdJ0QGCJDYsgMPQt9MSgg0HVCYxAGJYCgDAgMkaF70GfMAgJdJxSGytAYhEFXBeME1wmBITIg2wegUYniW2aAEuBbZgAylwBciPhiGVAZkAV4gHHIACXAOKSvMwUEug4DhauxcDUW9qCwB4U9wDhkgDBwQ6rckCp7UPmhGHo0NEsMPfqST0AI7AQlwNBjQGCIDIkBWoXaxo1YAypDYxAGJcC9mQMCw/mciEmCHvQ605XSyCYKAGoyQAmgJgMCQ2RIDJmhMFQG9kDZAyUPECY7ITBEhsSQGQpDZegFjVkohMlOUAJMoAzoHvQFiYDI2IiZKxzUOqEy9Jz2FbSAmNkJSgDR6YtmATGzwwCuyBmQGNiDyB5E9gCfRQOEQQlwrc4A9iDxQzE86Qt6AWGyE4QBmcNvIDoDAkNk6NXYV9ACwmQnFIbKAA96u8YpsLUv/gQcAzshMuA5aAcQnQGFoTI0BmFQAoiOooVAdAZEhsSQGQpDZWgEEB1Fc8FYRVHwGKsMqAyNQRiUAGMVRZVgrDIgMiSGzFAYKkNjgAeoRujOBdCdAYEhMiSGTBUM3RlQGRoDaq73bYTJXiWKMNkJmaEwIHMNQIWIs18nBAY8RwCJITPgOQqobKAxCAN7ENmDyB5gFDMgMWSGwsAeRH7odYk3CuS6xPuCxJAZHqYbFiTqdVX3ZU0JME0yIPTfBEBkSAy5A56Dj59hoDI0BvYgsweFPcBn0YDIkBgyA3tQ+KFdKdqAwBAZkLkCyAyFoTK0DhUgDErQDgZ4gKbc8By0xFYYKgOegzbahEEJ5GAIDJEhMXQPAlpIF5QJlaExCIMSdEGZEBhgGs1FYQAFr7oAga0TAkNkSAzIQgEUhsrQGIRBCcLBEBjgQQUkhsxQGCpDY5BVwQhsHRAPhsCAmsuAukoU571OEAYlSMhcA3AhpsxQGPAceJAagzDgOb1VIZZ1GMhcjZmrMbMHmT3I7EGuDI1BGLghFfag8EO7UjQsLiCWtWGZC7GsE4RBCSAoAwJDZHhkLuCticNfJxSGytAYhEEJuqBM6M/B6BaxrBMKQ2VATtEoumwEuSAwRIZeWVjQa5CNAYUBJYo22mVjGhAGJVD2QNkDZQ80MWSGwlAZ2AOlhyKWtWF5ELGsEzIDMtcAlaExCAOaS+8YiGWdEBgiAzxQQH9OD/YPCGydIAz9OVi2Q2DrhMAQGRJDZigM8ABFBXUZIAxKAHUZEBgiQ2KA6d5cELHasLaGiNUJkSExZIbCgCygSiAbA4RBCSAbAwJDZEgM8ADVCHUZUBkagzAoAdTlqmCoy4DIkBjQRitAqEQxDrkA45ABgQGm0fgaFyLGIQMaQ38OFhcQ2DoA45AB/TlYAENg6zAgXI3C1SjsgbAHwh5gHDJACZQbknJDUvZA+aFdKRpW3RDLOkEXIJZ1AjKXAJEhMWSGR+YOfIkjlnVCYxAGJeiCMiEwRIbE0AsRy0IIeZ0gDEoAQcG6H0JeJ0SGxJD7/VQBUBgqQ2MQBiXoV4hPCAwo0QooDJWhMQiDEkBd+pbZgFjWhgUwHOfasBKE41wnCEO31neVBkS5TujlhhVBRLlOSAw9P1jqQ5TrhMrQGIRBCaAhA+ABGh80ZEBiyAyFoTL0msMXJUJeR7lBUAZwiTY8B60KnzwDCkNlaAzIKZoYpOYCSM2AwICcwgNIzYDMAA9QjZCaAY2he4AVAATDDoDUDIAHaFWQGixZIRi2YS0KwbANa1E4HHZCZcBzHmUQERk7ITBEBjynAOpsyhHxrxOEQQkwQhnw6M7SJyBiD3ldUBlaB3jwEJQFSvAQlAWBITIkhsxQGFAlFaAEGIcMCAwoqgZIDJmhMPSc9mnH2CNjFwiDEvSr+SYEhsiQGDJDf05fsoo9/nUBcor6gdQMCAyRATmFaUjNgMJQGRqDMPScNlR9vx54QmCIDIkhMxSGytAYhABS0w85jQiTnZAYMkPPaV9SjAiTndAYhAE5hQFcAjogMESGxJAZCkNl6HV6VTAEZUBgiAyJITOczxG094ecjGRbSVlJHcl+WOxInk/tM/2xx8+OZFrJvJJlJetKIke9uhAB2/p6ZUQE7ITM0MsHPTVAXwY0BmFQAujLgMAQGRJDZmAPInsQ2YPIHkT2ILEHiT1I7AH0pa/ZRpwIO6ExCANKFAbwoTQgMESGxJAZCkNlgAeoRgxyBigBlGcAPBBAZEgMmaFQ1UN5BjQGYVACDHIGBAZub5XbG4YyfWEyIp52gjD05/Tlx4h42tYnTiLiaSdEhsTQc9onGiLiaSdUhsbQPRA4ikHO1R0xyBkQGCJDYsgMhaEyNAZhYA8emnS5+VCkkYwr+dAG9PaHFo1kWcmHNqBwuhJdSVlJHckefDuSYSXjSqaVzCtZVrKu5HwaQmobFAqBsw2vWxwk2/qSX0QU7YTK0AjwedQXqCKOi20YDuG42AmFoTI0BmHoZd+X7yKiaCcEhsiQGDJDYagM8AClA7UZoARQmwHwoAIiAzwQwMMDOVBUXW0mVIbGIAxK0NVmQmCIDImBPXioTYioq4fYzHSjtDzSqIGH0oz0Q2hmOjzSKImHzMx0onSmdKF0pXSjtFBaV7pfPDjS9NxGz20o2QtQfvC0ofy6nOBA2QmBITLAGqpTYA29RZRAD4bAEBkSA2oD3U0LQ2VoDMKgCxBNOyEwwIMCSAyZoTB0D/pCVUQ07YTuQV84iDh3dkDXkgmBITIkhsxQGOBBBTQGYVCCeDAEhsiQGB5NsyBvD2Ga6UrpRmmhtK50whMaADkRQGXAqCkDhEEJ8LU0IDBEhsSQGQoDSgzNASoS4TVUZEBgiAyJITMUhp5T9EPE3k4QBiWo8CACAkNkSAyZoTBUBniA9lThAQqkKkE7GAJDZEgMmeq0cW03ru3WGIRBCaBFAwJDZCAtQojuhMYgDMgpejVrUWItSpcWXYAShQFo0YDGgBK9fkNqmI+DITBEhsSQGQpDZWgMwsAeBH4oRKYvKkWE6E6oDN10Xz+ICNGdoAQQmQH9OX2BKCJEd0JiyAzdg77YExGIK31bVkQg7oB0MOA5GRAZEkNmKAyVoTHAgwJQgnwwBIbIkBgyQ2GAaVQJ1CWh4KEuAzJDYagMjaFnIaNKoC4XQF0GBIbIkBgyQ2HoHmRUI9RlgDAoAdRlQGCIVMFQlwGZoTCgA3YlRyDuKFHIxoDIkBiQOTQ+4UKEbAxQAgxuMjzA4GZAZEAholUpV6NyNSpXo7IHyh4oeYBY3AmBITIkhsxQGTCS72WAINsJgSEyIHMFQN8sJTQGYUA76GqJINsJgQGF2AD01VT4q6nwV1Phr6bCX02Fv5rK9dUEuL6aLggMkYE9SPxQKAXmwRFkOwBKMaBnDsMiBNlOSAyZobeQvvITEWQ7oTEIQ/egoH4gKAWOQlAGZAY8JwMqQ2MQBiWAoAwIDPAALQSCMiAzFIbK0BiEQQmgFAXNBaONgoKHOAwQBiWAbAwIDD0LFVUC2RiQGQpDZWgMwqAEEJSKaoSgDIgMiSEzFIZKFQxBGSAMugCn1EpfqowIsr1KFEG2EypDY0DmeuNDkO1ViAiynZAYkAV4gHHIgMqAQswAYQNUjQiyncAeRPYgsgcYhwwoDJWhMbAHiR+KoQcW1hBke83mIsh2QmVoBJCNAbCG4oU4DIA1PBQSgHUXBL9eSwYIfp1QGLoHWMFAJOwEYVB6Djr69Rd09AGRITH0L7B8GSgMlaERNC4DjA+ubGN8MIBLp8EaGh96fbsA+UFDQq+/AL1+QGCIDIkhM6BE0SzR6wc0BniARoFej2l0RMIK5scRCSuY+O4nwcZrGNFPgl2QGXq5hQvwHLQD9G3MTiNgdkJgiAyJITMUhp5TTJciYHaCMMCDXgsImBVM8yJgVjCJjYBZ6REosQfMnvm5/pIZCkOfJTgu00qA1Z0BeE4DRAbkVAGZoTD0nGIqF9GzE4Sh5xTDIkTPTggMkSExdA8w34q42gmVoTEIgxJAQwYEBjynAnrbwUQgImFFUTqY9RgQGeC1ADIDvEa5QV0GNIaH14gMiQiYHdDVZUJgiAyJITOUDmh8fRgxoTEIgxK0gyFQ6TQ8B5XVCkNlaAx4zmVACeRgCAyPXn9NjvdQ2gWZoTBUhsYgDEqgKFF0Jk0MmaEwIKdoSNoYhEEX9DNi47WW0s+IXRAZEkNmKAyVoREElGgFBIbIgJxev8kMhQE5FUBjQE4VoATxYOgeYHYYcbUTEkNmKAyVoTF0D/pZZhFxtQO67kwIDJEhMfSyxmuqB9nGK3yjHxgbr1XlfmDshD4POyEwRIbEkBl6neK93cNvFzQGYYAHKINyMASGyJAYMkNhqAyNoEetILYrIshW+w6JiCDbCYkhMxSGytAYUKcJoARQpAGBoecUHw/SEkNmKAyVoTEIgxL0eJYJyCmai2SGwoCcoralMQgDcoquqQcDcoqqh1YNSAzwAF0TWjWgMjQGYdAFCNmdAA8UEBkSQ2YoDJUBZd1LpwfmjlaFwNyrHSAwd0JiyAyFoTI0BmpVCNkdEA+GwECtqofsLsgMhaEyNAZhoFaFkN0T/uf//E//8u//z//xr//t//5//uN//2//5d/+7V/+8/+Y/+O//st//t/+x7/8v//6X/7tP/7bv/zn//jv//7v/+lf/r9//ff/3v/Rf/1///U/+n//27/+l/Ovp9l/+4//8/zvafD/+r///d8eqf/5n9avj9c/fZw4U6+fP86LWSbCEX4YCa+N5Mc0WDdxzohOAy39+H18/fv0aBz99+eKxHKgRX8uUj5mLs758Je5yK+NxH6FabdxTgm2ZSImr4lzTWgU5iPwh0zUHyaqYeLx/XCVRVplKd7f1zAK4vzonr8/Vyl/GBCjLPut7SjKc/rypQm16jPOYjg/VF+asEpSyzHLQfLLkgxGs3zMd44KTWm5ca7Q/rRhNc1UphurOINEf0Z0ZORcBkuvM2LYOGcPh40zuaqkPvXQYtXq4xPkqtUSX5owWlaPfusWzpET9dLDbUFmJz0HFK8tGI3zEeA5qjQcS2vyz/oIRuPs8zlwQttLJ6KhNink2bzPwlzNW8p39dFe14fVKvo2c7SKc7rhlYnHcvdryXvMSVySl8NLE/luncZyu05jvV2n7bWF8+U/SuJMruadSvBnJDzW1K6MlPAyI0bjjEv9j5cGbKnQOhtFSK9qNIX76m3ZONenh41z2fn1izAl80UUZxeh0ojpZ3Ekqzhk1Mg5j08Wgr9h5DIbRqFe9twwktE8tV90cdnQSoLxlBPDj7iGFo8ZplWxH9TJ7CWZXwG/6sRon48tzqNOzk/ZZeOpRLM1WKv9FgQYOaeuyZP0NNIK91tHjndbh50XneOtM13T67xYI8/QlgKKkif5p41yu33U+xJolsc5fzvK9HGqgVG3Yr1g2xz8hcbl8TR+tJQ01VkeqdFLWn++FIr1ou8hMfDjnKt5bcMahDYdNs5pO3ltw2inoYfqXb0uhdc2LDWNefjxOBaXhrL+BuKUwlLuS2Gpd5u6XbES57D+yK8L1Gqkcb0mz8b22ober9h63K5YqzhymYO4XNrrNlrj/eKoaUNx5NvFYUpHnt3+ESP22g2jjeZ+kuU1J0KS/mzD9KNfu3uNztXww2ilNU4/zo/I1zL4iajXl6LejtvD/Ga981u/BORypGV57Ui0iiSGWSQ/xjBPNoyWmsN8V+ZAH04fFYjvc6GVm58LZj7arJR8zre/zocxMj0XsOYn4FHXWD89va2bmHMLo2LPNcHy2oY16zRne7iJnrN6P2e+zBrR2eEiveB+2TDaaIlDwko6vrOgc1RKJfFswWzhqyhqTq+7q5gfkrNGSpUvbbQ593Umw3c2+l4C2DiXFl/aML9a+iI56vWQ9vKrRayZpx6gfY3j6usvH1GrbcxJzbOZcJlGv40eFQYb55LHSxu64dtJb387mWp+DofXxyQr4HPd6u0vfLtm25z3P9eavmsdGpcNo3Vos1ppms3jcUZLejGwtf2Yk7TnYo689sPqLWv+5/F5Tjae5mmPw1wJSXMlhOfkPjGS+8Ff19vpCIaReL+xhyP9bWsvq3bPPvz6XRsOa944yHTlcdVPftFIwnH7A8pqZ+dyyvwyPlesvuozKc2xR8r5eGkjHPq3neYcBM5hVDUEIJiLTf2eT5Rp/THjKU9GjLZ6fvTEucYi5Tsj2q+AwCd2q5aRvKHXWIsczl5jjU97rA4UQOkz6lefCRsGqCFsGKGGcHuIGuKGMWrf/XxvkGqbcI1S7ffMev2rHK/V3Vp+inW9eIWDB34ZKeZIZL7xJPIabXsy8reiupZ5z4WX4ztRreuTsMX4WsusVShXDILpBb39NdbXXljrFY9ruUatJJoNOl3/wIjmtob+h2EkWYpaxttOK8+PPfd9aylK5yhTaVCVSv7ED1l+qCFk1izu43i5WSKk7M+emIMZTaGst+6PT6onYU5y9/1gdt3H/vUph1Ved117FafNBZjHeeH6alCVzQHAnB2P9YiGJ9GaJItrTqgab5mcNrzvrDUp9/vOWpRyvu9y3fC+y+32+8404ZuVsb4hes3Di7P+Xs+1mR1P43ppajE6nrkoldocrHJcU0zPESzx7gvP9iPP1dPInwC//DBH3nWGDz4W216Pd611qccBp1MVaVrlV4iVFbq35lKP11EooVir/DFMEYmN12Cfht3WytTjeufZSB53sr9cZTNfnY+w1Vk5wXj/mqtT3u+IGm6/J0x1lhlzkAJ/4z2rs7U+1fLsfC1n+hp5DpU1jbQpio0XhH8bsV57S44euxnX1P/zsNdaozp1fUhr09QMI0aLbTor55yiqa/fE9YqVSnz/VsKTSck/4dAWm/Oc53L+BCwlmQeF/TMBaai9D3xJGqWRqdjDZ9/9JtfnkRr/fDQuX6oNG59jl213jheUWv5tqiZq1ReUWt1i6hZOnCuTc/Kibwk8awD1mpVXF34sX/ldZu3lqvcozRrxco9SrMWnJyjNIkbRmmSbo/STBOuUZopaP56qTvqpd2vF9lRL3q/XvR2vSR7rCgrGsL4krdXrdaqphZDVnWDrOp9WdUdsqr/C2Q1RVoPMGbQ1Gqsab7zIi8q/Oo0ukFW47FBVuNxW1bjsUFW43FbVm0TTlk141NXVoT8eB5sRmvh6nFl8FztyWfGDDNtRxuRHW3k9oJADBsWBGK4vSBgm3C2EWviqs7ILPkx6H36NIrWylVKa1WRF7+eLFjLVm1OKJwfI/SFVp+NWJMBx5zvPWWtvjRiF0icmZEf4W6/CsSaDpAZCf1jwfgxv/jTiFoLcekfGsgvE+bKlfObNVrLTt5v1n4D9d1v1mjtnfJ9s5p+uHXImgF365C1eOXUIWujjFuHotzWIdOES4fslup9V5krT/53VdrRRlLa0EasBSxnG0llQxuxFrCcbcQ04Wsj5jbSGdqoRV4LohWW6J1GiNbalbt9WMN3d/uw1q6c7cNauXK3D2vlytk+TBPO9mG9dfvFH9dbl2cBn1uIteiUwhwQncOaYhiRHc1sx2dV2fFZVe5/VpUdn1Xl/mdV2fBZZY0Q+6FWqBdp4fUI0Vy4qtPI49bf1y8qa+nqnB+YG28yLV1re7Jhhq/OzXLpoLNIzsH0kxFz55/MaYRMJy6k513t1rrV49zCOVjl/Tsl+t8RKzchcCzOc++19lV5J0Vi3RAREOuGiIBYb0cExLohIiDW2xEBtgnfS8LU97wWrbIYLwlzH5G3hViLVu4WYi1auVuItWjlbCEtb2gh1qqVs4WYJnwtxBazedbI44D412Jm7q7yfu9a61XO713LD3cjkx1jVbk/VpUdY1W5P1aV+2NVcyvzkdeiKIWu/Xrtyo5JVdkxqSr3J1V1x6Sq3p9U1fC3lRtXLC5vOvtVueYuqyPP+b+j8RziB6PMfuzfNcqkExl+jTLVPEJqTohS8NsvNbT2WZUZkVSUV82ehEx3NFO93UzTsaGZpuN2M7VNOJupee5dmq1DjdaRjnxfg9KxYUI1HfV+5bYdlSv3K/f2hKp9KNU8Y7LU+vKYMcPCOfSZR0xK5cX/5/OPrJd+kLVIfbAR+cBIWmfT/DgS8JcRc3eV6zS+FOxmOpq6cRyfacJ3dluy9lY5T3VI1lSZ7/S2ZG6sch7J56+VZtSKs3lkKo8P29ixPgvD64jmFO3j01zneCYzqtJ9FpyVnbaWZMXMjvXijzPC5ExSv3uK3HljZG4pkmhEVaYo9zuvtcPK2XktE87Oa4ZUOTuvuT7l67zW6pS787prxei8ZvNI87CcczQir5uHtbbkPFMzWYf9eetWNtTt7aNSk7U85T1UzjbiPYPRWp5yH8JoLlD5TtmzG9kxhSylb4WszrODRMLro42TtbUqlLxOU+KjiZ9LxBL3HOZOwPNVZQyq8gZJzfclNd+X1LJBUst9SS07JDVvkFS7eczj2M4PIX3dPEq93zys5Sln8yj3VdmcznU2D2tpytk8rA1V7ubhrpWvmwepBy9ffjK+zGEqe+YP5V9GrIUp5xnrqW5op/V+O63322nd0E7b/XbadrTTuqGd2q3j7gxGCeu09lBe3wOQrAWlWmdQSZVmvPatnVS6tu4f/A0kH1y3sU7MCY8TJ16GHaRmhsj4DpNO1rJUXiGyOdIZYtVv4lxtnd+WZzq9PlYymduoKPI4UbBu/cBEPuZcfY4vM2MtS+0pD+cB3UnswylXFGWILzNj3pLgPALeWpjy7R42TdT5EVOjfmliinKlk6R/m7BKo8zWEQrFk/wuDbNI41JDOuvmlxFrG5X31K03zcx7dnrSDYenJ71/errpR5xn08YYD8MPy8g6iTmWYhgxC7YdbX3YhUONgtXbemaacOlZtpaWdujZz/IIrw/NeGPGfba9tUZ1jml0jWkyVbF8a0Q2GKnpWyPOs/oPc+ef77D+bO6lcp7Wn4Md+u86rj8H85zqudAU+ESSz4w4D0PP4f6p/28cmWuZj0Msv83NPHE/aJYvK2cVyeP+0K+NrBqOZYMRWlj93WCtVu883z1be1XOL5N1TnPT77qO9wKAHDfcAJDNVStv14kb7hHI5qGAzq5jO+LsOrYRZ9exK2ceYXcmdYMRemF8aKTOt060tN40wufP5uNLI3kOC9KPZYXPPKnrxGUO0PzeSP3WyDpPl1evPiwTikhO31ZxXtdgZtqk+aGR2YnP6Yavq7ius3hq+7YDrg20YlaxaUTXF9MRvpYCWUbiBiPhe09oe9O3Yq9xlUluGzyx5NEeO/ouBMp5w41AOeuGF2DecK9QLuH+C9B2xPkCtI04X4B25ThfgG4j1gvQNuJ8AWbZ8AI0jXhfgOYo1nlbUrbWtH5el5S/GwpnXetAKuU7I+4Lk/zZsQrW+2Utxud5vX+5arYWUFI6aBdqNRyx1rVKmwc3cNz1s5pUs70GOlmPprXakw1L6Y81JXXE/NKGeUxgOGYY+pnmM/blk2ItNOhrRrGaRnTVjb5uJB/NbL2+7Sfb265cF1rl2zda2V44W7x1pdUnBWKaKccyU4wzf7NVPUvWzuU1avXSPnHFe3VathaovHenZTHX632Xp9lGnDeXZdmwXyDLhv0CWW7vF8iyYb9Altv7BWwTrv0CduU6r/3IumFLa9YNW1qz3t7SmnXDltast7e02ibuV673HHS7hawphsxTDB8ZOZf650FfSeuXkui8bK+YG6ict+3ZRpzX7dlGnPftvfFkxrieyfKlEZ1zN2ery9++gtd74vy0Po5vzQjFykr5dkDgvvKuHHo3osE04YtosE24IhrelIf3UrRirnI5L0Ur1u4f563Sth+6zkB5xEi8NGJewz6jIjS+XDN/Y2JmRXnmpn5SM21lRZp83eB1ntp7po3QqmJ9lPtCEWwTrlCEYk0m+0IRPikPaxj+zkxbZkr+2kxZ84Ta1Kider926v3akb+uHS4Pa+D5rnbWgoHqt+8cPdaHn4ZYvjXjvauppNs3YJomnO8c08SGd46WeQFW0JqNd461RcsX3WiaOMcmc2LtTIf8nRGa628c0PCZkTXXfw5vvntlaEtrOef7V4b7iqOS05+biXF9d6WDJ+nKl0ZC/NKI886mYh045RzkmH4472yyjZQ8r20sNXxn5KyP+d45fkyQP+0OMIPQnXeDm0ZiWGUS0+tI9lI2bNguZceGbTM7x4puOrKVHesKjHlPeWsvZ2GLeUyj88r1Yh5/4ywQ04j34nbbyHrvPH0Uf2Kk5fWN/+P78clIjbcHbKYJ34DNOk/QN2B7Uxq6TmpPapRGtcYUM4KuZr674pcRa5PBWjUMx6vlINuNMr8M6o8z1j/KS5kL1LVI+drIzEw99Gsjc1qs/gi5/qS1yxSRopYR897FHUa8O1FKu30ftmnCOYY2TbjG0HZpOHeivClS306UYl2A5d2J8uZFM+9qOEdq2XjRWEa0reVcvjXi2Yi1eyust9Vj5xUZOZ6MWGMAun258dbLT4zkPOfGc1Y1jNyfGZD7MwNye2bALo0yNeRHgPSv0tD7s1h6fxZL49+WRp3bcjPvhv1dGvl+aeT7pVHvD0K8sci8F/YT9fDe/W4bcV67bhtZp1bn41sxTDq3FuUjvPakWrdfeT+IqnV1lX/8b9bOCktpfJL3r+xYR18vGxSo08Rvoc6vzEofmb+Lo+0o0w3fVPUwg6jW6egx833pP9eSq7UPx1mmlhvrSLBzYuj1Lce2kaplLWMdXxrR3NZMhGHEPMPOOR4yjeh62z1OTXoZ9GAb6X0bRvgD4FMjYRpJ4Vsj86NIaxPDiBmENWpYeYNGyX4TYR2iGw6OlP1lxMyMrMyoUazR3L/d1gTPYXhiGYnH/BY5Z4nSl9lpSWa58i6PjypYVlMT43zzai1BbTFyTgTOSdqQjHZiGll3FMfIZfLLiNpr4mspOn5pZEWXhszbIj4ykulObQ6hejZiHTOYZR0UxOsTQT8o135qzjWDLka5mkcuxxVe+uN272eVTnejXE0L3vmImm6fjGGa8M1H2CZc8xF2aTjnI94UqW8+ouYNJ2PYbcx51XE177ByXnVcs1UmLa8Vyrwq+Onco5rvn4pV8+1TsUwTvlOxar5/KlYtt0/FqmXDqVj+WmlGrVitQ6eOnUus6aWNYl5fMb+ezw91/dIP14Xc1Tx/3nUhd7XOB/TeGWUbWQs8ZzJ8ZyQcx5zQzMbV4LYnJa2DbOu3RpyXlFdrscl/Sfk7M1KXGVrs/dBMmVcVnGk6feVTM7OSHiZfn0hrF3DSVdU8bP2olvI8Vy5m/qj4ZcSaSlsjND7LqX3wujkF9lgCK1+JwY8hOG0lfLZhnjvoE4NmDgTK2mVNJ1v+EmnLD2eR2lU7v+XPWk7fdsCwTsgLIX3dAWNePSfWrztgnLFXD5NGzzHHnbTKmb4duuo0kV+bsD+xphvhx/kRn31irc1dPBH+/cde/HZ6otE8ibzeL1Pl9tKAbcK1NFDvrzyZJnyrC28KdO6COMs2GwVqne/T5pWYWfjciOf+YhkJZZ1MUA+jpZpG6gqNrUm/NCLr+FGeDPjMiHcOTHTDHJjpyQqVekRwvjZiLWS553tMI975HtOId77HOjnQO99jl6uuWPsQvi0Spz7bReLUZ3flGEbeLFauQ4Jyfr3O2I5yf5Kj3V/MajsWs9qxJUDQDIebipSqsWjazEPlCn0/csDyc3asg/aazsnjptxxPjEi/bz1a75FypdG2hRY0RK+M6Jhnv2iQa0yKXfHE2/8mAcCKB8f81lm4lq7iWoZkb/NTFqDtKSv7+xo9/dk2X70ffXXOuNh+XE7mNU24RrptXg7mNUujUojvWp0OnMVa4cR7+JCi3J3ccE04VtcsE24Fhfs0nAuLrwpUt/iQktpw3vXfMvUOse9fMDYrxaS7q8LtHR/XaCl2+sC7f5dWy3dXxdo+fa6QC/2u+sC/lppRq3cXxdo+f66wBs/XOsCLd9eF2h5w7qAbcS5LmAa8a4L2J441wVsI851gVa2rAu8M+NcF3hjxrsu8M6Mc13ALmDnuoBtxLkuYPYg3yS22ZGd6wK2Dd+6QKu31wVa3bAuYPrhLNK8YV3gTVv1rgu8MeNdF3hnxrkuYA8ZXesCb0adnnWBN9tJ4tqTYmx+bNb6kXvAaBlxTtS0DVtbW9uwtdXeG1PnkCDVH1fOfLI3JsyA0pxC+dJInmdN5J93Tn1ipDfDMbH/eidGM6/Q2mHE/c0o4fY3o31Coeub0TTh+2Y0S8P7zWgXqfOb0VqCcm+Qs7elrWOrlEPTn1uItQ1ri5FYlyyKxtdGrF1UQY51Pkvku/jakxHrplfXUQq2H1rWySw/PsXbJ0Z0+nHwgW0fGZG0TkHgHf+/jJQNKm+tcnhV3sxOjOtM6vOTy8iO2V5bpmvwysuX5xsj85CKM02Tvj+NiBkPujZkR155fc6OHObNxHGdzltfr8yLtSXLe6amWFuyvGdqink6tutMTTnMLwLfmZpdLV6+slxnatomXGdq2i1E5o2NKYRstBDrBu08353n1AwtTzxd6mkbabNiGl+g9cuINRUeV5GcK2E0ofak8mJdC9zWCU3nolgzjFhtVeeQRA5jV4hYMRylTA04pwXom89fwWntCUlRX6u8WOcCxlU3UaoYmWkbJMBaxHJLgLWfyikB1iKWWwJiuC0BpgmfBFgt1V0v1jKWu16sm7O89VJ31Eu7Xy/tT6X5XJ6k7eGvB5t9BPZ6Nu+YN9/xHvNf9ZI2HIgtacOB2JJuH4jd73O83ULS7QOxbRPOnmt+Says8GWCv15UyRpo5jwPMgu50LfvbzO6oY1Ya1nuNmKuZvnaiLUZy91GrFPmnG3ENOFUEate6rx4QSqHbDwPq8y1rBUp8eMb78mCecxVXQdu8SE39dmIFcFyzPCTU9bqayNmgayAC/lxncVzgRTzs3fd7MbHRj++j34asSbj59D7x7Fdv0zEDeNd6/xA93jX2o7lHu+Wcnu8WzbczCGlbdAh8wBBnw4V3aBD1p1STh0yTfh0yGyp3ndVTVveVXVHG6kbbm+Revv2FqltRxuR+21E7rcRa5w5F2u1yGtBbGHDl2rbMVnVdkxWtfuTVW3HZFW7P1nV7k9WmW/d1uju0GC0EOvjP0S6lK68NiLHhmYmOz6rZMdnldz/rJIdn1Vy/7NK7n9WmSPEtf1DhCItfo0QxdwdMI2kFo33nbkRJa+7NDJNvevTDIC5pLGOZUsHHTH7OJT8pxFLVtPcBxbzQYsrT0EwYh0g6A1nM98RKzch8IFqz73XvBPLOyliLVq5e6+1aOXuvdpu916VDb3X2nrl7L2mCV/vNfWdLyKX1y8JtZarvC1Ejw0Tq3psmFjV4/bEqh4bJlb1uD2xapvwtRBbzGa4c8y8M+9JzNSKhvd+76o1gef73jX9cDeysGGsquH2WFXDhrGqhttjVduEs5FZs/dHXutuvOn56bWrYcOkqsYNk6oab0+qatwwqdqvX7lZuTH9beXGdV4uX+vwq3KtpaqyTnUsB19TWD8YZbYZC5gaXQn/PMpUK+hUZmSj0ObRX2poHQFRZgwfX9GdypOQpR3NNN1vpmlHM033m2m630zN1iFzX0FSq3VY+3rcGpTajsqV+5W7YUJV8+0JVduEq3LNULXcdB3NwesHn4Tv5TavAzyNvI53U2vHlTd8T63Tl9zhe2aQp/L5mEaQp2lEZsGmI74ON9UsO8pE/7hM0grfS0d5XSZqfXWHomuL0inxr6IR3xmhAz5U40sj5t1dq4p/HKP6KzvmPQTz8y7/WBQtz0bubxLU+4cH6o6D8tRaq/JviHtjxruT7V1Daav3qLzam691R2sz90u5dufbzcS341mrqbCuHc/6Zr1qvMaNHc+mCd+OZzVXq3w7ntVaafLteNZqLgL4djz7a+X1juc3IuLa8azWcpVzx7PuOIJUdxxBqjuOINUdR5C+E0Xn9t53oujcl6s7zuvUHed16v3zOs1m79yXa9vw7ctVc1ef7/0rZg/27cvVNxsDXUW6YV/um7bq3Zf7xox3X+47M959ue+20sx149r01U3Hai1eeffj6P0rtMyoYO8X25stPdT9wpdbetwz4NbaValzwFgqn8j45IelA3zrBd0H9NmWnhbWpjzjq/58Ox1/bSXU9e3I1858aKW1dTikRsuKtTIwv3Farl/a0LwO65IvbYQjzt531GJZsd5cvsMh3xSszo/HoNFqb8YAtMo80a2eSwCvYwyON+d/zpHFmeZBwSc7r+raedX4Nfjky8nm5mfP0QVvHJkt5XRELEesptJSW3fS55Belko4zBuxRFeML1uRn8dmvtlLNs93bHwV9e+9ZOY2sLnt+Pz6q69E0jSxtrefyfydCZdUuy8osqTaNOIW2Rj+2opfqk0rbqk2t2A5pdqy4ZVqy4Zfqq0NVG6pNgvWK9XWmoF3nBMOa3nL2XvMXSne3mMacbd7a3FqjxV/7zGtuHuPtczl7T2WDW/vMY/Rc/eepBt6j31qpLP32JtLnC9Ae1+I6wVomvC9AG0Tri5sbujwdmHTiLvz2ecC7rDi78KmFXcXtsLDvV3YsuHtwmaYursLWx3H3YXNgvV24bpha9eZn3q795iLB97eU7e0+z19sOiO3mNacfce63xBb++xbHh7j3nOobv3WEtV7t5jFqz7Bej7LuZN/E/RyGdujBnMvCJWc2r0hV4/iJwPvHeuBcOVZh4YM7c1UIBFfS5Wa49WCStaLFBunqPn3jkywxpoubo+R4rHHbrW7n8Wtx0zmG3LDGZrf23Fr2tty6hANowKZMOoQLaMCmTHqKC1P9a189uB8lMNObFOGTwFYGpB5CMkn5XN2orj78hWoJSzI5vbaLwd2TTi7oIa/tqKvyPrlvkt3TC/pRvmt3TL/JbumN/SHfNb5oapY55HmQ55vSE2BHNd8piz5Tnk+Loj23tzVzh74HtufrtivdfnQnhrLyOMzJ25bkEJx/2Rgbmr1isophGvFISj/bUVt6DYVryCEsL9kYFpwykopg23oISwYWRgF+wWQVmB+ikfxodGCOZa7bp6UlN6KSjmFkx/Rw63Rwb29klnR7aNuLvglpWvsGXlK2xZ+QobVr7ChpWvsGXlK+xY+QpbVr7M4wfS3H8QUlst5en4gVOWrIHBDH/OfOy2HB/YKPONznG2H9qYMWBF6pc26jHyUukkhe9tlG9tzPKoX5dHneVRvy6PNvPSvi4PtvFtefCI79vyWDGC7evykJkX+bo82Ma35SHzLj9pX/sxz9oT+dYPnTOO+nV5sI2v/Vh3gRoaZB9e4oxtt4049+o8QsatV6+ul2YxrVhbW2r7B11+3rJrZ8cZkm4a8cb725544/3t0xg8q8y2Cdcq8xsTrsFm2DCfbBtxDxPr8ddW/IPNuiMiNtT7EbGmDe9gs+6IiA11Q0SsXbDOwaZ51oX/U63q7d4TN4RZ2Ubc7b79uRV/7zGtuHuPtUrl7T2WDW/vsWz4e0+TDb3HLFjvp5p9Ikmhax7K6zXVIOZFsActqvJU8LMRs6HU1VCEd1U9G0nWF06dXzjlOxNt3qT14+PkMxOztcaXXrw55GVeO1UO/q74VaLWjECZh95lvlnshhF9ZcR97k06DqOVmXdG5dnKQuYtTM/ZsZY+6jH3M9cQmmHEvPgxF9qaecgWMz9OJv1ktkVXsbw+7NE+h2dNcmh4Oag/c1PvfhjYZ+h4X6Fpy8tP9a+t+F+huiNQKx73A7VMG85XqGnD/QqNx4ZALbtg3bOd5mlJc6YhiXG0+Jkfy0qevYdOfXueMY2HeezLLBE+fqY99526YTAdN3yKJt2hBDv6cAz5r624lcC24lYC60YtrxJYNrxKENoOJbDOKfQqgV2w7s2Z3kvx0utL8c78WB/oMo/lCEIXjTwHIpg17O7H8f7GhXhsCESIOyaDYpS/tuLvx6YVdz+2Ti309mPLhrcfp7CjH1sXbLn7sVmw7p17O8J4Yrp/REHaEcaTtry/8vHXVvy9J++YkI35/oSsacPbe/KOCdmYN0zI2gW74y2Y1vdoytm6PNh6qYd14kkoyXiVlj+3UmXuXah6vDoF5o2NdQ5i1Rq+tNGWH/rahtlg5xSKxq8b/dyGwYfDft1xDBu2rqU5UXfKZPjSSFwXVKTDkhJzw4+7C5tWwjwx95wZkq+tzOo5J/a+9oUmlZJ+7UuJ6zzG3L62Utd5eaJf52hp2+Mg1NdW6v3t3qYN70uj7tjuHeuG7d5vCjbP75VU2reF4hQm04ZTmJyVY9owx9TOvJg2nHlxju0tkY3HBpG1PwK9Itu2iGzbIrJti8i2LSLbtohs2yKybYvIygaRlQ0iK1tEVnaIbNsisrJBZGWDyMoGkTUnIJ15MW048+KcCDVs2PPUTpF9M2PuFVndIrK6RWR1i8jqFpHVLSKrW0RWd4hsOu6LrGnDKbKmDXeLS8cOkdUdImsXik+YbBs+YfJWjilu5nqvU2RNG06Rda47myIbd4hs3CCyKewQWduKV2TfWHGKrG3FK7K2Fa/IvrHiFNk3OfKKbNwgsnGDyMYtIhs3iOybgvWKbNwgsnGDyMb7ImvHpfryYtvw5cUbH2uJbNwhsnGLyKYtIpu2iGzaIrJpi8imLSKbtohs2iKyeYPI5g0im7eIbN4hsmmLyOYNIps3iGzeILL1/sKXbcMpsvX2wpe9w8orsvZeL6/Ibln4SlsWvtKWha+0ZeErbVn4SlsWvtKWha+0YeErbVj4SlsWvtKOha+0ZeErbVj4ShsWvtL9ha83W1DncZOlltfXkpsm5o6IwvdBfLK72Hmh0Rsjvguv3hwO4nzpmDacLx3nISVW3ZpnyHhfOvZpNt6XjuwImLKtuF86thXvS8e04n7pmFbcLx3bivelY+fI+9LR+ydtmTa8Lx3dcdJW0g0nbb0pWO9LxywU50vHtOF86TgrxxS3cD8vtg2nyIbbebFP3PNGW8iOkLa85eIs24pXZN9YcYqsbcUrsrYVr8i+seIU2Tc5cops3nCcYd5wnGHecpxh3nGc4ZuCdYps3iBMeYMw5fvC9OYAXF9ebBu+vHgP4rVE1jwn2Suy9onNXpGNW0Q2bhHZuEVk4xaRjVtENm4R2bhFZNMGkU0bRDZtEdm0Q2TjFpFNG0Q2bRDZtEFk5X5ebBtOkZX7I9m2YY76zf0WXpHdsr/KtuIW2bxFZPMWkc1bRDZvEdm8RWQ3XOSVN1zklbdc5JV3XOT1pmC9Ils2iGzZILJlg8jW+yFttg2nyDrvvLJE1rySzCuy9uVoXpHdcqqgbcUtsnWLyNYtIlu3iGzdIrJ1i8i2DSLbNohs2yKybYfI1i0i2zaIbNsgsm2DyG54YRwbXhjH/ReGfWuqV2TLjs0ZecvCV96y8JW3LHzlLQtfecvCV96y8JW3LHzlDQtfecPCV96y8JV3LHzlLQtfecPCV96w8JV1gzCVu9EWb0y4oi2ydW5dP+Gym0jpx0GYT4ES5bBO3JnNfVVsfjp80r5C3fnCSfejaLxXuVv1mjfEUNtGvC+ccuw4oM224n3hvLHifOHYVrwvHNuK94XzxorzhfMmR84XTgn3r0IybThfOKYNf4sLG65CelOwzheOXSg+YbJt+ITJWzmmuG0IZzs2hLMd98PZJG4IZ7ONuEU2bhHZuEVk4xaRjVtENm4R2bhFZOMWkU0bRDZtENm0RWTTDpGNW0Q2bRDZtEFk031hCvn2qN424RnVh+O4v13GtuGU+uP+OXHHjqXIY8dSZMk7tsvYVtxSn3dsl7GtuKU+79gu88aKV+rzju0ypdzfLmPa8Ep92bFdppQN22XeFKxX6sv9D33bhlPqy+0P/WbdmlPLvI2zrm0qp0Z9YCLPU0VJ6J9NFCvIwueFbcLnhbVOHcs8YzX+6LupfGCk6jwuuWr60si6Pzryaa8fGTlfEfMM3CMa2bFuWkzHnBY7Z9bSd0Z8h9faJlxn174x4Tm61q6XNo/Ff9yp+WXl/jCSvzUSl5H0ul5CsW87T2vilN7i9RMbeQ5tUo4vTwQu5t1dG2zkuM5ZjuXL6p3XB8XGJ4N/VjMyBaDptyrCnnxtROYY/Ex+bWSOImwjVqymU99NEz59D9brMk4b53v7ZQuxTcz7bTTSvs4nE9YpYc6yME34ysJa7CgtDTEsjcoipPSBkb4qAyNSji+NaBjj7vLjluTPPGnLE63fGpmVe9r71hOd6l40f18msoy8rp1s3WWYi8xL8wpfHf29kfalkRrHfEKu1Gs+M7IuW8/NaGzZ2pfWdI5E5DiMWzXqYd4yN+/kzpUvrJT4kSu+Cz6qdWWX74KPLGbwne+CD9uI92qOau2832PFfcGHbcV7wUfdsKZVN6xp1S1rWnXHmpZdsM4LPrKGHR3ZvLbL25F1x0091TpwzNmRdcNNPbYRdxeM5a+t+DuyacXdka1Lnbwd2bLh7cjm5VLujmydyu/uyGbBejuy9VovR5xDnSO/HnSd+bGWG6LMQWTk8d9zF0zWFFKbRVsbfQ0/GXmTHZljyHBEKzttR3bkj7MT2nQktC/HkOd33eiA58pV/dJIXJ6cX8cbjMjxbXaOWcUp6LeezButSzq+L1hdBVu+NZKXkZqMFmtKm29K3LbhmxL3Sqxhw34DOtfq3ryLnWt157t+h9ibVrxrdW+sONfqbCvetTrbinet7o0V51rdmxw51+qqtbrlHV5YNrzDiy2HKVZrX5l7eGEXrHOtzi4UpzCZNpzC5Kwc08aGOL66IY6v3o/js+cLvCIrO7YN1rZFZNsWkW1bRLZtEdm2RWTbFpFtW0S2bRDZtkFkt9wiVmWHyLYtIts2iGzbILLttshmcy9JP6D0WhKlL56kx7dG6rdGaFcL9eLPjOQVBJBpnfhDI6kuI+1bI0GnEZq//9BIDdNItTyxup/M2gliVrFpRKc66hG+NTJnMU8jcYOR8L0nbRmpXxrR9cbQ3DZ4ko1mb84xe6vYNuKsYtuIs4rdRsL3nviq2J68d1ax2xOjipP9hZ3nCDIWXknPP98Y7bgfAWPb8EWvtBD+1oYvAsYu1DTfoDG1wyhUM/h7TrjXcLyad7T9yCuIJvMI9rcf9f40arPWvJzTqHZ2SpxttcTyMjtvjJRZJqWKYcQ6M7DkYxopx3dGfPF8tglXPN8bE554vmR9QPpicWwTrlicVM0d0G1tt5D1iqif2FjREWdSX9k45/CtxpGPuWqXQzaMWO/vrOuDr8TXRsyjCmeJSFp+nDL8gQ2ZLV04wOm3DWsL8zHH4DHQMnOOz0aM0DWpc6maI2h+O2J0/hTmlpx0FiutVJdv66bFL1tJ75WjldQvjZS4xIy+S363Eiv4RdcmI636rREK2Kpf9xxZAk8BW7+M5HC/0Vs2vI3eDPkMaQafBhpH/Gr02XpbzRd4OiwTaUPns+5t8na+bGl8mIEV57zoYXQ+v5XyrZU851oqDxR/W7HOJPLWjpmdGRlYearyw+zEObVQI4e9fGillWlFv66gNMNZ649Zm99Fa0VFHMeaCT7TVEUlfGBH4xwznsn8tZW5zqy8WP2hlVSOaaXWb63kOdzScli+VOvUmr4b4bKiXEvPrbeakYZpBSiV+vJ7y/RE5rewCn2B/oMnXiv1+NrKfAGdyfqllXCEMudNjtAsO2ZNlyl1yuOMT1udrFbHvfpDK3MB4rRi9Ub/C15ev+DNYwvnpVCtvXydvflU0Pmp0IIxbLLm/HOYPShH6ochyidW1hVX53xesKyY4YZpTjicgwEjQ2XDJ0er90dflg3v6KvJhlGPtRDiHfVYJ3D7PzncdWN9ctitZC4OxSb5OyNpNfvzTdi+NnLcN5LW8IuF7UMjs45Pe4YRa/bC/QVlG3F+QZnZyau15SobjHzb2FLUtWQmRhVbd/eFOvcSnS8WqwuarrQ55XcOSA11tOYN3XVsG9lRx336+sqO1Y3VPKpoTvuFwPvFPizZOS5OYjU3tSb+p1KfH2WvHZHDGnJpWUs7zfqeszzJKxSAQzh/F4m51WstHxQKBfj1QhfrsBTvHKIc+f4L3TwuxflCN204X+hineHmfaGLtc/L+UIXc53K+0L3102z6ibdn0O0jTjnEMW6q8srbG8avW/6T8KG9ho2tNewo72GDe016Ib5Aok75gsk3p8vsAvWOa8qMd2duTPL9YMZKrt+vF/WthXvXIFtxTtb9saKc7bsTbk4Z8vsduudXfJbsWaX3lhxzi6ZVj6YXXpTvs55oQ80+/UIUKyjll0zOm+GXX1/N4ZdbOTD2ZjSaJ++MRsj1lrYOUBYIb+BAnN+WcnWxMHa7p94u3/6KEclrBXtSEGyv3NknUH9QY7Sn+dohas/9pBZOSp/2uRKnSP90opajlibwcOKNqK47t825P5r1fQj1X/49vnth3lb1tnYZhx0OGiNr35i5ZB5bM+Z5i/cj6zo3EN6prV8Vyrz3K6sVu2U/Lc2znKIusqkGCWbt5Rs3lGyphVvW7H7YJuzTDVmSwzMBRs5VpxrpC//c8rpycqGwW215zFm0apmyxPTylzfiEcM31qROb6NP/aU/7ZSdrw6at3w6jBzdI5u53Fvkaar/iFH1uu9thkze6ZLel3TtpWpC4/tGPrSirUWFsv8uIuVN0D/ylGzWu464zAGGiT8OntDrL4o63vo7E/NspLM7/cxkGsSTF+sickyNTcYW2nsO0vDOoOSF/j+wYoZPUujlW9tLJELxbJhxqroDI0OwVKWN3u/5rjpXK9cVo7wiZU2q+dcOxPDinVUYVzFco5saRCXnqdHrP1fZyMbtdw0NcuK1Wq9p9eIdZjVOV88R5RFXp0YbtdzWsfXnEswlvaLdR/CqqHIE/v/kJ+2QxFEdiiC6H1FsK568iuCddKRVxFMG05FsNqsv3asJS1/7WjZUDt1S+20DbXT/lavU5pH055FaYxJ1VoXi2vHb0ysKM+1o9ZBiu6Wokfc0FLUmnBythS1Fl/cLUWtVS1nS7FtePux+d2xciPkya83mB7mpFU+5kA9F5qL+Ac7uqOthGNHWzG3gznbSog72oq5PuZsK/Yam1NVzIimudgnlSZ9f4281NoRRrv9fnwXPpuwJLLVuWAowbhsUK31sXTMiOVT6OprK3ahrB1/8mNv2q9CMeflabPsqT7kS3m2Yu0+1PQPDeUfbMQNA2O1lsjcA2ONO85nVeuMPOfA2PTEL0zWLUd+YbLiYL3CZO1C8guTtb3LK0ymDZ8w2W3W/RKz9oh98hJLW9pKKjvairU45m0rqW1pK7KhrciGtmINR+eBAnx4zG+NzGHDB67mHVNemndMeWm+P+WleceUl+b7U162DW87sd7IrdFRDcFqKWa8V1xhxrTr/LcVc6uYu72VLR9iZcuHWNnwIVa2fIiVDR9iZcOHmDmObDMc75wWC8Y4slhjgzqtpBatN6F5AmFeq2uZpvT1efbAXC/RFd570BkU57D72YoltWmdL5cPWrt5jhFR6zDEc71mxjpW4aCi+MGrY2UoBDpr+XdfrnnHpIq1MObvy7Xu6Mu13e/L1oKWvy9Xvd+XTRvOd4ep+nzil1jvDmtJzN9S2o6JWm07Jmq13Z+o1bZjolbb/Yla24azpdjylleoPkde/pI3a5uY/zvZmgr0fidbnvhbm2wZ08qGMa1sGdPKhjGtbBjTWq/kdOS1vMcHof16JcuWSVrdMkmrGyZpdcskrW6YpNX0x3Uc50n/iQ/c+l3H1nJYOWaUSjkaz0d+MhhtZe72bHQY6O/BqHXG1Lr8TmhH1G+BtPZmlbl3tSgHpv+UtngcGxrsaeV2gz1tbGiw0bxS29dg39hwNlizlcg8hiyp0UpOT+p9UTqttC11LBvqWHfUcTju13G4P0Frxs7lNjesZZ6g/SymMPdDAoeV1xF48TCv4XLGFJ5WrKHslnD0HycJ8Y6zD63QGXrH8a2VdSdubVawv22lziZXJb7ewXoOP44ddWR9r2+qo/UCqlLNHFmLC2Wdtnim86uIzbdWpkCdabpJ65cV65KlHt8AlctBrRyZNzDOz9P8YzW4POu2tSSGKXLo3BFe7vSPh7ki5toEftqwBDeGdZZtyy+niOKR3mximOG9jyD1ZUc+s1NWcwmFVip+nwJkNd5W51kZraoYVZ3s67I9J8ScRu5vKD+N3N6ga9vwbdA9bdzfoHsaub1B97SxYUP5B3XTrLqxL8z2nBBjG3GeEPPWyHHfiO/gj8fuBmvwRFvby5cF6zyr5p0R11k1Z3bun/b5zohru/+b7ORjXWUQw2sjJfy5J65Tcz4w8m0HdJ6ac5aJfeGn69Scd+3e21DKX1eP78Cbs1DM7fq+A2/eueI68CYe1oyxd6xjLYd5D7yxPfEdePN2QNvWSF9FXg5ozW1i7mGxZcV3dv+b4WybM6xn0miy5u4u70ip6v2RkmXDO1Kyt4c5R0rm7jDnSKmlHSMld91YQm1/9MwX+mNC+LURe1+XUx3Nrx7nwvgbK23daNBy+NJKOOalrudaWP7Wl5LWmRL1xnec1PUdRy/Tj7/jZqYe33TVsGPmKukqG17h+6xs8oxpOufvmmVFNui+/f10LFWQ77pRDGE23mC92mXD3IHojvep7ChXs4bn0RRnZaevW3+IK9QlpO9nMWJesxixft+L4hzEPWxavciK+J/r240j0p9noN/su55RgbW9PL3gbN7NtuLZvW1b8Q1X7H1i3hn1dzvAqTOHb3eAe4MYTr2wz1WZSx6VD7N/9sRa9F+7YGPMxp2mtpV+L9L1UrRWX8Lx51bOj7pjNTj51kqbl0o9Tl61rFid0HUDqG3DdwOobcN7A+jZpK2PIN8NoG8KVtfVqhrNBqfWQsW6DULDt9vrwznXtSYAarLOTjO36de1Tb/xm/XJm7N4q7W05bna6Z0ns7WcnojlidVcWprHez2+8tLLcjnt2JdWrp1ebEWerlV7c/DAnJxsUo3QijdHBsyja87vzPpSLE0bdR7qcCbzlzZ8om1u4HaLtmnFLbfxz634Rdu04hbtqPdFO+p90Y66Q7RT3CDaZsF6Rdvc8ewf9aRyuwPZe5W9Hci24m76Sf7air8DmVbcHci8WMzZgSwb3g5k2fB3IGu7mLsDmQXr7kD2TmPnm/DNHmHXm9C24XsTvrHh68h2JIO3I9tzet4uWOJfW/F3ZNOKuyNb62PejvzmFi5XR7bvOPN2ZCv40t2RzYJ1d+S0YbN/DNailLcDmcEd7g5kWnE3fXO72BYr/g5kWnF3IGu7mLcDWTa8Hai2HR3InEHzdiCzYP1vwuD6VuYjn572nJ3ZMd6mee1HyolmSX+frGJ5EvgghRYsX6ypr7k0lQIttP2qHWuNLKzA/0DZed4M8c6RGVbBt6n82hG4ZXKz6X1xyzsmN20rblmS+NdW/OImW0YHsmF0IBtGB7JldCA7RgcS/1rcwpEoQ9WQFPPkw7C2OMYjGPJmBYr4O7O52cvZmc1t0+7OXLd8be+ZOtMtk166ZdJLN0x66YZJL90x6RWPHZNeumXSy9wff8zDztMhr09FOTNkxWsdcyY9hxyNzmyf0FIo4FgtX6xBretGCPN4FreqxGPDEME8WMWtKmXHl0vcMp9oWnGrim3Fqyox3B8imDacqmLa8KtK2DBEsAt2j6qsfZcpH8ZXRzTPUJR54EzWlAxVaWlHZ44bhghtx7qYbcXdDeOfW/F35i3rYnHDuljcsC4Wt6yLxR3rYnHPupgZcZ/m3s2Q2moqT0dQnfmxRggzGDtTDQc5PrBR5pudw30/tDGDxgrd3PaZjTqv4qp0mNb3Nsq3NmZ51K/Lo87yqF+XR5t5aV+XB9v4tjx45PdteaygwvZ1ecjMi3xdHmzj2/LotxzBRvvaj3kws8i3fuicgtSvy4NtfO2HDGFWQ4PeHF/njK9/Y8W7wzna+8N0vTeLacXcPN7+QZmfD2R5kx9nTLxtxbvr4I0vzl0H707g8q1Cmzacq9CyYRFNtswzy4555lj/3Ip/3Fl3BNHGej+I1rThHXfWHUG0sW0IorUL1j3ulB3xWLHdD2i0jyVzdyDdMn/S2l9b8Xcg04q7A5lHJjo7kGXD24Hk2NGBrAMT3R3ILFh3B7LPnyt0hVh5veQardMOUzhozZVniJ+NmC2lrpYivLnr2YhY3zt1fu+U70y0I/3Tp8pnJmZzjS+9eHekX5xb8g/+zHguUjXvuJ5b2HPNW4zoKyP+cw7TcRjtTM0LRmc7C5k3QP3Kj7VJ4Zh7rWsIzTBiNdazmdNO0UO2mPlxcP1H0y+6ysU6Adw8dXFNe2h4OciPyTov0feh8Oa8ROeb9I0V7zswHfmvrbjfpLYV75s0HffjuUwbzjepacP9Jk1hQzyXXbD+KVDzYMw5/ZDEuI3mzJB5sszsQHTi7/M0arJOTEzzRJgc+f31q/fUDePqZG0H842r35ys6VeDHeHRKfy5Fb8amFbcamBdxeRVA8uGVw1i3KEGVji+Ww3MgvXv7vRewZxeX8F8Zsj6Xpd5aEgQuq3uOVLBvJnX35fNi7+8m/6ODd/IthV3L7SPv9thxd+XTSvuvmxdHubty5YNb1+2bPj7snVSorsvmwXr3/S3I9Qn5ftHHdiX2bonmfYMarfEFJtW/B0o75ilTfn+LK1pw9uB8o5Z2lQ2zNLaBbvlZZgSnXTIoX+/zy2xxvphnaASSjJeqdaC2B4rVeZuh6rHy3NlbBvriOmqNXxpoy0/9LUNs8nOORWNXzf7uXGD7wT4uuu08q20pTl5d0pl+NZKXLeYpcOSE3ObkLsbm1bCvCnhnCySr63MCgpBvvaFppmSfu1LiesMydy+tlLXyX6iX+do6dvjnPnXVtr93eKmDe+Lo+3YLZ7aht3ibwo2zy+XVNq3heKUJtOGU5qclWPaMIfWzryYNpx5cQ7xLZm1P8G8Mvvmc9Ars7JFZmWLzMoWmZUtMitbZFa2yKxskVndILO6QWZ1i8zqDpmVLTKrG2RWN8isbpBZczbSmRfThjMvzllRy4Y9a+2U2Xcz6E6ZzccOmbWteGX2jRWnzNpWvDJrW/HK7BsrTpl9kyOnzOZwX2ZNG06ZNW34W1zYILNvCtYps3ah+KTJtuGTJm/lmPJmLgE7Zda04ZRZ51K0LbNxi8zGHTIbt8hs3CKzcYvMxi0yG7fIbNwis3GLzKYNMps2yGzaIrNph8zGLTKbNshs2iCz6b7M2jGrvrzYNnx58cbOmnOzukFm38VZe2U2b5HZvEVm8xaZzVtkNm+R2bxFZvMWmS0bZLZskNmyRWbLDpnNW2S2bJDZskFmywaZrfeXwGwbTpmtG5bAzD1Ybpm194N5ZXbLEljesgSWtyyB5S1LYHnLEljesgSWtyyB5Q1LYHnDEljesgSWdyyB5S1LYHnDEljesASW7y+BvduoOo+rLJXuwPlss+u6qpIvmfhoK7Lz2qV3VpzXc9nHiThfPaYN56vHeayJWb/msTPuV499BI731SM7gqhsK+5Xj23F++oxrbhfPaYV96vHtuJ99dg58r569P4JXaYN76tHd5zQlXXDCV1vCtb76jELxfnqMW04Xz3OyjHlLdzPi23DKbOh3JfZsiXIrewIcitbruWyrXhl9o0Vp8zaVrwya1vxyuwbK06ZfZMjp8yWDQchlg0HIZYtByGWHQchvilYp8yWDdJUNkhTuS9Nb87P9eXFtuHLi/ccX1NmzXOW3TJrn/nsldm4RWbjFpmNW2Q2bpHZuEVm4xaZjVtkNm2Q2bRBZtMWmU07ZDZukdm0QWbTBplNG2RW7ufFtuGUWdkwms1b5qvzjvnqsmXnlW3FLbN5i8zmLTKbt8hs3iKzeYvMbrgXrGy4F6xsuRes7LgX7E3BemW2bJDZskFmywaZrfeD3GwbTpmt7b7MmvebuWXWvmvNK7NbjiG0rbhltm6R2bpFZusWma1bZLZukdm2QWbbBpltW2S27ZDZukVm2waZbRtktm2Q2Q2vjLDhlRHKhtFs1B0yG3ds2ShblsDKliWwsmUJrGxZAitblsDKliWwsmUJrGxYAisblsDKliWwsmMJrGxZAisblsDKhiWwojukqdyPvrBt+KIvrKn3FHRe/JN+HJz5FDdRzRPqZotfdZufDpazr2d3vnXy/cAa7zXxZtWGLaHVYUdodQ07jnKzrXjfOm+sON86thXvW8e24n3rvLHifOu8yZHzrVPD/duUTBvOt45pw9/i4obblN4UrPOtYxeKT5psGz5p8laOKW8b4tvChvi2sCG+TXRHfJttxS2zaYvMpi0ym7bIbNois2mLzKYtMpu2yGzaILNpg8ymLTKbd8hs2iKzaYPMpg0ymzZIk+Tbg/s3NjyD+xiO+ztpbBtOuT/u76SRtmNl0rbilvuyYyeNbcUt92XHThrbilvuy46dNG+seOW+7NhJU+v9nTSmDa/c1x07aWrdsJPmTcF65b7e/+C3bTjlvt7/4Be7Cx5x9p5wpNVk62dWclpW6vHCSqzWzqCUp0ymHMNXNnJcp7LGEl7n5thSJseWMimmlZCXlfydFW+pRPPGKsrPcdClp0niZ3ZSJTvJsJPMF1koy05o9Us7vhN439hwncD7zobnBN4zn3vq6J0dbx21WrfUkWnHWUe2DV8dvbHhq6NsRD7UNK93OZN0UZqUT6zEeS3EaaW+tGKe4BnzvHf0cfbVyk540hbrHI2QdQ156MX824hxvn6bN2kJ33HRjg9syLwsV6h6/8GGNcY+5pLC+VmwijU/ryhY8zJSRyMRbZYjzVrbmJ9h6SzWl/X7Qd20l3VjN5KkshpJ/c5GifO6gZLSyzbSrNsTznWt+VWpVb81Mi9CsYwkK3bJ11hTfiOwxxLYxNekBb8ZTfNz41S3b42UeReEciP5zEicd/vpuS73bXbKvHg71WoYsc7LlPkhp1Jev7n8Rmjo9qERSdOIVMOIWSayykSP12ViC72sa6rpc/1X17EOQOQb718qY4qWMPbTBNFzfty6WI5nP6xBRcvDypk0dCC0+2+tZi1AO99apg3nW6tZQ2rvW6vFcPut1aylL/dby183zaobq5X0wx9gRNV45ZhRCr63xTtP5kRMPOia0N+eWOOBWcP5MGvHDOPyXXlve5LXPExNVqOvZoM9VoOV78o1hjAHJkFej16btQDgLVf7cqgis6m1YLR6yxNfudr6WmeJSI35pb6aby3/N+Q7M85PyDdmvF+QZ+nq39tx3tdj2/Dd1/PGhutL1FykaWuhR16rbLr//djMm6G8b+Jc77+Jc73/Jra2vrjfxFnvv4mt2Uf/m9hdN+27NuL7fDRNeL8erSlq99ejbcQ3Hsj3W+qOb0fLiveDzbTh/V6rGz7XvDasr7W64WOt7nnJbPger1vmF+qG6YX6t7lxTy7U+23V3NfhbKtuG0ZbtW342qq9X9TbVu1S9c1O2KMI5+SEddabb3LCWjhcEQ3nSHyZCPF5WGZt7EoprZB0zssnNnzLoM06Ztu34GeWxzGbRw70UfO7PMScgF63spawyuMR1fBkxbrLvsY5mKn8JfFkxfxIc06FWyt0cS65RArtSB9YmEPMyiEZzxasbJTZOELhe1RT/KAo4iqKmF7aOCvFvN58KeqZpm/Wnw0k326m5kR6LXGuj9fCk4rpKdysWSsl3o5r2nB2XPMyL1+JGB03ypxkPZPxlYV4t52bFlzt3MqFt52bNrztXI5jQzs3j8g75kfQmSZPst9GmYUaSzFsWHlpx5w2OEX90Ne9RaxrjJy9xbbh6y1i7d3aoB8/S4SmZ59LJJs70bKur+1MdSNf2pD7Nmp6aaNYr+wmU1BPqVovWz38NqTMkD/h2YePbMi0odTGftmwtXCGzErM39rIy0a5b4OuuH+2YW33L3XOMp9Td/raRrpft6YNZ93aNnx1a52anWIZeTmTet8G9ZfPbMyP5BRb+c5GmvNKZ+r4zkaeQna+sL4sj1TnQDvxx/rXNuqXNmhnr37ZPvIM4kw5fVm3ea5hnMn2pY2pQSmXb+u2hmmjti/73KyXIFbdmjZ0DYWO8G3fX6tlR7xvI3ztR1s26nc2dG0a0Nzu+2G953TDO1s3vLN1wztb7uu624ah67YNn64Xua/rpg2vrlvj5HPWZC4uS/5q/JG1jfLIKq/Lwx6ftmOOT+X1+DSKOZpyLrJJMV8xx5TUxNs4frtixa2WNqy0Qh0v/DJifgmFpe40vX1+jDwZMeZz07E+pw5e+/9lxFo2CEdeO7J4s87vDJllW2gI0KyytQcBq4b0dWMxb/FpqUx1bbz++Px5Z1spx7JScjI+m80NO7MHnTPuVM/ys46a0eDyGpFkHpH8yo5ho6T5tihJXxeJucWzHdNGoziIj2zoHNUUpXikz6qmTTE434LH8aUVyWsWQMrrMtHb88N6e344HOaGIaUNQ+fc1cuJFfOSplNYx7pONCZnbBuzqWqsryYizWqRtvIiTb7svaIzLOpMW1PE5v5b76SXacM56dXa3UmvD0oky9fl2paVkr+1UnRZadaUpHWdl7d25P4GRLHWqrbUDpeI6Ne1s773VL8URj3WO0tDfC30wTq93aeMtgmXNNp5KW2qidZ8GC1Nj7sLLLaN87V1rCD2xrFzH1lZ85tnOpZvraxd0Y33Vn/QZrWteBO1lDqYd9uqzpZypkv7zkyMc+QY08Hjz/KlkRC/NFLmHu1YKKrwIyNnFqa0HT++mp72+lkHgYb5Qo8xcTd+irLQI2xYzj8ndjYs51v5Wdui45HN/Nzd0mItgnuzYtkoS5aehtJ+P04Tx7RBb51nG2dx3I9esW343qEabocF2OUxI8aKJDXKI5jL2HPJpWZJlhXrc2vOvdRwvPygth0pc7xWSzq+zU6Zs2LnWlL53srMTz30eytxWvmx6vrTilp7OWV236KWjduxDno71kE3xDrojlgHjel+rEOwAiZyntMLOSs3kOPZlftfW7YNpxbF219bdoGU2U5zaWIViG4oEL1fICn8bYGsM8Zy5b0WvwrECmPzFohpw1sgtw9XsY6YTjrfVvkI+eVgxrYxQz9OG9UYEFlfWf4BXtowKjLP2axhHZNRDEfylvFq3jBeDVa3Oefi5kdWzHR+VdRnV6ylgrmplWfE2yd+9PMvrmkBij9/9iOkHe8Jy4guWTy/9GhhK8kHRuoxD9LiccSnRuYehcp7JX4ZMc8jom2TlTdL5Ccj5sbYOR45P2uSYcTKTktjtKiNIw4+KhNZBSu8PP68hmPeDbzHyo+dvqm+LJU3VuLciRIjF8tvK9buq7BCD87l/2+trLWtkI/8rZU8dwqe8lYMK9ZhT96T9d5cJV3bnC2R14Ubqj2zNuc5wqvP8WCtsDknGk0TvjUY8/gs54DeNuIe0Vs3frmVWs2wQd+JG1qt2BDnPl9tRqE4d0+aNpz7fLXF+yEIaq3DOvf5arMGBN59vv66eb05xm4kzgM31Frbcm6wDeYZXnUq9Jnk3YLxAyNrQu1Mhu+MeA/csD0paW2Pq5YRO7BD6grsEBooyUdmyjy64ExTlPqnZmbBPEwaxwKaJZN0FS8PLj4q3tzmiytTN/xtxNq14zq7w+w+ziNRbBvOE1HUWg5ynoiiai+1+U5EMT3xlqpZu/Mb46zo9G3nCWuPWQj04vmw1ce8Ok+sX/fBONcfHyaNzmMOc2gWN307UprHmNT80sS7gfD0I/yIOP9wIDz3VwWexrkxKI/h24+vtk5l5jDJpy8exOvdm9t6Y8M1t5WOo/ytDeeEoV2oM1LsLN9sFaoVwdrmAfpZDuNcI9NKKCvWuh6vW+wbK3VFZ9Sk31rpcbLXZE752hdtay31CF9a8U5dvPFlLck+IhoMK6Hc/0h/Y8X5kf7GivMj/bRy/yrDd4WrK+wrhK+LxSfZ74rFJ9kfVJEl2cftmeZHVPX9mebTStkw02wtrTad81xNual8YkTa1ARRDij4xIiGuR1EA3/i/i6U2wtfbxwp68oG2lPyWW7iFP5zkU2N3KT4t7lJa4jBh678gyP5bx05pWjO4B+mI/X+WMe04RynWGtfznGKdaaeVhqn8O6JX+2s3J7DNE345jBD3jCHaRpxzmGmw1r0cs9hmucd+eYwT0/q7TnM08j948NNG745zNOG3p7DTId1zqBvDvO0Ee7PYX5QN8YcptlIfHOYZ3buHxIYrE9R9xymacQ7h1nahjlM0xPvHGaRLXOYthn3HOYbM945TLNkvHOYphHvHKa1988521bK/TlM04ZvDjMd9fZp2acNuT+HaXviLdW2YQ7Tbq7uOUzbjHsO840Z7xymOczxzWHaIyXPHKZ1U4v367G1HV+P5sGB3q9HKzYv1bkDOHGpPsfm2QF+YUYa5xTKl0by3AaVfx7s9mzEOlW9n4g/5vyCYSTdHpGbJpw7O+OGEblpxD0ilx1RBeaUSZW110eO11UTzRHbPNb5HLHRcDq2T4zoPMf8iOFLIzJ3QP3ckfJkJB0adyiBbjgwM9hHK7YV0VZbeV3J1uR/0zXnzjsXPina3OZG09OIWEW7RWR1h8haTT8qRzpFo+lbRmQW7TmB9rr/pLBjS1cKO7Z0hWaGTa2LEc50fnnvZtsSomAGuZd5P2sulJ/n02/PUrGiOVsq6wPs9edkOO7fVJTMW6ydcw6mDeecQwj3byo6jdy+qSiZU5fuOQd/3TSrbsxWMttabMYXj2kkhbZOftT2tZHjvpE21yRTq0ajt5a7fsyhlC8LNlG0PM+Tf2hktrbEga2/jMT7Vxe+M+K7utDOTj70HyfKf3mS/9yT1QPPJdINRr7tgCnqOilQjGZvXq5V6xyItmjKkmxoKO7O83X1tHUolalKyby9aR2uG/g78PeLx3Rlbp1JYrUUc7nLNyUUUtkwJWR64pwSejNSamvUpvJy0cw8UuP8JYUmqMavrDiXzdr9+PLznR02jJOsrV7ecZJlwztOMg/79o6TrNubvOOkXHeMk9x1Y6zNtPvx5TgC++7aTNsRX952xJe3HfHlbUd8edsTX972BIa3HYHhbUdgeNug9RsCw9v9wPBkhvt636DWQcb+N2gN90t1R2B42xMY3vYEhrc9geFvpv1mwz/TWl6OCswdRaeVSFb0KyvOsYX16vHOHZqv9B99MLwO6g7ZOitW50HPchh7YZOpKKXO6a1SOeT3yRFrwoE3wtJW9LMVfmCkzQDmc5rreGnkzE37ayvnt9ex2pp8a6W1FXqs0bBi3bzV5vJZ44Wej2xoXmF18qWNc7p29j8+yPcfrFinGTrDju2C1WOdIRiN9mYdk34OuubhRcqH5x7Bb+QRXb6+0mt6fQ2gaabVeXhRa/wuPJ7fpyJ3l57fODJbyumIGI7YBwCmdTDiORhNL0vltGMfOTnHgMpW5HkPuHWR39rS0ITabX5eGjHvSinzYuLzU7C+Ekn7upW56Fv4Lu2PTLik2mojbqk2jbhFVv/cil+qTSteqY7W0pdTqk0bTqk2bbilOlpnGbql2ixYp1RHa1XEPdAxrfh6TzRXm5y9xzbibff/C6y4e49txd17rGMNvb3HsuHtPZYNf+8J9X7vsQvW23usZR7vCzBaB/n5XoC2CdcL8I0JVxe2jt9zd+G44ysjmvEWW6z4u7Bpxd2FrXLxdmHztnJnF7ZvtPd24XRs6MJmwXq7cIo7XoDpfu+xFqzcvcc04m73qf61FX/vMa24e491yqG391g2vL3HsuHvPdYUl7v3mAXr7T1BXd/FfOZyLc+5sSIG0zphlG8gOien/Y6c06SzsWW+Av23K9bLZ64W8Sny9VfdWB+SYUYIlUC5eZxt/4kjM8qB7xt4qhlrativa9Z2L6euWVOpbl0zjbgVqeS/tuLXtbJlVFA2jArKhlFB2TIqqDtGBSX/sa6FI1F+qiEn1pTfKQBTCyJvaHhWtrpjKSLWcrsj1w1LEbYRdxes8tdW/B25bpnfahvmt9qG+a22ZX6rbZjfsgvW25GtFymOIsCb9OB7FH51ZPMar2POlufAB0I/d2TTlVAo7FctV6yRrOcalGjF1fgFRe6PDKxLI92CYhpxS4Hkv7biFxTZMjKQDSMD2TAykC0jA90xMpD814KS5npiyof1oaHmWu063kxTei0o5jvD3ZH1/sig5Q0duW3pgltWvuKWla+4ZeUrbVj5ShtWvtKWla+0Y+Urbln5sk+QnNvgQmqrpWh7zo41MJjB0JkqOMjxgY11tQKH235oY4aBFb7P7yMb62KFn3dffWujfGtjlkf9ujzqLI/6dXmsWx/b1+XBNr4tDx7xfVseK0ywfV0eMvMiX5cH2/i2PGSe2yXtaz/mqWwi3/qhc8ZRvy4PtvG1H+vgPkODzIkXb4S7baQv/V6jACPCPSVzfanqemkW04q10WXecJF/HCmaPsiOMzDdNOKN+rc9cUb9m9+NzlVm04Rvldk24Rpsyo75ZNkxn5xS+2sr7sGmbcU92Mz3I2JNG97BZt4REZvyhohYu2C9g03ZEWaVrDhuZ+/RHWFWuiNAKplnGm6x4u89phV377Hmory9p8T7vafEHb3HOt3N3XvMgnV/qlnnuMR1TEGkTS6/1lSTaaUfDzEWVXkq+NmI2VD4zHPeWvVkxHqh11rnF075zkSb50v9+Dj5zMRsrfGlF9G6SqX0A7KhRwd/VzyXaLVmBMq6UJPP27phRF8ZedPK5jDrHHAfRiur9vUWc0dW5j1Mv7JjbTc45t7mGvi25F9GrKZ6NnLaoHnIFjMhvC5c+76OVSwkSfrc3HyTHBpeDurPl3m6+2GQjg2vUNuI++XX6l9b8b9C245ArdTuB2qZNryv0LYjUCvJhkAtu2Ddr1DrbACZMw2nx0sgnyOVz/yYV8zM3kO3qfyaMRXLkXn0SuZz0Npz38k7BtNye8ePOfPiV4ItH5HWfq49VvxKYFpxK4E1uPAqgWXDqwSadyiB9e5yK4F9VZtzc6a1yTrKnGBLvA3+1wGN2Xp/BZmHcwShiyCeL4BtOwIRsnWcoXfn3oZABNuItwfmo/y1FXc/tq14+3E2jzP09WPThrMfmzbc/Thb5xl6+7FdsN5+rFt6T7h9REE8doTxHFt6T2h/bcXfe8KOCdlzHHS/98T7E7KmDX/viRsmZO2C3fEWTInOEeSIvl9HjZhn26wjT0JJxqs0tr+2UmXuXah6vDwIxraxzvStWsOXNtryQw0bVoM91g1gXzf6uQ1DW7nfcQwbtq6lOVF3ymT40kic0WKnPUtKzA0/7i5sWgnz6PRzZki+tjKrJwT52heaVEr6tS8lrvMZc/vaSl3H5tFJc5/maGnb4zzu11by/e3epg3vSyPv2O6d84bt3m8KNs/vlVTat4XiFCbThlOYnJVj2jDH1M68mDaceXGO7Q0b9qeXU2TffAR6RbZsEdmyRWTLFpEtW0S2bBHZskVkyxaRrRtEtm4Q2bpFZOsOkS1bRLZuENm6QWTrfZG1JyB9ebFt+PLinQi1bJjz1E6RfTNj7hXZtkVk2xaRbVtEtm0R2bZFZNsWkW1bRFY2iKxsEFnZIrKyQ2TbFpGVDSIrG0RWNoisud7rFFnThlNknevOpsgeO0T22CGyukVkdYvI6haR1S0iq1tEVreIrO4Q2XLcF1nThlNkTRvuFleOHSKrO0TWLhSfMNk2fMLkrRxT3My4VKfImjacIuuMj7XmZHWDyL4JpHaKbAk7RNa24hXZN1acImtb8YqsbcUrsm+sOEX2TY68Ihs3iGzcILJxi8jGDSL7pmC9Ihs3iGzcILJxg8jm+wtftg2nyOb7C1/mDiuvyNp7vbwiu2Xhq2xZ+CpbFr7KloWvsmXhq2xZ+CpbFr7KhoWvsmHhq2xZ+Co7Fr7KloWvsmHhq2xY+Cr3F77ebEGdx02WSvfUfLSLdd38yPdBfLK72Hmn0Rsjvmuv3hwO4nzpmDacLx3nISVm3eYNLx37NBvvS6fuCJiyrbhfOrYV70vHtOJ+6ZhW3C8d24r3pWPnyPvSqfdP2jJteF86dcdJW6VtOGnrTcF6XzpmoThfOqYN50vHWTmWDfsoNV9ebBu+vHiPdLNEtuwIaSs7oi3KlouzbCtukZUtIitbRFa2iKxsEVnZIrIbjjMsG44zLFuOMyw7jjN8U7Bekd0gTGWDMBXZILLt/kjWtuEU2XZ/JGuek+wVWfvEZqfI1mOHyNpWvCL7xopTZG0rXpG1rXhF9o0Vp8i+yZFTZOtxX2RNG06RNW34W1zYILJvCtYpsnah+ITJtuETJm/lmOJWNoxky4aRbLk/ks075qjzjjnqumV/lW3FLbJxi8jGLSIbt4hs3CKycYvIbrjIq264yKtuucir7rjI603BekU2bhDZuEFk4waRTfdD2mwbTpFNt0Pa7CvJvCJrX47mFdktpwraVtwim7eIbN4isnmLyOYtIpu3iGzeILJ5g8jmLSJbdohs3iKyeYPI5g0imzeI7IYXRtzwwoj3Xxj2ralekY07NmfULQtfdcvCV92y8FW3LHzVLQtfdcvCV92y8FU3LHzVDQtfdcvCV92x8FW3LHzVDQtfdcPCV60bhCndjrawTbiiLaxIwxR0XtqTfhyEGZ9biHWS0Wzuq2Lz03Fx9hXqzhdOuB9F473K3arXsCOGOuyIoa6y44A224r7hWNb8b5wTCvuF45pxf3Csa14Xzh2jrwvHL1/FZJpw/vC0R1XIVXdcBXSm4L1vnD0/sKZbcP5wtHbC2cpbghnixvC2eL9cLZgHVHqP9dCNohsO3aIrG3FK7JvrDhF1rbiFVnbildk31hxiuybHDlFtoX7ImvacIqsacPf4sIGkX1TsE6RtQvFJ0y2DZ8weSvHEqYqd0f1b0x4RvUpyP3tMrYNX4naNnwlmjfEe9hG3FIfd2yXsa24pT7u2C5jW3FLfdyxXeaNFa/Uxx3bZVq6v13GtOGV+rRju0xLG7bLvClYr9Sn+x/6tg2n1KfbH/rB2jtey7yNs65tKqdGfWAiz1NFSeifTWi864RpweVDKNbB6WWesBp/9NxUPjDSv39gpGr60si6PTryWa8fGTlfEPME3CO+zk5UKz4qHXNW7JxYS19a8R1e+8aG6/DadzY8h9faddPmwfiPWzW/rOAfRvK3RuIykl5XTWrmxSEpralTeo/XT2zkObhJOYbXNuRvbeS4TlqO5cvqnRcIxcZng39WMzJFoOm3SsKefG1E5ij8TH5tZI4jbCNJbr9nTBMujY9ihm7HaeR8db9UkTc25h03Gmlv508b1tSg832X75aFNbNYWhpaWBqVREjJb0PytCHl+M6GhjHsLj8uSf7Ij7b80PqljVmrp7kv/dCp60Xz1+Uhy8brejFvQSsyr8srfGn01zbadzZqHPMIuVJP+cjGumM9N6ONNft61lGmchzGXRpNzNzMm7hz5WsqJX7iie9Wj2bd0+W71UM2XHInO+64a+b89RYr7js9bCveOz3ahmWstmEZq21Zxmo7lrHsgvXe6RG29GLzpi5nL37nirMb6+3b0kPc0I9tI94uKFuu+DGtuDuybcXbkcW6x8nZkU0bzo5s2nB35P+/tnPbbRuGwfC79LoXOpCS/CxDUKRZNgQImiJrL3bRd5+8ZrSQwb9pmb0xYhv5oAP9iyZpu6AX8WsvZDywygsZrejsgng4juY9rVhQmoNDEb8xtD5fuYegsFGWkU25ufu9g+DeFPEbvQuoN2TRG/7a3vgs7fC5z3PkKB9a5kipjxGmdtQ74e2M4jr74mR2ox862yEfr+bousd0mMaUOxk0MVIElgoFTRf7xgxd7FsrrCj2HQyK3BZWYGVSrgSL7xFjijYpt0BRJuUwRZuUwxRtUm6BokzKLfRImZQrKI2ldSoQQ+tUmLw1saAHyNROBR5YZVIOD4pSmCBDKUzKyYGJPYOCvWxQsJe3F+wVA40tJhJLJhJLJhJLJhJLJhJLJhJLJhJLJhLLBhLLBhJr8rGwmlUxkFgykVg2kFg2kFjeLLEw3RhTkrRnc58TB9fJSJ2M5smV5hJexaAp009NIngdI6aJkTsZfhBGE6lfx0heGAm0A9l6kXnxBc0tZAwiioPznQyJV1ZG2M7w3e3IEyP1MYZpkRgob28HAVsPBnMbDOY2GMxtMJjbYDC3wWBuw/a5JfhiXhJXMXCbF6e7taFsL2jBDF0xSinlaxm6ghY4plGWyhCzA2OKbgNYounJu7mwImwGTRUx1Hqq/zcjGgRJYeWELkgKe/P3QxGfveHAs73BDJYR4TQ/IrXL6OVUTE4o7DopyvI8zNCV5y0wNOV5tLmQlDYXksbNxT1xc3EPw4yREy2tv9uF8i7NuUARr3CkxFlKyBk+XOZ54vjWVV7FUdopZujsdIGhsVP4SpAoSjaMS6SMB/sVDLnjrgw/y8BBQK2dLFDUdpKM7CQZ2EkysJPUZye7urM/nK5P58th/3a6vPyq//sYUdfT/vl8vO3+eH85NGfffr/+O/N8PZ3Pp59Pr9fL4fj9/XocSeO5B3fbfAt1jXSPdZuH3eNDrEeq8HGov/3tdM3TjdsyHvKfh6pbNG7L7mNs5B8=" + }, + { + "name": "public_dispatch", + "is_unconstrained": true, + "custom_attributes": [ + "abi_public" + ], + "abi": { + "parameters": [ + { + "name": "selector", + "type": { + "kind": "field" + }, + "visibility": "private" + } + ], + "return_type": null, + "error_types": { + "361444214588792908": { + "error_kind": "string", + "string": "attempt to multiply with overflow" + }, + "459713770342432051": { + "error_kind": "string", + "string": "Not initialized" + }, + "1998584279744703196": { + "error_kind": "string", + "string": "attempt to subtract with overflow" + }, + "2360858009427093503": { + "error_kind": "string", + "string": "InvalidTimelock" + }, + "2369193878689457446": { + "error_kind": "string", + "string": "HTLCNotExists" + }, + "2718955667607728260": { + "error_kind": "string", + "string": "Function get_htlc can only be called statically" + }, + "3380315280177356474": { + "error_kind": "string", + "string": "FundsNotSent" + }, + "3781809441605198943": { + "error_kind": "string", + "string": "Function get_user_swaps_count can only be called statically" + }, + "4493654309393309420": { + "error_kind": "string", + "string": "AlreadyClaimed" + }, + "4736483829072576196": { + "error_kind": "string", + "string": "HTLCAlreadyExists" + }, + "5029608433027800177": { + "error_kind": "string", + "string": "NotPassedTimelock" + }, + "7413154743021792023": { + "error_kind": "string", + "string": "InvalidRewardAmount" + }, + "9967937311635654895": { + "error_kind": "string", + "string": "Initialization hash does not match" + }, + "12697770001660251253": { + "error_kind": "fmtstring", + "length": 24, + "item_types": [] + }, + "13455385521185560676": { + "error_kind": "string", + "string": "Storage slot 0 not allowed. Storage slots must start from 1." + }, + "14415304921900233953": { + "error_kind": "string", + "string": "Initializer address is not the contract deployer" + }, + "14924807131364042204": { + "error_kind": "string", + "string": "HashlockNotMatch" + }, + "14990209321349310352": { + "error_kind": "string", + "string": "attempt to add with overflow" + }, + "15764276373176857197": { + "error_kind": "string", + "string": "Stack too deep" + }, + "16190783185788596410": { + "error_kind": "string", + "string": "Function has_htlc can only be called statically" + }, + "16431471497789672479": { + "error_kind": "string", + "string": "Index out of bounds" + }, + "16810041750452690220": { + "error_kind": "fmtstring", + "length": 27, + "item_types": [ + { + "kind": "field" + } + ] + }, + "16884080922827299127": { + "error_kind": "string", + "string": "InvalidRewardTimelock" + }, + "17552554873437466887": { + "error_kind": "string", + "string": "SwapAlreadyInitialized" + } + } + }, + "bytecode": "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LQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHQAiHQIdLQxYHS0OGxQtDFIWLQsSEwAiEwITLQ4TEi0IARMnAhsEIQAIARsBJwMTBAEAIhMCGycCHAQg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AiYtCiYnLQ4ZJwAiJwInLQ4aJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxYJwAiJwInLQxY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Kg4SGS0LGRAcChAZBRwKGRIAACoOExktCxkQHAoQGQIcChkTAAAqDhQZLQsZEBwKEBkGHAoZFAAAIg5eGS0LGRAcChAZBRwKGQ4AJwIZBAwnAhsEAwAqGRsaLQgBEAAIARoBJwMQBAEAIhACGi0OGRoAIhoCGi0OGRonAhoEAwAqEBoZLQoZGi0OERoAIhoCGi0OAhoAIhoCGi0OFhoAIhoCGi0OFxoAIhoCGi0OGBoAIhoCGi0OBBoAIhoCGi0OFRoAIhoCGi0OCRoAIhoCGi0OEhoAIhoCGi0OExoAIhoCGi0OFBoAIhoCGi0ODhoAIhACCS0LCQktCgkEJwIOBAMAKhAOAjsOAAQAAiMAAE5pKQIAAgCOfK5ICioBAgQkAgAEAABOhCMAAE+4LQgBAicCBAQCAAgBBAEnAwIEAQAiAgIEHzAAUgBSAAQAIgJSCS0LCQQeAgACAB4CAAkAHgIACgAeAgAMADMqAAoADAAOJAIADgAATtYlAABlah4CAAoJJAIACgAATuglAABwaS0IAQonAgwEAwAIAQwBJwMKBAEAIgoCDC0KDA4tDgsOACIOAg4tDgQOJwILBBAtCAAQLQoKES0IWxItCFQTAAgACwAlAABlji0CAAAtChEECiIEWAoKIgpUCyQCAAsAAE9PJQAAZzUvCgAEAAonAgsEAScCDgQDACoLDgwtCAEEAAgBDAEnAwQEAQAiBAIMLQ4LDAAiDAIMLQ4LDCcCDAQDACoEDAstCgsMLQ4KDAAiBAIMLQsMDC0KDAsnAg4EAwAqBA4KOw4ACwAKIwAAT7gnAgICbCcCBAJjJwIJAlUnAgoCaycCCwJ3JwIMAnsnAg4CfS0IARAnAhEEHAAIAREBJwMQBAEAIhACES0KERItDgkSACISAhItDgYSACISAhItDgoSACISAhItDgYSACISAhItDg8SACISAhItDgsSACISAhItDgYSACISAhItDg0SACISAhItDgcSACISAhItDggSACISAhItDgISACISAhItDggSACISAhItDgQSACISAhItDgMSACISAhItDg8SACISAhItDgUSACISAhItDg0SACISAhItDgwSACISAhItDgcSACISAhItDggSACISAhItDgISACISAhItDggSACISAhItDgQSACISAhItDgMSACISAhItDg8SACISAhItDgUS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", + "debug_symbols": "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" + }, + { + "name": "sync_private_state", + "is_unconstrained": true, + "custom_attributes": [ + "abi_utility" + ], + "abi": { + "parameters": [], + "return_type": null, + "error_types": { + "344423948968719440": { + "error_kind": "fmtstring", + "length": 98, + "item_types": [ + { + "kind": "integer", + "sign": "unsigned", + "width": 32 + }, + { + "kind": "integer", + "sign": "unsigned", + "width": 32 + }, + { + "kind": "field" + } + ] + }, + "361444214588792908": { + "error_kind": "string", + "string": "attempt to multiply with overflow" + }, + "992401946138144806": { + "error_kind": "string", + "string": "Attempted to read past end of BoundedVec" + }, + "1998584279744703196": { + "error_kind": "string", + "string": "attempt to subtract with overflow" + }, + "3080037330898348111": { + "error_kind": "fmtstring", + "length": 132, + "item_types": [ + { + "kind": "integer", + "sign": "unsigned", + "width": 32 + } + ] + }, + "4261968856572588300": { + "error_kind": "string", + "string": "Value does not fit in field" + }, + "4440399188109668273": { + "error_kind": "string", + "string": "Input length must be a multiple of 32" + }, + "7564993426627941149": { + "error_kind": "fmtstring", + "length": 48, + "item_types": [ + { + "kind": "field" + }, + { + "kind": "field" + } + ] + }, + "7995966536718645961": { + "error_kind": "fmtstring", + "length": 61, + "item_types": [ + { + "kind": "field" + }, + { + "kind": "field" + } + ] + }, + "8556029555939094797": { + "error_kind": "fmtstring", + "length": 75, + "item_types": [] + }, + "8992688621799713766": { + "error_kind": "string", + "string": "Invalid public keys hint for address" + }, + "9791669845391776238": { + "error_kind": "string", + "string": "0 has a square root; you cannot claim it is not square" + }, + "9885968605480832328": { + "error_kind": "string", + "string": "Attempted to read past the length of a CapsuleArray" + }, + "10522114655416116165": { + "error_kind": "string", + "string": "Can't read a transient note with a zero contract address" + }, + "10791800398362570014": { + "error_kind": "string", + "string": "extend_from_bounded_vec out of bounds" + }, + "11021520179822076911": { + "error_kind": "string", + "string": "Attempted to delete past the length of a CapsuleArray" + }, + "12469291177396340830": { + "error_kind": "string", + "string": "call to assert_max_bit_size" + }, + "12913276134398371456": { + "error_kind": "string", + "string": "push out of bounds" + }, + "13060541637244024094": { + "error_kind": "fmtstring", + "length": 98, + "item_types": [] + }, + "13450089406971132036": { + "error_kind": "fmtstring", + "length": 144, + "item_types": [ + { + "kind": "integer", + "sign": "unsigned", + "width": 32 + } + ] + }, + "14990209321349310352": { + "error_kind": "string", + "string": "attempt to add with overflow" + }, + "15764276373176857197": { + "error_kind": "string", + "string": "Stack too deep" + }, + "16431471497789672479": { + "error_kind": "string", + "string": "Index out of bounds" + }, + "16792019527863081935": { + "error_kind": "fmtstring", + "length": 77, + "item_types": [ + { + "kind": "integer", + "sign": "unsigned", + "width": 32 + } + ] + }, + "17154023812102399658": { + "error_kind": "fmtstring", + "length": 128, + "item_types": [ + { + "kind": "integer", + "sign": "unsigned", + "width": 32 + } + ] + }, + "17803644318014042523": { + "error_kind": "fmtstring", + "length": 58, + "item_types": [ + { + "kind": "field" + } + ] + } + } + }, + "bytecode": "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", + "debug_symbols": "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i26LbpklM1cns+ThIE7iIm7iIRrRiUGk26Hboduh26Hboduh26Hboduh26Gb0c3oZnQzuhndjG5GN6Ob0c3o5nRzujndnG5ON6eb083p5nRzugXdgm5Bt6Bb0C3oFnQLugXdgm6Xbpdul26Xbpdul26Xbpdul2633bIptHAQJ3ERN/EQjejEINJt0G3QbdBt0G3QbdBt0G3QbdBt0G3SbdJt0m3SbdJt0m3SbdJt0m3SbdFt0W3RbdFt0W3RbdFt0W3RjVkSzJJglgSzJJglwSwJZkkwS4JZEsySYJYEsySYJcEsCWZJMEuCWRLMkmCWBLMkmCXBLAlmSTBLglkSzJJglgSzJJglwSwJZkkwS4JZEsySYJYEsySYJcEsCWZJMEuCWRLMkmCWBLMkmCXBLAlmSTBLglkSzJJglgSzJJglwSwJZkkwS4JZEsySYJYEsySYJZdZcpkll1lymSWXWXKZJZdZcpkll1lymSWXWXKZJZdZcpkll1lymSWXWXKZJRdZEom3EVkCHMRJXMRNPEQjOpFuk26Lbotui26Lbotui26Lbotui26Lbptum26bbptum26bbptum26bbptuh26Hboduh26Hboduh26Hboduh25GN6Ob0c3oZnQzuhndjG5GN6Ob083p5nRzujndnG5ON6eb0y2z5PtrbzMbWQsH8XPLP96VvayFm3iIRnRiEG9jZsnDQaTbpdul26Xbpdul26XbLbeVza2FgziJi7iJh2hEJwaRboNug26DboNug26DboNug26DboNuk26TbpNuk26TbpNuk26TbpNuk26Lbotui26Lbotui26Lbotui26Lbptum26bbptum26bbptum26bbptuh26Hboduh26Hboduh26Hboduh25GN6Ob0c3oZnQzuhndjG5GN6Ob083p5nRzujndnG5ON6eb083pFnQLugXdgm5Bt6Bb0C3oFnQLul26Xbpdul26Xbpdul26XbpdujFLBrNkMEsGs2QwSwazZDBLBrNkMEsGs2QwSwazZDBLBrNkMEsGs2QwSwazZDBLBrNkMEsGs2QwSwazZDBLBrNkMEsGs2QwSwazZDBLBrNkMEsGs2QwSwazZDBLBrNkMEsGs2QwSwazZDBLBrNkMEsGs2QwSwazZDBLBrNkMEsGs2QwSwazZDBLBrNkMEsGs2QwSwazZDBLBrNkMEsG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" + } + ], + "outputs": { + "globals": { + "storage": [ + { + "fields": [ + { + "name": "contract_name", + "value": { + "kind": "string", + "value": "Token" + } + }, + { + "name": "fields", + "value": { + "fields": [ + { + "name": "admin", + "value": { + "fields": [ + { + "name": "slot", + "value": { + "kind": "integer", + "sign": false, + "value": "0000000000000000000000000000000000000000000000000000000000000001" + } + } + ], + "kind": "struct" + } + }, + { + "name": "minters", + "value": { + "fields": [ + { + "name": "slot", + "value": { + "kind": "integer", + "sign": false, + "value": "0000000000000000000000000000000000000000000000000000000000000002" + } + } + ], + "kind": "struct" + } + }, + { + "name": "balances", + "value": { + "fields": [ + { + "name": "slot", + "value": { + "kind": "integer", + "sign": false, + "value": "0000000000000000000000000000000000000000000000000000000000000003" + } + } + ], + "kind": "struct" + } + }, + { + "name": "total_supply", + "value": { + "fields": [ + { + "name": "slot", + "value": { + "kind": "integer", + "sign": false, + "value": "0000000000000000000000000000000000000000000000000000000000000004" + } + } + ], + "kind": "struct" + } + }, + { + "name": "public_balances", + "value": { + "fields": [ + { + "name": "slot", + "value": { + "kind": "integer", + "sign": false, + "value": "0000000000000000000000000000000000000000000000000000000000000005" + } + } + ], + "kind": "struct" + } + }, + { + "name": "symbol", + "value": { + "fields": [ + { + "name": "slot", + "value": { + "kind": "integer", + "sign": false, + "value": "0000000000000000000000000000000000000000000000000000000000000006" + } + } + ], + "kind": "struct" + } + }, + { + "name": "name", + "value": { + "fields": [ + { + "name": "slot", + "value": { + "kind": "integer", + "sign": false, + "value": "0000000000000000000000000000000000000000000000000000000000000008" + } + } + ], + "kind": "struct" + } + }, + { + "name": "decimals", + "value": { + "fields": [ + { + "name": "slot", + "value": { + "kind": "integer", + "sign": false, + "value": "000000000000000000000000000000000000000000000000000000000000000a" + } + } + ], + "kind": "struct" + } + } + ], + "kind": "struct" + } + } + ], + "kind": "struct" + }, + { + "fields": [ + { + "name": "contract_name", + "value": { + "kind": "string", + "value": "Train" + } + }, + { + "name": "fields", + "value": { + "fields": [ + { + "name": "contracts", + "value": { + "fields": [ + { + "name": "slot", + "value": { + "kind": "integer", + "sign": false, + "value": "0000000000000000000000000000000000000000000000000000000000000001" + } + } + ], + "kind": "struct" + } + }, + { + "name": "user_swaps_count", + "value": { + "fields": [ + { + "name": "slot", + "value": { + "kind": "integer", + "sign": false, + "value": "0000000000000000000000000000000000000000000000000000000000000002" + } + } + ], + "kind": "struct" + } + }, + { + "name": "user_swaps", + "value": { + "fields": [ + { + "name": "slot", + "value": { + "kind": "integer", + "sign": false, + "value": "0000000000000000000000000000000000000000000000000000000000000003" + } + } + ], + "kind": "struct" + } + } + ], + "kind": "struct" + } + } + ], + "kind": "struct" + } + ] + }, + "structs": { + "events": [ + { + "fields": [ + { + "name": "swap_id", + "type": { + "kind": "field" + } + }, + { + "name": "htlc_id", + "type": { + "kind": "field" + } + }, + { + "name": "hashlock", + "type": { + "kind": "array", + "length": 32, + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 8 + } + } + }, + { + "name": "dst_chain", + "type": { + "kind": "string", + "length": 30 + } + }, + { + "name": "dst_address", + "type": { + "kind": "string", + "length": 90 + } + }, + { + "name": "dst_asset", + "type": { + "kind": "string", + "length": 30 + } + }, + { + "name": "sender", + "type": { + "fields": [ + { + "name": "inner", + "type": { + "kind": "field" + } + } + ], + "kind": "struct", + "path": "aztec::protocol_types::address::aztec_address::AztecAddress" + } + }, + { + "name": "src_receiver", + "type": { + "fields": [ + { + "name": "inner", + "type": { + "kind": "field" + } + } + ], + "kind": "struct", + "path": "aztec::protocol_types::address::aztec_address::AztecAddress" + } + }, + { + "name": "src_asset", + "type": { + "kind": "string", + "length": 30 + } + }, + { + "name": "amount", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 128 + } + }, + { + "name": "reward", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 128 + } + }, + { + "name": "reward_timelock", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 64 + } + }, + { + "name": "timelock", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 64 + } + } + ], + "kind": "struct", + "path": "Train::DstLocked" + }, + { + "fields": [ + { + "name": "swap_id", + "type": { + "kind": "field" + } + }, + { + "name": "hashlock", + "type": { + "kind": "array", + "length": 32, + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 8 + } + } + }, + { + "name": "dst_chain", + "type": { + "kind": "string", + "length": 30 + } + }, + { + "name": "dst_address", + "type": { + "kind": "string", + "length": 90 + } + }, + { + "name": "dst_asset", + "type": { + "kind": "string", + "length": 30 + } + }, + { + "name": "sender", + "type": { + "fields": [ + { + "name": "inner", + "type": { + "kind": "field" + } + } + ], + "kind": "struct", + "path": "aztec::protocol_types::address::aztec_address::AztecAddress" + } + }, + { + "name": "src_receiver", + "type": { + "fields": [ + { + "name": "inner", + "type": { + "kind": "field" + } + } + ], + "kind": "struct", + "path": "aztec::protocol_types::address::aztec_address::AztecAddress" + } + }, + { + "name": "src_asset", + "type": { + "kind": "string", + "length": 30 + } + }, + { + "name": "amount", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 128 + } + }, + { + "name": "timelock", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 64 + } + } + ], + "kind": "struct", + "path": "Train::SrcLocked" + }, + { + "fields": [ + { + "name": "swap_id", + "type": { + "kind": "field" + } + }, + { + "name": "htlc_id", + "type": { + "kind": "field" + } + }, + { + "name": "redeem_address", + "type": { + "fields": [ + { + "name": "inner", + "type": { + "kind": "field" + } + } + ], + "kind": "struct", + "path": "aztec::protocol_types::address::aztec_address::AztecAddress" + } + }, + { + "name": "secret_high", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 128 + } + }, + { + "name": "secret_low", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 128 + } + }, + { + "name": "hashlock", + "type": { + "kind": "array", + "length": 32, + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 8 + } + } + } + ], + "kind": "struct", + "path": "Train::TokenRedeemed" + }, + { + "fields": [ + { + "name": "swap_id", + "type": { + "kind": "field" + } + }, + { + "name": "htlc_id", + "type": { + "kind": "field" + } + } + ], + "kind": "struct", + "path": "Train::TokenRefunded" + } + ], + "functions": [ + { + "fields": [ + { + "name": "parameters", + "type": { + "fields": [], + "kind": "struct", + "path": "Train::constructor_parameters" + } + } + ], + "kind": "struct", + "path": "Train::constructor_abi" + }, + { + "fields": [ + { + "name": "parameters", + "type": { + "fields": [ + { + "name": "_swap_id", + "type": { + "kind": "field" + } + }, + { + "name": "_htlc_id", + "type": { + "kind": "field" + } + } + ], + "kind": "struct", + "path": "Train::get_htlc_parameters" + } + }, + { + "name": "return_type", + "type": { + "fields": [ + { + "name": "amount", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 128 + } + }, + { + "name": "token", + "type": { + "fields": [ + { + "name": "inner", + "type": { + "kind": "field" + } + } + ], + "kind": "struct", + "path": "aztec::protocol_types::address::aztec_address::AztecAddress" + } + }, + { + "name": "hashlock_high", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 128 + } + }, + { + "name": "hashlock_low", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 128 + } + }, + { + "name": "secret_high", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 128 + } + }, + { + "name": "secret_low", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 128 + } + }, + { + "name": "sender", + "type": { + "fields": [ + { + "name": "inner", + "type": { + "kind": "field" + } + } + ], + "kind": "struct", + "path": "aztec::protocol_types::address::aztec_address::AztecAddress" + } + }, + { + "name": "src_receiver", + "type": { + "fields": [ + { + "name": "inner", + "type": { + "kind": "field" + } + } + ], + "kind": "struct", + "path": "aztec::protocol_types::address::aztec_address::AztecAddress" + } + }, + { + "name": "timelock", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 64 + } + }, + { + "name": "claimed", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 8 + } + }, + { + "name": "reward", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 128 + } + }, + { + "name": "reward_timelock", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 64 + } + } + ], + "kind": "struct", + "path": "Train::HTLC_Public" + } + } + ], + "kind": "struct", + "path": "Train::get_htlc_abi" + }, + { + "fields": [ + { + "name": "parameters", + "type": { + "fields": [ + { + "name": "_user", + "type": { + "fields": [ + { + "name": "inner", + "type": { + "kind": "field" + } + } + ], + "kind": "struct", + "path": "aztec::protocol_types::address::aztec_address::AztecAddress" + } + } + ], + "kind": "struct", + "path": "Train::get_user_swaps_count_parameters" + } + }, + { + "name": "return_type", + "type": { + "kind": "field" + } + } + ], + "kind": "struct", + "path": "Train::get_user_swaps_count_abi" + }, + { + "fields": [ + { + "name": "parameters", + "type": { + "fields": [ + { + "name": "_swap_id", + "type": { + "kind": "field" + } + }, + { + "name": "_htlc_id", + "type": { + "kind": "field" + } + } + ], + "kind": "struct", + "path": "Train::has_htlc_parameters" + } + }, + { + "name": "return_type", + "type": { + "kind": "boolean" + } + } + ], + "kind": "struct", + "path": "Train::has_htlc_abi" + }, + { + "fields": [ + { + "name": "parameters", + "type": { + "fields": [ + { + "name": "_swap_id", + "type": { + "kind": "field" + } + }, + { + "name": "_htlc_id", + "type": { + "kind": "field" + } + }, + { + "name": "_hashlock_high", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 128 + } + }, + { + "name": "_hashlock_low", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 128 + } + }, + { + "name": "_reward", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 128 + } + }, + { + "name": "_reward_timelock", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 64 + } + }, + { + "name": "_timelock", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 64 + } + }, + { + "name": "_src_receiver", + "type": { + "fields": [ + { + "name": "inner", + "type": { + "kind": "field" + } + } + ], + "kind": "struct", + "path": "aztec::protocol_types::address::aztec_address::AztecAddress" + } + }, + { + "name": "_token", + "type": { + "fields": [ + { + "name": "inner", + "type": { + "kind": "field" + } + } + ], + "kind": "struct", + "path": "aztec::protocol_types::address::aztec_address::AztecAddress" + } + }, + { + "name": "_total_amount", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 128 + } + }, + { + "name": "_src_asset", + "type": { + "kind": "string", + "length": 30 + } + }, + { + "name": "_dst_chain", + "type": { + "kind": "string", + "length": 30 + } + }, + { + "name": "_dst_asset", + "type": { + "kind": "string", + "length": 30 + } + }, + { + "name": "_dst_address", + "type": { + "kind": "string", + "length": 90 + } + } + ], + "kind": "struct", + "path": "Train::lock_dst_parameters" + } + } + ], + "kind": "struct", + "path": "Train::lock_dst_abi" + }, + { + "fields": [ + { + "name": "parameters", + "type": { + "fields": [ + { + "name": "_swap_id", + "type": { + "kind": "field" + } + }, + { + "name": "_hashlock_high", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 128 + } + }, + { + "name": "_hashlock_low", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 128 + } + }, + { + "name": "_timelock", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 64 + } + }, + { + "name": "_src_receiver", + "type": { + "fields": [ + { + "name": "inner", + "type": { + "kind": "field" + } + } + ], + "kind": "struct", + "path": "aztec::protocol_types::address::aztec_address::AztecAddress" + } + }, + { + "name": "_token", + "type": { + "fields": [ + { + "name": "inner", + "type": { + "kind": "field" + } + } + ], + "kind": "struct", + "path": "aztec::protocol_types::address::aztec_address::AztecAddress" + } + }, + { + "name": "_amount", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 128 + } + }, + { + "name": "_src_asset", + "type": { + "kind": "string", + "length": 30 + } + }, + { + "name": "_dst_chain", + "type": { + "kind": "string", + "length": 30 + } + }, + { + "name": "_dst_asset", + "type": { + "kind": "string", + "length": 30 + } + }, + { + "name": "_dst_address", + "type": { + "kind": "string", + "length": 90 + } + } + ], + "kind": "struct", + "path": "Train::lock_src_parameters" + } + } + ], + "kind": "struct", + "path": "Train::lock_src_abi" + }, + { + "fields": [ + { + "name": "parameters", + "type": { + "fields": [ + { + "name": "message_ciphertext", + "type": { + "fields": [ + { + "name": "storage", + "type": { + "kind": "array", + "length": 17, + "type": { + "kind": "field" + } + } + }, + { + "name": "len", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 32 + } + } + ], + "kind": "struct", + "path": "std::collections::bounded_vec::BoundedVec" + } + }, + { + "name": "message_context", + "type": { + "fields": [ + { + "name": "tx_hash", + "type": { + "kind": "field" + } + }, + { + "name": "unique_note_hashes_in_tx", + "type": { + "fields": [ + { + "name": "storage", + "type": { + "kind": "array", + "length": 64, + "type": { + "kind": "field" + } + } + }, + { + "name": "len", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 32 + } + } + ], + "kind": "struct", + "path": "std::collections::bounded_vec::BoundedVec" + } + }, + { + "name": "first_nullifier_in_tx", + "type": { + "kind": "field" + } + }, + { + "name": "recipient", + "type": { + "fields": [ + { + "name": "inner", + "type": { + "kind": "field" + } + } + ], + "kind": "struct", + "path": "aztec::protocol_types::address::aztec_address::AztecAddress" + } + } + ], + "kind": "struct", + "path": "aztec::messages::processing::message_context::MessageContext" + } + } + ], + "kind": "struct", + "path": "Train::process_message_parameters" + } + } + ], + "kind": "struct", + "path": "Train::process_message_abi" + }, + { + "fields": [ + { + "name": "parameters", + "type": { + "fields": [ + { + "name": "_swap_id", + "type": { + "kind": "field" + } + }, + { + "name": "_htlc_id", + "type": { + "kind": "field" + } + }, + { + "name": "_secret_high", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 128 + } + }, + { + "name": "_secret_low", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 128 + } + } + ], + "kind": "struct", + "path": "Train::redeem_parameters" + } + } + ], + "kind": "struct", + "path": "Train::redeem_abi" + }, + { + "fields": [ + { + "name": "parameters", + "type": { + "fields": [ + { + "name": "_swap_id", + "type": { + "kind": "field" + } + }, + { + "name": "_htlc_id", + "type": { + "kind": "field" + } + } + ], + "kind": "struct", + "path": "Train::refund_parameters" + } + } + ], + "kind": "struct", + "path": "Train::refund_abi" + }, + { + "fields": [ + { + "name": "parameters", + "type": { + "fields": [], + "kind": "struct", + "path": "Train::sync_private_state_parameters" + } + } + ], + "kind": "struct", + "path": "Train::sync_private_state_abi" + } + ] + } + }, + "file_map": { + "101": { + "path": "/home/ubuntu/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.20251212/noir-projects/aztec-nr/aztec/src/macros/aztec.nr", + "source": "use crate::macros::{\n calls_generation::{\n external_functions::{\n generate_external_function_calls, generate_external_function_self_calls_structs,\n },\n internal_functions::generate_call_internal_struct,\n },\n dispatch::generate_public_dispatch,\n internals_functions_generation::{create_fn_abi_exports, process_functions},\n notes::NOTES,\n storage::STORAGE_LAYOUT_NAME,\n utils::{\n get_trait_impl_method, is_fn_contract_library_method, is_fn_external, is_fn_internal,\n is_fn_test, module_has_storage,\n },\n};\n\n/// Marks a contract as an Aztec contract, generating the interfaces for its functions and notes, as well as injecting\n/// the `sync_private_state` utility function.\n/// Note: This is a module annotation, so the returned quote gets injected inside the module (contract) itself.\npub comptime fn aztec(m: Module) -> Quoted {\n // Functions that don't have #[external(...)], #[contract_library_method], or #[test] are not allowed in contracts.\n check_each_fn_macroified(m);\n\n // We generate new functions prefixed with `__aztec_nr_internals__` and we replace the original functions' bodies\n // with `static_assert(false, ...)` to prevent them from being called directly from within the contract.\n let functions = process_functions(m);\n\n // We generate structs and their implementations necessary for convenient functions calls.\n let interface = generate_contract_interface(m);\n let self_call_structs = generate_external_function_self_calls_structs(m);\n let call_internal_struct = generate_call_internal_struct(m);\n\n // We generate ABI exports for all the external functions in the contract.\n let fn_abi_exports = create_fn_abi_exports(m);\n\n // We generate `_compute_note_hash_and_nullifier`, `sync_private_state` and `process_message`\n // functions only if they are not already implemented. If they are implemented we just insert empty\n // quotes.\n let contract_library_method_compute_note_hash_and_nullifier = if !m.functions().any(|f| {\n f.name() == quote { _compute_note_hash_and_nullifier }\n }) {\n generate_contract_library_method_compute_note_hash_and_nullifier()\n } else {\n quote {}\n };\n let sync_private_state_fn_and_abi_export = if !m.functions().any(|f| {\n f.name() == quote { sync_private_state }\n }) {\n generate_sync_private_state()\n } else {\n quote {}\n };\n\n let process_message_fn_and_abi_export = if !m.functions().any(|f| {\n f.name() == quote { process_message }\n }) {\n generate_process_message()\n } else {\n quote {}\n };\n let public_dispatch = generate_public_dispatch(m);\n\n quote {\n $interface\n $self_call_structs\n $call_internal_struct\n $functions\n $fn_abi_exports\n $contract_library_method_compute_note_hash_and_nullifier\n $public_dispatch\n $sync_private_state_fn_and_abi_export\n $process_message_fn_and_abi_export\n }\n}\n\ncomptime fn generate_contract_interface(m: Module) -> Quoted {\n let calls = generate_external_function_calls(m);\n\n let module_name = m.name();\n\n let has_storage_layout = module_has_storage(m) & STORAGE_LAYOUT_NAME.get(m).is_some();\n let storage_layout_getter = if has_storage_layout {\n let storage_layout_name = STORAGE_LAYOUT_NAME.get(m).unwrap();\n quote {\n pub fn storage_layout() -> StorageLayoutFields {\n $storage_layout_name.fields\n }\n }\n } else {\n quote {}\n };\n\n let library_storage_layout_getter = if has_storage_layout {\n quote {\n #[contract_library_method]\n $storage_layout_getter\n }\n } else {\n quote {}\n };\n\n quote {\n pub struct $module_name {\n pub target_contract: dep::aztec::protocol_types::address::AztecAddress\n }\n\n impl $module_name {\n $calls\n\n pub fn at(\n addr: aztec::protocol_types::address::AztecAddress\n ) -> Self {\n Self { target_contract: addr }\n }\n\n pub fn interface() -> Self {\n Self { target_contract: aztec::protocol_types::address::AztecAddress::zero() }\n }\n\n $storage_layout_getter\n }\n\n #[contract_library_method]\n pub fn at(\n addr: aztec::protocol_types::address::AztecAddress\n ) -> $module_name {\n $module_name { target_contract: addr }\n }\n\n #[contract_library_method]\n pub fn interface() -> $module_name {\n $module_name { target_contract: aztec::protocol_types::address::AztecAddress::zero() }\n }\n\n $library_storage_layout_getter\n\n }\n}\n\n/// Generates a contract library method called `_compute_note_hash_and_nullifier` which is used for note\n/// discovery (to create the `aztec::messages::discovery::ComputeNoteHashAndNullifier` function) and to implement the\n/// `compute_note_hash_and_nullifier` unconstrained contract function.\ncomptime fn generate_contract_library_method_compute_note_hash_and_nullifier() -> Quoted {\n if NOTES.len() > 0 {\n // Contracts that do define notes produce an if-else chain where `note_type_id` is matched against the\n // `get_note_type_id()` function of each note type that we know of, in order to identify the note type. Once we\n // know it we call we correct `unpack` method from the `Packable` trait to obtain the underlying note type, and\n // compute the note hash (non-siloed) and inner nullifier (also non-siloed).\n\n let mut if_note_type_id_match_statements_list = &[];\n for i in 0..NOTES.len() {\n let typ = NOTES.get(i);\n\n let get_note_type_id = get_trait_impl_method(\n typ,\n quote { crate::note::note_interface::NoteType },\n quote { get_id },\n );\n let unpack = get_trait_impl_method(\n typ,\n quote { crate::protocol_types::traits::Packable },\n quote { unpack },\n );\n\n let compute_note_hash = get_trait_impl_method(\n typ,\n quote { crate::note::note_interface::NoteHash },\n quote { compute_note_hash },\n );\n\n let compute_nullifier_unconstrained = get_trait_impl_method(\n typ,\n quote { crate::note::note_interface::NoteHash },\n quote { compute_nullifier_unconstrained },\n );\n\n let if_or_else_if = if i == 0 {\n quote { if }\n } else {\n quote { else if }\n };\n\n if_note_type_id_match_statements_list = if_note_type_id_match_statements_list.push_back(\n quote {\n $if_or_else_if note_type_id == $get_note_type_id() {\n // As an extra safety check we make sure that the packed_note BoundedVec has the expected\n // length, since we're about to interpret its raw storage as a fixed-size array by calling the\n // unpack function on it.\n let expected_len = <$typ as $crate::protocol_types::traits::Packable>::N;\n let actual_len = packed_note.len();\n assert(\n actual_len == expected_len,\n f\"Expected packed note of length {expected_len} but got {actual_len} for note type id {note_type_id}\"\n );\n\n let note = $unpack(aztec::utils::array::subarray(packed_note.storage(), 0));\n\n let note_hash = $compute_note_hash(note, owner, storage_slot, randomness);\n \n // The message discovery process finds settled notes, that is, notes that were created in prior\n // transactions and are therefore already part of the note hash tree. We therefore compute the\n // nullification note hash by treating the note as a settled note with the provided note nonce.\n let note_hash_for_nullification = aztec::note::utils::compute_note_hash_for_nullification(\n aztec::note::retrieved_note::RetrievedNote{ \n note,\n contract_address,\n owner,\n randomness,\n storage_slot,\n metadata: aztec::note::note_metadata::SettledNoteMetadata::new(note_nonce).into()\n }\n );\n\n let inner_nullifier = $compute_nullifier_unconstrained(note, owner, note_hash_for_nullification);\n\n Option::some(\n aztec::messages::discovery::NoteHashAndNullifier {\n note_hash, inner_nullifier\n }\n )\n }\n },\n );\n }\n\n let if_note_type_id_match_statements = if_note_type_id_match_statements_list.join(quote {});\n\n quote {\n /// Unpacks an array into a note corresponding to `note_type_id` and then computes its note hash\n /// (non-siloed) and inner nullifier (non-siloed) assuming the note has been inserted into the note hash\n /// tree with `note_nonce`.\n ///\n /// The signature of this function notably matches the `aztec::messages::discovery::ComputeNoteHashAndNullifier` type,\n /// and so it can be used to call functions from that module such as `discover_new_messages`, \n /// `do_process_message` and `attempt_note_discovery`.\n ///\n /// This function is automatically injected by the `#[aztec]` macro.\n #[contract_library_method]\n unconstrained fn _compute_note_hash_and_nullifier(\n packed_note: BoundedVec,\n owner: aztec::protocol_types::address::AztecAddress,\n storage_slot: Field,\n note_type_id: Field,\n contract_address: aztec::protocol_types::address::AztecAddress,\n randomness: Field,\n note_nonce: Field,\n ) -> Option {\n $if_note_type_id_match_statements\n else {\n Option::none()\n }\n }\n }\n } else {\n // Contracts with no notes still implement this function to avoid having special-casing, the implementation\n // simply throws immediately.\n quote {\n /// This contract does not use private notes, so this function should never be called as it will\n /// unconditionally fail.\n ///\n /// This function is automatically injected by the `#[aztec]` macro.\n #[contract_library_method]\n unconstrained fn _compute_note_hash_and_nullifier(\n _packed_note: BoundedVec,\n _owner: aztec::protocol_types::address::AztecAddress,\n _storage_slot: Field,\n _note_type_id: Field,\n _contract_address: aztec::protocol_types::address::AztecAddress,\n _randomness: Field,\n _nonce: Field,\n ) -> Option {\n panic(f\"This contract does not use private notes\")\n }\n }\n }\n}\n\ncomptime fn generate_sync_private_state() -> Quoted {\n quote {\n pub struct sync_private_state_parameters {}\n\n #[abi(functions)]\n pub struct sync_private_state_abi {\n parameters: sync_private_state_parameters,\n }\n\n #[aztec::macros::internals_functions_generation::abi_attributes::abi_utility]\n unconstrained fn sync_private_state() {\n let address = aztec::context::utility_context::UtilityContext::new().this_address();\n \n aztec::messages::discovery::discover_new_messages(address, _compute_note_hash_and_nullifier);\n }\n }\n}\n\ncomptime fn generate_process_message() -> Quoted {\n quote {\n pub struct process_message_parameters {\n pub message_ciphertext: BoundedVec,\n pub message_context: aztec::messages::processing::message_context::MessageContext,\n }\n\n #[abi(functions)]\n pub struct process_message_abi {\n parameters: process_message_parameters,\n }\n\n #[aztec::macros::internals_functions_generation::abi_attributes::abi_utility]\n unconstrained fn process_message(\n message_ciphertext: BoundedVec,\n message_context: aztec::messages::processing::message_context::MessageContext,\n ) {\n let address = aztec::context::utility_context::UtilityContext::new().this_address();\n\n aztec::messages::discovery::discover_new_messages(address, _compute_note_hash_and_nullifier); \n aztec::messages::discovery::process_message::process_message_ciphertext(\n address,\n _compute_note_hash_and_nullifier,\n message_ciphertext,\n message_context,\n );\n }\n }\n}\n\n/// Checks if each function in the module is marked with either #[external(...)], #[contract_library_method], or #[test].\n/// Non-macroified functions are not allowed in contracts.\ncomptime fn check_each_fn_macroified(m: Module) {\n for f in m.functions() {\n let name = f.name();\n if !is_fn_external(f)\n & !is_fn_contract_library_method(f)\n & !is_fn_internal(f)\n & !is_fn_test(f) {\n // We don't suggest that #[contract_library_method] is allowed because we don't want to introduce another\n // concept\n panic(\n f\"Function {name} must be marked as either #[external(...)], #[internal(...)], or #[test]\",\n );\n }\n }\n}\n" + }, + "106": { + "path": "/home/ubuntu/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.20251212/noir-projects/aztec-nr/aztec/src/macros/dispatch.nr", + "source": "use crate::macros::internals_functions_generation::external_functions_registry::get_public_functions;\nuse super::utils::compute_fn_selector;\nuse poseidon::poseidon2::Poseidon2Hasher;\nuse protocol_types::meta::utils::get_params_len_quote;\nuse std::{collections::umap::UHashMap, hash::BuildHasherDefault, panic};\n\n/// Returns an `fn public_dispatch(...)` function for the given module that's assumed to be an Aztec contract.\npub comptime fn generate_public_dispatch(m: Module) -> Quoted {\n let functions = get_public_functions(m);\n\n let unit = get_type::<()>();\n\n let seen_selectors =\n &mut UHashMap::>::default();\n\n let ifs = functions.map(|function: FunctionDefinition| {\n let parameters = function.parameters();\n let return_type = function.return_type();\n\n let selector: Field = compute_fn_selector(function);\n let fn_name = function.name();\n\n // Since function selectors are computed as the first 4 bytes of the hash of the function signature,\n // it's possible to have collisions. With the following check, we ensure it doesn't happen within\n // the same contract.\n if seen_selectors.contains_key(selector) {\n let existing_fn = seen_selectors.get(selector).unwrap();\n panic(\n f\"Public function selector collision detected between functions '{fn_name}' and '{existing_fn}'\",\n );\n }\n seen_selectors.insert(selector, fn_name);\n\n let params_len_quote = get_params_len_quote(parameters);\n\n let initial_read = if parameters.len() == 0 {\n quote {}\n } else {\n // The initial calldata_copy offset is 1 to skip the Field selector\n // The expected calldata is the serialization of\n // - FunctionSelector: the selector of the function intended to dispatch\n // - Parameters: the parameters of the function intended to dispatch\n // That is, exactly what is expected for a call to the target function,\n // but with a selector added at the beginning.\n quote {\n let input_calldata: [Field; $params_len_quote] = dep::aztec::context::public_context::calldata_copy(1, $params_len_quote);\n let mut reader = dep::aztec::protocol_types::utils::reader::Reader::new(input_calldata);\n }\n };\n\n let parameter_index: &mut u32 = &mut 0;\n let reads = parameters.map(|param: (Quoted, Type)| {\n let parameter_index_value = *parameter_index;\n let param_name = f\"arg{parameter_index_value}\".quoted_contents();\n let param_type = param.1;\n let read = quote {\n let $param_name: $param_type = reader.read_struct(dep::aztec::protocol_types::traits::Deserialize::deserialize);\n };\n *parameter_index += 1;\n quote { $read }\n });\n let read = reads.join(quote { });\n\n let mut args = &[];\n for parameter_index in 0..parameters.len() {\n let param_name = f\"arg{parameter_index}\".quoted_contents();\n args = args.push_back(quote { $param_name });\n }\n\n // We call a function whose name is prefixed with `__aztec_nr_internals__`. This is necessary because the\n // original function is intentionally made uncallable, preventing direct invocation within the contract.\n // Instead, a new function with the same name, but prefixed by `__aztec_nr_internals__`, has been generated to\n // be called here. For more details see the `process_functions` function.\n let name = f\"__aztec_nr_internals__{fn_name}\".quoted_contents();\n let args = args.join(quote { , });\n let call = quote { $name($args) };\n\n let return_code = if return_type == unit {\n quote {\n $call;\n // Force early return.\n dep::aztec::context::public_context::avm_return([]);\n }\n } else {\n quote {\n let return_value = dep::aztec::protocol_types::traits::Serialize::serialize($call);\n dep::aztec::context::public_context::avm_return(return_value.as_slice());\n }\n };\n\n let if_ = quote {\n if selector == $selector {\n $initial_read\n $read\n $return_code\n }\n };\n if_\n });\n\n if ifs.len() == 0 {\n // No dispatch function if there are no public functions\n quote {}\n } else {\n let ifs = ifs.push_back(quote { panic(f\"Unknown selector {selector}\") });\n let dispatch = ifs.join(quote { });\n\n let body = quote {\n // We mark this as public because our whole system depends on public functions having this attribute.\n #[aztec::macros::internals_functions_generation::abi_attributes::abi_public]\n pub unconstrained fn public_dispatch(selector: Field) {\n $dispatch\n }\n };\n\n body\n }\n}\n\ncomptime fn get_type() -> Type {\n let t: T = std::mem::zeroed();\n std::meta::type_of(t)\n}\n" + }, + "109": { + "path": "/home/ubuntu/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.20251212/noir-projects/aztec-nr/aztec/src/macros/functions/initialization_utils.nr", + "source": "use dep::protocol_types::{\n abis::function_selector::FunctionSelector, address::AztecAddress,\n constants::GENERATOR_INDEX__CONSTRUCTOR, hash::poseidon2_hash_with_separator, traits::ToField,\n};\n\nuse crate::{\n context::{PrivateContext, PublicContext},\n oracle::get_contract_instance::{\n get_contract_instance, get_contract_instance_deployer_avm,\n get_contract_instance_initialization_hash_avm,\n },\n};\n\n// Used by `create_mark_as_initialized` (you won't find it through searching)\npub fn mark_as_initialized_public(context: PublicContext) {\n let init_nullifier =\n compute_unsiloed_contract_initialization_nullifier((context).this_address());\n context.push_nullifier(init_nullifier);\n}\n\n// Used by `create_mark_as_initialized` (you won't find it through searching)\npub fn mark_as_initialized_private(context: &mut PrivateContext) {\n let init_nullifier =\n compute_unsiloed_contract_initialization_nullifier((*context).this_address());\n context.push_nullifier(init_nullifier);\n}\n\n// Used by `create_init_check` (you won't find it through searching)\npub fn assert_is_initialized_public(context: PublicContext) {\n let init_nullifier = compute_unsiloed_contract_initialization_nullifier(context.this_address());\n assert(context.nullifier_exists(init_nullifier, context.this_address()), \"Not initialized\");\n}\n\n// Used by `create_init_check` (you won't find it through searching)\npub fn assert_is_initialized_private(context: &mut PrivateContext) {\n let init_nullifier = compute_unsiloed_contract_initialization_nullifier(context.this_address());\n context.push_nullifier_read_request(init_nullifier, context.this_address());\n}\n\nfn compute_unsiloed_contract_initialization_nullifier(address: AztecAddress) -> Field {\n address.to_field()\n}\n\n// Used by `create_assert_correct_initializer_args` (you won't find it through searching)\npub fn assert_initialization_matches_address_preimage_public(context: PublicContext) {\n let address = context.this_address();\n let deployer = get_contract_instance_deployer_avm(address).unwrap();\n let initialization_hash = get_contract_instance_initialization_hash_avm(address).unwrap();\n let expected_init = compute_initialization_hash(context.selector(), context.get_args_hash());\n assert(initialization_hash == expected_init, \"Initialization hash does not match\");\n assert(\n (deployer.is_zero()) | (deployer == context.msg_sender().unwrap()),\n \"Initializer address is not the contract deployer\",\n );\n}\n\n// Used by `create_assert_correct_initializer_args` (you won't find it through searching)\npub fn assert_initialization_matches_address_preimage_private(context: PrivateContext) {\n let address = context.this_address();\n let instance = get_contract_instance(address);\n let expected_init = compute_initialization_hash(context.selector(), context.get_args_hash());\n assert(instance.initialization_hash == expected_init, \"Initialization hash does not match\");\n assert(\n (instance.deployer.is_zero()) | (instance.deployer == context.msg_sender().unwrap()),\n \"Initializer address is not the contract deployer\",\n );\n}\n\n/// This function is not only used in macros but it's also used by external people to check that an instance has been\n/// initialized with the correct constructor arguments. Don't hide this unless you implement factory functionality.\npub fn compute_initialization_hash(\n init_selector: FunctionSelector,\n init_args_hash: Field,\n) -> Field {\n poseidon2_hash_with_separator(\n [init_selector.to_field(), init_args_hash],\n GENERATOR_INDEX__CONSTRUCTOR,\n )\n}\n" + }, + "116": { + "path": "/home/ubuntu/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.20251212/noir-projects/aztec-nr/aztec/src/macros/internals_functions_generation/external/public.nr", + "source": "use crate::macros::{\n internals_functions_generation::external::helpers::{\n create_authorize_once_check, get_abi_relevant_attributes,\n },\n utils::{\n fn_has_authorize_once, fn_has_noinitcheck, is_fn_initializer, is_fn_only_self, is_fn_view,\n module_has_initializer, module_has_storage,\n },\n};\nuse std::meta::ctstring::AsCtString;\n\npub(crate) comptime fn generate_public_external(f: FunctionDefinition) -> Quoted {\n let module_has_initializer = module_has_initializer(f.module());\n let module_has_storage = module_has_storage(f.module());\n\n // Public functions undergo a lot of transformations from their Aztec.nr form.\n let original_params = f.parameters();\n\n let args_len_quote = if original_params.len() == 0 {\n // If the function has no parameters, we set the args_len to 0.\n quote { 0 }\n } else {\n // The following will give us ::N + ::N + ...\n original_params\n .map(|(_, param_type): (Quoted, Type)| {\n quote {\n <$param_type as $crate::protocol_types::traits::Serialize>::N\n }\n })\n .join(quote {+})\n };\n\n let storage_init = if module_has_storage {\n quote {\n let storage = Storage::init(context);\n }\n } else {\n // Contract does not have Storage defined, so we set storage to the unit type `()`. ContractSelf requires a\n // storage struct in its constructor. Using an Option type would lead to worse developer experience and higher\n // constraint counts so we use the unit type `()` instead.\n quote {\n let storage = ();\n }\n };\n\n // Unlike in the private case, in public the `context` does not need to receive the hash of the original params.\n let contract_self_creation = quote {\n #[allow(unused_variables)]\n let mut self = {\n let context = dep::aztec::context::public_context::PublicContext::new(|| {\n // We start from 1 because we skip the selector for the dispatch function.\n let serialized_args : [Field; $args_len_quote] = dep::aztec::context::public_context::calldata_copy(1, $args_len_quote);\n dep::aztec::hash::hash_args(serialized_args)\n });\n $storage_init\n let self_address = context.this_address();\n let call_self: CallSelf = CallSelf { address: self_address, context };\n let call_self_static: CallSelfStatic = CallSelfStatic { address: self_address, context };\n let internal: CallInternal = CallInternal { context };\n aztec::contract_self::ContractSelf::new_public(context, storage, call_self, call_self_static, internal)\n };\n };\n\n let original_function_name = f.name();\n\n // Modifications introduced by the different marker attributes.\n let internal_check = if is_fn_only_self(f) {\n let assertion_message =\n f\"Function {original_function_name} can only be called by the same contract\";\n quote { assert(self.msg_sender().unwrap() == self.address, $assertion_message); }\n } else {\n quote {}\n };\n\n let view_check = if is_fn_view(f) {\n let assertion_message = f\"Function {original_function_name} can only be called statically\"\n .as_ctstring()\n .as_quoted_str();\n quote { assert(self.context.is_static_call(), $assertion_message); }\n } else {\n quote {}\n };\n\n let (assert_initializer, mark_as_initialized) = if is_fn_initializer(f) {\n (\n quote { aztec::macros::functions::initialization_utils::assert_initialization_matches_address_preimage_public(self.context); },\n quote { aztec::macros::functions::initialization_utils::mark_as_initialized_public(self.context); },\n )\n } else {\n (quote {}, quote {})\n };\n\n // Initialization checks are not included in contracts that don't have initializers.\n let init_check = if module_has_initializer & !fn_has_noinitcheck(f) & !is_fn_initializer(f) {\n quote { aztec::macros::functions::initialization_utils::assert_is_initialized_public(self.context); }\n } else {\n quote {}\n };\n\n // Inject the authwit check if the function is marked with #[authorize_once].\n let authorize_once_check = if fn_has_authorize_once(f) {\n create_authorize_once_check(f, false)\n } else {\n quote {}\n };\n\n let to_prepend = quote {\n $contract_self_creation\n $assert_initializer\n $init_check\n $internal_check\n $view_check\n $authorize_once_check\n };\n\n let to_append = quote {\n $mark_as_initialized\n };\n\n let fn_name = f\"__aztec_nr_internals__{original_function_name}\".quoted_contents();\n let body = f.body();\n let return_type = f.return_type();\n\n // New function parameters are the same as the original function's ones.\n let params = original_params\n .map(|(param_name, param_type)| quote { $param_name: $param_type })\n .join(quote {, });\n\n // Preserve all attributes that are relevant to the function's ABI.\n let abi_relevant_attributes = get_abi_relevant_attributes(f);\n\n // All public functions are automatically made unconstrained, even if they were not marked as such. This is because\n // instead of compiling into a circuit, they will compile to bytecode that will be later transpiled into AVM\n // bytecode.\n quote {\n #[aztec::macros::internals_functions_generation::abi_attributes::abi_public]\n $abi_relevant_attributes\n unconstrained fn $fn_name($params) -> pub $return_type {\n $to_prepend\n $body\n $to_append\n }\n }\n}\n" + }, + "12": { + "path": "std/convert.nr", + "source": "// docs:start:from-trait\npub trait From {\n fn from(input: T) -> Self;\n}\n// docs:end:from-trait\n\nimpl From for T {\n fn from(input: T) -> T {\n input\n }\n}\n\n// docs:start:into-trait\npub trait Into {\n fn into(self) -> T;\n}\n\nimpl Into for U\nwhere\n T: From,\n{\n fn into(self) -> T {\n T::from(self)\n }\n}\n// docs:end:into-trait\n\n// docs:start:from-impls\n// Unsigned integers\n\nimpl From for u16 {\n fn from(value: u8) -> u16 {\n value as u16\n }\n}\n\nimpl From for u32 {\n fn from(value: u8) -> u32 {\n value as u32\n }\n}\n\nimpl From for u32 {\n fn from(value: u16) -> u32 {\n value as u32\n }\n}\n\nimpl From for u64 {\n fn from(value: u8) -> u64 {\n value as u64\n }\n}\n\nimpl From for u64 {\n fn from(value: u16) -> u64 {\n value as u64\n }\n}\n\nimpl From for u64 {\n fn from(value: u32) -> u64 {\n value as u64\n }\n}\n\nimpl From for u128 {\n fn from(value: u8) -> u128 {\n value as u128\n }\n}\n\nimpl From for u128 {\n fn from(value: u16) -> u128 {\n value as u128\n }\n}\n\nimpl From for u128 {\n fn from(value: u32) -> u128 {\n value as u128\n }\n}\nimpl From for u128 {\n fn from(value: u64) -> u128 {\n value as u128\n }\n}\n\nimpl From for Field {\n fn from(value: u8) -> Field {\n value as Field\n }\n}\n\nimpl From for Field {\n fn from(value: u16) -> Field {\n value as Field\n }\n}\n\nimpl From for Field {\n fn from(value: u32) -> Field {\n value as Field\n }\n}\nimpl From for Field {\n fn from(value: u64) -> Field {\n value as Field\n }\n}\n\nimpl From for Field {\n fn from(value: u128) -> Field {\n value as Field\n }\n}\n\n// Signed integers\n\nimpl From for i16 {\n fn from(value: i8) -> i16 {\n value as i16\n }\n}\n\nimpl From for i32 {\n fn from(value: i8) -> i32 {\n value as i32\n }\n}\n\nimpl From for i32 {\n fn from(value: i16) -> i32 {\n value as i32\n }\n}\n\nimpl From for i64 {\n fn from(value: i8) -> i64 {\n value as i64\n }\n}\n\nimpl From for i64 {\n fn from(value: i16) -> i64 {\n value as i64\n }\n}\n\nimpl From for i64 {\n fn from(value: i32) -> i64 {\n value as i64\n }\n}\n\n// Booleans\nimpl From for u8 {\n fn from(value: bool) -> u8 {\n value as u8\n }\n}\nimpl From for u16 {\n fn from(value: bool) -> u16 {\n value as u16\n }\n}\nimpl From for u32 {\n fn from(value: bool) -> u32 {\n value as u32\n }\n}\nimpl From for u64 {\n fn from(value: bool) -> u64 {\n value as u64\n }\n}\nimpl From for u128 {\n fn from(value: bool) -> u128 {\n value as u128\n }\n}\nimpl From for i8 {\n fn from(value: bool) -> i8 {\n value as i8\n }\n}\nimpl From for i16 {\n fn from(value: bool) -> i16 {\n value as i16\n }\n}\nimpl From for i32 {\n fn from(value: bool) -> i32 {\n value as i32\n }\n}\nimpl From for i64 {\n fn from(value: bool) -> i64 {\n value as i64\n }\n}\nimpl From for Field {\n fn from(value: bool) -> Field {\n value as Field\n }\n}\n// docs:end:from-impls\n\n/// A generic interface for casting between primitive types,\n/// equivalent of using the `as` keyword between values.\n///\n/// # Example\n///\n/// ```\n/// let x: Field = 1234567890;\n/// let y: u8 = x as u8;\n/// let z: u8 = x.as_();\n/// assert_eq(y, z);\n/// ```\npub trait AsPrimitive {\n /// The equivalent of doing `self as T`.\n fn as_(self) -> T;\n}\n\n#[generate_as_primitive_impls]\ncomptime fn generate_as_primitive_impls(_: FunctionDefinition) -> Quoted {\n let types = [\n quote { bool },\n quote { u8 },\n quote { u16 },\n quote { u32 },\n quote { u64 },\n quote { u128 },\n quote { i8 },\n quote { i16 },\n quote { i32 },\n quote { i64 },\n ];\n\n let mut impls = &[];\n for type1 in types {\n for type2 in types {\n let body = if type1 == type2 {\n quote { self }\n } else if type1 == quote { bool } {\n quote { self != 0 }\n } else {\n quote { self as $type1 }\n };\n\n impls = impls.push_back(\n quote {\n impl AsPrimitive<$type1> for $type2 {\n fn as_(self) -> $type1 {\n $body\n }\n }\n },\n );\n }\n }\n\n let u_types =\n [quote { bool }, quote { u8 }, quote { u16 }, quote { u32 }, quote { u64 }, quote { u128 }];\n\n for type2 in u_types {\n let body = quote { self as Field };\n\n impls = impls.push_back(\n quote {\n impl AsPrimitive for $type2 {\n fn as_(self) -> Field {\n $body\n }\n }\n },\n );\n }\n\n for type1 in u_types {\n let body = if type1 == quote { bool } {\n quote { self != 0 }\n } else {\n quote { self as $type1 }\n };\n\n impls = impls.push_back(\n quote {\n impl AsPrimitive<$type1> for Field {\n fn as_(self) -> $type1 {\n $body\n }\n }\n },\n );\n }\n\n impls.join(quote {})\n}\n" + }, + "123": { + "path": "/home/ubuntu/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.20251212/noir-projects/aztec-nr/aztec/src/macros/notes.nr", + "source": "use crate::note::note_getter_options::PropertySelector;\nuse std::{collections::bounded_vec::BoundedVec, meta::{ctstring::AsCtString, type_of}};\n\n/// Maximum number of note types within 1 contract.\ncomptime global MAX_NOTE_TYPES: u32 = 128;\n\n/// A BoundedVec containing all the note types within this contract.\npub comptime mut global NOTES: BoundedVec = BoundedVec::new();\n\ncomptime mut global NOTE_TYPE_ID_COUNTER: u32 = 0;\n\n/// The note type id is set by enumerating the note types.\ncomptime fn get_next_note_type_id() -> Field {\n // We assert that the note type id fits within 7 bits\n assert(\n NOTE_TYPE_ID_COUNTER < MAX_NOTE_TYPES,\n f\"A contract can contain at most {MAX_NOTE_TYPES} different note types\",\n );\n\n let note_type_id = NOTE_TYPE_ID_COUNTER as Field;\n NOTE_TYPE_ID_COUNTER += 1;\n note_type_id\n}\n\n/// Generates default `NoteType` implementation for a given note struct `s` and returns it as a quote.\n///\n/// impl NoteType for NoteStruct {\n/// fn get_id() -> Field {\n/// ...\n/// }\n/// }\ncomptime fn generate_note_type_impl(s: TypeDefinition, note_type_id: Field) -> Quoted {\n let name = s.name();\n let typ = s.as_type();\n let note_type_name: str<_> = f\"{name}\".as_ctstring().as_quoted_str!();\n let max_note_packed_len = crate::messages::discovery::private_notes::MAX_NOTE_PACKED_LEN;\n\n quote {\n impl aztec::note::note_interface::NoteType for $name {\n fn get_id() -> Field {\n // This static assertion ensures the note's packed length doesn't exceed the maximum allowed size.\n // While this check would ideally live in the Packable trait implementation, we place it here since\n // this function is always generated by our macros and the Packable trait implementation is not.\n // Note: We set the note type name and max packed length as local variables because injecting them\n // directly into the error message doesn't work.\n let note_type_name = $note_type_name;\n let max_note_packed_len: u32 = $max_note_packed_len; // Casting to u32 to avoid the value to be printed in hex.\n let note_packed_len = <$typ as Packable>::N;\n std::static_assert(note_packed_len <= $max_note_packed_len, f\"{note_type_name} has a packed length of {note_packed_len} fields, which exceeds the maximum allowed length of {max_note_packed_len} fields\");\n\n $note_type_id\n }\n }\n }\n}\n\n/// Generates default `NoteHash` trait implementation for a given note struct `s` and returns it as a quote.\n///\n/// # Generated Implementation\n/// ```\n/// impl NoteHash for NoteStruct {\n/// fn compute_note_hash(self, owner: AztecAddress, storage_slot: Field, randomness: Field) -> Field { ... }\n///\n/// fn compute_nullifier(self, context: &mut PrivateContext, note_hash_for_nullification: Field, owner: AztecAddress) -> Field { ... }\n///\n/// unconstrained fn compute_nullifier_unconstrained(note_hash_for_nullification: Field, owner: AztecAddress) -> Field { ... }\n/// }\n/// ```\ncomptime fn generate_note_hash_trait_impl(s: TypeDefinition) -> Quoted {\n let name = s.name();\n\n quote {\n impl aztec::note::note_interface::NoteHash for $name {\n fn compute_note_hash(self, owner: aztec::protocol_types::address::AztecAddress, storage_slot: Field, randomness: Field) -> Field {\n let inputs = aztec::protocol_types::traits::Packable::pack(self).concat( [aztec::protocol_types::traits::ToField::to_field(owner), storage_slot, randomness]);\n aztec::protocol_types::hash::poseidon2_hash_with_separator(inputs, aztec::protocol_types::constants::GENERATOR_INDEX__NOTE_HASH)\n }\n\n fn compute_nullifier(\n self,\n context: &mut aztec::context::PrivateContext,\n owner: aztec::protocol_types::address::AztecAddress,\n note_hash_for_nullification: Field,\n ) -> Field {\n let owner_npk_m = aztec::keys::getters::get_public_keys(owner).npk_m;\n // We invoke hash as a static trait function rather than calling owner_npk_m.hash() directly\n // in the quote to avoid \"trait not in scope\" compiler warnings.\n let owner_npk_m_hash = aztec::protocol_types::traits::Hash::hash(owner_npk_m);\n let secret = context.request_nsk_app(owner_npk_m_hash);\n aztec::protocol_types::hash::poseidon2_hash_with_separator(\n [note_hash_for_nullification, secret],\n aztec::protocol_types::constants::GENERATOR_INDEX__NOTE_NULLIFIER as Field,\n )\n }\n\n unconstrained fn compute_nullifier_unconstrained(\n self,\n owner: aztec::protocol_types::address::AztecAddress,\n note_hash_for_nullification: Field,\n ) -> Field {\n let owner_npk_m = aztec::keys::getters::get_public_keys(owner).npk_m;\n // We invoke hash as a static trait function rather than calling owner_npk_m.hash() directly\n // in the quote to avoid \"trait not in scope\" compiler warnings.\n let owner_npk_m_hash = aztec::protocol_types::traits::Hash::hash(owner_npk_m);\n let secret = aztec::keys::getters::get_nsk_app(owner_npk_m_hash);\n aztec::protocol_types::hash::poseidon2_hash_with_separator(\n [note_hash_for_nullification, secret],\n aztec::protocol_types::constants::GENERATOR_INDEX__NOTE_NULLIFIER as Field,\n )\n }\n }\n }\n}\n\n/// Generates note properties struct for a given note struct `s`.\n///\n/// Example:\n/// ```\n/// struct TokenNoteProperties {\n/// amount: aztec::note::note_getter_options::PropertySelector,\n/// npk_m_hash: aztec::note::note_getter_options::PropertySelector\n/// randomness: aztec::note::note_getter_options::PropertySelector\n/// }\n///\n/// impl aztec::note::note_interface::NoteProperties for TokenNote {\n/// fn properties() -> TokenNoteProperties {\n/// Self {\n/// amount: aztec::note::note_getter_options::PropertySelector { index: 0, offset: 0, length: 32 },\n/// npk_m_hash: aztec::note::note_getter_options::PropertySelector { index: 1, offset: 0, length: 32 },\n/// randomness: aztec::note::note_getter_options::PropertySelector { index: 2, offset: 0, length: 32 }\n/// }\n/// }\n/// }\n/// ```\ncomptime fn generate_note_properties(s: TypeDefinition) -> Quoted {\n let name = s.name();\n\n let struct_name = f\"{name}Properties\".quoted_contents();\n\n let property_selector_type = type_of(PropertySelector { index: 0, offset: 0, length: 0 });\n\n let note_fields = s.fields_as_written();\n\n let properties_types = note_fields\n .map(|(name, _, _)| quote { pub $name: $property_selector_type })\n .join(quote {,});\n\n // TODO #8694: Properly handle non-field types https://github.com/AztecProtocol/aztec-packages/issues/8694\n let mut properties_list = &[];\n for i in 0..note_fields.len() {\n let (name, _, _) = note_fields[i];\n let i = i as u8;\n properties_list = properties_list.push_back(\n quote { $name: aztec::note::note_getter_options::PropertySelector { index: $i, offset: 0, length: 32 } },\n );\n }\n\n let properties = properties_list.join(quote {,});\n\n quote {\n pub struct $struct_name {\n $properties_types\n }\n\n impl aztec::note::note_interface::NoteProperties<$struct_name> for $name {\n fn properties() -> $struct_name {\n $struct_name {\n $properties\n }\n }\n }\n }\n}\n\n/// Generates the core note functionality for a struct:\n///\n/// - NoteTypeProperties: Defines the structure and properties of note fields\n/// - NoteType trait implementation: Provides the note type ID\n/// - NoteHash trait implementation: Handles note hash and nullifier computation\n///\n/// # Requirements\n///\n/// The note struct must:\n/// - Implement the `Packable` trait\n/// - Not exceed `MAX_NOTE_PACKED_LEN` when packed\n///\n/// # Registration\n///\n/// Registers the note in the global `NOTES` BoundedVec to enable note processing functionality.\n///\n/// # Generated Code\n///\n/// For detailed documentation on the generated implementations, see:\n/// - `generate_note_properties()`\n/// - `generate_note_type_impl()`\n/// - `generate_note_hash_trait_impl()`\npub comptime fn note(s: TypeDefinition) -> Quoted {\n assert_has_packable(s);\n\n // We register the note in the global `NOTES` BoundedVec because we need that information inside the #[aztec] macro\n // to generate note processing functionality.\n NOTES.push(s.as_type());\n\n let note_properties = generate_note_properties(s);\n let note_type_id = get_next_note_type_id();\n let note_type_impl = generate_note_type_impl(s, note_type_id);\n let note_hash_impl = generate_note_hash_trait_impl(s);\n\n quote {\n $note_properties\n $note_type_impl\n $note_hash_impl\n }\n}\n\n/// Generates code for a custom note implementation that requires specialized note hash or nullifier computation.\n///\n/// # Generated Code\n/// - NoteTypeProperties: Defines the structure and properties of note fields\n/// - NoteType trait implementation: Provides the note type ID\n///\n/// # Requirements\n///\n/// The note struct must:\n/// - Implement the `Packable` trait\n/// - Not exceed `MAX_NOTE_PACKED_LEN` when packed\n///\n/// # Registration\n///\n/// Registers the note in the global `NOTES` BoundedVec to enable note processing functionality.\n///\n/// # Use Cases\n/// Use this macro when implementing a note that needs custom:\n/// - Note hash computation logic\n/// - Nullifier computation logic\n///\n/// The macro omits generating default NoteHash trait implementation, allowing you to provide your own.\n///\n/// # Example\n/// ```\n/// #[custom_note]\n/// struct CustomNote {\n/// value: Field,\n/// metadata: Field\n/// }\n///\n/// impl NoteHash for CustomNote {\n/// // Custom note hash computation...\n/// fn compute_note_hash(...) -> Field { ... }\n///\n/// // Custom nullifier computation...\n/// fn compute_nullifier(...) -> Field { ... }\n/// fn compute_nullifier_unconstrained(...) -> Field { ... }\n/// }\n/// ```\npub comptime fn custom_note(s: TypeDefinition) -> Quoted {\n assert_has_packable(s);\n\n // We register the note in the global `NOTES` BoundedVec because we need that information inside the #[aztec] macro\n // to generate note processing functionality.\n NOTES.push(s.as_type());\n\n let note_type_id = get_next_note_type_id();\n let note_properties = generate_note_properties(s);\n let note_type_impl = generate_note_type_impl(s, note_type_id);\n\n quote {\n $note_properties\n $note_type_impl\n }\n}\n\n/// Asserts that the given note implements the `Packable` trait.\n///\n/// We require that notes have the `Packable` trait implemented because it is used when emitting a note in a log or as\n/// an offchain message.\ncomptime fn assert_has_packable(note: TypeDefinition) {\n let packable_constraint =\n quote { crate::protocol_types::traits::Packable }.as_trait_constraint();\n let note_name = note.name();\n\n assert(\n note.as_type().implements(packable_constraint),\n f\"{note_name} does not implement Packable trait. Either implement it manually or place #[derive(Packable)] on the note struct before #[note] macro invocation.\",\n );\n}\n" + }, + "126": { + "path": "/home/ubuntu/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.20251212/noir-projects/aztec-nr/aztec/src/messages/discovery/mod.nr", + "source": "use protocol_types::{address::AztecAddress, debug_log::{debug_log, debug_log_format}};\n\npub mod nonce_discovery;\npub mod partial_notes;\npub mod private_events;\npub mod private_notes;\npub mod process_message;\n\nuse crate::{\n messages::{\n discovery::{\n private_notes::MAX_NOTE_PACKED_LEN, process_message::process_message_ciphertext,\n },\n processing::{\n get_private_logs, pending_tagged_log::PendingTaggedLog,\n validate_enqueued_notes_and_events,\n },\n },\n utils::array,\n};\n\npub struct NoteHashAndNullifier {\n /// The result of NoteHash::compute_note_hash\n pub note_hash: Field,\n /// The result of NoteHash::compute_nullifier_unconstrained (since all of message discovery is unconstrained)\n pub inner_nullifier: Field,\n}\n\n/// A function which takes a note's packed content, address of the emitting contract, note nonce, storage slot and note\n/// type ID and attempts to compute its note hash (not hashed by note nonce nor siloed by address) and inner nullifier\n/// (not siloed by address).\n///\n/// This function must be user-provided as its implementation requires knowledge of how note type IDs are allocated in a\n/// contract. The `#[aztec]` macro automatically creates such a contract library method called\n/// `_compute_note_hash_and_nullifier`, which looks something like this:\n///\n/// ```\n/// |packed_note, owner, storage_slot, note_type_id, contract_address, randomness, note_nonce| {\n/// if note_type_id == MyNoteType::get_id() {\n/// assert(packed_note.len() == MY_NOTE_TYPE_SERIALIZATION_LENGTH);\n///\n/// let note = MyNoteType::unpack(aztec::utils::array::subarray(packed_note.storage(), 0));\n///\n/// let note_hash = note.compute_note_hash(owner, storage_slot, randomness);\n/// let note_hash_for_nullification = aztec::note::utils::compute_note_hash_for_nullification(\n/// RetrievedNote{ note, contract_address, metadata: SettledNoteMetadata::new(note_nonce).into() },\n/// storage_slot\n/// );\n///\n/// let inner_nullifier = note.compute_nullifier_unconstrained(owner, note_hash_for_nullification);\n///\n/// Option::some(\n/// aztec::messages::discovery::NoteHashAndNullifier {\n/// note_hash, inner_nullifier\n/// }\n/// )\n/// } else if note_type_id == MyOtherNoteType::get_id() {\n/// ... // Similar to above but calling MyOtherNoteType::unpack_content\n/// } else {\n/// Option::none() // Unknown note type ID\n/// };\n/// }\n/// ```\npub type ComputeNoteHashAndNullifier = unconstrained fn[Env](/* packed_note */BoundedVec, /* owner */ AztecAddress, /* storage_slot */ Field, /* note_type_id */ Field, /* contract_address */ AztecAddress, /* randomness */ Field, /* note nonce */ Field) -> Option;\n\n/// Performs the message discovery process, in which private logs are downloaded and inspected to find new private\n/// notes, partial notes and events, etc., and pending partial notes are processed to search for their completion logs.\n/// This is the mechanism via which a contract updates its knowledge of its private state.\n///\n/// Note that the state is synchronized up to the latest block synchronized by PXE. That should be close to the chain\n/// tip as block synchronization is performed before contract function simulation is done.\n///\n/// Receives the address of the contract on which discovery is performed along with its\n/// `compute_note_hash_and_nullifier` function.\npub unconstrained fn discover_new_messages(\n contract_address: AztecAddress,\n compute_note_hash_and_nullifier: ComputeNoteHashAndNullifier,\n) {\n debug_log(\"Performing message discovery\");\n\n // First we process all private logs, which can contain different kinds of messages e.g. private notes, partial\n // notes, private events, etc.\n let mut logs = get_private_logs(contract_address);\n logs.for_each(|i, pending_tagged_log: PendingTaggedLog| {\n debug_log_format(\n \"Processing log with tag {0}\",\n [pending_tagged_log.log.get(0)],\n );\n\n // We remove the tag from the pending tagged log and process the message ciphertext contained in it.\n let message_ciphertext = array::subbvec(pending_tagged_log.log, 1);\n\n process_message_ciphertext(\n contract_address,\n compute_note_hash_and_nullifier,\n message_ciphertext,\n pending_tagged_log.context,\n );\n logs.remove(i);\n });\n\n // Then we process all pending partial notes, regardless of whether they were found in the current or previous\n // executions.\n partial_notes::fetch_and_process_partial_note_completion_logs(\n contract_address,\n compute_note_hash_and_nullifier,\n );\n\n // Finally we validate all notes and events that were found as part of the previous processes, resulting in them\n // being added to PXE's database and retrievable via oracles (get_notes) and our TS API (PXE::getPrivateEvents).\n validate_enqueued_notes_and_events(contract_address);\n}\n" + }, + "127": { + "path": "/home/ubuntu/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.20251212/noir-projects/aztec-nr/aztec/src/messages/discovery/nonce_discovery.nr", + "source": "use crate::messages::discovery::{ComputeNoteHashAndNullifier, private_notes::MAX_NOTE_PACKED_LEN};\n\nuse dep::protocol_types::{\n address::AztecAddress,\n constants::MAX_NOTE_HASHES_PER_TX,\n debug_log::debug_log_format,\n hash::{compute_note_hash_nonce, compute_siloed_note_hash, compute_unique_note_hash},\n traits::ToField,\n};\n\n/// A struct with the discovered information of a complete note, required for delivery to PXE. Note that this is *not*\n/// the complete note information, since it does not include content, storage slot, etc.\npub struct DiscoveredNoteInfo {\n pub note_nonce: Field,\n pub note_hash: Field,\n pub inner_nullifier: Field,\n}\n\n/// Searches for note nonces that will result in a note that was emitted in a transaction. While rare, it is possible\n/// for multiple notes to have the exact same packed content and storage slot but different nonces, resulting in\n/// different unique note hashes. Because of this this function returns a *vector* of discovered notes, though in most\n/// cases it will contain a single element.\n///\n/// Due to how nonces are computed, this function requires knowledge of the transaction in which the note was created,\n/// more specifically the list of all unique note hashes in it plus the value of its first nullifier.\npub unconstrained fn attempt_note_nonce_discovery(\n unique_note_hashes_in_tx: BoundedVec,\n first_nullifier_in_tx: Field,\n compute_note_hash_and_nullifier: ComputeNoteHashAndNullifier,\n contract_address: AztecAddress,\n owner: AztecAddress,\n storage_slot: Field,\n randomness: Field,\n note_type_id: Field,\n packed_note: BoundedVec,\n) -> BoundedVec {\n let discovered_notes = &mut BoundedVec::new();\n\n debug_log_format(\n \"Attempting nonce discovery on {0} potential notes on contract {1} for storage slot {2}\",\n [unique_note_hashes_in_tx.len() as Field, contract_address.to_field(), storage_slot],\n );\n\n // We need to find nonces (typically just one) that result in a note hash that, once siloed into a unique note hash,\n // is one of the note hashes created by the transaction.\n unique_note_hashes_in_tx.for_eachi(|i, expected_unique_note_hash| {\n // Nonces are computed by hashing the first nullifier in the transaction with the index of the note in the\n // new note hashes array. We therefore know for each note in every transaction what its nonce is.\n let candidate_nonce = compute_note_hash_nonce(first_nullifier_in_tx, i);\n\n // Given note nonce, note content and metadata, we can compute the note hash and silo it to check if it matches\n // the note hash at the array index we're currently processing.\n // TODO(#11157): handle failed note_hash_and_nullifier computation\n let hashes = compute_note_hash_and_nullifier(\n packed_note,\n owner,\n storage_slot,\n note_type_id,\n contract_address,\n randomness,\n candidate_nonce,\n )\n .expect(f\"Failed to compute a note hash for note type {note_type_id}\");\n\n let siloed_note_hash = compute_siloed_note_hash(contract_address, hashes.note_hash);\n let unique_note_hash = compute_unique_note_hash(candidate_nonce, siloed_note_hash);\n\n if unique_note_hash == expected_unique_note_hash {\n // Note that while we did check that the note hash is the preimage of the expected unique note hash, we\n // perform no validations on the nullifier - we fundamentally cannot, since only the application knows\n // how to compute nullifiers. We simply trust it to have provided the correct one: if it hasn't, then\n // PXE may fail to realize that a given note has been nullified already, and calls to the application\n // could result in invalid transactions (with duplicate nullifiers). This is not a concern because an\n // application already has more direct means of making a call to it fail the transaction.\n discovered_notes.push(\n DiscoveredNoteInfo {\n note_nonce: candidate_nonce,\n note_hash: hashes.note_hash,\n inner_nullifier: hashes.inner_nullifier,\n },\n );\n\n // We don't exit the loop - it is possible (though rare) for the exact same note content to be present\n // multiple times in the same transaction with different nonces. This typically doesn't happen due to\n // notes containing random values in order to hide their contents.\n }\n });\n\n debug_log_format(\n \"Found valid nonces for a total of {0} notes\",\n [discovered_notes.len() as Field],\n );\n\n *discovered_notes\n}\n\nmod test {\n use crate::{\n messages::discovery::{NoteHashAndNullifier, private_notes::MAX_NOTE_PACKED_LEN},\n note::{\n note_interface::{NoteHash, NoteType},\n note_metadata::SettledNoteMetadata,\n retrieved_note::RetrievedNote,\n utils::compute_note_hash_for_nullification,\n },\n oracle::random::random,\n test::mocks::mock_note::MockNote,\n utils::array,\n };\n\n use dep::protocol_types::{\n address::AztecAddress,\n hash::{compute_note_hash_nonce, compute_siloed_note_hash, compute_unique_note_hash},\n traits::{FromField, Packable},\n };\n\n use super::attempt_note_nonce_discovery;\n\n // This implementation could be simpler, but this serves as a nice example of the expected flow in a real\n // implementation, and as a sanity check that the interface is sufficient.\n unconstrained fn compute_note_hash_and_nullifier(\n packed_note: BoundedVec,\n owner: AztecAddress,\n storage_slot: Field,\n note_type_id: Field,\n contract_address: AztecAddress,\n randomness: Field,\n note_nonce: Field,\n ) -> Option {\n if note_type_id == MockNote::get_id() {\n let note = MockNote::unpack(array::subarray(packed_note.storage(), 0));\n let note_hash = note.compute_note_hash(owner, storage_slot, randomness);\n\n let note_hash_for_nullification = compute_note_hash_for_nullification(\n RetrievedNote {\n note,\n contract_address,\n owner,\n randomness,\n storage_slot,\n metadata: SettledNoteMetadata::new(note_nonce).into(),\n },\n );\n\n let inner_nullifier =\n note.compute_nullifier_unconstrained(owner, note_hash_for_nullification);\n\n Option::some(NoteHashAndNullifier { note_hash, inner_nullifier })\n } else {\n Option::none()\n }\n }\n\n global VALUE: Field = 7;\n global FIRST_NULLIFIER_IN_TX: Field = 47;\n global CONTRACT_ADDRESS: AztecAddress = AztecAddress::from_field(13);\n global OWNER: AztecAddress = AztecAddress::from_field(14);\n global STORAGE_SLOT: Field = 99;\n global RANDOMNESS: Field = 99;\n\n #[test]\n unconstrained fn no_note_hashes() {\n let unique_note_hashes_in_tx = BoundedVec::new();\n let packed_note = BoundedVec::new();\n\n let discovered_notes = attempt_note_nonce_discovery(\n unique_note_hashes_in_tx,\n FIRST_NULLIFIER_IN_TX,\n compute_note_hash_and_nullifier,\n CONTRACT_ADDRESS,\n OWNER,\n STORAGE_SLOT,\n RANDOMNESS,\n MockNote::get_id(),\n packed_note,\n );\n\n assert_eq(discovered_notes.len(), 0);\n }\n\n #[test(should_fail_with = \"Failed to compute a note hash\")]\n unconstrained fn failed_hash_computation() {\n let unique_note_hashes_in_tx = BoundedVec::from_array([random()]);\n let packed_note = BoundedVec::new();\n let note_type_id = 0; // This note type id is unknown to compute_note_hash_and_nullifier\n\n let discovered_notes = attempt_note_nonce_discovery(\n unique_note_hashes_in_tx,\n FIRST_NULLIFIER_IN_TX,\n compute_note_hash_and_nullifier,\n CONTRACT_ADDRESS,\n OWNER,\n STORAGE_SLOT,\n RANDOMNESS,\n note_type_id,\n packed_note,\n );\n\n assert_eq(discovered_notes.len(), 0);\n }\n\n struct NoteAndData {\n note: MockNote,\n note_nonce: Field,\n note_hash: Field,\n unique_note_hash: Field,\n inner_nullifier: Field,\n }\n\n unconstrained fn construct_note(value: Field, note_index_in_tx: u32) -> NoteAndData {\n let note_nonce = compute_note_hash_nonce(FIRST_NULLIFIER_IN_TX, note_index_in_tx);\n\n let retrieved_note = MockNote::new(value)\n .contract_address(CONTRACT_ADDRESS)\n .owner(OWNER)\n .randomness(RANDOMNESS)\n .storage_slot(STORAGE_SLOT)\n .note_metadata(SettledNoteMetadata::new(note_nonce).into())\n .build_retrieved_note();\n let note = retrieved_note.note;\n\n let note_hash = note.compute_note_hash(OWNER, STORAGE_SLOT, RANDOMNESS);\n let unique_note_hash = compute_unique_note_hash(\n note_nonce,\n compute_siloed_note_hash(CONTRACT_ADDRESS, note_hash),\n );\n let inner_nullifier = note.compute_nullifier_unconstrained(\n OWNER,\n compute_note_hash_for_nullification(retrieved_note),\n );\n\n NoteAndData { note, note_nonce, note_hash, unique_note_hash, inner_nullifier }\n }\n\n #[test]\n unconstrained fn single_note() {\n let note_index_in_tx = 2;\n let note_and_data = construct_note(VALUE, note_index_in_tx);\n\n let mut unique_note_hashes_in_tx = BoundedVec::from_array([\n random(), random(), random(), random(), random(), random(), random(),\n ]);\n unique_note_hashes_in_tx.set(note_index_in_tx, note_and_data.unique_note_hash);\n\n let discovered_notes = attempt_note_nonce_discovery(\n unique_note_hashes_in_tx,\n FIRST_NULLIFIER_IN_TX,\n compute_note_hash_and_nullifier,\n CONTRACT_ADDRESS,\n OWNER,\n STORAGE_SLOT,\n RANDOMNESS,\n MockNote::get_id(),\n BoundedVec::from_array(note_and_data.note.pack()),\n );\n\n assert_eq(discovered_notes.len(), 1);\n let discovered_note = discovered_notes.get(0);\n\n assert_eq(discovered_note.note_nonce, note_and_data.note_nonce);\n assert_eq(discovered_note.note_hash, note_and_data.note_hash);\n assert_eq(discovered_note.inner_nullifier, note_and_data.inner_nullifier);\n }\n\n #[test]\n unconstrained fn multiple_notes_same_preimage() {\n let first_note_index_in_tx = 3;\n let first_note_and_data = construct_note(VALUE, first_note_index_in_tx);\n\n let second_note_index_in_tx = 5;\n let second_note_and_data = construct_note(VALUE, second_note_index_in_tx);\n\n // Both notes have the same preimage (and therefore packed representation), so both should be found in the same\n // call.\n assert_eq(first_note_and_data.note, second_note_and_data.note);\n let packed_note = first_note_and_data.note.pack();\n\n let mut unique_note_hashes_in_tx = BoundedVec::from_array([\n random(), random(), random(), random(), random(), random(), random(),\n ]);\n unique_note_hashes_in_tx.set(first_note_index_in_tx, first_note_and_data.unique_note_hash);\n unique_note_hashes_in_tx.set(second_note_index_in_tx, second_note_and_data.unique_note_hash);\n\n let discovered_notes = attempt_note_nonce_discovery(\n unique_note_hashes_in_tx,\n FIRST_NULLIFIER_IN_TX,\n compute_note_hash_and_nullifier,\n CONTRACT_ADDRESS,\n OWNER,\n STORAGE_SLOT,\n RANDOMNESS,\n MockNote::get_id(),\n BoundedVec::from_array(packed_note),\n );\n\n assert_eq(discovered_notes.len(), 2);\n\n assert(discovered_notes.any(|discovered_note| {\n (discovered_note.note_nonce == first_note_and_data.note_nonce)\n & (discovered_note.note_hash == first_note_and_data.note_hash)\n & (discovered_note.inner_nullifier == first_note_and_data.inner_nullifier)\n }));\n\n assert(discovered_notes.any(|discovered_note| {\n (discovered_note.note_nonce == second_note_and_data.note_nonce)\n & (discovered_note.note_hash == second_note_and_data.note_hash)\n & (discovered_note.inner_nullifier == second_note_and_data.inner_nullifier)\n }));\n }\n}\n" + }, + "128": { + "path": "/home/ubuntu/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.20251212/noir-projects/aztec-nr/aztec/src/messages/discovery/partial_notes.nr", + "source": "use crate::{\n capsules::CapsuleArray,\n messages::{\n discovery::{ComputeNoteHashAndNullifier, nonce_discovery::attempt_note_nonce_discovery},\n encoding::MAX_MESSAGE_CONTENT_LEN,\n processing::{\n enqueue_note_for_validation, get_pending_partial_notes_completion_logs,\n log_retrieval_response::LogRetrievalResponse,\n },\n },\n utils::array,\n};\n\nuse protocol_types::{\n address::AztecAddress,\n debug_log::debug_log_format,\n hash::sha256_to_field,\n traits::{Deserialize, FromField, Serialize},\n};\n\n/// [ owner, storage slot, randomness, note_completion_log_tag ]\nglobal PARTIAL_NOTE_PRIVATE_MSG_CONTENT_NON_NOTE_FIELDS_LEN: u32 = 4;\nglobal PARTIAL_NOTE_PRIVATE_MSG_CONTENT_OWNER_INDEX: u32 = 0;\nglobal PARTIAL_NOTE_PRIVATE_MSG_CONTENT_STORAGE_SLOT_INDEX: u32 = 1;\nglobal PARTIAL_NOTE_PRIVATE_MSG_CONTENT_RANDOMNESS_INDEX: u32 = 2;\nglobal PARTIAL_NOTE_PRIVATE_MSG_CONTENT_NOTE_COMPLETION_LOG_TAG_INDEX: u32 = 3;\n\n/// Partial notes have a maximum packed length of their private fields bound by extra content in their private message\n/// (e.g. the storage slot, note completion log tag, etc.).\npub global MAX_PARTIAL_NOTE_PRIVATE_PACKED_LEN: u32 =\n MAX_MESSAGE_CONTENT_LEN - PARTIAL_NOTE_PRIVATE_MSG_CONTENT_NON_NOTE_FIELDS_LEN;\n\n/// The slot in the PXE capsules where we store a `CapsuleArray` of `DeliveredPendingPartialNote`.\npub global DELIVERED_PENDING_PARTIAL_NOTE_ARRAY_LENGTH_CAPSULES_SLOT: Field = sha256_to_field(\n \"AZTEC_NR::DELIVERED_PENDING_PARTIAL_NOTE_ARRAY_LENGTH_CAPSULES_SLOT\".as_bytes(),\n);\n\n/// A partial note that was delivered but is still pending completion. Contains the information necessary to find the\n/// log that will complete it and lead to a note being discovered and delivered.\n#[derive(Serialize, Deserialize)]\npub(crate) struct DeliveredPendingPartialNote {\n pub(crate) note_completion_log_tag: Field,\n pub(crate) owner: AztecAddress,\n pub(crate) storage_slot: Field,\n pub(crate) randomness: Field,\n pub(crate) note_type_id: Field,\n pub(crate) packed_private_note_content: BoundedVec,\n pub(crate) recipient: AztecAddress,\n}\n\npub unconstrained fn process_partial_note_private_msg(\n contract_address: AztecAddress,\n recipient: AztecAddress,\n msg_metadata: u64,\n msg_content: BoundedVec,\n) {\n // We store the information of the partial note we found in a persistent capsule in PXE, so that we can later search\n // for the public log that will complete it.\n let pending = decode_partial_note_private_msg(msg_metadata, msg_content, recipient);\n\n CapsuleArray::at(\n contract_address,\n DELIVERED_PENDING_PARTIAL_NOTE_ARRAY_LENGTH_CAPSULES_SLOT,\n )\n .push(pending);\n}\n\n/// Searches for logs that would result in the completion of pending partial notes, ultimately resulting in the notes\n/// being delivered to PXE if completed.\npub unconstrained fn fetch_and_process_partial_note_completion_logs(\n contract_address: AztecAddress,\n compute_note_hash_and_nullifier: ComputeNoteHashAndNullifier,\n) {\n let pending_partial_notes = CapsuleArray::at(\n contract_address,\n DELIVERED_PENDING_PARTIAL_NOTE_ARRAY_LENGTH_CAPSULES_SLOT,\n );\n\n debug_log_format(\n \"{} pending partial notes\",\n [pending_partial_notes.len() as Field],\n );\n\n // Each of the pending partial notes might get completed by a log containing its public values. For performance\n // reasons, we fetch all of these logs concurrently and then process them one by one, minimizing the amount of time\n // waiting for the node roundtrip.\n let maybe_completion_logs =\n get_pending_partial_notes_completion_logs(contract_address, pending_partial_notes);\n\n // Each entry in the maybe completion logs array corresponds to the entry in the pending partial notes array at the\n // same index. This means we can use the same index as we iterate through the responses to get both the partial note\n // and the log that might complete it.\n assert_eq(maybe_completion_logs.len(), pending_partial_notes.len());\n\n maybe_completion_logs.for_each(|i, maybe_log: Option| {\n // We clear the completion logs as we read them so that the array is empty by the time we next query it.\n // TODO(#14943): use volatile arrays to avoid having to manually clear this.\n maybe_completion_logs.remove(i);\n\n let pending_partial_note = pending_partial_notes.get(i);\n\n if maybe_log.is_none() {\n debug_log_format(\n \"Found no completion logs for partial note with tag {}\",\n [pending_partial_note.note_completion_log_tag],\n );\n\n // Note that we're not removing the pending partial note from the capsule array, so we will continue\n // searching for this tagged log when performing message discovery in the future until we either find it or\n // the entry is somehow removed from the array.\n } else {\n debug_log_format(\n \"Completion log found for partial note with tag {}\",\n [pending_partial_note.note_completion_log_tag],\n );\n let log = maybe_log.unwrap();\n\n // Public fields are assumed to all be placed at the end of the packed representation, so we combine the\n // private and public packed fields (i.e. the contents of the private message and public log plaintext to get\n // the complete packed content.\n let complete_packed_note = array::append(\n pending_partial_note.packed_private_note_content,\n log.log_payload,\n );\n\n let discovered_notes = attempt_note_nonce_discovery(\n log.unique_note_hashes_in_tx,\n log.first_nullifier_in_tx,\n compute_note_hash_and_nullifier,\n contract_address,\n pending_partial_note.owner,\n pending_partial_note.storage_slot,\n pending_partial_note.randomness,\n pending_partial_note.note_type_id,\n complete_packed_note,\n );\n\n // TODO(#11627): is there anything reasonable we can do if we get a log but it doesn't result in a note\n // being found?\n if discovered_notes.len() == 0 {\n panic(\n f\"A partial note's completion log did not result in any notes being found - this should never happen\",\n );\n }\n\n debug_log_format(\n \"Discovered {0} notes for partial note with tag {1}\",\n [discovered_notes.len() as Field, pending_partial_note.note_completion_log_tag],\n );\n\n discovered_notes.for_each(|discovered_note| {\n enqueue_note_for_validation(\n contract_address,\n pending_partial_note.owner,\n pending_partial_note.storage_slot,\n pending_partial_note.randomness,\n discovered_note.note_nonce,\n complete_packed_note,\n discovered_note.note_hash,\n discovered_note.inner_nullifier,\n log.tx_hash,\n pending_partial_note.recipient,\n );\n });\n\n // Because there is only a single log for a given tag, once we've processed the tagged log then we\n // simply delete the pending work entry, regardless of whether it was actually completed or not.\n pending_partial_notes.remove(i);\n }\n });\n}\n\nfn decode_partial_note_private_msg(\n msg_metadata: u64,\n msg_content: BoundedVec,\n recipient: AztecAddress,\n) -> DeliveredPendingPartialNote {\n let note_type_id = msg_metadata as Field; // TODO: make note type id not be a full field\n\n // The following ensures that the message content contains at least the minimum number of fields required for a\n // valid partial note private message. (Refer to the description of\n // PARTIAL_NOTE_PRIVATE_MSG_CONTENT_NON_NOTE_FIELDS_LEN for more information about these fields.)\n assert(\n msg_content.len() >= PARTIAL_NOTE_PRIVATE_MSG_CONTENT_NON_NOTE_FIELDS_LEN,\n f\"Invalid private note message: all partial note private messages must have at least {PARTIAL_NOTE_PRIVATE_MSG_CONTENT_NON_NOTE_FIELDS_LEN} fields\",\n );\n\n // If PARTIAL_NOTE_PRIVATE_MSG_CONTENT_NON_NOTE_FIELDS_LEN is changed, causing the assertion below to fail, then the\n // destructuring of the partial note private message encoding below must be updated as well.\n std::static_assert(\n PARTIAL_NOTE_PRIVATE_MSG_CONTENT_NON_NOTE_FIELDS_LEN == 4,\n \"unexpected value for PARTIAL_NOTE_PRIVATE_MSG_CONTENT_NON_NOTE_FIELDS_LEN\",\n );\n\n // We currently have four fields that are not the partial note's packed representation,\n // which are the owner, the storage slot, the randomness, and the note completion log tag.\n let owner = AztecAddress::from_field(msg_content.get(\n PARTIAL_NOTE_PRIVATE_MSG_CONTENT_OWNER_INDEX,\n ));\n let storage_slot = msg_content.get(PARTIAL_NOTE_PRIVATE_MSG_CONTENT_STORAGE_SLOT_INDEX);\n let randomness = msg_content.get(PARTIAL_NOTE_PRIVATE_MSG_CONTENT_RANDOMNESS_INDEX);\n let note_completion_log_tag =\n msg_content.get(PARTIAL_NOTE_PRIVATE_MSG_CONTENT_NOTE_COMPLETION_LOG_TAG_INDEX);\n\n let packed_private_note_content: BoundedVec = array::subbvec(\n msg_content,\n PARTIAL_NOTE_PRIVATE_MSG_CONTENT_NON_NOTE_FIELDS_LEN,\n );\n\n DeliveredPendingPartialNote {\n note_completion_log_tag,\n owner,\n storage_slot,\n randomness,\n note_type_id,\n packed_private_note_content,\n recipient,\n }\n}\n" + }, + "129": { + "path": "/home/ubuntu/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.20251212/noir-projects/aztec-nr/aztec/src/messages/discovery/private_events.nr", + "source": "use crate::{\n event::event_selector::EventSelector,\n messages::{encoding::MAX_MESSAGE_CONTENT_LEN, processing::enqueue_event_for_validation},\n utils::array,\n};\nuse protocol_types::{\n address::AztecAddress, constants::GENERATOR_INDEX__EVENT_COMMITMENT,\n hash::poseidon2_hash_with_separator_bounded_vec, traits::FromField,\n};\n\n/// The number of fields in a private event message content that are not the event's serialized representation\n/// (1 field for randomness).\nglobal PRIVATE_EVENT_MSG_CONTENT_NON_EVENT_FIELDS_LEN: u32 = 1;\n\n/// The maximum length of the packed representation of an event's contents. This is limited by private log size,\n/// encryption overhead and extra fields in the message (e.g. message type id, randomness, etc.).\npub global MAX_EVENT_SERIALIZED_LEN: u32 =\n MAX_MESSAGE_CONTENT_LEN - PRIVATE_EVENT_MSG_CONTENT_NON_EVENT_FIELDS_LEN;\n\npub unconstrained fn process_private_event_msg(\n contract_address: AztecAddress,\n recipient: AztecAddress,\n msg_metadata: u64,\n msg_content: BoundedVec,\n tx_hash: Field,\n) {\n // In the case of events, the msg metadata is the event selector.\n let event_type_id = EventSelector::from_field(msg_metadata as Field);\n\n assert(\n msg_content.len() > PRIVATE_EVENT_MSG_CONTENT_NON_EVENT_FIELDS_LEN,\n f\"Invalid private event message: all private event messages must have at least {PRIVATE_EVENT_MSG_CONTENT_NON_EVENT_FIELDS_LEN} fields\",\n );\n\n // If PRIVATE_EVENT_MSG_CONTENT_NON_EVENT_FIELDS_LEN is changed, causing the assertion below to fail, then the\n // destructuring of the private event message encoding below must be updated as well.\n std::static_assert(\n PRIVATE_EVENT_MSG_CONTENT_NON_EVENT_FIELDS_LEN == 1,\n \"unexpected value for PRIVATE_EVENT_MSG_CONTENT_NON_EVENT_FIELDS_LEN\",\n );\n\n let serialized_event_with_randomness = msg_content;\n\n let event_commitment = poseidon2_hash_with_separator_bounded_vec(\n serialized_event_with_randomness,\n GENERATOR_INDEX__EVENT_COMMITMENT,\n );\n\n // Randomness was injected into the event payload in `emit_event_in_private` but we have already used it\n // to compute the event commitment, so we can safely discard it now.\n let serialized_event = array::subbvec(\n serialized_event_with_randomness,\n PRIVATE_EVENT_MSG_CONTENT_NON_EVENT_FIELDS_LEN,\n );\n\n enqueue_event_for_validation(\n contract_address,\n event_type_id,\n serialized_event,\n event_commitment,\n tx_hash,\n recipient,\n );\n}\n" + }, + "130": { + "path": "/home/ubuntu/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.20251212/noir-projects/aztec-nr/aztec/src/messages/discovery/private_notes.nr", + "source": "use crate::{\n messages::{\n discovery::{ComputeNoteHashAndNullifier, nonce_discovery::attempt_note_nonce_discovery},\n encoding::MAX_MESSAGE_CONTENT_LEN,\n processing::enqueue_note_for_validation,\n },\n utils::array,\n};\nuse protocol_types::{\n address::AztecAddress, constants::MAX_NOTE_HASHES_PER_TX, debug_log::debug_log_format,\n traits::FromField,\n};\n\n/// The number of fields in a private note message content that are not the note's packed representation.\n// See the call to `std::static_assert` below to see what's in these fields.\nglobal PRIVATE_NOTE_MSG_CONTENT_NON_NOTE_FIELDS_LEN: u32 = 3;\nglobal PRIVATE_NOTE_MSG_CONTENT_OWNER_INDEX: u32 = 0;\nglobal PRIVATE_NOTE_MSG_CONTENT_STORAGE_SLOT_INDEX: u32 = 1;\nglobal PRIVATE_NOTE_MSG_CONTENT_RANDOMNESS_INDEX: u32 = 2;\n\n/// The maximum length of the packed representation of a note's contents. This is limited by private log size,\n/// encryption overhead and extra fields in the message (e.g. message type id, storage slot, randomness, etc.).\npub global MAX_NOTE_PACKED_LEN: u32 =\n MAX_MESSAGE_CONTENT_LEN - PRIVATE_NOTE_MSG_CONTENT_NON_NOTE_FIELDS_LEN;\n\npub unconstrained fn process_private_note_msg(\n contract_address: AztecAddress,\n tx_hash: Field,\n unique_note_hashes_in_tx: BoundedVec,\n first_nullifier_in_tx: Field,\n recipient: AztecAddress,\n compute_note_hash_and_nullifier: ComputeNoteHashAndNullifier,\n msg_metadata: u64,\n msg_content: BoundedVec,\n) {\n let (note_type_id, owner, storage_slot, randomness, packed_note) =\n decode_private_note_msg(msg_metadata, msg_content);\n\n attempt_note_discovery(\n contract_address,\n tx_hash,\n unique_note_hashes_in_tx,\n first_nullifier_in_tx,\n recipient,\n compute_note_hash_and_nullifier,\n owner,\n storage_slot,\n randomness,\n note_type_id,\n packed_note,\n );\n}\n\n/// Attempts discovery of a note given information about its contents and the transaction in which it is\n/// suspected the note was created.\npub unconstrained fn attempt_note_discovery(\n contract_address: AztecAddress,\n tx_hash: Field,\n unique_note_hashes_in_tx: BoundedVec,\n first_nullifier_in_tx: Field,\n recipient: AztecAddress,\n compute_note_hash_and_nullifier: ComputeNoteHashAndNullifier,\n owner: AztecAddress,\n storage_slot: Field,\n randomness: Field,\n note_type_id: Field,\n packed_note: BoundedVec,\n) {\n let discovered_notes = attempt_note_nonce_discovery(\n unique_note_hashes_in_tx,\n first_nullifier_in_tx,\n compute_note_hash_and_nullifier,\n contract_address,\n owner,\n storage_slot,\n randomness,\n note_type_id,\n packed_note,\n );\n\n debug_log_format(\n \"Discovered {0} notes from a private message\",\n [discovered_notes.len() as Field],\n );\n\n discovered_notes.for_each(|discovered_note| {\n enqueue_note_for_validation(\n contract_address,\n owner,\n storage_slot,\n randomness,\n discovered_note.note_nonce,\n packed_note,\n discovered_note.note_hash,\n discovered_note.inner_nullifier,\n tx_hash,\n recipient,\n );\n });\n}\n\nfn decode_private_note_msg(\n msg_metadata: u64,\n msg_content: BoundedVec,\n) -> (Field, AztecAddress, Field, Field, BoundedVec) {\n let note_type_id = msg_metadata as Field; // TODO: make note type id not be a full field\n\n assert(\n msg_content.len() > PRIVATE_NOTE_MSG_CONTENT_NON_NOTE_FIELDS_LEN,\n f\"Invalid private note message: all private note messages must have at least {PRIVATE_NOTE_MSG_CONTENT_NON_NOTE_FIELDS_LEN} fields\",\n );\n\n // If PRIVATE_NOTE_MSG_CONTENT_NON_NOTE_FIELDS_LEN is changed, causing the assertion below to fail, then the\n // destructuring of the private note message encoding below must be updated as well.\n std::static_assert(\n PRIVATE_NOTE_MSG_CONTENT_NON_NOTE_FIELDS_LEN == 3,\n \"unexpected value for PRIVATE_NOTE_MSG_CONTENT_NON_NOTE_FIELDS_LEN\",\n );\n\n // We currently have two fields that are not the note's packed representation, which are the owner and the storage slot.\n let owner = AztecAddress::from_field(msg_content.get(PRIVATE_NOTE_MSG_CONTENT_OWNER_INDEX));\n let storage_slot = msg_content.get(PRIVATE_NOTE_MSG_CONTENT_STORAGE_SLOT_INDEX);\n let randomness = msg_content.get(PRIVATE_NOTE_MSG_CONTENT_RANDOMNESS_INDEX);\n let packed_note = array::subbvec(msg_content, PRIVATE_NOTE_MSG_CONTENT_NON_NOTE_FIELDS_LEN);\n\n (note_type_id, owner, storage_slot, randomness, packed_note)\n}\n" + }, + "131": { + "path": "/home/ubuntu/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.20251212/noir-projects/aztec-nr/aztec/src/messages/discovery/process_message.nr", + "source": "use crate::messages::{\n discovery::{\n ComputeNoteHashAndNullifier, partial_notes::process_partial_note_private_msg,\n private_events::process_private_event_msg, private_notes::process_private_note_msg,\n },\n encoding::{decode_message, MESSAGE_CIPHERTEXT_LEN, MESSAGE_PLAINTEXT_LEN},\n encryption::{aes128::AES128, message_encryption::MessageEncryption},\n msg_type::{\n PARTIAL_NOTE_PRIVATE_MSG_TYPE_ID, PRIVATE_EVENT_MSG_TYPE_ID, PRIVATE_NOTE_MSG_TYPE_ID,\n },\n processing::message_context::MessageContext,\n};\n\nuse protocol_types::{address::AztecAddress, debug_log::{debug_log, debug_log_format}};\n\n/// Processes a message that can contain notes, partial notes, or events.\n///\n/// Notes result in nonce discovery being performed prior to delivery, which requires knowledge of the transaction hash\n/// in which the notes would've been created (typically the same transaction in which the log was emitted), along with\n/// the list of unique note hashes in said transaction and the `compute_note_hash_and_nullifier` function. Once\n/// discovered, the notes are enqueued for validation.\n///\n/// Partial notes result in a pending partial note entry being stored in a PXE capsule, which will later be retrieved to\n/// search for the note's completion public log.\n///\n/// Events are processed by computing an event commitment from the serialized event data and its randomness field, then\n/// enqueueing the event data and commitment for validation.\npub unconstrained fn process_message_ciphertext(\n contract_address: AztecAddress,\n compute_note_hash_and_nullifier: ComputeNoteHashAndNullifier,\n message_ciphertext: BoundedVec,\n message_context: MessageContext,\n) {\n let message_plaintext_option = AES128::decrypt(message_ciphertext, message_context.recipient);\n\n if message_plaintext_option.is_some() {\n process_message_plaintext(\n contract_address,\n compute_note_hash_and_nullifier,\n message_plaintext_option.unwrap(),\n message_context,\n );\n } else {\n debug_log_format(\n \"Found invalid message from tx {0}, ignoring\",\n [message_context.tx_hash],\n );\n }\n}\n\npub unconstrained fn process_message_plaintext(\n contract_address: AztecAddress,\n compute_note_hash_and_nullifier: ComputeNoteHashAndNullifier,\n message_plaintext: BoundedVec,\n message_context: MessageContext,\n) {\n // The first thing to do after decrypting the message is to determine what type of message we're processing. We\n // have 3 message types: private notes, partial notes and events.\n\n // We decode the message to obtain the message type id, metadata and content.\n let (msg_type_id, msg_metadata, msg_content) = decode_message(message_plaintext);\n\n if msg_type_id == PRIVATE_NOTE_MSG_TYPE_ID {\n debug_log(\"Processing private note msg\");\n\n process_private_note_msg(\n contract_address,\n message_context.tx_hash,\n message_context.unique_note_hashes_in_tx,\n message_context.first_nullifier_in_tx,\n message_context.recipient,\n compute_note_hash_and_nullifier,\n msg_metadata,\n msg_content,\n );\n } else if msg_type_id == PARTIAL_NOTE_PRIVATE_MSG_TYPE_ID {\n debug_log(\"Processing partial note private msg\");\n\n process_partial_note_private_msg(\n contract_address,\n message_context.recipient,\n msg_metadata,\n msg_content,\n );\n } else if msg_type_id == PRIVATE_EVENT_MSG_TYPE_ID {\n debug_log(\"Processing private event msg\");\n\n process_private_event_msg(\n contract_address,\n message_context.recipient,\n msg_metadata,\n msg_content,\n message_context.tx_hash,\n );\n } else {\n debug_log_format(\"Unknown msg type id {0}\", [msg_type_id as Field]);\n }\n}\n" + }, + "132": { + "path": "/home/ubuntu/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.20251212/noir-projects/aztec-nr/aztec/src/messages/encoding.nr", + "source": "// TODO(#12750): don't make these values assume we're using AES.\nuse crate::utils::array;\nuse protocol_types::constants::PRIVATE_LOG_CIPHERTEXT_LEN;\n\n// We reassign to the constant here to communicate the distinction between a log and a message. In Aztec.nr, unlike in\n// protocol circuits, we have a concept of a message that can be emitted either as a private log or as an offchain\n// message. Message is a piece of data that is to be eventually delivered to a contract via the `process_message(...)`\n// utility function function that is injected by the #[aztec] macro.\n// Note: PRIVATE_LOG_CIPHERTEXT_LEN is an amount of fields,\n// so MESSAGE_CIPHERTEXT_LEN is the size of the message in fields.\npub global MESSAGE_CIPHERTEXT_LEN: u32 = PRIVATE_LOG_CIPHERTEXT_LEN;\n\n// TODO(#12750): The global variables below should not be here as they are AES128 specific.\n// ciphertext_length (2) + 14 bytes pkcs#7 AES padding.\npub(crate) global HEADER_CIPHERTEXT_SIZE_IN_BYTES: u32 = 16;\n\npub global EPH_PK_X_SIZE_IN_FIELDS: u32 = 1;\npub global EPH_PK_SIGN_BYTE_SIZE_IN_BYTES: u32 = 1;\n\n// (17 - 1) * 31 - 16 - 1 = 479\n// Note: We multiply by 31 because ciphertext bytes are stored in fields using bytes_to_fields, which packs 31 bytes per\n// field (since a Field is ~254 bits and can safely store 31 whole bytes).\nglobal MESSAGE_PLAINTEXT_SIZE_IN_BYTES: u32 = (MESSAGE_CIPHERTEXT_LEN - EPH_PK_X_SIZE_IN_FIELDS)\n * 31\n - HEADER_CIPHERTEXT_SIZE_IN_BYTES\n - EPH_PK_SIGN_BYTE_SIZE_IN_BYTES;\n// The plaintext bytes represent Field values that were originally serialized using fields_to_bytes, which converts each\n// Field to 32 bytes. To convert the plaintext bytes back to fields, we divide by 32.\n// 479 / 32 = 14\npub global MESSAGE_PLAINTEXT_LEN: u32 = MESSAGE_PLAINTEXT_SIZE_IN_BYTES / 32;\n\npub global MESSAGE_EXPANDED_METADATA_LEN: u32 = 1;\n\n// The standard message layout is composed of:\n// - an initial field called the 'expanded metadata'\n// - an arbitrary number of fields following that called the 'message content'\n//\n// ```\n// message: [ msg_expanded_metadata, ...msg_content ]\n// ```\n//\n// The expanded metadata itself is interpreted as a u128, of which:\n// - the upper 64 bits are the message type id\n// - the lower 64 bits are called the 'message metadata'\n//\n// ```\n// msg_expanded_metadata: [ msg_type_id | msg_metadata ]\n// <--- 64 bits --->|<--- 64 bits --->\n// ```\n//\n// The meaning of the message metadata and message content depend on the value of the message type id. Note that there\n// is nothing special about the message metadata, it _can_ be considered part of the content. It just has a different\n// name to make it distinct from the message content given that it is not a full field.\n\n/// The maximum length of a message's content, i.e. not including the expanded message metadata.\npub global MAX_MESSAGE_CONTENT_LEN: u32 = MESSAGE_PLAINTEXT_LEN - MESSAGE_EXPANDED_METADATA_LEN;\n\n/// Encodes a message following aztec-nr's standard message encoding. This message can later be decoded with\n/// `decode_message` to retrieve the original values.\n///\n/// - The `msg_type` is an identifier that groups types of messages that are all processed the same way, e.g. private\n/// notes or events. Possible values are defined in `aztec::messages::msg_type`.\n/// - The `msg_metadata` and `msg_content` are the values stored in the message, whose meaning depends on the\n/// `msg_type`. The only special thing about `msg_metadata` that separates it from `msg_content` is that it is a u64\n/// instead of a full Field (due to details of how messages are encoded), allowing applications that can fit values into\n/// this smaller variable to achieve higher data efficiency.\npub fn encode_message(\n msg_type: u64,\n msg_metadata: u64,\n msg_content: [Field; N],\n) -> [Field; (N + MESSAGE_EXPANDED_METADATA_LEN)] {\n std::static_assert(\n msg_content.len() <= MAX_MESSAGE_CONTENT_LEN,\n \"Invalid message content: it must have a length of at most MAX_MESSAGE_CONTENT_LEN\",\n );\n\n // If MESSAGE_EXPANDED_METADATA_LEN is changed, causing the assertion below to fail, then the destructuring of\n // the message encoding below must be updated as well.\n std::static_assert(\n MESSAGE_EXPANDED_METADATA_LEN == 1,\n \"unexpected value for MESSAGE_EXPANDED_METADATA_LEN\",\n );\n let mut message: [Field; (N + MESSAGE_EXPANDED_METADATA_LEN)] = std::mem::zeroed();\n\n message[0] = to_expanded_metadata(msg_type, msg_metadata);\n for i in 0..msg_content.len() {\n message[MESSAGE_EXPANDED_METADATA_LEN + i] = msg_content[i];\n }\n\n message\n}\n\n/// Decodes a standard aztec-nr message, i.e. one created via `encode_message`, returning the original encoded values.\n///\n/// Note that `encode_message` returns a fixed size array while this function takes a `BoundedVec`: this is because\n/// prior to decoding the message type is unknown, and consequentially not known at compile time. If working with\n/// fixed-size messages, consider using `BoundedVec::from_array` to convert them.\npub unconstrained fn decode_message(\n message: BoundedVec,\n) -> (u64, u64, BoundedVec) {\n assert(\n message.len() >= MESSAGE_EXPANDED_METADATA_LEN,\n f\"Invalid message: it must have at least {MESSAGE_EXPANDED_METADATA_LEN} fields\",\n );\n\n // If MESSAGE_EXPANDED_METADATA_LEN is changed, causing the assertion below to fail, then the destructuring of\n // the message encoding below must be updated as well.\n std::static_assert(\n MESSAGE_EXPANDED_METADATA_LEN == 1,\n \"unexpected value for MESSAGE_EXPANDED_METADATA_LEN\",\n );\n\n let msg_expanded_metadata = message.get(0);\n let (msg_type_id, msg_metadata) = from_expanded_metadata(msg_expanded_metadata);\n let msg_content = array::subbvec(message, MESSAGE_EXPANDED_METADATA_LEN);\n\n (msg_type_id, msg_metadata, msg_content)\n}\n\nglobal U64_SHIFT_MULTIPLIER: Field = 2.pow_32(64);\n\nfn to_expanded_metadata(msg_type: u64, msg_metadata: u64) -> Field {\n // We use multiplication instead of bit shifting operations to shift the type bits as bit shift operations are\n // expensive in circuits.\n let type_field: Field = (msg_type as Field) * U64_SHIFT_MULTIPLIER;\n let msg_metadata_field = msg_metadata as Field;\n\n type_field + msg_metadata_field\n}\n\nfn from_expanded_metadata(input: Field) -> (u64, u64) {\n input.assert_max_bit_size::<128>();\n let msg_metadata = (input as u64);\n let msg_type = ((input - (msg_metadata as Field)) / U64_SHIFT_MULTIPLIER) as u64;\n // Use division instead of bit shift since bit shifts are expensive in circuits\n (msg_type, msg_metadata)\n}\n\nmod tests {\n use crate::utils::array::subarray::subarray;\n use super::{\n decode_message, encode_message, from_expanded_metadata, MAX_MESSAGE_CONTENT_LEN,\n to_expanded_metadata,\n };\n\n global U64_MAX: u64 = (2.pow_32(64) - 1) as u64;\n global U128_MAX: Field = (2.pow_32(128) - 1);\n\n #[test]\n unconstrained fn encode_decode_empty_message(msg_type: u64, msg_metadata: u64) {\n let encoded = encode_message(msg_type, msg_metadata, []);\n let (decoded_msg_type, decoded_msg_metadata, decoded_msg_content) =\n decode_message(BoundedVec::from_array(encoded));\n\n assert_eq(decoded_msg_type, msg_type);\n assert_eq(decoded_msg_metadata, msg_metadata);\n assert_eq(decoded_msg_content.len(), 0);\n }\n\n #[test]\n unconstrained fn encode_decode_short_message(\n msg_type: u64,\n msg_metadata: u64,\n msg_content: [Field; MAX_MESSAGE_CONTENT_LEN / 2],\n ) {\n let encoded = encode_message(msg_type, msg_metadata, msg_content);\n let (decoded_msg_type, decoded_msg_metadata, decoded_msg_content) =\n decode_message(BoundedVec::from_array(encoded));\n\n assert_eq(decoded_msg_type, msg_type);\n assert_eq(decoded_msg_metadata, msg_metadata);\n assert_eq(decoded_msg_content.len(), msg_content.len());\n assert_eq(subarray(decoded_msg_content.storage(), 0), msg_content);\n }\n\n #[test]\n unconstrained fn encode_decode_full_message(\n msg_type: u64,\n msg_metadata: u64,\n msg_content: [Field; MAX_MESSAGE_CONTENT_LEN],\n ) {\n let encoded = encode_message(msg_type, msg_metadata, msg_content);\n let (decoded_msg_type, decoded_msg_metadata, decoded_msg_content) =\n decode_message(BoundedVec::from_array(encoded));\n\n assert_eq(decoded_msg_type, msg_type);\n assert_eq(decoded_msg_metadata, msg_metadata);\n assert_eq(decoded_msg_content.len(), msg_content.len());\n assert_eq(subarray(decoded_msg_content.storage(), 0), msg_content);\n }\n\n #[test]\n unconstrained fn to_expanded_metadata_packing() {\n // Test case 1: All bits set\n let packed = to_expanded_metadata(U64_MAX, U64_MAX);\n let (msg_type, msg_metadata) = from_expanded_metadata(packed);\n assert_eq(msg_type, U64_MAX);\n assert_eq(msg_metadata, U64_MAX);\n\n // Test case 2: Only log type bits set\n let packed = to_expanded_metadata(U64_MAX, 0);\n let (msg_type, msg_metadata) = from_expanded_metadata(packed);\n assert_eq(msg_type, U64_MAX);\n assert_eq(msg_metadata, 0);\n\n // Test case 3: Only msg_metadata bits set\n let packed = to_expanded_metadata(0, U64_MAX);\n let (msg_type, msg_metadata) = from_expanded_metadata(packed);\n assert_eq(msg_type, 0);\n assert_eq(msg_metadata, U64_MAX);\n\n // Test case 4: No bits set\n let packed = to_expanded_metadata(0, 0);\n let (msg_type, msg_metadata) = from_expanded_metadata(packed);\n assert_eq(msg_type, 0);\n assert_eq(msg_metadata, 0);\n }\n\n #[test]\n unconstrained fn from_expanded_metadata_packing() {\n // Test case 1: All bits set\n let input = U128_MAX as Field;\n let (msg_type, msg_metadata) = from_expanded_metadata(input);\n assert_eq(msg_type, U64_MAX);\n assert_eq(msg_metadata, U64_MAX);\n\n // Test case 2: Only log type bits set\n let input = (U128_MAX - U64_MAX as Field);\n let (msg_type, msg_metadata) = from_expanded_metadata(input);\n assert_eq(msg_type, U64_MAX);\n assert_eq(msg_metadata, 0);\n\n // Test case 3: Only msg_metadata bits set\n let input = U64_MAX as Field;\n let (msg_type, msg_metadata) = from_expanded_metadata(input);\n assert_eq(msg_type, 0);\n assert_eq(msg_metadata, U64_MAX);\n\n // Test case 4: No bits set\n let input = 0;\n let (msg_type, msg_metadata) = from_expanded_metadata(input);\n assert_eq(msg_type, 0);\n assert_eq(msg_metadata, 0);\n }\n\n #[test]\n unconstrained fn to_from_expanded_metadata(original_msg_type: u64, original_msg_metadata: u64) {\n let packed = to_expanded_metadata(original_msg_type, original_msg_metadata);\n let (unpacked_msg_type, unpacked_msg_metadata) = from_expanded_metadata(packed);\n\n assert_eq(original_msg_type, unpacked_msg_type);\n assert_eq(original_msg_metadata, unpacked_msg_metadata);\n }\n}\n" + }, + "133": { + "path": "/home/ubuntu/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.20251212/noir-projects/aztec-nr/aztec/src/messages/encryption/aes128.nr", + "source": "use dep::protocol_types::{\n address::AztecAddress,\n constants::{GENERATOR_INDEX__SYMMETRIC_KEY, GENERATOR_INDEX__SYMMETRIC_KEY_2},\n hash::poseidon2_hash_with_separator,\n point::Point,\n public_keys::AddressPoint,\n};\n\nuse crate::{\n keys::{ecdh_shared_secret::derive_ecdh_shared_secret, ephemeral::generate_ephemeral_key_pair},\n messages::{\n encoding::{\n EPH_PK_SIGN_BYTE_SIZE_IN_BYTES, EPH_PK_X_SIZE_IN_FIELDS,\n HEADER_CIPHERTEXT_SIZE_IN_BYTES, MESSAGE_CIPHERTEXT_LEN, MESSAGE_PLAINTEXT_LEN,\n },\n encryption::message_encryption::MessageEncryption,\n logs::arithmetic_generics_utils::{\n get_arr_of_size__message_bytes__from_PT,\n get_arr_of_size__message_bytes_padding__from_PT,\n },\n },\n oracle::{\n aes128_decrypt::aes128_decrypt_oracle, random::random, shared_secret::get_shared_secret,\n },\n utils::{\n array,\n conversion::{\n bytes_to_fields::{bytes_from_fields, bytes_to_fields},\n fields_to_bytes::{fields_from_bytes, fields_to_bytes},\n },\n point::{get_sign_of_point, point_from_x_coord_and_sign},\n random::get_random_bytes,\n },\n};\n\nuse std::aes128::aes128_encrypt;\n\n/**\n * Computes N close-to-uniformly-random 256 bits from a given ECDH shared_secret.\n *\n * NEVER re-use the same iv and sym_key.\n * DO NOT call this function more than once with the same shared_secret.\n *\n * This function is only known to be safe if shared_secret is computed by combining a \n * random ephemeral key with an address point. See big comment within the body of the function.\n * See big comment within the body of the function.\n */\nfn extract_many_close_to_uniformly_random_256_bits_from_ecdh_shared_secret_using_poseidon2_unsafe(\n shared_secret: Point,\n) -> [[u8; 32]; N] {\n /*\n * Unsafe because of https://eprint.iacr.org/2010/264.pdf Page 13, Lemma 2 (and the * two paragraphs below it).\n *\n * If you call this function, you need to be careful and aware of how the arg\n * `shared_secret` has been derived.\n *\n * The paper says that the way you derive aes keys and IVs should be fine with poseidon2\n * (modelled as a RO), as long as you _don't_ use Poseidon2 as a PRG to generate the * two exponents x & y which multiply to the shared secret S:\n *\n * S = [x*y]*G.\n *\n * (Otherwise, you would have to \"key\" poseidon2, i.e. generate a uniformly string K\n * which can be public and compute Hash(x) as poseidon(K,x)).\n * In that lemma, k would be 2*254=508, and m would be the number of points on the * grumpkin curve (which is close to r according to the Hasse bound).\n *\n * Our shared secret S is [esk * address_sk] * G, and the question is: * Can we compute hash(S) using poseidon2 instead of sha256?\n *\n * Well, esk is random and not generated with poseidon2, so that's good.\n * What about address_sk?\n * Well, address_sk = poseidon2(stuff) + ivsk, so there was some\n * discussion about whether address_sk is independent of poseidon2.\n * Given that ivsk is random and independent of poseidon2, the address_sk is also\n * independent of poseidon2.\n *\n * Tl;dr: we believe it's safe to hash S = [esk * address_sk] * G using poseidon2,\n * in order to derive a symmetric key.\n *\n * If you're calling this function for a differently-derived `shared_secret`, be\n * careful.\n *\n */\n\n /* The output of this function needs to be 32 random bytes.\n * A single field won't give us 32 bytes of entropy.\n * So we compute two \"random\" fields, by poseidon-hashing with two different\n * generators.\n * We then extract the last 16 (big endian) bytes of each \"random\" field.\n * Note: we use to_be_bytes because it's slightly more efficient. But we have to\n * be careful not to take bytes from the \"big end\", because the \"big\" byte is\n * not uniformly random over the byte: it only has < 6 bits of randomness, because\n * it's the big end of a 254-bit field element.\n */\n\n let mut all_bytes: [[u8; 32]; N] = std::mem::zeroed();\n // We restrict N to be < 2^8, because of how we compute the domain separator\n // from k below (where k <= N must be 8 bits). In practice, it's extremely\n // unlikely that an app will want to compute >= 256 ciphertexts.\n std::static_assert(N < 256, \"N too large\");\n for k in 0..N {\n // We augment the domain separator with the loop index, so that we can\n // generate N lots of randomness.\n let k_shift = (k as u16 << 8);\n let separator_1 = k_shift + GENERATOR_INDEX__SYMMETRIC_KEY as u16;\n let separator_2 = k_shift + GENERATOR_INDEX__SYMMETRIC_KEY_2 as u16;\n\n let rand1: Field =\n poseidon2_hash_with_separator([shared_secret.x, shared_secret.y], separator_1);\n let rand2: Field =\n poseidon2_hash_with_separator([shared_secret.x, shared_secret.y], separator_2);\n\n let rand1_bytes: [u8; 32] = rand1.to_be_bytes();\n let rand2_bytes: [u8; 32] = rand2.to_be_bytes();\n\n let mut bytes: [u8; 32] = [0; 32];\n for i in 0..16 {\n // We take bytes from the \"little end\" of the be-bytes arrays:\n let j = 32 - i - 1;\n bytes[i] = rand1_bytes[j];\n bytes[16 + i] = rand2_bytes[j];\n }\n\n all_bytes[k] = bytes;\n }\n\n all_bytes\n}\n\nfn derive_aes_symmetric_key_and_iv_from_uniformly_random_256_bits(\n many_random_256_bits: [[u8; 32]; N],\n) -> [([u8; 16], [u8; 16]); N] {\n // Many (sym_key, iv) pairs:\n let mut many_pairs: [([u8; 16], [u8; 16]); N] = std::mem::zeroed();\n for k in 0..N {\n let random_256_bits = many_random_256_bits[k];\n let mut sym_key = [0; 16];\n let mut iv = [0; 16];\n for i in 0..16 {\n sym_key[i] = random_256_bits[i];\n iv[i] = random_256_bits[i + 16];\n }\n many_pairs[k] = (sym_key, iv);\n }\n\n many_pairs\n}\n\npub fn derive_aes_symmetric_key_and_iv_from_ecdh_shared_secret_using_poseidon2_unsafe(\n shared_secret: Point,\n) -> [([u8; 16], [u8; 16]); N] {\n let many_random_256_bits: [[u8; 32]; N] = extract_many_close_to_uniformly_random_256_bits_from_ecdh_shared_secret_using_poseidon2_unsafe(\n shared_secret,\n );\n\n derive_aes_symmetric_key_and_iv_from_uniformly_random_256_bits(many_random_256_bits)\n}\n\npub struct AES128 {}\n\nimpl MessageEncryption for AES128 {\n fn encrypt(\n plaintext: [Field; PlaintextLen],\n recipient: AztecAddress,\n ) -> [Field; MESSAGE_CIPHERTEXT_LEN] {\n // AES 128 operates on bytes, not fields, so we need to convert the fields to bytes.\n // (This process is then reversed when processing the message in `do_process_message`)\n let plaintext_bytes = fields_to_bytes(plaintext);\n\n // *****************************************************************************\n // Compute the shared secret\n // *****************************************************************************\n\n let (eph_sk, eph_pk) = generate_ephemeral_key_pair();\n\n let eph_pk_sign_byte: u8 = get_sign_of_point(eph_pk) as u8;\n\n // (not to be confused with the tagging shared secret)\n // TODO (#17158): Currently we unwrap the Option returned by derive_ecdh_shared_secret.\n // We need to handle the case where the ephemeral public key is invalid to prevent potential DoS vectors.\n let ciphertext_shared_secret = derive_ecdh_shared_secret(\n eph_sk,\n recipient\n .to_address_point()\n .unwrap_or(\n // Safety: if the recipient is an invalid address, then it is not possible to encrypt a message for\n // them because we cannot establish a shared secret. This is never expected to occur during normal\n // operation. However, it is technically possible for us to receive an invalid address, and we must\n // therefore handle it.\n // We could simply fail, but that'd introduce a potential security issue in which an attacker forces\n // a contract to encrypt a message for an invalid address, resulting in an impossible transaction -\n // this is sometimes called a 'king of the hill' attack.\n // We choose instead to not fail and encrypt the plaintext regardless using the shared secret that\n // results from a random valid address. The sender is free to choose this address and hence shared\n // secret, but this has no security implications as they already know not only the full plaintext\n // but also the ephemeral private key anyway.\n unsafe { random_address_point() },\n )\n .inner,\n );\n // TODO: also use this shared secret for deriving note randomness.\n\n // *****************************************************************************\n // Convert the plaintext into whatever format the encryption function expects\n // *****************************************************************************\n\n // Already done for this strategy: AES expects bytes.\n\n // *****************************************************************************\n // Encrypt the plaintext\n // *****************************************************************************\n\n // It is safe to call the `unsafe` function here, because we know the `shared_secret`\n // was derived using an AztecAddress (the recipient). See the block comment\n // at the start of this unsafe target function for more info.\n let pairs = derive_aes_symmetric_key_and_iv_from_ecdh_shared_secret_using_poseidon2_unsafe::<2>(\n ciphertext_shared_secret,\n );\n let (body_sym_key, body_iv) = pairs[0];\n let (header_sym_key, header_iv) = pairs[1];\n\n let ciphertext_bytes = aes128_encrypt(plaintext_bytes, body_iv, body_sym_key);\n\n // |full_pt| = |pt_length| + |pt|\n // |pt_aes_padding| = 16 - (|full_pt| % 16)\n // or... since a % b is the same as a - b * (a // b) (integer division), so:\n // |pt_aes_padding| = 16 - (|full_pt| - 16 * (|full_pt| // 16))\n // |ct| = |full_pt| + |pt_aes_padding|\n // = |full_pt| + 16 - (|full_pt| - 16 * (|full_pt| // 16))\n // = 16 + 16 * (|full_pt| // 16)\n // = 16 * (1 + |full_pt| // 16)\n std::static_assert(\n ciphertext_bytes.len() == 16 * (1 + (PlaintextLen * 32) / 16),\n \"unexpected ciphertext length\",\n );\n\n // *****************************************************************************\n // Compute the header ciphertext\n // *****************************************************************************\n\n // Header contains only the length of the ciphertext stored in 2 bytes.\n let mut header_plaintext: [u8; 2] = [0 as u8; 2];\n let ciphertext_bytes_length = ciphertext_bytes.len();\n header_plaintext[0] = (ciphertext_bytes_length >> 8) as u8;\n header_plaintext[1] = ciphertext_bytes_length as u8;\n\n // Note: the aes128_encrypt builtin fn automatically appends bytes to the\n // input, according to pkcs#7; hence why the output `header_ciphertext_bytes` is 16\n // bytes larger than the input in this case.\n let header_ciphertext_bytes = aes128_encrypt(header_plaintext, header_iv, header_sym_key);\n // I recall that converting a slice to an array incurs constraints, so I'll check the length this way instead:\n std::static_assert(\n header_ciphertext_bytes.len() == HEADER_CIPHERTEXT_SIZE_IN_BYTES,\n \"unexpected ciphertext header length\",\n );\n\n // *****************************************************************************\n // Prepend / append more bytes of data to the ciphertext, before converting back\n // to fields.\n // *****************************************************************************\n\n let mut message_bytes_padding_to_mult_31 =\n get_arr_of_size__message_bytes_padding__from_PT::();\n // Safety: this randomness won't be constrained to be random. It's in the\n // interest of the executor of this fn to encrypt with random bytes.\n message_bytes_padding_to_mult_31 = unsafe { get_random_bytes() };\n\n let mut message_bytes = get_arr_of_size__message_bytes__from_PT::();\n\n std::static_assert(\n message_bytes.len() % 31 == 0,\n \"Unexpected error: message_bytes.len() should be divisible by 31, by construction.\",\n );\n\n message_bytes[0] = eph_pk_sign_byte;\n let mut offset = 1;\n for i in 0..header_ciphertext_bytes.len() {\n message_bytes[offset + i] = header_ciphertext_bytes[i];\n }\n offset += header_ciphertext_bytes.len();\n\n for i in 0..ciphertext_bytes.len() {\n message_bytes[offset + i] = ciphertext_bytes[i];\n }\n offset += ciphertext_bytes.len();\n\n for i in 0..message_bytes_padding_to_mult_31.len() {\n message_bytes[offset + i] = message_bytes_padding_to_mult_31[i];\n }\n offset += message_bytes_padding_to_mult_31.len();\n\n // Ideally we would be able to have a static assert where we check that the offset would be such that we've\n // written to the entire log_bytes array, but we cannot since Noir does not treat the offset as a comptime\n // value (despite the values that it goes through being known at each stage). We instead check that the\n // computation used to obtain the offset computes the expected value (which we _can_ do in a static check), and\n // then add a cheap runtime check to also validate that the offset matches this.\n std::static_assert(\n 1\n + header_ciphertext_bytes.len()\n + ciphertext_bytes.len()\n + message_bytes_padding_to_mult_31.len()\n == message_bytes.len(),\n \"unexpected message length\",\n );\n assert(offset == message_bytes.len(), \"unexpected encrypted message length\");\n\n // *****************************************************************************\n // Convert bytes back to fields\n // *****************************************************************************\n\n // TODO(#12749): As Mike pointed out, we need to make messages produced by different encryption schemes\n // indistinguishable from each other and for this reason the output here and in the last for-loop of this function\n // should cover a full field.\n let message_bytes_as_fields = bytes_to_fields(message_bytes);\n\n // *****************************************************************************\n // Prepend / append fields, to create the final message\n // *****************************************************************************\n\n let mut ciphertext: [Field; MESSAGE_CIPHERTEXT_LEN] = [0; MESSAGE_CIPHERTEXT_LEN];\n\n ciphertext[0] = eph_pk.x;\n\n let mut offset = 1;\n for i in 0..message_bytes_as_fields.len() {\n ciphertext[offset + i] = message_bytes_as_fields[i];\n }\n offset += message_bytes_as_fields.len();\n\n for i in offset..MESSAGE_CIPHERTEXT_LEN {\n // We need to get a random value that fits in 31 bytes to not leak information about the size of the message\n // (all the \"real\" message fields contain at most 31 bytes because of the way we convert the bytes to fields).\n // TODO(#12749): Long term, this is not a good solution.\n\n // Safety: we assume that the sender wants for the message to be private - a malicious one could simply reveal its\n // contents publicly. It is therefore fine to trust the sender to provide random padding.\n let field_bytes = unsafe { get_random_bytes::<31>() };\n ciphertext[i] = Field::from_be_bytes::<31>(field_bytes);\n }\n\n ciphertext\n }\n\n unconstrained fn decrypt(\n ciphertext: BoundedVec,\n recipient: AztecAddress,\n ) -> Option> {\n let eph_pk_x = ciphertext.get(0);\n\n let ciphertext_without_eph_pk_x_fields = array::subbvec::(\n ciphertext,\n EPH_PK_X_SIZE_IN_FIELDS,\n );\n\n // Convert the ciphertext represented as fields to a byte representation (its original format)\n let ciphertext_without_eph_pk_x = bytes_from_fields(ciphertext_without_eph_pk_x_fields);\n\n // First byte of the ciphertext represents the ephemeral public key sign\n let eph_pk_sign_bool = ciphertext_without_eph_pk_x.get(0) != 0;\n\n // With the sign and the x-coordinate of the ephemeral public key, we can reconstruct the point. This may fail\n // however, as not all x-coordinates are on the curve. In that case, we simply return `Option::none`.\n point_from_x_coord_and_sign(eph_pk_x, eph_pk_sign_bool).map(|eph_pk| {\n // Derive shared secret\n let ciphertext_shared_secret = get_shared_secret(recipient, eph_pk);\n\n // Derive symmetric keys:\n let pairs = derive_aes_symmetric_key_and_iv_from_ecdh_shared_secret_using_poseidon2_unsafe::<2>(\n ciphertext_shared_secret,\n );\n let (body_sym_key, body_iv) = pairs[0];\n let (header_sym_key, header_iv) = pairs[1];\n\n // Extract the header ciphertext\n let header_start = EPH_PK_SIGN_BYTE_SIZE_IN_BYTES; // Skip eph_pk_sign byte\n let header_ciphertext: [u8; HEADER_CIPHERTEXT_SIZE_IN_BYTES] =\n array::subarray(ciphertext_without_eph_pk_x.storage(), header_start);\n // We need to convert the array to a BoundedVec because the oracle expects a BoundedVec as it's designed to work\n // with messages with unknown length at compile time. This would not be necessary here as the header ciphertext length\n // is fixed. But we do it anyway to not have to have duplicate oracles.\n let header_ciphertext_bvec =\n BoundedVec::::from_array(header_ciphertext);\n\n // Decrypt header\n let header_plaintext =\n aes128_decrypt_oracle(header_ciphertext_bvec, header_iv, header_sym_key);\n\n // Extract ciphertext length from header (2 bytes, big-endian)\n let ciphertext_length =\n ((header_plaintext.get(0) as u32) << 8) | (header_plaintext.get(1) as u32);\n\n // Extract and decrypt main ciphertext\n let ciphertext_start = header_start + HEADER_CIPHERTEXT_SIZE_IN_BYTES;\n let ciphertext_with_padding: [u8; (MESSAGE_CIPHERTEXT_LEN - EPH_PK_X_SIZE_IN_FIELDS) * 31 - HEADER_CIPHERTEXT_SIZE_IN_BYTES - EPH_PK_SIGN_BYTE_SIZE_IN_BYTES] =\n array::subarray(ciphertext_without_eph_pk_x.storage(), ciphertext_start);\n let ciphertext: BoundedVec =\n BoundedVec::from_parts(ciphertext_with_padding, ciphertext_length);\n\n // Decrypt main ciphertext and return it\n let plaintext_bytes = aes128_decrypt_oracle(ciphertext, body_iv, body_sym_key);\n\n // Each field of the original note message was serialized to 32 bytes so we convert the bytes back to fields.\n fields_from_bytes(plaintext_bytes)\n })\n }\n}\n\n/// Produces a random valid address point, i.e. one that is on the curve. This is equivalent to calling\n/// [AztecAddress::to_address_point] on a random valid address.\nunconstrained fn random_address_point() -> AddressPoint {\n let mut result = std::mem::zeroed();\n\n loop {\n // We simply produce random x coordinates until we find one that is on the curve. About half of the x\n // coordinates fulfill this condition, so this should only take a few iterations at most.\n let x_coord = random();\n let point = point_from_x_coord_and_sign(x_coord, true);\n if point.is_some() {\n result = AddressPoint { inner: point.unwrap() };\n break;\n }\n }\n\n result\n}\n\nmod test {\n use crate::{\n keys::ecdh_shared_secret::derive_ecdh_shared_secret,\n messages::{\n encoding::MESSAGE_PLAINTEXT_LEN, encryption::message_encryption::MessageEncryption,\n },\n test::helpers::test_environment::TestEnvironment,\n };\n use super::{AES128, random_address_point};\n use protocol_types::{address::AztecAddress, traits::FromField};\n use std::{embedded_curve_ops::EmbeddedCurveScalar, test::OracleMock};\n\n #[test]\n unconstrained fn encrypt_decrypt_deterministic() {\n let env = TestEnvironment::new();\n\n // Message decryption requires oracles that are only available during private execution\n env.private_context(|_| {\n let plaintext = [1, 2, 3];\n\n let recipient = AztecAddress::from_field(\n 0x25afb798ea6d0b8c1618e50fdeafa463059415013d3b7c75d46abf5e242be70c,\n );\n\n // Mock random values for deterministic test\n let eph_sk = 0x1358d15019d4639393d62b97e1588c095957ce74a1c32d6ec7d62fe6705d9538;\n let _ = OracleMock::mock(\"utilityGetRandomField\").returns(eph_sk).times(1);\n\n let randomness = 0x0101010101010101010101010101010101010101010101010101010101010101;\n let _ = OracleMock::mock(\"utilityGetRandomField\").returns(randomness).times(1000000);\n\n let _ = OracleMock::mock(\"privateGetNextAppTagAsSender\").returns(42);\n\n // Encrypt the message\n let encrypted_message = BoundedVec::from_array(AES128::encrypt(plaintext, recipient));\n\n // Mock shared secret for deterministic test\n let shared_secret = derive_ecdh_shared_secret(\n EmbeddedCurveScalar::from_field(eph_sk),\n recipient.to_address_point().unwrap().inner,\n );\n\n let _ = OracleMock::mock(\"utilityGetSharedSecret\").returns(shared_secret);\n\n // Decrypt the message\n let decrypted = AES128::decrypt(encrypted_message, recipient).unwrap();\n\n // The decryption function spits out a BoundedVec because it's designed to work with messages with unknown length\n // at compile time. For this reason we need to convert the original input to a BoundedVec.\n let plaintext_bvec = BoundedVec::::from_array(plaintext);\n\n // Verify decryption matches original plaintext\n assert_eq(\n decrypted,\n plaintext_bvec,\n \"Decrypted bytes should match original plaintext\",\n );\n\n // The following is a workaround of \"struct is never constructed\" Noir compilation error (we only ever use\n // static methods of the struct).\n let _ = AES128 {};\n });\n }\n\n #[test]\n unconstrained fn encrypt_decrypt_random() {\n // Same as `encrypt_decrypt_deterministic`, except we don't mock any of the oracles and rely on\n // `TestEnvironment` instead.\n let mut env = TestEnvironment::new();\n\n let recipient = env.create_light_account();\n\n env.private_context(|_| {\n let plaintext = [1, 2, 3];\n let ciphertext = AES128::encrypt(plaintext, recipient);\n\n assert_eq(\n AES128::decrypt(BoundedVec::from_array(ciphertext), recipient).unwrap(),\n BoundedVec::from_array(plaintext),\n );\n });\n }\n\n #[test]\n unconstrained fn encrypt_to_invalid_address() {\n // x = 3 is a non-residue for this curve, resulting in an invalid address\n let invalid_address = AztecAddress { inner: 3 };\n\n // We just test that we produced some output and did not crash - the result is gibberish as it is encrypted\n // using a public key for which we do not know the private key.\n let _ = AES128::encrypt([1, 2, 3, 4], invalid_address);\n }\n\n #[test]\n unconstrained fn random_address_point_produces_valid_points() {\n // About half of random addresses are invalid, so testing just a couple gives us high confidence that\n // `random_address_point` is indeed producing valid addresses.\n for _ in 0..10 {\n let random_address = AztecAddress { inner: random_address_point().inner.x };\n assert(random_address.to_address_point().is_some());\n }\n }\n\n #[test]\n unconstrained fn decrypt_invalid_ephemeral_public_key() {\n let mut env = TestEnvironment::new();\n\n let recipient = env.create_light_account();\n\n env.private_context(|_| {\n let plaintext = [1, 2, 3, 4];\n let ciphertext = AES128::encrypt(plaintext, recipient);\n\n // The first field of the ciphertext is the x-coordinate of the ephemeral public key. We set it to a known\n // non-residue (3), causing `decrypt` to fail to produce a decryption shared secret.\n let mut bad_ciphertext = BoundedVec::from_array(ciphertext);\n bad_ciphertext.set(0, 3);\n\n assert(AES128::decrypt(bad_ciphertext, recipient).is_none());\n });\n }\n}\n" + }, + "150": { + "path": "/home/ubuntu/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.20251212/noir-projects/aztec-nr/aztec/src/messages/processing/mod.nr", + "source": "pub(crate) mod event_validation_request;\npub mod message_context;\npub(crate) mod note_validation_request;\npub(crate) mod log_retrieval_request;\npub(crate) mod log_retrieval_response;\npub(crate) mod pending_tagged_log;\n\nuse crate::{\n capsules::CapsuleArray,\n event::event_selector::EventSelector,\n messages::{\n discovery::{\n partial_notes::DeliveredPendingPartialNote, private_events::MAX_EVENT_SERIALIZED_LEN,\n private_notes::MAX_NOTE_PACKED_LEN,\n },\n processing::{\n log_retrieval_request::LogRetrievalRequest,\n log_retrieval_response::LogRetrievalResponse,\n note_validation_request::NoteValidationRequest, pending_tagged_log::PendingTaggedLog,\n },\n },\n oracle,\n};\nuse event_validation_request::EventValidationRequest;\nuse protocol_types::{address::AztecAddress, hash::sha256_to_field};\n\n// Base slot for the pending tagged log array to which the fetch_tagged_logs oracle inserts found private logs.\nglobal PENDING_TAGGED_LOG_ARRAY_BASE_SLOT: Field =\n sha256_to_field(\"AZTEC_NR::PENDING_TAGGED_LOG_ARRAY_BASE_SLOT\".as_bytes());\n\nglobal NOTE_VALIDATION_REQUESTS_ARRAY_BASE_SLOT: Field = sha256_to_field(\n \"AZTEC_NR::NOTE_VALIDATION_REQUESTS_ARRAY_BASE_SLOT\".as_bytes(),\n);\n\nglobal EVENT_VALIDATION_REQUESTS_ARRAY_BASE_SLOT: Field = sha256_to_field(\n \"AZTEC_NR::EVENT_VALIDATION_REQUESTS_ARRAY_BASE_SLOT\".as_bytes(),\n);\n\nglobal LOG_RETRIEVAL_REQUESTS_ARRAY_BASE_SLOT: Field = sha256_to_field(\n \"AZTEC_NR::LOG_RETRIEVAL_REQUESTS_ARRAY_BASE_SLOT\".as_bytes(),\n);\n\nglobal LOG_RETRIEVAL_RESPONSES_ARRAY_BASE_SLOT: Field = sha256_to_field(\n \"AZTEC_NR::LOG_RETRIEVAL_RESPONSES_ARRAY_BASE_SLOT\".as_bytes(),\n);\n\n/// Searches for private logs emitted by `contract_address` that might contain messages for one of the local accounts,\n/// and stores them in a `CapsuleArray` which is then returned.\npub(crate) unconstrained fn get_private_logs(\n contract_address: AztecAddress,\n) -> CapsuleArray {\n // We will eventually perform log discovery via tagging here, but for now we simply call the `fetchTaggedLogs`\n // oracle. This makes PXE synchronize tags, download logs and store the pending tagged logs in a capsule array.\n oracle::message_processing::fetch_tagged_logs(PENDING_TAGGED_LOG_ARRAY_BASE_SLOT);\n\n CapsuleArray::at(contract_address, PENDING_TAGGED_LOG_ARRAY_BASE_SLOT)\n}\n\n/// Enqueues a note for validation by PXE, so that it becomes aware of a note's existence allowing for later retrieval\n/// via `get_notes` oracle. The note will be scoped to `contract_address`, meaning other contracts will not be able to\n/// access it unless authorized.\n///\n/// In order for the note validation and insertion to occur, `validate_enqueued_notes_and_events` must be later called.\n/// For optimal performance, accumulate as many note validation requests as possible and then validate them all at the\n/// end (which results in PXE minimizing the number of network round-trips).\n///\n/// The `packed_note` is what `getNotes` will later return. PXE indexes notes by `storage_slot`, so this value\n/// is typically used to filter notes that correspond to different state variables. `note_hash` and `nullifier` are\n/// the inner hashes, i.e. the raw hashes returned by `NoteHash::compute_note_hash` and\n/// `NoteHash::compute_nullifier`. PXE will verify that the siloed unique note hash was inserted into the tree\n/// at `tx_hash`, and will store the nullifier to later check for nullification.\n///\n/// `owner` is the address used in note hash and nullifier computation, often requiring knowledge of their\n/// nullifier secret key.\n///\n/// `recipient` is the account to which the note message was delivered (i.e. the address the message was encrypted to).\n/// This determines which PXE account can see the note - other accounts will not be able to access it (e.g. other\n/// accounts will not be able to see one another's token balance notes, even in the same PXE) unless authorized. In most\n/// cases `recipient` equals `owner`, but they can differ in scenarios like delegated discovery.\npub(crate) unconstrained fn enqueue_note_for_validation(\n contract_address: AztecAddress,\n owner: AztecAddress,\n storage_slot: Field,\n randomness: Field,\n note_nonce: Field,\n packed_note: BoundedVec,\n note_hash: Field,\n nullifier: Field,\n tx_hash: Field,\n recipient: AztecAddress,\n) {\n // We store requests in a `CapsuleArray`, which PXE will later read from and deserialize into its version of the\n // Noir `NoteValidationRequest`\n CapsuleArray::at(contract_address, NOTE_VALIDATION_REQUESTS_ARRAY_BASE_SLOT).push(\n NoteValidationRequest {\n contract_address,\n owner,\n storage_slot,\n randomness,\n note_nonce,\n packed_note,\n note_hash,\n nullifier,\n tx_hash,\n recipient,\n },\n )\n}\n\n/// Enqueues an event for validation by PXE, so that it can be efficiently validated and then inserted into the event\n/// store.\n///\n/// In order for the event validation and insertion to occur, `validate_enqueued_notes_and_events` must be later\n/// called. For optimal performance, accumulate as many event validation requests as possible and then validate them\n/// all at the end (which results in PXE minimizing the number of network round-trips).\npub(crate) unconstrained fn enqueue_event_for_validation(\n contract_address: AztecAddress,\n event_type_id: EventSelector,\n serialized_event: BoundedVec,\n event_commitment: Field,\n tx_hash: Field,\n recipient: AztecAddress,\n) {\n // We store requests in a `CapsuleArray`, which PXE will later read from and deserialize into its version of the\n // Noir `EventValidationRequest`\n CapsuleArray::at(contract_address, EVENT_VALIDATION_REQUESTS_ARRAY_BASE_SLOT).push(\n EventValidationRequest {\n contract_address,\n event_type_id,\n serialized_event,\n event_commitment,\n tx_hash,\n recipient,\n },\n )\n}\n\n/// Validates all note and event validation requests enqueued via `enqueue_note_for_validation` and\n/// `enqueue_event_for_validation`, inserting them into the note database and event store respectively, making them\n/// queryable via `get_notes` oracle and our TS API (PXE::getPrivateEvents).\n///\n/// This automatically clears both validation request queues, so no further work needs to be done by the caller.\npub(crate) unconstrained fn validate_enqueued_notes_and_events(contract_address: AztecAddress) {\n oracle::message_processing::validate_enqueued_notes_and_events(\n contract_address,\n NOTE_VALIDATION_REQUESTS_ARRAY_BASE_SLOT,\n EVENT_VALIDATION_REQUESTS_ARRAY_BASE_SLOT,\n );\n}\n\n/// Efficiently queries the node for logs that result in the completion of all `DeliveredPendingPartialNote`s stored in\n/// a `CapsuleArray` by performing all node communication concurrently. Returns a second `CapsuleArray` with Options for\n/// the responses that correspond to the pending partial notes at the same index.\n///\n/// For example, given an array with pending partial notes `[ p1, p2, p3 ]`, where `p1` and `p3` have corresponding\n/// completion logs but `p2` does not, the returned `CapsuleArray` will have contents\n/// `[some(p1_log), none(), some(p3_log)]`.\npub(crate) unconstrained fn get_pending_partial_notes_completion_logs(\n contract_address: AztecAddress,\n pending_partial_notes: CapsuleArray,\n) -> CapsuleArray> {\n let log_retrieval_requests =\n CapsuleArray::at(contract_address, LOG_RETRIEVAL_REQUESTS_ARRAY_BASE_SLOT);\n\n // We create a LogRetrievalRequest for each PendingPartialNote in the CapsuleArray. Because we need the indices in\n // the request array to match the indices in the partial note array, we can't use CapsuleArray::for_each, as that\n // function has arbitrary iteration order. Instead, we manually iterate the array from the beginning and push into\n // the requests array, which we expect to be empty.\n let mut i = 0;\n let pending_partial_notes_count = pending_partial_notes.len();\n while i < pending_partial_notes_count {\n let pending_partial_note = pending_partial_notes.get(i);\n log_retrieval_requests.push(\n LogRetrievalRequest {\n contract_address,\n unsiloed_tag: pending_partial_note.note_completion_log_tag,\n },\n );\n i += 1;\n }\n\n oracle::message_processing::bulk_retrieve_logs(\n contract_address,\n LOG_RETRIEVAL_REQUESTS_ARRAY_BASE_SLOT,\n LOG_RETRIEVAL_RESPONSES_ARRAY_BASE_SLOT,\n );\n\n CapsuleArray::at(contract_address, LOG_RETRIEVAL_RESPONSES_ARRAY_BASE_SLOT)\n}\n" + }, + "16": { + "path": "std/embedded_curve_ops.nr", + "source": "use crate::cmp::Eq;\nuse crate::hash::Hash;\nuse crate::ops::arith::{Add, Neg, Sub};\n\n/// A point on the embedded elliptic curve\n/// By definition, the base field of the embedded curve is the scalar field of the proof system curve, i.e the Noir Field.\n/// x and y denotes the Weierstrass coordinates of the point, if is_infinite is false.\npub struct EmbeddedCurvePoint {\n pub x: Field,\n pub y: Field,\n pub is_infinite: bool,\n}\n\nimpl EmbeddedCurvePoint {\n /// Elliptic curve point doubling operation\n /// returns the doubled point of a point P, i.e P+P\n pub fn double(self) -> EmbeddedCurvePoint {\n embedded_curve_add(self, self)\n }\n\n /// Returns the null element of the curve; 'the point at infinity'\n pub fn point_at_infinity() -> EmbeddedCurvePoint {\n EmbeddedCurvePoint { x: 0, y: 0, is_infinite: true }\n }\n\n /// Returns the curve's generator point.\n pub fn generator() -> EmbeddedCurvePoint {\n // Generator point for the grumpkin curve (y^2 = x^3 - 17)\n EmbeddedCurvePoint {\n x: 1,\n y: 17631683881184975370165255887551781615748388533673675138860, // sqrt(-16)\n is_infinite: false,\n }\n }\n}\n\nimpl Add for EmbeddedCurvePoint {\n /// Adds two points P+Q, using the curve addition formula, and also handles point at infinity\n fn add(self, other: EmbeddedCurvePoint) -> EmbeddedCurvePoint {\n embedded_curve_add(self, other)\n }\n}\n\nimpl Sub for EmbeddedCurvePoint {\n /// Points subtraction operation, using addition and negation\n fn sub(self, other: EmbeddedCurvePoint) -> EmbeddedCurvePoint {\n self + other.neg()\n }\n}\n\nimpl Neg for EmbeddedCurvePoint {\n /// Negates a point P, i.e returns -P, by negating the y coordinate.\n /// If the point is at infinity, then the result is also at infinity.\n fn neg(self) -> EmbeddedCurvePoint {\n EmbeddedCurvePoint { x: self.x, y: -self.y, is_infinite: self.is_infinite }\n }\n}\n\nimpl Eq for EmbeddedCurvePoint {\n /// Checks whether two points are equal\n fn eq(self: Self, b: EmbeddedCurvePoint) -> bool {\n (self.is_infinite & b.is_infinite)\n | ((self.is_infinite == b.is_infinite) & (self.x == b.x) & (self.y == b.y))\n }\n}\n\nimpl Hash for EmbeddedCurvePoint {\n fn hash(self, state: &mut H)\n where\n H: crate::hash::Hasher,\n {\n if self.is_infinite {\n self.is_infinite.hash(state);\n } else {\n self.x.hash(state);\n self.y.hash(state);\n }\n }\n}\n\n/// Scalar for the embedded curve represented as low and high limbs\n/// By definition, the scalar field of the embedded curve is base field of the proving system curve.\n/// It may not fit into a Field element, so it is represented with two Field elements; its low and high limbs.\npub struct EmbeddedCurveScalar {\n pub lo: Field,\n pub hi: Field,\n}\n\nimpl EmbeddedCurveScalar {\n pub fn new(lo: Field, hi: Field) -> Self {\n EmbeddedCurveScalar { lo, hi }\n }\n\n #[field(bn254)]\n pub fn from_field(scalar: Field) -> EmbeddedCurveScalar {\n let (a, b) = crate::field::bn254::decompose(scalar);\n EmbeddedCurveScalar { lo: a, hi: b }\n }\n\n //Bytes to scalar: take the first (after the specified offset) 16 bytes of the input as the lo value, and the next 16 bytes as the hi value\n #[field(bn254)]\n pub(crate) fn from_bytes(bytes: [u8; 64], offset: u32) -> EmbeddedCurveScalar {\n let mut v = 1;\n let mut lo = 0 as Field;\n let mut hi = 0 as Field;\n for i in 0..16 {\n lo = lo + (bytes[offset + 31 - i] as Field) * v;\n hi = hi + (bytes[offset + 15 - i] as Field) * v;\n v = v * 256;\n }\n let sig_s = crate::embedded_curve_ops::EmbeddedCurveScalar { lo, hi };\n sig_s\n }\n}\n\nimpl Eq for EmbeddedCurveScalar {\n fn eq(self, other: Self) -> bool {\n (other.hi == self.hi) & (other.lo == self.lo)\n }\n}\n\nimpl Hash for EmbeddedCurveScalar {\n fn hash(self, state: &mut H)\n where\n H: crate::hash::Hasher,\n {\n self.hi.hash(state);\n self.lo.hash(state);\n }\n}\n\n// Computes a multi scalar multiplication over the embedded curve.\n// For bn254, We have Grumpkin and Baby JubJub.\n// For bls12-381, we have JubJub and Bandersnatch.\n//\n// The embedded curve being used is decided by the\n// underlying proof system.\n// docs:start:multi_scalar_mul\npub fn multi_scalar_mul(\n points: [EmbeddedCurvePoint; N],\n scalars: [EmbeddedCurveScalar; N],\n) -> EmbeddedCurvePoint\n// docs:end:multi_scalar_mul\n{\n multi_scalar_mul_array_return(points, scalars, true)[0]\n}\n\n#[foreign(multi_scalar_mul)]\npub(crate) fn multi_scalar_mul_array_return(\n points: [EmbeddedCurvePoint; N],\n scalars: [EmbeddedCurveScalar; N],\n predicate: bool,\n) -> [EmbeddedCurvePoint; 1] {}\n\n// docs:start:fixed_base_scalar_mul\npub fn fixed_base_scalar_mul(scalar: EmbeddedCurveScalar) -> EmbeddedCurvePoint\n// docs:end:fixed_base_scalar_mul\n{\n multi_scalar_mul([EmbeddedCurvePoint::generator()], [scalar])\n}\n\n/// This function only assumes that the points are on the curve\n/// It handles corner cases around the infinity point causing some overhead compared to embedded_curve_add_not_nul and embedded_curve_add_unsafe\n// docs:start:embedded_curve_add\npub fn embedded_curve_add(\n point1: EmbeddedCurvePoint,\n point2: EmbeddedCurvePoint,\n) -> EmbeddedCurvePoint {\n // docs:end:embedded_curve_add\n if crate::runtime::is_unconstrained() {\n // `embedded_curve_add_unsafe` requires the inputs not to be the infinity point, so we check it here.\n // This is because `embedded_curve_add_unsafe` uses the `embedded_curve_add` opcode.\n // For efficiency, the backend does not check the inputs for the infinity point, but it assumes that they are not the infinity point\n // so that it can apply the ec addition formula directly.\n if point1.is_infinite {\n point2\n } else if point2.is_infinite {\n point1\n } else {\n embedded_curve_add_unsafe(point1, point2)\n }\n } else {\n // In a constrained context, we also need to check the inputs are not the infinity point because we also use `embedded_curve_add_unsafe`\n // However we also need to identify the case where the two inputs are the same, because then\n // the addition formula does not work and we need to use the doubling formula instead.\n // In unconstrained context, we can check directly if the input values are the same when solving the opcode, so it is not an issue.\n\n // x_coordinates_match is true if both abscissae are the same\n let x_coordinates_match = point1.x == point2.x;\n // y_coordinates_match is true if both ordinates are the same\n let y_coordinates_match = point1.y == point2.y;\n // double_predicate is true if both abscissae and ordinates are the same\n let double_predicate = (x_coordinates_match & y_coordinates_match);\n // If the abscissae are the same, but not the ordinates, then one point is the opposite of the other\n let infinity_predicate = (x_coordinates_match & !y_coordinates_match);\n\n // `embedded_curve_add_unsafe` would not perform doubling, even if the inputs point1 and point2 are the same, because it cannot know this without adding some logic (and some constraints)\n // However we did this logic when we computed `double_predicate`, so we set the result to 2*point1 if point1 and point2 are the same\n let mut result = if double_predicate {\n // `embedded_curve_add_unsafe` is doing a doubling if the input is the same variable, because in this case it is guaranteed (at 'compile time') that the input is the same.\n embedded_curve_add_unsafe(point1, point1)\n } else {\n let point1_1 = EmbeddedCurvePoint {\n x: point1.x + (x_coordinates_match as Field),\n y: point1.y,\n is_infinite: false,\n };\n let point2_1 = EmbeddedCurvePoint { x: point2.x, y: point2.y, is_infinite: false };\n // point1_1 is guaranteed to have a different abscissa than point2:\n // - if x_coordinates_match is 0, that means point1.x != point2.x, and point1_1.x = point1.x + 0\n // - if x_coordinates_match is 1, that means point1.x = point2.x, but point1_1.x = point1.x + 1 in this case\n // Because the abscissa is different, the addition formula is guaranteed to succeed, so we can safely use `embedded_curve_add_unsafe`\n // Note that this computation may be garbage: if x_coordinates_match is 1, or if one of the input is the point at infinity.\n // therefore we only want to do this if we need the result, otherwise it needs to be eliminated as a dead instruction, lest we want the circuit to fail.\n embedded_curve_add_unsafe(point1_1, point2_1)\n };\n\n // Same logic as above for unconstrained context, we set the proper result when one of the inputs is the infinity point\n if point1.is_infinite {\n result = point2;\n }\n if point2.is_infinite {\n result = point1;\n }\n\n // Finally, we set the is_infinity flag of the result:\n // Opposite points should sum into the infinity point, however, if one of them is point at infinity, their coordinates are not meaningful\n // so we should not use the fact that the inputs are opposite in this case:\n let mut result_is_infinity =\n infinity_predicate & (!point1.is_infinite & !point2.is_infinite);\n // However, if both of them are at infinity, then the result is also at infinity\n result.is_infinite = result_is_infinity | (point1.is_infinite & point2.is_infinite);\n result\n }\n}\n\n#[foreign(embedded_curve_add)]\nfn embedded_curve_add_array_return(\n _point1: EmbeddedCurvePoint,\n _point2: EmbeddedCurvePoint,\n _predicate: bool,\n) -> [EmbeddedCurvePoint; 1] {}\n\n/// This function assumes that:\n/// The points are on the curve, and\n/// The points don't share an x-coordinate, and\n/// Neither point is the infinity point.\n/// If it is used with correct input, the function ensures the correct non-zero result is returned.\n/// Except for points on the curve, the other assumptions are checked by the function. It will cause assertion failure if they are not respected.\npub fn embedded_curve_add_not_nul(\n point1: EmbeddedCurvePoint,\n point2: EmbeddedCurvePoint,\n) -> EmbeddedCurvePoint {\n assert(point1.x != point2.x);\n assert(!point1.is_infinite);\n assert(!point2.is_infinite);\n // Ensure is_infinite is comptime\n let point1_1 = EmbeddedCurvePoint { x: point1.x, y: point1.y, is_infinite: false };\n let point2_1 = EmbeddedCurvePoint { x: point2.x, y: point2.y, is_infinite: false };\n embedded_curve_add_unsafe(point1_1, point2_1)\n}\n\n/// Unsafe ec addition\n/// If the inputs are the same, it will perform a doubling, but only if point1 and point2 are the same variable.\n/// If they have the same value but are different variables, the result will be incorrect because in this case\n/// it assumes (but does not check) that the points' x-coordinates are not equal.\n/// It also assumes neither point is the infinity point.\npub fn embedded_curve_add_unsafe(\n point1: EmbeddedCurvePoint,\n point2: EmbeddedCurvePoint,\n) -> EmbeddedCurvePoint {\n embedded_curve_add_array_return(point1, point2, true)[0]\n}\n" + }, + "162": { + "path": "/home/ubuntu/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.20251212/noir-projects/aztec-nr/aztec/src/note/note_metadata.nr", + "source": "use protocol_types::traits::{Deserialize, Packable, Serialize};\n\n// There's temporarily quite a bit of boilerplate here because Noir does not yet support enums. This file will\n// eventually be simplified into something closer to:\n//\n// pub enum NoteMetadata {\n// PendingSamePhase{ note_hash_counter: u32 },\n// PendingOtherPhase{ note_hash_counter: u32, note_nonce: Field },\n// Settled{ note_nonce: Field },\n// }\n//\n// For now, we have `NoteMetadata` acting as a sort of tagged union.\n\nstruct NoteStageEnum {\n /// A note that was created in the transaction that is currently being executed, during the current execution phase,\n /// i.e. non-revertible or revertible.\n ///\n /// These notes are not yet in the note hash tree, though they will be inserted unless nullified in this transaction\n /// (becoming a transient note).\n PENDING_SAME_PHASE: u8,\n /// A note that was created in the transaction that is currently being executed, during the previous execution\n /// phase. Because there are only two phases and their order is always the same (first non-revertible and then\n /// revertible) this implies that the note was created in the non-revertible phase, and that the current phase is\n /// the revertible phase.\n ///\n /// These notes are not yet in the note hash tree, though they will be inserted **even if nullified in this\n /// transaction**. This means that they must be nullified as if they were settled (i.e. using the unique note hash)\n /// in order to avoid double spends once they become settled.\n PENDING_PREVIOUS_PHASE: u8,\n /// A note that was created in a prior transaction and is therefore already in the note hash tree.\n SETTLED: u8,\n}\n\nglobal NoteStage: NoteStageEnum =\n NoteStageEnum { PENDING_SAME_PHASE: 1, PENDING_PREVIOUS_PHASE: 2, SETTLED: 3 };\n\n/// The metadata required to both prove a note's existence and destroy it, by computing the correct note hash for kernel\n/// read requests, as well as the correct nullifier to avoid double-spends.\n///\n/// This represents a note in any of the three valid stages (pending same phase, pending previous phase, or settled). In\n/// order to access the underlying fields callers must first find the appropriate stage (e.g. via `is_settled()`) and\n/// then convert this into the appropriate type (e.g. via `to_settled()`).\n#[derive(Deserialize, Eq, Serialize, Packable)]\npub struct NoteMetadata {\n stage: u8,\n maybe_note_nonce: Field,\n}\n\nimpl NoteMetadata {\n /// Constructs a `NoteMetadata` object from optional note hash counter and nonce. Both a zero note hash counter and\n /// a zero nonce are invalid, so those are used to signal non-existent values.\n pub fn from_raw_data(nonzero_note_hash_counter: bool, maybe_note_nonce: Field) -> Self {\n if nonzero_note_hash_counter {\n if maybe_note_nonce == 0 {\n Self { stage: NoteStage.PENDING_SAME_PHASE, maybe_note_nonce }\n } else {\n Self { stage: NoteStage.PENDING_PREVIOUS_PHASE, maybe_note_nonce }\n }\n } else if maybe_note_nonce != 0 {\n Self { stage: NoteStage.SETTLED, maybe_note_nonce }\n } else {\n panic(\n f\"Note has a zero note hash counter and no nonce - existence cannot be proven\",\n )\n }\n }\n\n /// Returns true if the note is pending **and** from the same phase, i.e. if it's been created in the current\n /// transaction during the current execution phase (either non-revertible or revertible).\n pub fn is_pending_same_phase(self) -> bool {\n self.stage == NoteStage.PENDING_SAME_PHASE\n }\n\n /// Returns true if the note is pending **and** from the previous phase, i.e. if it's been created in the current\n /// transaction during an execution phase prior to the current one. Because private execution only has two phases\n /// with strict ordering, this implies that the note was created in the non-revertible phase, and that the current\n /// phase is the revertible phase.\n pub fn is_pending_previous_phase(self) -> bool {\n self.stage == NoteStage.PENDING_PREVIOUS_PHASE\n }\n\n /// Returns true if the note is settled, i.e. if it's been created in a prior transaction and is therefore already\n /// in the note hash tree.\n pub fn is_settled(self) -> bool {\n self.stage == NoteStage.SETTLED\n }\n\n /// Asserts that the metadata is that of a pending note from the same phase and converts it accordingly.\n pub fn to_pending_same_phase(self) -> PendingSamePhaseNoteMetadata {\n assert_eq(self.stage, NoteStage.PENDING_SAME_PHASE);\n PendingSamePhaseNoteMetadata::new()\n }\n\n /// Asserts that the metadata is that of a pending note from a previous phase and converts it accordingly.\n pub fn to_pending_previous_phase(self) -> PendingPreviousPhaseNoteMetadata {\n assert_eq(self.stage, NoteStage.PENDING_PREVIOUS_PHASE);\n PendingPreviousPhaseNoteMetadata::new(self.maybe_note_nonce)\n }\n\n /// Asserts that the metadata is that of a settled note and converts it accordingly.\n pub fn to_settled(self) -> SettledNoteMetadata {\n assert_eq(self.stage, NoteStage.SETTLED);\n SettledNoteMetadata::new(self.maybe_note_nonce)\n }\n}\n\nimpl From for NoteMetadata {\n fn from(_value: PendingSamePhaseNoteMetadata) -> Self {\n NoteMetadata::from_raw_data(true, std::mem::zeroed())\n }\n}\n\nimpl From for NoteMetadata {\n fn from(value: PendingPreviousPhaseNoteMetadata) -> Self {\n NoteMetadata::from_raw_data(true, value.note_nonce())\n }\n}\n\nimpl From for NoteMetadata {\n fn from(value: SettledNoteMetadata) -> Self {\n NoteMetadata::from_raw_data(false, value.note_nonce())\n }\n}\n\n/// The metadata required to both prove a note's existence and destroy it, by computing the correct note hash for kernel\n/// read requests, as well as the correct nullifier to avoid double-spends.\n///\n/// This represents a pending same phase note, i.e. a note that was created in the transaction that is currently being\n/// executed during the current execution phase (either non-revertible or revertible).\npub struct PendingSamePhaseNoteMetadata {\n // This struct contains no fields since there is no metadata associated with a pending same phase note: it has no\n // nonce (since it may get squashed by a nullifier emitted in the same phase), and while it does have a note hash\n // counter we cannot constrain its value (and don't need to - only that it is non-zero).\n}\n\nimpl PendingSamePhaseNoteMetadata {\n pub fn new() -> Self {\n Self {}\n }\n}\n\n/// The metadata required to both prove a note's existence and destroy it, by computing the correct note hash for kernel\n/// read requests, as well as the correct nullifier to avoid double-spends.\n///\n/// This represents a pending previous phase note, i.e. a note that was created in the transaction that is currently\n/// being executed, during the previous execution phase. Because there are only two phases and their order is always the\n/// same (first non-revertible and then revertible) this implies that the note was created in the non-revertible phase,\n/// and that the current phase is the revertible phase.\npub struct PendingPreviousPhaseNoteMetadata {\n note_nonce: Field,\n // This struct does not contain a note hash counter, even though one exists for this note, because we cannot\n // constrain its value (and don't need to - only that it is non-zero).\n}\n\nimpl PendingPreviousPhaseNoteMetadata {\n pub fn new(note_nonce: Field) -> Self {\n Self { note_nonce }\n }\n\n pub fn note_nonce(self) -> Field {\n self.note_nonce\n }\n}\n\n/// The metadata required to both prove a note's existence and destroy it, by computing the correct note hash for kernel\n/// read requests, as well as the correct nullifier to avoid double-spends.\n///\n/// This represents a settled note, i.e. a note that was created in a prior transaction and is therefore already in the\n/// note hash tree.\npub struct SettledNoteMetadata {\n note_nonce: Field,\n}\n\nimpl SettledNoteMetadata {\n pub fn new(note_nonce: Field) -> Self {\n Self { note_nonce }\n }\n\n pub fn note_nonce(self) -> Field {\n self.note_nonce\n }\n}\n" + }, + "165": { + "path": "/home/ubuntu/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.20251212/noir-projects/aztec-nr/aztec/src/note/utils.nr", + "source": "use crate::{\n context::{note_hash_read::NoteHashRead, PrivateContext},\n note::{note_interface::NoteHash, retrieved_note::RetrievedNote},\n};\n\nuse protocol_types::hash::{\n compute_siloed_note_hash, compute_siloed_nullifier, compute_unique_note_hash,\n};\n\n/// Returns the note hash that must be used to issue a private kernel read request for a note.\npub fn compute_note_hash_read(retrieved_note: RetrievedNote) -> NoteHashRead\nwhere\n Note: NoteHash,\n{\n let note_hash = retrieved_note.note.compute_note_hash(\n retrieved_note.owner,\n retrieved_note.storage_slot,\n retrieved_note.randomness,\n );\n\n if retrieved_note.metadata.is_settled() {\n // Settled notes are read by siloing with contract address and nonce (resulting in the final unique note hash,\n // which is already in the note hash tree).\n let siloed_note_hash = compute_siloed_note_hash(retrieved_note.contract_address, note_hash);\n NoteHashRead::new_settled(compute_unique_note_hash(\n retrieved_note.metadata.to_settled().note_nonce(),\n siloed_note_hash,\n ))\n } else {\n // Pending notes (both same phase and previous phase ones) re read by their non-siloed hash (not even by\n // contract address), which is what is stored in the new note hashes array (at the position hinted by note hash\n // counter).\n NoteHashRead::new_transient(note_hash, retrieved_note.contract_address)\n }\n}\n\n/// Returns the note hash that must be used to compute a note's nullifier when calling `NoteHash::compute_nullifier` or\n/// `NoteHash::compute_nullifier_unconstrained`.\npub fn compute_note_hash_for_nullification(retrieved_note: RetrievedNote) -> Field\nwhere\n Note: NoteHash,\n{\n compute_note_hash_for_nullification_from_note_hash_read(\n retrieved_note,\n compute_note_hash_read(retrieved_note),\n )\n}\n\n/// Same as `compute_note_hash_for_nullification`, except it takes the note hash used in a read request (i.e. what\n/// `compute_note_hash_read` would return). This is useful in scenarios where that hash has already been\n/// computed to reduce constraints by reusing this value.\npub fn compute_note_hash_for_nullification_from_note_hash_read(\n retrieved_note: RetrievedNote,\n note_hash_read: NoteHashRead,\n) -> Field {\n // There is just one instance in which the note hash for nullification does not match the note hash used for a read\n // request, which is when dealing with pending previous phase notes. These had their existence proven using their\n // non-siloed note hash along with the note hash counter (like all pending notes), but since they will be\n // unconditionally inserted in the note hash tree (since they cannot be squashed) they must be nullified using the\n // *unique* note hash.\n // If we didn't, it'd be possible to emit a second different nullifier for the same note in a follow up transaction,\n // once the note is settled, resulting in a double spend.\n\n if retrieved_note.metadata.is_pending_previous_phase() {\n let siloed_note_hash = compute_siloed_note_hash(\n note_hash_read.contract_address().unwrap(), // Safe since contract address must be populated for pending note reads.\n note_hash_read.note_hash(),\n );\n let note_nonce = retrieved_note.metadata.to_pending_previous_phase().note_nonce();\n\n compute_unique_note_hash(note_nonce, siloed_note_hash)\n } else {\n note_hash_read.note_hash()\n }\n}\n\n/// Computes a note's siloed nullifier, i.e. the one that will be inserted into the nullifier tree.\npub fn compute_siloed_note_nullifier(\n retrieved_note: RetrievedNote,\n context: &mut PrivateContext,\n) -> Field\nwhere\n Note: NoteHash,\n{\n let note_hash_for_nullification = compute_note_hash_for_nullification(retrieved_note);\n let inner_nullifier = retrieved_note.note.compute_nullifier(\n context,\n retrieved_note.owner,\n note_hash_for_nullification,\n );\n\n compute_siloed_nullifier(retrieved_note.contract_address, inner_nullifier)\n}\n" + }, + "17": { + "path": "std/field/bn254.nr", + "source": "use crate::field::field_less_than;\nuse crate::runtime::is_unconstrained;\n\n// The low and high decomposition of the field modulus\npub(crate) global PLO: Field = 53438638232309528389504892708671455233;\npub(crate) global PHI: Field = 64323764613183177041862057485226039389;\n\npub(crate) global TWO_POW_128: Field = 0x100000000000000000000000000000000;\n\n// Decomposes a single field into two 16 byte fields.\nfn compute_decomposition(x: Field) -> (Field, Field) {\n // Here's we're taking advantage of truncating 128 bit limbs from the input field\n // and then subtracting them from the input such the field division is equivalent to integer division.\n let low = (x as u128) as Field;\n let high = (x - low) / TWO_POW_128;\n\n (low, high)\n}\n\npub(crate) unconstrained fn decompose_hint(x: Field) -> (Field, Field) {\n compute_decomposition(x)\n}\n\nunconstrained fn lte_hint(x: Field, y: Field) -> bool {\n if x == y {\n true\n } else {\n field_less_than(x, y)\n }\n}\n\n// Assert that (alo > blo && ahi >= bhi) || (alo <= blo && ahi > bhi)\nfn assert_gt_limbs(a: (Field, Field), b: (Field, Field)) {\n let (alo, ahi) = a;\n let (blo, bhi) = b;\n // Safety: borrow is enforced to be boolean due to its type.\n // if borrow is 0, it asserts that (alo > blo && ahi >= bhi)\n // if borrow is 1, it asserts that (alo <= blo && ahi > bhi)\n unsafe {\n let borrow = lte_hint(alo, blo);\n\n let rlo = alo - blo - 1 + (borrow as Field) * TWO_POW_128;\n let rhi = ahi - bhi - (borrow as Field);\n\n rlo.assert_max_bit_size::<128>();\n rhi.assert_max_bit_size::<128>();\n }\n}\n\n/// Decompose a single field into two 16 byte fields.\npub fn decompose(x: Field) -> (Field, Field) {\n if is_unconstrained() {\n compute_decomposition(x)\n } else {\n // Safety: decomposition is properly checked below\n unsafe {\n // Take hints of the decomposition\n let (xlo, xhi) = decompose_hint(x);\n\n // Range check the limbs\n xlo.assert_max_bit_size::<128>();\n xhi.assert_max_bit_size::<128>();\n\n // Check that the decomposition is correct\n assert_eq(x, xlo + TWO_POW_128 * xhi);\n\n // Assert that the decomposition of P is greater than the decomposition of x\n assert_gt_limbs((PLO, PHI), (xlo, xhi));\n (xlo, xhi)\n }\n }\n}\n\npub fn assert_gt(a: Field, b: Field) {\n if is_unconstrained() {\n assert(\n // Safety: already unconstrained\n unsafe { field_less_than(b, a) },\n );\n } else {\n // Decompose a and b\n let a_limbs = decompose(a);\n let b_limbs = decompose(b);\n\n // Assert that a_limbs is greater than b_limbs\n assert_gt_limbs(a_limbs, b_limbs)\n }\n}\n\npub fn assert_lt(a: Field, b: Field) {\n assert_gt(b, a);\n}\n\npub fn gt(a: Field, b: Field) -> bool {\n if is_unconstrained() {\n // Safety: unsafe in unconstrained\n unsafe {\n field_less_than(b, a)\n }\n } else if a == b {\n false\n } else {\n // Safety: Take a hint of the comparison and verify it\n unsafe {\n if field_less_than(a, b) {\n assert_gt(b, a);\n false\n } else {\n assert_gt(a, b);\n true\n }\n }\n }\n}\n\npub fn lt(a: Field, b: Field) -> bool {\n gt(b, a)\n}\n\nmod tests {\n // TODO: Allow imports from \"super\"\n use crate::field::bn254::{assert_gt, decompose, gt, lt, lte_hint, PHI, PLO, TWO_POW_128};\n\n #[test]\n fn check_decompose() {\n assert_eq(decompose(TWO_POW_128), (0, 1));\n assert_eq(decompose(TWO_POW_128 + 0x1234567890), (0x1234567890, 1));\n assert_eq(decompose(0x1234567890), (0x1234567890, 0));\n }\n\n #[test]\n unconstrained fn check_lte_hint() {\n assert(lte_hint(0, 1));\n assert(lte_hint(0, 0x100));\n assert(lte_hint(0x100, TWO_POW_128 - 1));\n assert(!lte_hint(0 - 1, 0));\n\n assert(lte_hint(0, 0));\n assert(lte_hint(0x100, 0x100));\n assert(lte_hint(0 - 1, 0 - 1));\n }\n\n #[test]\n fn check_gt() {\n assert(gt(1, 0));\n assert(gt(0x100, 0));\n assert(gt((0 - 1), (0 - 2)));\n assert(gt(TWO_POW_128, 0));\n assert(!gt(0, 0));\n assert(!gt(0, 0x100));\n assert(gt(0 - 1, 0 - 2));\n assert(!gt(0 - 2, 0 - 1));\n assert_gt(0 - 1, 0);\n }\n\n #[test]\n fn check_plo_phi() {\n assert_eq(PLO + PHI * TWO_POW_128, 0);\n let p_bytes = crate::field::modulus_le_bytes();\n let mut p_low: Field = 0;\n let mut p_high: Field = 0;\n\n let mut offset = 1;\n for i in 0..16 {\n p_low += (p_bytes[i] as Field) * offset;\n p_high += (p_bytes[i + 16] as Field) * offset;\n offset *= 256;\n }\n assert_eq(p_low, PLO);\n assert_eq(p_high, PHI);\n }\n\n #[test]\n fn check_decompose_edge_cases() {\n assert_eq(decompose(0), (0, 0));\n assert_eq(decompose(TWO_POW_128 - 1), (TWO_POW_128 - 1, 0));\n assert_eq(decompose(TWO_POW_128 + 1), (1, 1));\n assert_eq(decompose(TWO_POW_128 * 2), (0, 2));\n assert_eq(decompose(TWO_POW_128 * 2 + 0x1234567890), (0x1234567890, 2));\n }\n\n #[test]\n fn check_decompose_large_values() {\n let large_field = 0xffffffffffffffff;\n let (lo, hi) = decompose(large_field);\n assert_eq(large_field, lo + TWO_POW_128 * hi);\n\n let large_value = large_field - TWO_POW_128;\n let (lo2, hi2) = decompose(large_value);\n assert_eq(large_value, lo2 + TWO_POW_128 * hi2);\n }\n\n #[test]\n fn check_lt_comprehensive() {\n assert(lt(0, 1));\n assert(!lt(1, 0));\n assert(!lt(0, 0));\n assert(!lt(42, 42));\n\n assert(lt(TWO_POW_128 - 1, TWO_POW_128));\n assert(!lt(TWO_POW_128, TWO_POW_128 - 1));\n }\n}\n" + }, + "170": { + "path": "/home/ubuntu/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.20251212/noir-projects/aztec-nr/aztec/src/oracle/capsules.nr", + "source": "use protocol_types::{address::AztecAddress, traits::{Deserialize, Serialize}};\n\n/// Stores arbitrary information in a per-contract non-volatile database, which can later be retrieved with `load`. If\n/// data was already stored at this slot, it is overwritten.\npub unconstrained fn store(contract_address: AztecAddress, slot: Field, value: T)\nwhere\n T: Serialize,\n{\n let serialized = value.serialize();\n store_oracle(contract_address, slot, serialized);\n}\n\n/// Returns data previously stored via `storeCapsule` in the per-contract non-volatile database. Returns Option::none() if\n/// nothing was stored at the given slot.\npub unconstrained fn load(contract_address: AztecAddress, slot: Field) -> Option\nwhere\n T: Deserialize,\n{\n let serialized_option = load_oracle(contract_address, slot, ::N);\n serialized_option.map(|arr| Deserialize::deserialize(arr))\n}\n\n/// Deletes data in the per-contract non-volatile database. Does nothing if no data was present.\npub unconstrained fn delete(contract_address: AztecAddress, slot: Field) {\n delete_oracle(contract_address, slot);\n}\n\n/// Copies a number of contiguous entries in the per-contract non-volatile database. This allows for efficient data\n/// structures by avoiding repeated calls to `loadCapsule` and `storeCapsule`.\n/// Supports overlapping source and destination regions (which will result in the overlapped source values being\n/// overwritten). All copied slots must exist in the database (i.e. have been stored and not deleted)\npub unconstrained fn copy(\n contract_address: AztecAddress,\n src_slot: Field,\n dst_slot: Field,\n num_entries: u32,\n) {\n copy_oracle(contract_address, src_slot, dst_slot, num_entries);\n}\n\n#[oracle(utilityStoreCapsule)]\nunconstrained fn store_oracle(\n contract_address: AztecAddress,\n slot: Field,\n values: [Field; N],\n) {}\n\n/// We need to pass in `array_len` (the value of N) as a parameter to tell the oracle how many fields the response must\n/// have.\n///\n/// Note that the oracle returns an Option<[Field; N]> because we cannot return an Option directly. That would\n/// require for the oracle resolver to know the shape of T (e.g. if T were a struct of 3 u32 values then the expected\n/// response shape would be 3 single items, whereas it were a struct containing `u32, [Field;10], u32` then the expected\n/// shape would be single, array, single.). Instead, we return the serialization and deserialize in Noir.\n#[oracle(utilityLoadCapsule)]\nunconstrained fn load_oracle(\n contract_address: AztecAddress,\n slot: Field,\n array_len: u32,\n) -> Option<[Field; N]> {}\n\n#[oracle(utilityDeleteCapsule)]\nunconstrained fn delete_oracle(contract_address: AztecAddress, slot: Field) {}\n\n#[oracle(utilityCopyCapsule)]\nunconstrained fn copy_oracle(\n contract_address: AztecAddress,\n src_slot: Field,\n dst_slot: Field,\n num_entries: u32,\n) {}\n\nmod test {\n // These tests are sort of redundant since we already test the oracle implementation directly in TypeScript, but\n // they are cheap regardless and help ensure both that the TXE implementation works accordingly and that the Noir\n // oracles are hooked up correctly.\n\n use crate::{\n oracle::capsules::{copy, delete, load, store},\n test::{helpers::test_environment::TestEnvironment, mocks::mock_struct::MockStruct},\n };\n use protocol_types::{address::AztecAddress, traits::{FromField, ToField}};\n\n global SLOT: Field = 1;\n\n #[test]\n unconstrained fn stores_and_loads() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n\n let value = MockStruct::new(5, 6);\n store(contract_address, SLOT, value);\n\n assert_eq(load(contract_address, SLOT).unwrap(), value);\n });\n }\n\n #[test]\n unconstrained fn store_overwrites() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n\n let value = MockStruct::new(5, 6);\n store(contract_address, SLOT, value);\n\n let new_value = MockStruct::new(7, 8);\n store(contract_address, SLOT, new_value);\n\n assert_eq(load(contract_address, SLOT).unwrap(), new_value);\n });\n }\n\n #[test]\n unconstrained fn loads_empty_slot() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n\n let loaded_value: Option = load(contract_address, SLOT);\n assert_eq(loaded_value, Option::none());\n });\n }\n\n #[test]\n unconstrained fn deletes_stored_value() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n\n let value = MockStruct::new(5, 6);\n store(contract_address, SLOT, value);\n delete(contract_address, SLOT);\n\n let loaded_value: Option = load(contract_address, SLOT);\n assert_eq(loaded_value, Option::none());\n });\n }\n\n #[test]\n unconstrained fn deletes_empty_slot() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n\n delete(contract_address, SLOT);\n let loaded_value: Option = load(contract_address, SLOT);\n assert_eq(loaded_value, Option::none());\n });\n }\n\n #[test]\n unconstrained fn copies_non_overlapping_values() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n\n let src = 5;\n\n let values = [MockStruct::new(5, 6), MockStruct::new(7, 8), MockStruct::new(9, 10)];\n store(contract_address, src, values[0]);\n store(contract_address, src + 1, values[1]);\n store(contract_address, src + 2, values[2]);\n\n let dst = 10;\n copy(contract_address, src, dst, 3);\n\n assert_eq(load(contract_address, dst).unwrap(), values[0]);\n assert_eq(load(contract_address, dst + 1).unwrap(), values[1]);\n assert_eq(load(contract_address, dst + 2).unwrap(), values[2]);\n });\n }\n\n #[test]\n unconstrained fn copies_overlapping_values_with_src_ahead() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n\n let src = 1;\n\n let values = [MockStruct::new(5, 6), MockStruct::new(7, 8), MockStruct::new(9, 10)];\n store(contract_address, src, values[0]);\n store(contract_address, src + 1, values[1]);\n store(contract_address, src + 2, values[2]);\n\n let dst = 2;\n copy(contract_address, src, dst, 3);\n\n assert_eq(load(contract_address, dst).unwrap(), values[0]);\n assert_eq(load(contract_address, dst + 1).unwrap(), values[1]);\n assert_eq(load(contract_address, dst + 2).unwrap(), values[2]);\n\n // src[1] and src[2] should have been overwritten since they are also dst[0] and dst[1]\n assert_eq(load(contract_address, src).unwrap(), values[0]); // src[0] (unchanged)\n assert_eq(load(contract_address, src + 1).unwrap(), values[0]); // dst[0]\n assert_eq(load(contract_address, src + 2).unwrap(), values[1]); // dst[1]\n });\n }\n\n #[test]\n unconstrained fn copies_overlapping_values_with_dst_ahead() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n\n let src = 2;\n\n let values = [MockStruct::new(5, 6), MockStruct::new(7, 8), MockStruct::new(9, 10)];\n store(contract_address, src, values[0]);\n store(contract_address, src + 1, values[1]);\n store(contract_address, src + 2, values[2]);\n\n let dst = 1;\n copy(contract_address, src, dst, 3);\n\n assert_eq(load(contract_address, dst).unwrap(), values[0]);\n assert_eq(load(contract_address, dst + 1).unwrap(), values[1]);\n assert_eq(load(contract_address, dst + 2).unwrap(), values[2]);\n\n // src[0] and src[1] should have been overwritten since they are also dst[1] and dst[2]\n assert_eq(load(contract_address, src).unwrap(), values[1]); // dst[1]\n assert_eq(load(contract_address, src + 1).unwrap(), values[2]); // dst[2]\n assert_eq(load(contract_address, src + 2).unwrap(), values[2]); // src[2] (unchanged)\n });\n }\n\n #[test(should_fail_with = \"copy empty slot\")]\n unconstrained fn cannot_copy_empty_values() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n\n copy(contract_address, SLOT, SLOT, 1);\n });\n }\n\n #[test(should_fail_with = \"not allowed to access\")]\n unconstrained fn cannot_store_other_contract() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n let other_contract_address = AztecAddress::from_field(contract_address.to_field() + 1);\n\n let value = MockStruct::new(5, 6);\n store(other_contract_address, SLOT, value);\n });\n }\n\n #[test(should_fail_with = \"not allowed to access\")]\n unconstrained fn cannot_load_other_contract() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n let other_contract_address = AztecAddress::from_field(contract_address.to_field() + 1);\n\n let _: Option = load(other_contract_address, SLOT);\n });\n }\n\n #[test(should_fail_with = \"not allowed to access\")]\n unconstrained fn cannot_delete_other_contract() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n let other_contract_address = AztecAddress::from_field(contract_address.to_field() + 1);\n\n delete(other_contract_address, SLOT);\n });\n }\n\n #[test(should_fail_with = \"not allowed to access\")]\n unconstrained fn cannot_copy_other_contract() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n let other_contract_address = AztecAddress::from_field(contract_address.to_field() + 1);\n\n copy(other_contract_address, SLOT, SLOT, 0);\n });\n }\n}\n" + }, + "172": { + "path": "/home/ubuntu/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.20251212/noir-projects/aztec-nr/aztec/src/oracle/execution.nr", + "source": "use crate::context::utility_context::UtilityContext;\n\n#[oracle(utilityGetUtilityContext)]\nunconstrained fn get_utility_context_oracle() -> UtilityContext {}\n\n/// Returns a utility context built from the global variables of anchor block and the contract address of the function\n/// being executed.\npub unconstrained fn get_utility_context() -> UtilityContext {\n get_utility_context_oracle()\n}\n" + }, + "174": { + "path": "/home/ubuntu/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.20251212/noir-projects/aztec-nr/aztec/src/oracle/get_contract_instance.nr", + "source": "use protocol_types::{\n address::AztecAddress, contract_class_id::ContractClassId, contract_instance::ContractInstance,\n traits::FromField,\n};\n\n// NOTE: this is for use in private only\n#[oracle(utilityGetContractInstance)]\nunconstrained fn get_contract_instance_oracle(_address: AztecAddress) -> ContractInstance {}\n\n// NOTE: this is for use in private only\nunconstrained fn get_contract_instance_internal(address: AztecAddress) -> ContractInstance {\n get_contract_instance_oracle(address)\n}\n\n// NOTE: this is for use in private only\npub fn get_contract_instance(address: AztecAddress) -> ContractInstance {\n // Safety: The to_address function combines all values in the instance object to produce an address,\n // so by checking that we get the expected address we validate the entire struct.\n let instance = unsafe { get_contract_instance_internal(address) };\n assert_eq(instance.to_address(), address);\n\n instance\n}\n\nstruct GetContractInstanceResult {\n exists: bool,\n member: Field,\n}\n\n// These oracles each return a ContractInstance member\n// plus a boolean indicating whether the instance was found.\n#[oracle(avmOpcodeGetContractInstanceDeployer)]\nunconstrained fn get_contract_instance_deployer_oracle_avm(\n _address: AztecAddress,\n) -> [GetContractInstanceResult; 1] {}\n#[oracle(avmOpcodeGetContractInstanceClassId)]\nunconstrained fn get_contract_instance_class_id_oracle_avm(\n _address: AztecAddress,\n) -> [GetContractInstanceResult; 1] {}\n#[oracle(avmOpcodeGetContractInstanceInitializationHash)]\nunconstrained fn get_contract_instance_initialization_hash_oracle_avm(\n _address: AztecAddress,\n) -> [GetContractInstanceResult; 1] {}\n\nunconstrained fn get_contract_instance_deployer_internal_avm(\n address: AztecAddress,\n) -> [GetContractInstanceResult; 1] {\n get_contract_instance_deployer_oracle_avm(address)\n}\nunconstrained fn get_contract_instance_class_id_internal_avm(\n address: AztecAddress,\n) -> [GetContractInstanceResult; 1] {\n get_contract_instance_class_id_oracle_avm(address)\n}\nunconstrained fn get_contract_instance_initialization_hash_internal_avm(\n address: AztecAddress,\n) -> [GetContractInstanceResult; 1] {\n get_contract_instance_initialization_hash_oracle_avm(address)\n}\n\npub fn get_contract_instance_deployer_avm(address: AztecAddress) -> Option {\n // Safety: AVM opcodes are constrained by the AVM itself\n let GetContractInstanceResult { exists, member } =\n unsafe { get_contract_instance_deployer_internal_avm(address)[0] };\n if exists {\n Option::some(AztecAddress::from_field(member))\n } else {\n Option::none()\n }\n}\npub fn get_contract_instance_class_id_avm(address: AztecAddress) -> Option {\n // Safety: AVM opcodes are constrained by the AVM itself\n let GetContractInstanceResult { exists, member } =\n unsafe { get_contract_instance_class_id_internal_avm(address)[0] };\n if exists {\n Option::some(ContractClassId::from_field(member))\n } else {\n Option::none()\n }\n}\npub fn get_contract_instance_initialization_hash_avm(address: AztecAddress) -> Option {\n // Safety: AVM opcodes are constrained by the AVM itself\n let GetContractInstanceResult { exists, member } =\n unsafe { get_contract_instance_initialization_hash_internal_avm(address)[0] };\n if exists {\n Option::some(member)\n } else {\n Option::none()\n }\n}\n" + }, + "179": { + "path": "/home/ubuntu/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.20251212/noir-projects/aztec-nr/aztec/src/oracle/key_validation_request.nr", + "source": "use protocol_types::abis::validation_requests::KeyValidationRequest;\n\n#[oracle(utilityGetKeyValidationRequest)]\nunconstrained fn get_key_validation_request_oracle(\n _pk_m_hash: Field,\n _key_index: Field,\n) -> KeyValidationRequest {}\n\npub unconstrained fn get_key_validation_request(\n pk_m_hash: Field,\n key_index: Field,\n) -> KeyValidationRequest {\n get_key_validation_request_oracle(pk_m_hash, key_index)\n}\n" + }, + "18": { + "path": "std/field/mod.nr", + "source": "pub mod bn254;\nuse crate::{runtime::is_unconstrained, static_assert};\nuse bn254::lt as bn254_lt;\n\nimpl Field {\n /// Asserts that `self` can be represented in `bit_size` bits.\n ///\n /// # Failures\n /// Causes a constraint failure for `Field` values exceeding `2^{bit_size}`.\n // docs:start:assert_max_bit_size\n pub fn assert_max_bit_size(self) {\n // docs:end:assert_max_bit_size\n static_assert(\n BIT_SIZE < modulus_num_bits() as u32,\n \"BIT_SIZE must be less than modulus_num_bits\",\n );\n __assert_max_bit_size(self, BIT_SIZE);\n }\n\n /// Decomposes `self` into its little endian bit decomposition as a `[u1; N]` array.\n /// This slice will be zero padded should not all bits be necessary to represent `self`.\n ///\n /// # Failures\n /// Causes a constraint failure for `Field` values exceeding `2^N` as the resulting slice will not\n /// be able to represent the original `Field`.\n ///\n /// # Safety\n /// The bit decomposition returned is canonical and is guaranteed to not overflow the modulus.\n // docs:start:to_le_bits\n pub fn to_le_bits(self: Self) -> [u1; N] {\n // docs:end:to_le_bits\n let bits = __to_le_bits(self);\n\n if !is_unconstrained() {\n // Ensure that the byte decomposition does not overflow the modulus\n let p = modulus_le_bits();\n assert(bits.len() <= p.len());\n let mut ok = bits.len() != p.len();\n for i in 0..N {\n if !ok {\n if (bits[N - 1 - i] != p[N - 1 - i]) {\n assert(p[N - 1 - i] == 1);\n ok = true;\n }\n }\n }\n assert(ok);\n }\n bits\n }\n\n /// Decomposes `self` into its big endian bit decomposition as a `[u1; N]` array.\n /// This array will be zero padded should not all bits be necessary to represent `self`.\n ///\n /// # Failures\n /// Causes a constraint failure for `Field` values exceeding `2^N` as the resulting slice will not\n /// be able to represent the original `Field`.\n ///\n /// # Safety\n /// The bit decomposition returned is canonical and is guaranteed to not overflow the modulus.\n // docs:start:to_be_bits\n pub fn to_be_bits(self: Self) -> [u1; N] {\n // docs:end:to_be_bits\n let bits = __to_be_bits(self);\n\n if !is_unconstrained() {\n // Ensure that the decomposition does not overflow the modulus\n let p = modulus_be_bits();\n assert(bits.len() <= p.len());\n let mut ok = bits.len() != p.len();\n for i in 0..N {\n if !ok {\n if (bits[i] != p[i]) {\n assert(p[i] == 1);\n ok = true;\n }\n }\n }\n assert(ok);\n }\n bits\n }\n\n /// Decomposes `self` into its little endian byte decomposition as a `[u8;N]` array\n /// This array will be zero padded should not all bytes be necessary to represent `self`.\n ///\n /// # Failures\n /// The length N of the array must be big enough to contain all the bytes of the 'self',\n /// and no more than the number of bytes required to represent the field modulus\n ///\n /// # Safety\n /// The result is ensured to be the canonical decomposition of the field element\n // docs:start:to_le_bytes\n pub fn to_le_bytes(self: Self) -> [u8; N] {\n // docs:end:to_le_bytes\n static_assert(\n N <= modulus_le_bytes().len(),\n \"N must be less than or equal to modulus_le_bytes().len()\",\n );\n // Compute the byte decomposition\n let bytes = self.to_le_radix(256);\n\n if !is_unconstrained() {\n // Ensure that the byte decomposition does not overflow the modulus\n let p = modulus_le_bytes();\n assert(bytes.len() <= p.len());\n let mut ok = bytes.len() != p.len();\n for i in 0..N {\n if !ok {\n if (bytes[N - 1 - i] != p[N - 1 - i]) {\n assert(bytes[N - 1 - i] < p[N - 1 - i]);\n ok = true;\n }\n }\n }\n assert(ok);\n }\n bytes\n }\n\n /// Decomposes `self` into its big endian byte decomposition as a `[u8;N]` array of length required to represent the field modulus\n /// This array will be zero padded should not all bytes be necessary to represent `self`.\n ///\n /// # Failures\n /// The length N of the array must be big enough to contain all the bytes of the 'self',\n /// and no more than the number of bytes required to represent the field modulus\n ///\n /// # Safety\n /// The result is ensured to be the canonical decomposition of the field element\n // docs:start:to_be_bytes\n pub fn to_be_bytes(self: Self) -> [u8; N] {\n // docs:end:to_be_bytes\n static_assert(\n N <= modulus_le_bytes().len(),\n \"N must be less than or equal to modulus_le_bytes().len()\",\n );\n // Compute the byte decomposition\n let bytes = self.to_be_radix(256);\n\n if !is_unconstrained() {\n // Ensure that the byte decomposition does not overflow the modulus\n let p = modulus_be_bytes();\n assert(bytes.len() <= p.len());\n let mut ok = bytes.len() != p.len();\n for i in 0..N {\n if !ok {\n if (bytes[i] != p[i]) {\n assert(bytes[i] < p[i]);\n ok = true;\n }\n }\n }\n assert(ok);\n }\n bytes\n }\n\n fn to_le_radix(self: Self, radix: u32) -> [u8; N] {\n // Brillig does not need an immediate radix\n if !crate::runtime::is_unconstrained() {\n static_assert(1 < radix, \"radix must be greater than 1\");\n static_assert(radix <= 256, \"radix must be less than or equal to 256\");\n static_assert(radix & (radix - 1) == 0, \"radix must be a power of 2\");\n }\n __to_le_radix(self, radix)\n }\n\n fn to_be_radix(self: Self, radix: u32) -> [u8; N] {\n // Brillig does not need an immediate radix\n if !crate::runtime::is_unconstrained() {\n static_assert(1 < radix, \"radix must be greater than 1\");\n static_assert(radix <= 256, \"radix must be less than or equal to 256\");\n static_assert(radix & (radix - 1) == 0, \"radix must be a power of 2\");\n }\n __to_be_radix(self, radix)\n }\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: [u1; 32] = exponent.to_le_bits();\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 `elem` {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 /// Convert a little endian byte array to a field element.\n /// If the provided byte array overflows the field modulus then the Field will silently wrap around.\n pub fn from_le_bytes(bytes: [u8; N]) -> Field {\n static_assert(\n N <= modulus_le_bytes().len(),\n \"N must be less than or equal to modulus_le_bytes().len()\",\n );\n let mut v = 1;\n let mut result = 0;\n\n for i in 0..N {\n result += (bytes[i] as Field) * v;\n v = v * 256;\n }\n result\n }\n\n /// Convert a big endian byte array to a field element.\n /// If the provided byte array overflows the field modulus then the Field will silently wrap around.\n pub fn from_be_bytes(bytes: [u8; N]) -> Field {\n let mut v = 1;\n let mut result = 0;\n\n for i in 0..N {\n result += (bytes[N - 1 - i] as Field) * v;\n v = v * 256;\n }\n result\n }\n}\n\n#[builtin(apply_range_constraint)]\nfn __assert_max_bit_size(value: Field, bit_size: u32) {}\n\n// `_radix` must be less than 256\n#[builtin(to_le_radix)]\nfn __to_le_radix(value: Field, radix: u32) -> [u8; N] {}\n\n// `_radix` must be less than 256\n#[builtin(to_be_radix)]\nfn __to_be_radix(value: Field, radix: u32) -> [u8; N] {}\n\n/// Decomposes `self` into its little endian bit decomposition as a `[u1; N]` array.\n/// This slice will be zero padded should not all bits be necessary to represent `self`.\n///\n/// # Failures\n/// Causes a constraint failure for `Field` values exceeding `2^N` as the resulting slice will not\n/// be able to represent the original `Field`.\n///\n/// # Safety\n/// Values of `N` equal to or greater than the number of bits necessary to represent the `Field` modulus\n/// (e.g. 254 for the BN254 field) allow for multiple bit decompositions. This is due to how the `Field` will\n/// wrap around due to overflow when verifying the decomposition.\n#[builtin(to_le_bits)]\nfn __to_le_bits(value: Field) -> [u1; N] {}\n\n/// Decomposes `self` into its big endian bit decomposition as a `[u1; N]` array.\n/// This array will be zero padded should not all bits be necessary to represent `self`.\n///\n/// # Failures\n/// Causes a constraint failure for `Field` values exceeding `2^N` as the resulting slice will not\n/// be able to represent the original `Field`.\n///\n/// # Safety\n/// Values of `N` equal to or greater than the number of bits necessary to represent the `Field` modulus\n/// (e.g. 254 for the BN254 field) allow for multiple bit decompositions. This is due to how the `Field` will\n/// wrap around due to overflow when verifying the decomposition.\n#[builtin(to_be_bits)]\nfn __to_be_bits(value: Field) -> [u1; N] {}\n\n#[builtin(modulus_num_bits)]\npub comptime fn modulus_num_bits() -> u64 {}\n\n#[builtin(modulus_be_bits)]\npub comptime fn modulus_be_bits() -> [u1] {}\n\n#[builtin(modulus_le_bits)]\npub comptime fn modulus_le_bits() -> [u1] {}\n\n#[builtin(modulus_be_bytes)]\npub comptime fn modulus_be_bytes() -> [u8] {}\n\n#[builtin(modulus_le_bytes)]\npub comptime fn modulus_le_bytes() -> [u8] {}\n\n/// An unconstrained only built in to efficiently compare fields.\n#[builtin(field_less_than)]\nunconstrained fn __field_less_than(x: Field, y: Field) -> bool {}\n\npub(crate) unconstrained fn field_less_than(x: Field, y: Field) -> bool {\n __field_less_than(x, y)\n}\n\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 if is_unconstrained() {\n // Safety: unconstrained context\n unsafe {\n field_less_than(x, y)\n }\n } else {\n let x_bytes: [u8; 32] = x.to_le_bytes();\n let y_bytes: [u8; 32] = y.to_le_bytes();\n let mut x_is_lt = false;\n let mut done = false;\n for i in 0..32 {\n if (!done) {\n let x_byte = x_bytes[32 - 1 - i] as u8;\n let y_byte = y_bytes[32 - 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\nmod tests {\n use crate::{panic::panic, runtime, static_assert};\n use super::{\n field_less_than, modulus_be_bits, modulus_be_bytes, modulus_le_bits, modulus_le_bytes,\n };\n\n #[test]\n // docs:start:to_be_bits_example\n fn test_to_be_bits() {\n let field = 2;\n let bits: [u1; 8] = field.to_be_bits();\n assert_eq(bits, [0, 0, 0, 0, 0, 0, 1, 0]);\n }\n // docs:end:to_be_bits_example\n\n #[test]\n // docs:start:to_le_bits_example\n fn test_to_le_bits() {\n let field = 2;\n let bits: [u1; 8] = field.to_le_bits();\n assert_eq(bits, [0, 1, 0, 0, 0, 0, 0, 0]);\n }\n // docs:end:to_le_bits_example\n\n #[test]\n // docs:start:to_be_bytes_example\n fn test_to_be_bytes() {\n let field = 2;\n let bytes: [u8; 8] = field.to_be_bytes();\n assert_eq(bytes, [0, 0, 0, 0, 0, 0, 0, 2]);\n assert_eq(Field::from_be_bytes::<8>(bytes), field);\n }\n // docs:end:to_be_bytes_example\n\n #[test]\n // docs:start:to_le_bytes_example\n fn test_to_le_bytes() {\n let field = 2;\n let bytes: [u8; 8] = field.to_le_bytes();\n assert_eq(bytes, [2, 0, 0, 0, 0, 0, 0, 0]);\n assert_eq(Field::from_le_bytes::<8>(bytes), field);\n }\n // docs:end:to_le_bytes_example\n\n #[test]\n // docs:start:to_be_radix_example\n fn test_to_be_radix() {\n // 259, in base 256, big endian, is [1, 3].\n // i.e. 3 * 256^0 + 1 * 256^1\n let field = 259;\n\n // The radix (in this example, 256) must be a power of 2.\n // The length of the returned byte array can be specified to be\n // >= the amount of space needed.\n let bytes: [u8; 8] = field.to_be_radix(256);\n assert_eq(bytes, [0, 0, 0, 0, 0, 0, 1, 3]);\n assert_eq(Field::from_be_bytes::<8>(bytes), field);\n }\n // docs:end:to_be_radix_example\n\n #[test]\n // docs:start:to_le_radix_example\n fn test_to_le_radix() {\n // 259, in base 256, little endian, is [3, 1].\n // i.e. 3 * 256^0 + 1 * 256^1\n let field = 259;\n\n // The radix (in this example, 256) must be a power of 2.\n // The length of the returned byte array can be specified to be\n // >= the amount of space needed.\n let bytes: [u8; 8] = field.to_le_radix(256);\n assert_eq(bytes, [3, 1, 0, 0, 0, 0, 0, 0]);\n assert_eq(Field::from_le_bytes::<8>(bytes), field);\n }\n // docs:end:to_le_radix_example\n\n #[test(should_fail_with = \"radix must be greater than 1\")]\n fn test_to_le_radix_1() {\n // this test should only fail in constrained mode\n if !runtime::is_unconstrained() {\n let field = 2;\n let _: [u8; 8] = field.to_le_radix(1);\n } else {\n panic(f\"radix must be greater than 1\");\n }\n }\n\n // Updated test to account for Brillig restriction that radix must be greater than 2\n #[test(should_fail_with = \"radix must be greater than 1\")]\n fn test_to_le_radix_brillig_1() {\n // this test should only fail in constrained mode\n if !runtime::is_unconstrained() {\n let field = 1;\n let _: [u8; 8] = field.to_le_radix(1);\n } else {\n panic(f\"radix must be greater than 1\");\n }\n }\n\n #[test(should_fail_with = \"radix must be a power of 2\")]\n fn test_to_le_radix_3() {\n // this test should only fail in constrained mode\n if !runtime::is_unconstrained() {\n let field = 2;\n let _: [u8; 8] = field.to_le_radix(3);\n } else {\n panic(f\"radix must be a power of 2\");\n }\n }\n\n #[test]\n fn test_to_le_radix_brillig_3() {\n // this test should only fail in constrained mode\n if runtime::is_unconstrained() {\n let field = 1;\n let out: [u8; 8] = field.to_le_radix(3);\n let mut expected = [0; 8];\n expected[0] = 1;\n assert(out == expected, \"unexpected result\");\n }\n }\n\n #[test(should_fail_with = \"radix must be less than or equal to 256\")]\n fn test_to_le_radix_512() {\n // this test should only fail in constrained mode\n if !runtime::is_unconstrained() {\n let field = 2;\n let _: [u8; 8] = field.to_le_radix(512);\n } else {\n panic(f\"radix must be less than or equal to 256\")\n }\n }\n\n #[test(should_fail_with = \"Field failed to decompose into specified 16 limbs\")]\n unconstrained fn not_enough_limbs_brillig() {\n let _: [u8; 16] = 0x100000000000000000000000000000000.to_le_bytes();\n }\n\n #[test(should_fail_with = \"Field failed to decompose into specified 16 limbs\")]\n fn not_enough_limbs() {\n let _: [u8; 16] = 0x100000000000000000000000000000000.to_le_bytes();\n }\n\n #[test]\n unconstrained fn test_field_less_than() {\n assert(field_less_than(0, 1));\n assert(field_less_than(0, 0x100));\n assert(field_less_than(0x100, 0 - 1));\n assert(!field_less_than(0 - 1, 0));\n }\n\n #[test]\n unconstrained fn test_large_field_values_unconstrained() {\n let large_field = 0xffffffffffffffff;\n\n let bits: [u1; 64] = large_field.to_le_bits();\n assert_eq(bits[0], 1);\n\n let bytes: [u8; 8] = large_field.to_le_bytes();\n assert_eq(Field::from_le_bytes::<8>(bytes), large_field);\n\n let radix_bytes: [u8; 8] = large_field.to_le_radix(256);\n assert_eq(Field::from_le_bytes::<8>(radix_bytes), large_field);\n }\n\n #[test]\n fn test_large_field_values() {\n let large_val = 0xffffffffffffffff;\n\n let bits: [u1; 64] = large_val.to_le_bits();\n assert_eq(bits[0], 1);\n\n let bytes: [u8; 8] = large_val.to_le_bytes();\n assert_eq(Field::from_le_bytes::<8>(bytes), large_val);\n\n let radix_bytes: [u8; 8] = large_val.to_le_radix(256);\n assert_eq(Field::from_le_bytes::<8>(radix_bytes), large_val);\n }\n\n #[test]\n fn test_decomposition_edge_cases() {\n let zero_bits: [u1; 8] = 0.to_le_bits();\n assert_eq(zero_bits, [0; 8]);\n\n let zero_bytes: [u8; 8] = 0.to_le_bytes();\n assert_eq(zero_bytes, [0; 8]);\n\n let one_bits: [u1; 8] = 1.to_le_bits();\n let expected: [u1; 8] = [1, 0, 0, 0, 0, 0, 0, 0];\n assert_eq(one_bits, expected);\n\n let pow2_bits: [u1; 8] = 4.to_le_bits();\n let expected: [u1; 8] = [0, 0, 1, 0, 0, 0, 0, 0];\n assert_eq(pow2_bits, expected);\n }\n\n #[test]\n fn test_pow_32() {\n assert_eq(2.pow_32(3), 8);\n assert_eq(3.pow_32(2), 9);\n assert_eq(5.pow_32(0), 1);\n assert_eq(7.pow_32(1), 7);\n\n assert_eq(2.pow_32(10), 1024);\n\n assert_eq(0.pow_32(5), 0);\n assert_eq(0.pow_32(0), 1);\n\n assert_eq(1.pow_32(100), 1);\n }\n\n #[test]\n fn test_sgn0() {\n assert_eq(0.sgn0(), 0);\n assert_eq(2.sgn0(), 0);\n assert_eq(4.sgn0(), 0);\n assert_eq(100.sgn0(), 0);\n\n assert_eq(1.sgn0(), 1);\n assert_eq(3.sgn0(), 1);\n assert_eq(5.sgn0(), 1);\n assert_eq(101.sgn0(), 1);\n }\n\n #[test(should_fail_with = \"Field failed to decompose into specified 8 limbs\")]\n fn test_bit_decomposition_overflow() {\n // 8 bits can't represent large field values\n let large_val = 0x1000000000000000;\n let _: [u1; 8] = large_val.to_le_bits();\n }\n\n #[test(should_fail_with = \"Field failed to decompose into specified 4 limbs\")]\n fn test_byte_decomposition_overflow() {\n // 4 bytes can't represent large field values\n let large_val = 0x1000000000000000;\n let _: [u8; 4] = large_val.to_le_bytes();\n }\n\n #[test]\n fn test_to_from_be_bytes_bn254_edge_cases() {\n if crate::compat::is_bn254() {\n // checking that decrementing this byte produces the expected 32 BE bytes for (modulus - 1)\n let mut p_minus_1_bytes: [u8; 32] = modulus_be_bytes().as_array();\n assert(p_minus_1_bytes[32 - 1] > 0);\n p_minus_1_bytes[32 - 1] -= 1;\n\n let p_minus_1 = Field::from_be_bytes::<32>(p_minus_1_bytes);\n assert_eq(p_minus_1 + 1, 0);\n\n // checking that converting (modulus - 1) from and then to 32 BE bytes produces the same bytes\n let p_minus_1_converted_bytes: [u8; 32] = p_minus_1.to_be_bytes();\n assert_eq(p_minus_1_converted_bytes, p_minus_1_bytes);\n\n // checking that incrementing this byte produces 32 BE bytes for (modulus + 1)\n let mut p_plus_1_bytes: [u8; 32] = modulus_be_bytes().as_array();\n assert(p_plus_1_bytes[32 - 1] < 255);\n p_plus_1_bytes[32 - 1] += 1;\n\n let p_plus_1 = Field::from_be_bytes::<32>(p_plus_1_bytes);\n assert_eq(p_plus_1, 1);\n\n // checking that converting p_plus_1 to 32 BE bytes produces the same\n // byte set to 1 as p_plus_1_bytes and otherwise zeroes\n let mut p_plus_1_converted_bytes: [u8; 32] = p_plus_1.to_be_bytes();\n assert_eq(p_plus_1_converted_bytes[32 - 1], 1);\n p_plus_1_converted_bytes[32 - 1] = 0;\n assert_eq(p_plus_1_converted_bytes, [0; 32]);\n\n // checking that Field::from_be_bytes::<32> on the Field modulus produces 0\n assert_eq(modulus_be_bytes().len(), 32);\n let p = Field::from_be_bytes::<32>(modulus_be_bytes().as_array());\n assert_eq(p, 0);\n\n // checking that converting 0 to 32 BE bytes produces 32 zeroes\n let p_bytes: [u8; 32] = 0.to_be_bytes();\n assert_eq(p_bytes, [0; 32]);\n }\n }\n\n #[test]\n fn test_to_from_le_bytes_bn254_edge_cases() {\n if crate::compat::is_bn254() {\n // checking that decrementing this byte produces the expected 32 LE bytes for (modulus - 1)\n let mut p_minus_1_bytes: [u8; 32] = modulus_le_bytes().as_array();\n assert(p_minus_1_bytes[0] > 0);\n p_minus_1_bytes[0] -= 1;\n\n let p_minus_1 = Field::from_le_bytes::<32>(p_minus_1_bytes);\n assert_eq(p_minus_1 + 1, 0);\n\n // checking that converting (modulus - 1) from and then to 32 BE bytes produces the same bytes\n let p_minus_1_converted_bytes: [u8; 32] = p_minus_1.to_le_bytes();\n assert_eq(p_minus_1_converted_bytes, p_minus_1_bytes);\n\n // checking that incrementing this byte produces 32 LE bytes for (modulus + 1)\n let mut p_plus_1_bytes: [u8; 32] = modulus_le_bytes().as_array();\n assert(p_plus_1_bytes[0] < 255);\n p_plus_1_bytes[0] += 1;\n\n let p_plus_1 = Field::from_le_bytes::<32>(p_plus_1_bytes);\n assert_eq(p_plus_1, 1);\n\n // checking that converting p_plus_1 to 32 LE bytes produces the same\n // byte set to 1 as p_plus_1_bytes and otherwise zeroes\n let mut p_plus_1_converted_bytes: [u8; 32] = p_plus_1.to_le_bytes();\n assert_eq(p_plus_1_converted_bytes[0], 1);\n p_plus_1_converted_bytes[0] = 0;\n assert_eq(p_plus_1_converted_bytes, [0; 32]);\n\n // checking that Field::from_le_bytes::<32> on the Field modulus produces 0\n assert_eq(modulus_le_bytes().len(), 32);\n let p = Field::from_le_bytes::<32>(modulus_le_bytes().as_array());\n assert_eq(p, 0);\n\n // checking that converting 0 to 32 LE bytes produces 32 zeroes\n let p_bytes: [u8; 32] = 0.to_le_bytes();\n assert_eq(p_bytes, [0; 32]);\n }\n }\n\n /// Convert a little endian bit array to a field element.\n /// If the provided bit array overflows the field modulus then the Field will silently wrap around.\n fn from_le_bits(bits: [u1; N]) -> Field {\n static_assert(\n N <= modulus_le_bits().len(),\n \"N must be less than or equal to modulus_le_bits().len()\",\n );\n let mut v = 1;\n let mut result = 0;\n\n for i in 0..N {\n result += (bits[i] as Field) * v;\n v = v * 2;\n }\n result\n }\n\n /// Convert a big endian bit array to a field element.\n /// If the provided bit array overflows the field modulus then the Field will silently wrap around.\n fn from_be_bits(bits: [u1; N]) -> Field {\n let mut v = 1;\n let mut result = 0;\n\n for i in 0..N {\n result += (bits[N - 1 - i] as Field) * v;\n v = v * 2;\n }\n result\n }\n\n #[test]\n fn test_to_from_be_bits_bn254_edge_cases() {\n if crate::compat::is_bn254() {\n // checking that decrementing this bit produces the expected 254 BE bits for (modulus - 1)\n let mut p_minus_1_bits: [u1; 254] = modulus_be_bits().as_array();\n assert(p_minus_1_bits[254 - 1] > 0);\n p_minus_1_bits[254 - 1] -= 1;\n\n let p_minus_1 = from_be_bits::<254>(p_minus_1_bits);\n assert_eq(p_minus_1 + 1, 0);\n\n // checking that converting (modulus - 1) from and then to 254 BE bits produces the same bits\n let p_minus_1_converted_bits: [u1; 254] = p_minus_1.to_be_bits();\n assert_eq(p_minus_1_converted_bits, p_minus_1_bits);\n\n // checking that incrementing this bit produces 254 BE bits for (modulus + 4)\n let mut p_plus_4_bits: [u1; 254] = modulus_be_bits().as_array();\n assert(p_plus_4_bits[254 - 3] < 1);\n p_plus_4_bits[254 - 3] += 1;\n\n let p_plus_4 = from_be_bits::<254>(p_plus_4_bits);\n assert_eq(p_plus_4, 4);\n\n // checking that converting p_plus_4 to 254 BE bits produces the same\n // bit set to 1 as p_plus_4_bits and otherwise zeroes\n let mut p_plus_4_converted_bits: [u1; 254] = p_plus_4.to_be_bits();\n assert_eq(p_plus_4_converted_bits[254 - 3], 1);\n p_plus_4_converted_bits[254 - 3] = 0;\n assert_eq(p_plus_4_converted_bits, [0; 254]);\n\n // checking that Field::from_be_bits::<254> on the Field modulus produces 0\n assert_eq(modulus_be_bits().len(), 254);\n let p = from_be_bits::<254>(modulus_be_bits().as_array());\n assert_eq(p, 0);\n\n // checking that converting 0 to 254 BE bytes produces 254 zeroes\n let p_bits: [u1; 254] = 0.to_be_bits();\n assert_eq(p_bits, [0; 254]);\n }\n }\n\n #[test]\n fn test_to_from_le_bits_bn254_edge_cases() {\n if crate::compat::is_bn254() {\n // checking that decrementing this bit produces the expected 254 LE bits for (modulus - 1)\n let mut p_minus_1_bits: [u1; 254] = modulus_le_bits().as_array();\n assert(p_minus_1_bits[0] > 0);\n p_minus_1_bits[0] -= 1;\n\n let p_minus_1 = from_le_bits::<254>(p_minus_1_bits);\n assert_eq(p_minus_1 + 1, 0);\n\n // checking that converting (modulus - 1) from and then to 254 BE bits produces the same bits\n let p_minus_1_converted_bits: [u1; 254] = p_minus_1.to_le_bits();\n assert_eq(p_minus_1_converted_bits, p_minus_1_bits);\n\n // checking that incrementing this bit produces 254 LE bits for (modulus + 4)\n let mut p_plus_4_bits: [u1; 254] = modulus_le_bits().as_array();\n assert(p_plus_4_bits[2] < 1);\n p_plus_4_bits[2] += 1;\n\n let p_plus_4 = from_le_bits::<254>(p_plus_4_bits);\n assert_eq(p_plus_4, 4);\n\n // checking that converting p_plus_4 to 254 LE bits produces the same\n // bit set to 1 as p_plus_4_bits and otherwise zeroes\n let mut p_plus_4_converted_bits: [u1; 254] = p_plus_4.to_le_bits();\n assert_eq(p_plus_4_converted_bits[2], 1);\n p_plus_4_converted_bits[2] = 0;\n assert_eq(p_plus_4_converted_bits, [0; 254]);\n\n // checking that Field::from_le_bits::<254> on the Field modulus produces 0\n assert_eq(modulus_le_bits().len(), 254);\n let p = from_le_bits::<254>(modulus_le_bits().as_array());\n assert_eq(p, 0);\n\n // checking that converting 0 to 254 LE bytes produces 254 zeroes\n let p_bits: [u1; 254] = 0.to_le_bits();\n assert_eq(p_bits, [0; 254]);\n }\n }\n}\n" + }, + "180": { + "path": "/home/ubuntu/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.20251212/noir-projects/aztec-nr/aztec/src/oracle/keys.nr", + "source": "use dep::protocol_types::{\n address::{AztecAddress, PartialAddress},\n point::Point,\n public_keys::{IvpkM, NpkM, OvpkM, PublicKeys, TpkM},\n};\n\n#[oracle(utilityGetPublicKeysAndPartialAddress)]\nunconstrained fn get_public_keys_and_partial_address_oracle(_address: AztecAddress) -> [Field; 13] {}\n\npub unconstrained fn get_public_keys_and_partial_address(\n address: AztecAddress,\n) -> (PublicKeys, PartialAddress) {\n let result = get_public_keys_and_partial_address_oracle(address);\n\n let keys = PublicKeys {\n npk_m: NpkM { inner: Point { x: result[0], y: result[1], is_infinite: result[2] != 0 } },\n ivpk_m: IvpkM { inner: Point { x: result[3], y: result[4], is_infinite: result[5] != 0 } },\n ovpk_m: OvpkM { inner: Point { x: result[6], y: result[7], is_infinite: result[8] != 0 } },\n tpk_m: TpkM { inner: Point { x: result[9], y: result[10], is_infinite: result[11] != 0 } },\n };\n\n let partial_address = PartialAddress::from_field(result[12]);\n\n (keys, partial_address)\n}\n" + }, + "182": { + "path": "/home/ubuntu/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.20251212/noir-projects/aztec-nr/aztec/src/oracle/message_processing.nr", + "source": "use protocol_types::address::AztecAddress;\n\n/// Finds new private logs that may have been sent to all registered accounts in PXE in the current contract and makes\n/// them available for later processing in Noir by storing them in a capsule array.\npub unconstrained fn fetch_tagged_logs(pending_tagged_log_array_base_slot: Field) {\n fetch_tagged_logs_oracle(pending_tagged_log_array_base_slot);\n}\n\n#[oracle(utilityFetchTaggedLogs)]\nunconstrained fn fetch_tagged_logs_oracle(pending_tagged_log_array_base_slot: Field) {}\n\n// This must be a single oracle and not one for notes and one for events because the entire point is to validate\n// all notes and events in one go, minimizing node round-trips.\npub(crate) unconstrained fn validate_enqueued_notes_and_events(\n contract_address: AztecAddress,\n note_validation_requests_array_base_slot: Field,\n event_validation_requests_array_base_slot: Field,\n) {\n validate_enqueued_notes_and_events_oracle(\n contract_address,\n note_validation_requests_array_base_slot,\n event_validation_requests_array_base_slot,\n );\n}\n\n#[oracle(utilityValidateEnqueuedNotesAndEvents)]\nunconstrained fn validate_enqueued_notes_and_events_oracle(\n contract_address: AztecAddress,\n note_validation_requests_array_base_slot: Field,\n event_validation_requests_array_base_slot: Field,\n) {}\n\npub(crate) unconstrained fn bulk_retrieve_logs(\n contract_address: AztecAddress,\n log_retrieval_requests_array_base_slot: Field,\n log_retrieval_responses_array_base_slot: Field,\n) {\n bulk_retrieve_logs_oracle(\n contract_address,\n log_retrieval_requests_array_base_slot,\n log_retrieval_responses_array_base_slot,\n );\n}\n\n#[oracle(utilityBulkRetrieveLogs)]\nunconstrained fn bulk_retrieve_logs_oracle(\n contract_address: AztecAddress,\n log_retrieval_requests_array_base_slot: Field,\n log_retrieval_responses_array_base_slot: Field,\n) {}\n" + }, + "187": { + "path": "/home/ubuntu/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.20251212/noir-projects/aztec-nr/aztec/src/oracle/shared_secret.nr", + "source": "use protocol_types::{address::aztec_address::AztecAddress, point::Point};\n\n// TODO(#12656): return an app-siloed secret + document this\n#[oracle(utilityGetSharedSecret)]\nunconstrained fn get_shared_secret_oracle(address: AztecAddress, ephPk: Point) -> Point {}\n\n/// Returns an app-siloed shared secret between `address` and someone who knows the secret key behind an\n/// ephemeral public key `ephPk`. The app-siloing means that contracts cannot retrieve secrets that belong to\n/// other contracts, and therefore cannot e.g. decrypt their messages. This is an important security consideration\n/// given that both the `address` and `ephPk` are public information.\n///\n/// The shared secret `S` is computed as:\n/// `let S = (ivsk + h) * ephPk`\n/// where `ivsk + h` is the 'preaddress' i.e. the preimage of the address, also called the address secret.\n/// TODO(#12656): app-silo this secret\npub unconstrained fn get_shared_secret(address: AztecAddress, ephPk: Point) -> Point {\n get_shared_secret_oracle(address, ephPk)\n}\n" + }, + "19": { + "path": "std/hash/mod.nr", + "source": "// Exposed only for usage in `std::meta`\npub(crate) mod poseidon2;\n\nuse crate::default::Default;\nuse crate::embedded_curve_ops::{\n EmbeddedCurvePoint, EmbeddedCurveScalar, multi_scalar_mul, multi_scalar_mul_array_return,\n};\nuse crate::meta::derive_via;\n\n#[foreign(sha256_compression)]\n// docs:start:sha256_compression\npub fn sha256_compression(input: [u32; 16], state: [u32; 8]) -> [u32; 8] {}\n// docs:end:sha256_compression\n\n#[foreign(keccakf1600)]\n// docs:start:keccakf1600\npub fn keccakf1600(input: [u64; 25]) -> [u64; 25] {}\n// docs:end:keccakf1600\n\npub mod keccak {\n #[deprecated(\"This function has been moved to std::hash::keccakf1600\")]\n pub fn keccakf1600(input: [u64; 25]) -> [u64; 25] {\n super::keccakf1600(input)\n }\n}\n\n#[foreign(blake2s)]\n// docs:start:blake2s\npub fn blake2s(input: [u8; N]) -> [u8; 32]\n// docs:end:blake2s\n{}\n\n// docs:start:blake3\npub fn blake3(input: [u8; N]) -> [u8; 32]\n// docs:end:blake3\n{\n if crate::runtime::is_unconstrained() {\n // Temporary measure while Barretenberg is main proving system.\n // Please open an issue if you're working on another proving system and running into problems due to this.\n crate::static_assert(\n N <= 1024,\n \"Barretenberg cannot prove blake3 hashes with inputs larger than 1024 bytes\",\n );\n }\n __blake3(input)\n}\n\n#[foreign(blake3)]\nfn __blake3(input: [u8; N]) -> [u8; 32] {}\n\n// docs:start:pedersen_commitment\npub fn pedersen_commitment(input: [Field; N]) -> EmbeddedCurvePoint {\n // docs:end:pedersen_commitment\n pedersen_commitment_with_separator(input, 0)\n}\n\n#[inline_always]\npub fn pedersen_commitment_with_separator(\n input: [Field; N],\n separator: u32,\n) -> EmbeddedCurvePoint {\n let mut points = [EmbeddedCurveScalar { lo: 0, hi: 0 }; N];\n for i in 0..N {\n // we use the unsafe version because the multi_scalar_mul will constrain the scalars.\n points[i] = from_field_unsafe(input[i]);\n }\n let generators = derive_generators(\"DEFAULT_DOMAIN_SEPARATOR\".as_bytes(), separator);\n multi_scalar_mul(generators, points)\n}\n\n// docs:start:pedersen_hash\npub fn pedersen_hash(input: [Field; N]) -> Field\n// docs:end:pedersen_hash\n{\n pedersen_hash_with_separator(input, 0)\n}\n\n#[no_predicates]\npub fn pedersen_hash_with_separator(input: [Field; N], separator: u32) -> Field {\n let mut scalars: [EmbeddedCurveScalar; N + 1] = [EmbeddedCurveScalar { lo: 0, hi: 0 }; N + 1];\n let mut generators: [EmbeddedCurvePoint; N + 1] =\n [EmbeddedCurvePoint::point_at_infinity(); N + 1];\n let domain_generators: [EmbeddedCurvePoint; N] =\n derive_generators(\"DEFAULT_DOMAIN_SEPARATOR\".as_bytes(), separator);\n\n for i in 0..N {\n scalars[i] = from_field_unsafe(input[i]);\n generators[i] = domain_generators[i];\n }\n scalars[N] = EmbeddedCurveScalar { lo: N as Field, hi: 0 as Field };\n\n let length_generator: [EmbeddedCurvePoint; 1] =\n derive_generators(\"pedersen_hash_length\".as_bytes(), 0);\n generators[N] = length_generator[0];\n multi_scalar_mul_array_return(generators, scalars, true)[0].x\n}\n\n#[field(bn254)]\n#[inline_always]\npub fn derive_generators(\n domain_separator_bytes: [u8; M],\n starting_index: u32,\n) -> [EmbeddedCurvePoint; N] {\n crate::assert_constant(domain_separator_bytes);\n // TODO(https://github.com/noir-lang/noir/issues/5672): Add back assert_constant on starting_index\n __derive_generators(domain_separator_bytes, starting_index)\n}\n\n#[builtin(derive_pedersen_generators)]\n#[field(bn254)]\nfn __derive_generators(\n domain_separator_bytes: [u8; M],\n starting_index: u32,\n) -> [EmbeddedCurvePoint; N] {}\n\n#[field(bn254)]\n// Decompose the input 'bn254 scalar' into two 128 bits limbs.\n// It is called 'unsafe' because it does not assert the limbs are 128 bits\n// Assuming the limbs are 128 bits:\n// Assert the decomposition does not overflow the field size.\nfn from_field_unsafe(scalar: Field) -> EmbeddedCurveScalar {\n // Safety: xlo and xhi decomposition is checked below\n let (xlo, xhi) = unsafe { crate::field::bn254::decompose_hint(scalar) };\n // Check that the decomposition is correct\n assert_eq(scalar, xlo + crate::field::bn254::TWO_POW_128 * xhi);\n // Check that the decomposition does not overflow the field size\n let (a, b) = if xhi == crate::field::bn254::PHI {\n (xlo, crate::field::bn254::PLO)\n } else {\n (xhi, crate::field::bn254::PHI)\n };\n crate::field::bn254::assert_lt(a, b);\n\n EmbeddedCurveScalar { lo: xlo, hi: xhi }\n}\n\npub fn poseidon2_permutation(input: [Field; N], state_len: u32) -> [Field; N] {\n assert_eq(input.len(), state_len);\n poseidon2_permutation_internal(input)\n}\n\n#[foreign(poseidon2_permutation)]\nfn poseidon2_permutation_internal(input: [Field; N]) -> [Field; N] {}\n\n// Generic hashing support.\n// Partially ported and impacted by rust.\n\n// Hash trait shall be implemented per type.\n#[derive_via(derive_hash)]\npub trait Hash {\n fn hash(self, state: &mut H)\n where\n H: Hasher;\n}\n\n// docs:start:derive_hash\ncomptime fn derive_hash(s: TypeDefinition) -> Quoted {\n let name = quote { $crate::hash::Hash };\n let signature = quote { fn hash(_self: Self, _state: &mut H) where H: $crate::hash::Hasher };\n let for_each_field = |name| quote { _self.$name.hash(_state); };\n crate::meta::make_trait_impl(\n s,\n name,\n signature,\n for_each_field,\n quote {},\n |fields| fields,\n )\n}\n// docs:end:derive_hash\n\n// Hasher trait shall be implemented by algorithms to provide hash-agnostic means.\n// TODO: consider making the types generic here ([u8], [Field], etc.)\npub trait Hasher {\n fn finish(self) -> Field;\n\n fn write(&mut self, input: Field);\n}\n\n// BuildHasher is a factory trait, responsible for production of specific Hasher.\npub trait BuildHasher {\n type H: Hasher;\n\n fn build_hasher(self) -> H;\n}\n\npub struct BuildHasherDefault;\n\nimpl BuildHasher for BuildHasherDefault\nwhere\n H: Hasher + Default,\n{\n type H = H;\n\n fn build_hasher(_self: Self) -> H {\n H::default()\n }\n}\n\nimpl Default for BuildHasherDefault\nwhere\n H: Hasher + Default,\n{\n fn default() -> Self {\n BuildHasherDefault {}\n }\n}\n\nimpl Hash for Field {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self);\n }\n}\n\nimpl Hash for u1 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u8 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u16 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u32 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u64 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u128 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for i8 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u8 as Field);\n }\n}\n\nimpl Hash for i16 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u16 as Field);\n }\n}\n\nimpl Hash for i32 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u32 as Field);\n }\n}\n\nimpl Hash for i64 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u64 as Field);\n }\n}\n\nimpl Hash for bool {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for () {\n fn hash(_self: Self, _state: &mut H)\n where\n H: Hasher,\n {}\n}\n\nimpl Hash for [T; N]\nwhere\n T: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n for elem in self {\n elem.hash(state);\n }\n }\n}\n\nimpl Hash for [T]\nwhere\n T: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n self.len().hash(state);\n for elem in self {\n elem.hash(state);\n }\n }\n}\n\nimpl Hash for (A, B)\nwhere\n A: Hash,\n B: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n }\n}\n\nimpl Hash for (A, B, C)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n }\n}\n\nimpl Hash for (A, B, C, D)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n D: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n self.3.hash(state);\n }\n}\n\nimpl Hash for (A, B, C, D, E)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n D: Hash,\n E: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n self.3.hash(state);\n self.4.hash(state);\n }\n}\n\n// Some test vectors for Pedersen hash and Pedersen Commitment.\n// They have been generated using the same functions so the tests are for now useless\n// but they will be useful when we switch to Noir implementation.\n#[test]\nfn assert_pedersen() {\n assert_eq(\n pedersen_hash_with_separator([1], 1),\n 0x1b3f4b1a83092a13d8d1a59f7acb62aba15e7002f4440f2275edb99ebbc2305f,\n );\n assert_eq(\n pedersen_commitment_with_separator([1], 1),\n EmbeddedCurvePoint {\n x: 0x054aa86a73cb8a34525e5bbed6e43ba1198e860f5f3950268f71df4591bde402,\n y: 0x209dcfbf2cfb57f9f6046f44d71ac6faf87254afc7407c04eb621a6287cac126,\n is_infinite: false,\n },\n );\n\n assert_eq(\n pedersen_hash_with_separator([1, 2], 2),\n 0x26691c129448e9ace0c66d11f0a16d9014a9e8498ee78f4d69f0083168188255,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2], 2),\n EmbeddedCurvePoint {\n x: 0x2e2b3b191e49541fe468ec6877721d445dcaffe41728df0a0eafeb15e87b0753,\n y: 0x2ff4482400ad3a6228be17a2af33e2bcdf41be04795f9782bd96efe7e24f8778,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3], 3),\n 0x0bc694b7a1f8d10d2d8987d07433f26bd616a2d351bc79a3c540d85b6206dbe4,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3], 3),\n EmbeddedCurvePoint {\n x: 0x1fee4e8cf8d2f527caa2684236b07c4b1bad7342c01b0f75e9a877a71827dc85,\n y: 0x2f9fedb9a090697ab69bf04c8bc15f7385b3e4b68c849c1536e5ae15ff138fd1,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4], 4),\n 0xdae10fb32a8408521803905981a2b300d6a35e40e798743e9322b223a5eddc,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4], 4),\n EmbeddedCurvePoint {\n x: 0x07ae3e202811e1fca39c2d81eabe6f79183978e6f12be0d3b8eda095b79bdbc9,\n y: 0x0afc6f892593db6fbba60f2da558517e279e0ae04f95758587760ba193145014,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5], 5),\n 0xfc375b062c4f4f0150f7100dfb8d9b72a6d28582dd9512390b0497cdad9c22,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5], 5),\n EmbeddedCurvePoint {\n x: 0x1754b12bd475a6984a1094b5109eeca9838f4f81ac89c5f0a41dbce53189bb29,\n y: 0x2da030e3cfcdc7ddad80eaf2599df6692cae0717d4e9f7bfbee8d073d5d278f7,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6], 6),\n 0x1696ed13dc2730062a98ac9d8f9de0661bb98829c7582f699d0273b18c86a572,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6], 6),\n EmbeddedCurvePoint {\n x: 0x190f6c0e97ad83e1e28da22a98aae156da083c5a4100e929b77e750d3106a697,\n y: 0x1f4b60f34ef91221a0b49756fa0705da93311a61af73d37a0c458877706616fb,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7], 7),\n 0x128c0ff144fc66b6cb60eeac8a38e23da52992fc427b92397a7dffd71c45ede3,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7], 7),\n EmbeddedCurvePoint {\n x: 0x015441e9d29491b06563fac16fc76abf7a9534c715421d0de85d20dbe2965939,\n y: 0x1d2575b0276f4e9087e6e07c2cb75aa1baafad127af4be5918ef8a2ef2fea8fc,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7, 8], 8),\n 0x2f960e117482044dfc99d12fece2ef6862fba9242be4846c7c9a3e854325a55c,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7, 8], 8),\n EmbeddedCurvePoint {\n x: 0x1657737676968887fceb6dd516382ea13b3a2c557f509811cd86d5d1199bc443,\n y: 0x1f39f0cb569040105fa1e2f156521e8b8e08261e635a2b210bdc94e8d6d65f77,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9], 9),\n 0x0c96db0790602dcb166cc4699e2d306c479a76926b81c2cb2aaa92d249ec7be7,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9], 9),\n EmbeddedCurvePoint {\n x: 0x0a3ceae42d14914a432aa60ec7fded4af7dad7dd4acdbf2908452675ec67e06d,\n y: 0xfc19761eaaf621ad4aec9a8b2e84a4eceffdba78f60f8b9391b0bd9345a2f2,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 10),\n 0x2cd37505871bc460a62ea1e63c7fe51149df5d0801302cf1cbc48beb8dff7e94,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 10),\n EmbeddedCurvePoint {\n x: 0x2fb3f8b3d41ddde007c8c3c62550f9a9380ee546fcc639ffbb3fd30c8d8de30c,\n y: 0x300783be23c446b11a4c0fabf6c91af148937cea15fcf5fb054abf7f752ee245,\n is_infinite: false,\n },\n );\n}\n" + }, + "193": { + "path": "/home/ubuntu/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.20251212/noir-projects/aztec-nr/aztec/src/state_vars/map.nr", + "source": "use crate::state_vars::state_variable::StateVariable;\nuse dep::protocol_types::{storage::map::derive_storage_slot_in_map, traits::ToField};\n\n/// Map\n///\n/// A key-value storage container that maps keys to state variables, similar\n/// to Solidity mappings.\n///\n/// `Map` enables you to associate keys (like addresses or other identifiers)\n/// with state variables in your Aztec smart contract. This is conceptually\n/// similar to Solidity's `mapping(K => V)` syntax, where you can store and\n/// retrieve values by their associated keys.\n///\n/// You can declare a state variable contained within a Map in your contract's\n/// #[storage] struct.\n///\n/// For example, you might use\n/// `Map, Context>` to track\n/// token balances for different users, similar to how you'd use\n/// `mapping(address => uint256)` in Solidity.\n///\n/// > Aside: the verbose `Context` in the declaration is a consequence of\n/// > leveraging Noir's regular syntax for generics to ensure that certain\n/// > state variable methods can only be called in some contexts (private,\n/// > public, utility).\n///\n/// The methods of Map are:\n/// - `at` (access state variable for a given key)\n/// (see the method's own doc comments for more info).\n///\n/// ## Generic Parameters\n/// - `K`: The key type (must implement `ToField` trait for hashing)\n/// - `V`: The value type:\n/// - any Aztec state variable (variable that implements the StateVariable trait):\n/// - `PublicMutable`\n/// - `PublicImmutable`\n/// - `DelayedPublicMutable`\n/// - `Map`\n/// - `Context`: The execution context (handles private/public function\n/// contexts)\n///\n/// ## Usage\n/// Maps are typically declared in your contract's #[storage] struct and\n/// accessed\n/// using the `at(key)` method to get the state variable for a specific key.\n/// The resulting state variable can then be read from or written to using its\n/// own methods.\n///\n/// Note that maps cannot be used with owned state variables (variables that\n/// implement the OwnedStateVariable trait) - those need to be wrapped in an\n/// `Owned` state variable instead.\n///\n/// ## Advanced\n/// Internally, `Map` uses a single base storage slot to represent the\n/// mapping\n/// itself, similar to Solidity's approach. Individual key-value pairs are\n/// stored at derived storage slots computed by hashing the base storage\n/// slot\n/// with the key using Poseidon2. This ensures:\n/// - No storage slot collisions between different keys\n/// - Uniform distribution of storage slots across the storage space\n/// - Compatibility with Aztec's storage tree structure\n/// - Gas-efficient storage access patterns similar to Solidity mappings\n///\n/// The storage slot derivation uses `derive_storage_slot_in_map(base_slot,\n/// key)` which computes `poseidon2_hash([base_slot, key.to_field()])`,\n/// ensuring cryptographically secure slot separation.\n///\n/// docs:start:map\npub struct Map {\n pub context: Context,\n storage_slot: Field,\n}\n\n// Map reserves a single storage slot regardless of what it stores because\n// nothing is stored at said slot: it is only used to derive the storage slots\n// of nested state variables, which is expected to never result in collisions\n// or slots being close to one another due to these being hashes. This mirrors\n// the strategy adopted by Solidity mappings.\nimpl StateVariable<1, Context> for Map {\n 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 Map { context, storage_slot }\n }\n\n fn get_storage_slot(self) -> Field {\n self.storage_slot\n }\n}\n\nimpl Map {\n /// Returns the state variable associated with the given key.\n ///\n /// This is equivalent to accessing `mapping[key]` in Solidity. It returns\n /// the state variable instance for the specified key, which can then be\n /// used to read or write the value at that key.\n ///\n /// Unlike Solidity mappings which return the value directly, this returns\n /// the state variable wrapper (like PublicMutable, nested Map etc.)\n /// that you then call methods on to interact with the actual value.\n ///\n /// # Arguments\n ///\n /// * `key` - The key to look up in the map. Must implement the ToField\n /// trait (which most basic Noir & Aztec types do).\n ///\n /// # Returns\n ///\n /// * `V` - The state variable instance for this key. You can then call\n /// methods like `.read()`, `.write()`, `.get_note()`, etc. on this\n /// depending on the specific state variable type.\n ///\n /// # Example\n ///\n /// ```noir\n /// // Get a user's balance (assuming PrivateMutable)\n /// let user_balance = self.storage.balances.at(user_address);\n /// let current_note = user_balance.get_note();\n ///\n /// // Update the balance\n /// user_balance.replace(new_note);\n /// ```\n ///\n pub fn at(self, key: K) -> V\n where\n K: ToField,\n V: StateVariable,\n {\n V::new(\n self.context,\n derive_storage_slot_in_map(self.storage_slot, key),\n )\n }\n}\n" + }, + "205": { + "path": "/home/ubuntu/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.20251212/noir-projects/aztec-nr/aztec/src/state_vars/public_mutable.nr", + "source": "use crate::context::{PublicContext, UtilityContext};\nuse crate::state_vars::state_variable::StateVariable;\nuse dep::protocol_types::traits::Packable;\n\n/// # PublicMutable\n///\n/// PublicMutable is a public state variable type for values that can be read\n/// and written within #[external(\"public\")] functions of your smart contract.\n///\n/// You can declare a state variable of type PublicMutable within your contract's\n/// #[storage] struct:\n///\n/// E.g.:\n/// `your_variable: PublicMutable`\n/// or:\n/// `your_mapping: Map>`\n///\n/// The methods of PublicMutable are:\n/// - `read`\n/// - `write`\n/// (see the methods' own doc comments for more info).\n///\n/// ## Example.\n///\n/// A voting contract's proposal count can be represented as a PublicMutable.\n/// The count can be read by anyone to see how many proposals exist, and incremented\n/// when new proposals are submitted.\n///\n/// # Generic Parameters:\n///\n/// * `T` - The type of value stored (must implement Packable).\n/// * `Context` - The execution context (PublicContext or UtilityContext).\n///\n/// # Advanced\n///\n/// Unlike private state variables which use notes, PublicMutable stores values\n/// directly in Aztec's public data tree. This enables direct read and write\n/// access to the current state during public function execution.\n///\n/// docs:start:public_mutable_struct\npub struct PublicMutable {\n context: Context,\n storage_slot: Field,\n}\n\nimpl StateVariable for PublicMutable\nwhere\n T: Packable,\n{\n 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 PublicMutable { context, storage_slot }\n }\n\n fn get_storage_slot(self) -> Field {\n self.storage_slot\n }\n}\n\nimpl PublicMutable {\n /// Reads the current value stored in this PublicMutable state variable.\n ///\n /// # Returns\n ///\n /// * `T` - The current value stored in this PublicMutable.\n ///\n /// docs:start:public_mutable_struct_read\n pub fn read(self) -> T\n where\n T: Packable,\n {\n self.context.storage_read(self.storage_slot)\n }\n\n /// Writes a new value to this PublicMutable state variable.\n ///\n /// # Arguments\n ///\n /// * `value` - The new value to store in this PublicMutable.\n ///\n /// # Advanced\n ///\n /// This function updates the value stored in Aztec's public data tree.\n /// The new value becomes immediately available to subsequent reads within\n /// the same transaction.\n ///\n /// docs:start:public_mutable_struct_write\n pub fn write(self, value: T)\n where\n T: Packable,\n {\n self.context.storage_write(self.storage_slot, value);\n }\n}\n\nimpl PublicMutable {\n /// Reads the current value stored in this PublicMutable state variable.\n ///\n /// Notice that this function is executable only within a UtilityContext, which\n /// is an unconstrained environment on the user's local device.\n ///\n /// # Returns\n ///\n /// * `T` - The current value stored in this PublicMutable.\n ///\n pub unconstrained fn read(self) -> T\n where\n T: Packable,\n {\n self.context.storage_read(self.storage_slot)\n }\n}\n" + }, + "228": { + "path": "/home/ubuntu/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.20251212/noir-projects/aztec-nr/aztec/src/utils/array/append.nr", + "source": "/// Appends the elements of the second `BoundedVec` to the end of the first one. The resulting `BoundedVec` can have any arbitrary maximum length, but it must be\n/// large enough to fit all of the elements of both the first and second vectors.\npub fn append(\n a: BoundedVec,\n b: BoundedVec,\n) -> BoundedVec {\n let mut dst = BoundedVec::new();\n\n dst.extend_from_bounded_vec(a);\n dst.extend_from_bounded_vec(b);\n\n dst\n}\n\nmod test {\n use super::append;\n\n #[test]\n unconstrained fn append_empty_vecs() {\n let a: BoundedVec<_, 3> = BoundedVec::new();\n let b: BoundedVec<_, 14> = BoundedVec::new();\n\n let result: BoundedVec = append(a, b);\n\n assert_eq(result.len(), 0);\n assert_eq(result.storage(), std::mem::zeroed());\n }\n\n #[test]\n unconstrained fn append_non_empty_vecs() {\n let a: BoundedVec<_, 3> = BoundedVec::from_array([1, 2, 3]);\n let b: BoundedVec<_, 14> = BoundedVec::from_array([4, 5, 6]);\n\n let result: BoundedVec = append(a, b);\n\n assert_eq(result.len(), 6);\n assert_eq(result.storage(), [1, 2, 3, 4, 5, 6, std::mem::zeroed(), std::mem::zeroed()]);\n }\n\n #[test(should_fail_with = \"out of bounds\")]\n unconstrained fn append_non_empty_vecs_insufficient_max_len() {\n let a: BoundedVec<_, 3> = BoundedVec::from_array([1, 2, 3]);\n let b: BoundedVec<_, 14> = BoundedVec::from_array([4, 5, 6]);\n\n let _: BoundedVec = append(a, b);\n }\n}\n" + }, + "231": { + "path": "/home/ubuntu/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.20251212/noir-projects/aztec-nr/aztec/src/utils/array/subarray.nr", + "source": "/// Returns `DstLen` elements from a source array, starting at `offset`. `DstLen` must not be larger than the number\n/// of elements past `offset`.\n///\n/// Examples:\n/// ```\n/// let foo: [Field; 2] = subarray([1, 2, 3, 4, 5], 2);\n/// assert_eq(foo, [3, 4]);\n///\n/// let bar: [Field; 5] = subarray([1, 2, 3, 4, 5], 2); // fails - we can't return 5 elements since only 3 remain\n/// ```\npub fn subarray(src: [T; SrcLen], offset: u32) -> [T; DstLen] {\n assert(offset + DstLen <= SrcLen, \"DstLen too large for offset\");\n\n let mut dst: [T; DstLen] = std::mem::zeroed();\n for i in 0..DstLen {\n dst[i] = src[i + offset];\n }\n\n dst\n}\n\nmod test {\n use super::subarray;\n\n #[test]\n unconstrained fn subarray_into_empty() {\n // In all of these cases we're setting DstLen to be 0, so we always get back an empty array.\n assert_eq(subarray::([], 0), []);\n assert_eq(subarray([1, 2, 3, 4, 5], 0), []);\n assert_eq(subarray([1, 2, 3, 4, 5], 2), []);\n }\n\n #[test]\n unconstrained fn subarray_complete() {\n assert_eq(subarray::([], 0), []);\n assert_eq(subarray([1, 2, 3, 4, 5], 0), [1, 2, 3, 4, 5]);\n }\n\n #[test]\n unconstrained fn subarray_different_end_sizes() {\n // We implicitly select how many values to read in the size of the return array\n assert_eq(subarray([1, 2, 3, 4, 5], 1), [2, 3, 4, 5]);\n assert_eq(subarray([1, 2, 3, 4, 5], 1), [2, 3, 4]);\n assert_eq(subarray([1, 2, 3, 4, 5], 1), [2, 3]);\n assert_eq(subarray([1, 2, 3, 4, 5], 1), [2]);\n }\n\n #[test(should_fail_with = \"DstLen too large for offset\")]\n unconstrained fn subarray_offset_too_large() {\n // With an offset of 1 we can only request up to 4 elements\n let _: [_; 5] = subarray([1, 2, 3, 4, 5], 1);\n }\n\n #[test(should_fail)]\n unconstrained fn subarray_bad_return_value() {\n assert_eq(subarray([1, 2, 3, 4, 5], 1), [3, 3, 4, 5]);\n }\n}\n" + }, + "232": { + "path": "/home/ubuntu/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.20251212/noir-projects/aztec-nr/aztec/src/utils/array/subbvec.nr", + "source": "use crate::utils::array;\n\n/// Returns `DstMaxLen` elements from a source BoundedVec, starting at `offset`. `offset` must not be larger than the\n/// original length, and `DstLen` must not be larger than the total number of elements past `offset` (including the\n/// zeroed elements past `len()`).\n///\n/// Only elements at the beginning of the vector can be removed: it is not possible to also remove elements at the end\n/// of the vector by passing a value for `DstLen` that is smaller than `len() - offset`.\n///\n/// Examples:\n/// ```\n/// let foo = BoundedVec::<_, 10>::from_array([1, 2, 3, 4, 5]);\n/// assert_eq(subbvec(foo, 2), BoundedVec::<_, 8>::from_array([3, 4, 5]));\n///\n/// let bar: BoundedVec<_, 1> = subbvec(foo, 2); // fails - we can't return just 1 element since 3 remain\n/// let baz: BoundedVec<_, 10> = subbvec(foo, 3); // fails - we can't return 10 elements since only 7 remain\n/// ```\npub fn subbvec(\n bvec: BoundedVec,\n offset: u32,\n) -> BoundedVec {\n // from_parts_unchecked does not verify that the elements past len are zeroed, but that is not an issue in our case\n // because we're constructing the new storage array as a subarray of the original one (which should have zeroed\n // storage past len), guaranteeing correctness. This is because `subarray` does not allow extending arrays past\n // their original length.\n BoundedVec::from_parts_unchecked(array::subarray(bvec.storage(), offset), bvec.len() - offset)\n}\n\nmod test {\n use super::subbvec;\n\n #[test]\n unconstrained fn subbvec_empty() {\n let bvec = BoundedVec::::from_array([]);\n assert_eq(subbvec(bvec, 0), bvec);\n }\n\n #[test]\n unconstrained fn subbvec_complete() {\n let bvec = BoundedVec::<_, 10>::from_array([1, 2, 3, 4, 5]);\n assert_eq(subbvec(bvec, 0), bvec);\n\n let smaller_capacity = BoundedVec::<_, 5>::from_array([1, 2, 3, 4, 5]);\n assert_eq(subbvec(bvec, 0), smaller_capacity);\n }\n\n #[test]\n unconstrained fn subbvec_partial() {\n let bvec = BoundedVec::<_, 10>::from_array([1, 2, 3, 4, 5]);\n\n assert_eq(subbvec(bvec, 2), BoundedVec::<_, 8>::from_array([3, 4, 5]));\n assert_eq(subbvec(bvec, 2), BoundedVec::<_, 3>::from_array([3, 4, 5]));\n }\n\n #[test]\n unconstrained fn subbvec_into_empty() {\n let bvec: BoundedVec<_, 10> = BoundedVec::from_array([1, 2, 3, 4, 5]);\n assert_eq(subbvec(bvec, 5), BoundedVec::<_, 5>::from_array([]));\n }\n\n #[test(should_fail)]\n unconstrained fn subbvec_offset_past_len() {\n let bvec = BoundedVec::<_, 10>::from_array([1, 2, 3, 4, 5]);\n let _: BoundedVec<_, 1> = subbvec(bvec, 6);\n }\n\n #[test(should_fail)]\n unconstrained fn subbvec_insufficient_dst_len() {\n let bvec = BoundedVec::<_, 10>::from_array([1, 2, 3, 4, 5]);\n\n // We're not providing enough space to hold all of the items inside the original BoundedVec. subbvec can cause\n // for the capacity to reduce, but not the length (other than by len - offset).\n let _: BoundedVec<_, 1> = subbvec(bvec, 2);\n }\n\n #[test(should_fail_with = \"DstLen too large for offset\")]\n unconstrained fn subbvec_dst_len_causes_enlarge() {\n let bvec = BoundedVec::<_, 10>::from_array([1, 2, 3, 4, 5]);\n\n // subbvec does not supprt capacity increases\n let _: BoundedVec<_, 11> = subbvec(bvec, 0);\n }\n\n #[test(should_fail_with = \"DstLen too large for offset\")]\n unconstrained fn subbvec_dst_len_too_large_for_offset() {\n let bvec = BoundedVec::<_, 10>::from_array([1, 2, 3, 4, 5]);\n\n // This effectively requests a capacity increase, since there'd be just one element plus the 5 empty slots,\n // which is less than 7.\n let _: BoundedVec<_, 7> = subbvec(bvec, 4);\n }\n}\n" + }, + "234": { + "path": "/home/ubuntu/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.20251212/noir-projects/aztec-nr/aztec/src/utils/conversion/bytes_to_fields.nr", + "source": "use std::static_assert;\n\n// These functions are used to facilitate the conversion of log ciphertext between byte and field representations.\n//\n// `bytes_to_fields` uses fixed-size arrays since encryption contexts have compile-time size information.\n// `bytes_from_fields` uses BoundedVec for flexibility in unconstrained contexts where sizes are dynamic.\n//\n// Together they provide bidirectional conversion between bytes and fields when processing encrypted logs.\n\n/// Converts the input bytes into an array of fields. A Field is ~254 bits meaning that each field can store 31 whole\n/// bytes. Use `bytes_from_fields` to obtain the original bytes array.\n///\n/// The input bytes are chunked into chunks of 31 bytes. Each 31-byte chunk is viewed as big-endian, and is converted\n/// into a Field.\n/// For example, [1, 10, 3, ..., 0] (31 bytes) is encoded as [1 * 256^30 + 10 * 256^29 + 3 * 256^28 + ... + 0]\n/// Note: N must be a multiple of 31 bytes\npub fn bytes_to_fields(bytes: [u8; N]) -> [Field; N / 31] {\n // Assert that N is a multiple of 31\n static_assert(N % 31 == 0, \"N must be a multiple of 31\");\n\n let mut fields = [0; N / 31];\n\n // Since N is a multiple of 31, we can simply process all chunks fully\n for i in 0..N / 31 {\n let mut field = 0;\n for j in 0..31 {\n // Shift the existing value left by 8 bits and add the new byte\n field = field * 256 + bytes[i * 31 + j] as Field;\n }\n fields[i] = field;\n }\n\n fields\n}\n\n/// Converts an input BoundedVec of fields into a BoundedVec of bytes in big-endian order. Arbitrary Field arrays\n/// are not allowed: this is assumed to be an array obtained via `bytes_to_fields`, i.e. one that actually represents\n/// bytes. To convert a Field array into bytes, use `fields_to_bytes`.\n///\n/// Each input field must contain at most 31 bytes (this is constrained to be so).\n/// Each field is converted into 31 big-endian bytes, and the resulting 31-byte chunks are concatenated\n/// back together in the order of the original fields.\npub fn bytes_from_fields(fields: BoundedVec) -> BoundedVec {\n let mut bytes = BoundedVec::new();\n\n for i in 0..fields.len() {\n let field = fields.get(i);\n\n // We expect that the field contains at most 31 bytes of information.\n field.assert_max_bit_size::<248>();\n\n // Now we can safely convert the field to 31 bytes.\n let field_as_bytes: [u8; 31] = field.to_be_bytes();\n\n for j in 0..31 {\n bytes.push(field_as_bytes[j]);\n }\n }\n\n bytes\n}\n\nmod tests {\n use crate::utils::array::subarray;\n use super::{bytes_from_fields, bytes_to_fields};\n\n #[test]\n unconstrained fn random_bytes_to_fields_and_back(input: [u8; 93]) {\n let fields = bytes_to_fields(input);\n\n // At this point in production, the log flies through the system and we get a BoundedVec on the other end.\n // So we need to convert the field array to a BoundedVec to be able to feed it to the `bytes_from_fields`\n // function.\n let fields_as_bounded_vec = BoundedVec::<_, 6>::from_array(fields);\n\n let bytes_back = bytes_from_fields(fields_as_bounded_vec);\n\n // Compare the original input with the round-tripped result\n assert_eq(bytes_back.len(), input.len());\n assert_eq(subarray(bytes_back.storage(), 0), input);\n }\n\n #[test(should_fail_with = \"N must be a multiple of 31\")]\n unconstrained fn bytes_to_fields_input_length_not_multiple_of_31() {\n // Try to convert 32 bytes (not a multiple of 31) to fields\n let _fields = bytes_to_fields([0; 32]);\n }\n\n}\n" + }, + "235": { + "path": "/home/ubuntu/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.20251212/noir-projects/aztec-nr/aztec/src/utils/conversion/fields_to_bytes.nr", + "source": "// These functions are used to facilitate the conversion of log plaintext represented as fields into bytes and back.\n//\n// `fields_to_bytes` uses fixed-size arrays since encryption contexts have compile-time size information.\n// `fields_from_bytes` uses BoundedVec for flexibility in unconstrained contexts where sizes are dynamic.\n//\n// Together they provide bidirectional conversion between fields and bytes.\n\n/// Converts an input array of fields into a single array of bytes. Use `fields_from_bytes` to obtain the original\n/// field array.\n/// Each field is converted to a 32-byte big-endian array.\n///\n/// For example, if you have a field array [123, 456], it will be converted to a 64-byte array:\n/// [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,123, // First field (32 bytes)\n/// 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,200] // Second field (32 bytes)\n///\n/// Since a field is ~254 bits, you'll end up with a subtle 2-bit \"gap\" at the big end, every 32 bytes. Be careful\n/// that such a gap doesn't leak information! This could happen if you for example expected the output to be\n/// indistinguishable from random bytes.\npub fn fields_to_bytes(fields: [Field; N]) -> [u8; 32 * N] {\n let mut bytes = [0; 32 * N];\n\n for i in 0..N {\n let field_as_bytes: [u8; 32] = fields[i].to_be_bytes();\n\n for j in 0..32 {\n bytes[i * 32 + j] = field_as_bytes[j];\n }\n }\n\n bytes\n}\n\n/// Converts an input BoundedVec of bytes into a BoundedVec of fields. Arbitrary byte arrays are not allowed: this\n/// is assumed to be an array obtained via `fields_to_bytes`, i.e. one that actually represents fields. To convert\n/// a byte array into Fields, use `bytes_to_fields`.\n///\n/// The input bytes are chunked into chunks of 32 bytes. Each 32-byte chunk is viewed as big-endian, and is converted\n/// into a Field.\n/// For example, [1, 10, 3, ..., 0] (32 bytes) is encoded as [1 * 256^31 + 10 * 256^30 + 3 * 256^29 + ... + 0]\n/// Note 1: N must be a multiple of 32 bytes\n/// Note 2: The max value check code was taken from std::field::to_be_bytes function.\npub fn fields_from_bytes(bytes: BoundedVec) -> BoundedVec {\n // Assert that input length is a multiple of 32\n assert(bytes.len() % 32 == 0, \"Input length must be a multiple of 32\");\n\n let mut fields = BoundedVec::new();\n\n let p = std::field::modulus_be_bytes();\n\n // Since input length is a multiple of 32, we can simply process all chunks fully\n for i in 0..bytes.len() / 32 {\n let mut field = 0;\n\n // Process each byte in the 32-byte chunk\n let mut ok = false;\n\n for j in 0..32 {\n let next_byte = bytes.get(i * 32 + j);\n field = field * 256 + next_byte as Field;\n\n if !ok {\n if next_byte != p[j] {\n assert(next_byte < p[j], \"Value does not fit in field\");\n ok = true;\n }\n }\n }\n assert(ok, \"Value does not fit in field\");\n\n fields.push(field);\n }\n\n fields\n}\n\nmod tests {\n use crate::utils::array::subarray;\n use super::{fields_from_bytes, fields_to_bytes};\n\n #[test]\n unconstrained fn random_fields_to_bytes_and_back(input: [Field; 3]) {\n // Convert to bytes\n let bytes = fields_to_bytes(input);\n\n // At this point in production, the log flies through the system and we get a BoundedVec on the other end.\n // So we need to convert the field array to a BoundedVec to be able to feed it to the `fields_from_bytes`\n // function.\n // 113 is an arbitrary max length that is larger than the input length of 96.\n let bytes_as_bounded_vec = BoundedVec::<_, 113>::from_array(bytes);\n\n // Convert back to fields\n let fields_back = fields_from_bytes(bytes_as_bounded_vec);\n\n // Compare the original input with the round-tripped result\n assert_eq(fields_back.len(), input.len());\n assert_eq(subarray(fields_back.storage(), 0), input);\n }\n\n #[test(should_fail_with = \"Input length must be a multiple of 32\")]\n unconstrained fn to_fields_assert() {\n // 143 is an arbitrary max length that is larger than 33\n let input = BoundedVec::<_, 143>::from_array([\n 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,\n 25, 26, 27, 28, 29, 30, 31, 32, 33,\n ]);\n\n // This should fail since 33 is not a multiple of 32\n let _fields = fields_from_bytes(input);\n }\n\n #[test]\n unconstrained fn fields_from_bytes_max_value() {\n let max_field_as_bytes: [u8; 32] = (-1).to_be_bytes();\n let input = BoundedVec::<_, 32>::from_array(max_field_as_bytes);\n\n let fields = fields_from_bytes(input);\n\n // The result should be a largest value storable in a field (-1 since we are modulo-ing)\n assert_eq(fields.get(0), -1);\n }\n\n // In this test we verify that overflow check works by taking the max allowed value, bumping a random byte\n // and then feeding it to `fields_from_bytes` as input.\n #[test(should_fail_with = \"Value does not fit in field\")]\n unconstrained fn fields_from_bytes_overflow(random_value: u8) {\n let index_of_byte_to_bump = random_value % 32;\n\n // Obtain the byte representation of the maximum field value\n let max_field_value_as_bytes: [u8; 32] = (-1).to_be_bytes();\n\n let byte_to_bump = max_field_value_as_bytes[index_of_byte_to_bump as u32];\n\n // Skip test execution if the selected byte is already at maximum value (255).\n // This is acceptable since we are using fuzz testing to generate many test cases.\n if byte_to_bump != 255 {\n let mut input = BoundedVec::<_, 32>::from_array(max_field_value_as_bytes);\n\n // Increment the selected byte to exceed the field's maximum value\n input.set(index_of_byte_to_bump as u32, byte_to_bump + 1);\n\n // Attempt the conversion, which should fail due to the value exceeding the field's capacity\n let _fields = fields_from_bytes(input);\n }\n }\n\n}\n" + }, + "238": { + "path": "/home/ubuntu/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.20251212/noir-projects/aztec-nr/aztec/src/utils/point.nr", + "source": "use protocol_types::{point::Point, utils::field::sqrt};\n\n// I am storing the modulus minus 1 divided by 2 here because full modulus would throw \"String literal too large\" error\n// Full modulus is 21888242871839275222246405745257275088548364400416034343698204186575808495617\nglobal BN254_FR_MODULUS_DIV_2: Field =\n 10944121435919637611123202872628637544274182200208017171849102093287904247808;\n\n/// Converts a point to a byte array.\n///\n/// We don't serialize the point at infinity flag because this function is used in situations where we do not want\n/// to waste the extra byte (encrypted log).\npub fn point_to_bytes(p: Point) -> [u8; 32] {\n // Note that there is 1 more free bit in the 32 bytes (254 bits currently occupied by the x coordinate, 1 bit for\n // the \"sign\") so it's possible to use that last bit as an \"is_infinite\" flag if desired in the future.\n assert(!p.is_infinite, \"Cannot serialize point at infinity as bytes.\");\n\n let mut result: [u8; 32] = p.x.to_be_bytes();\n\n if get_sign_of_point(p) {\n // y is <= (modulus - 1) / 2 so we set the sign bit to 1\n // Here we leverage that field fits into 254 bits (log2(Fr.MODULUS) < 254) and given that we serialize Fr to 32\n // bytes and we use big-endian the 2 most significant bits are never populated. Hence we can use one of\n // the bits as a sign bit.\n result[0] += 128;\n }\n\n result\n}\n\n/**\n * Returns: true if p.y <= MOD_DIV_2, else false.\n */\npub fn get_sign_of_point(p: Point) -> bool {\n // We store only a \"sign\" of the y coordinate because the rest can be derived from the x coordinate. To get\n // the sign we check if the y coordinate is less or equal than the curve's order minus 1 divided by 2.\n // Ideally we'd do `y <= MOD_DIV_2`, but there's no `lte` function, so instead we do `!(y > MOD_DIV_2)`, which is\n // equivalent, and then rewrite that as `!(MOD_DIV_2 < y)`, since we also have no `gt` function.\n !BN254_FR_MODULUS_DIV_2.lt(p.y)\n}\n\n/// Returns a `Point` in the Grumpkin curve given its x coordinate.\n///\n/// Because not all values in the field are valid x coordinates of points in the curve (i.e. there\n/// is no corresponding y value in the field that satisfies the curve equation), it may not be\n/// possible to reconstruct a `Point`. `Option::none()` is returned in such cases.\npub fn point_from_x_coord(x: Field) -> Option {\n // y ^ 2 = x ^ 3 - 17\n let rhs = x * x * x - 17;\n sqrt(rhs).map(|y| Point { x, y, is_infinite: false })\n}\n\n/// Returns a `Point` in the Grumpkin curve given its x coordinate and sign for the y coordinate.\n///\n/// Because not all values in the field are valid x coordinates of points in the curve (i.e. there\n/// is no corresponding y value in the field that satisfies the curve equation), it may not be\n/// possible to reconstruct a `Point`. `Option::none()` is returned in such cases.\n///\n/// @param x - The x coordinate of the point\n/// @param sign - The \"sign\" of the y coordinate - determines whether y <= (Fr.MODULUS - 1) / 2\npub fn point_from_x_coord_and_sign(x: Field, sign: bool) -> Option {\n // y ^ 2 = x ^ 3 - 17\n let rhs = x * x * x - 17;\n\n sqrt(rhs).map(|y| {\n // If there is a square root, we need to ensure it has the correct \"sign\"\n let y_is_positive = !BN254_FR_MODULUS_DIV_2.lt(y);\n let final_y = if y_is_positive == sign { y } else { -y };\n Point { x, y: final_y, is_infinite: false }\n })\n}\n\nmod test {\n use crate::utils::point::{point_from_x_coord, point_from_x_coord_and_sign, point_to_bytes};\n use dep::protocol_types::point::Point;\n use dep::protocol_types::utils::field::pow;\n\n #[test]\n unconstrained fn test_point_to_bytes_positive_sign() {\n let p = Point {\n x: 0x1af41f5de96446dc3776a1eb2d98bb956b7acd9979a67854bec6fa7c2973bd73,\n y: 0x07fc22c7f2c7057571f137fe46ea9c95114282bc95d37d71ec4bfb88de457d4a,\n is_infinite: false,\n };\n\n let compressed_point = point_to_bytes(p);\n\n let expected_compressed_point_positive_sign = [\n 154, 244, 31, 93, 233, 100, 70, 220, 55, 118, 161, 235, 45, 152, 187, 149, 107, 122,\n 205, 153, 121, 166, 120, 84, 190, 198, 250, 124, 41, 115, 189, 115,\n ];\n assert_eq(expected_compressed_point_positive_sign, compressed_point);\n }\n\n #[test]\n unconstrained fn test_point_to_bytes_negative_sign() {\n let p = Point {\n x: 0x247371652e55dd74c9af8dbe9fb44931ba29a9229994384bd7077796c14ee2b5,\n y: 0x26441aec112e1ae4cee374f42556932001507ad46e255ffb27369c7e3766e5c0,\n is_infinite: false,\n };\n\n let compressed_point = point_to_bytes(p);\n\n let expected_compressed_point_negative_sign = [\n 36, 115, 113, 101, 46, 85, 221, 116, 201, 175, 141, 190, 159, 180, 73, 49, 186, 41, 169,\n 34, 153, 148, 56, 75, 215, 7, 119, 150, 193, 78, 226, 181,\n ];\n\n assert_eq(expected_compressed_point_negative_sign, compressed_point);\n }\n\n #[test]\n unconstrained fn test_point_from_x_coord_and_sign() {\n // Test positive y coordinate\n let x = 0x1af41f5de96446dc3776a1eb2d98bb956b7acd9979a67854bec6fa7c2973bd73;\n let sign = true;\n let p = point_from_x_coord_and_sign(x, sign).unwrap();\n\n assert_eq(p.x, x);\n assert_eq(p.y, 0x07fc22c7f2c7057571f137fe46ea9c95114282bc95d37d71ec4bfb88de457d4a);\n assert_eq(p.is_infinite, false);\n\n // Test negative y coordinate\n let x2 = 0x247371652e55dd74c9af8dbe9fb44931ba29a9229994384bd7077796c14ee2b5;\n let sign2 = false;\n let p2 = point_from_x_coord_and_sign(x2, sign2).unwrap();\n\n assert_eq(p2.x, x2);\n assert_eq(p2.y, 0x26441aec112e1ae4cee374f42556932001507ad46e255ffb27369c7e3766e5c0);\n assert_eq(p2.is_infinite, false);\n }\n\n #[test]\n unconstrained fn test_point_from_x_coord_valid() {\n // x = 8 is a known quadratic residue - should give a valid point\n let result = point_from_x_coord(Field::from(8));\n assert(result.is_some());\n\n let point = result.unwrap();\n assert_eq(point.x, Field::from(8));\n // Check curve equation y^2 = x^3 - 17\n assert_eq(pow(point.y, 2), pow(point.x, 3) - 17);\n }\n\n #[test]\n unconstrained fn test_point_from_x_coord_invalid() {\n // x = 3 is a non-residue for this curve - should give None\n let x = Field::from(3);\n let maybe_point = point_from_x_coord(x);\n assert(maybe_point.is_none());\n }\n\n}\n" + }, + "249": { + "path": "/home/ubuntu/nargo/github.com/noir-lang/poseidon/v0.1.1/src/poseidon2.nr", + "source": "use std::default::Default;\nuse std::hash::Hasher;\n\ncomptime global RATE: u32 = 3;\n\npub struct Poseidon2 {\n cache: [Field; 3],\n state: [Field; 4],\n cache_size: u32,\n squeeze_mode: bool, // 0 => absorb, 1 => squeeze\n}\n\nimpl Poseidon2 {\n #[no_predicates]\n pub fn hash(input: [Field; N], message_size: u32) -> Field {\n Poseidon2::hash_internal(input, message_size, message_size != N)\n }\n\n pub(crate) fn new(iv: Field) -> Poseidon2 {\n let mut result =\n Poseidon2 { cache: [0; 3], state: [0; 4], cache_size: 0, squeeze_mode: false };\n result.state[RATE] = iv;\n result\n }\n\n fn perform_duplex(&mut self) {\n // add the cache into sponge state\n for i in 0..RATE {\n // We effectively zero-pad the cache by only adding to the state\n // cache that is less than the specified `cache_size`\n if i < self.cache_size {\n self.state[i] += self.cache[i];\n }\n }\n self.state = crate::poseidon2_permutation(self.state, 4);\n }\n\n fn absorb(&mut self, input: Field) {\n assert(!self.squeeze_mode);\n if self.cache_size == RATE {\n // If we're absorbing, and the cache is full, apply the sponge permutation to compress the cache\n self.perform_duplex();\n self.cache[0] = input;\n self.cache_size = 1;\n } else {\n // If we're absorbing, and the cache is not full, add the input into the cache\n self.cache[self.cache_size] = input;\n self.cache_size += 1;\n }\n }\n\n fn squeeze(&mut self) -> Field {\n assert(!self.squeeze_mode);\n // If we're in absorb mode, apply sponge permutation to compress the cache.\n self.perform_duplex();\n self.squeeze_mode = true;\n\n // Pop one item off the top of the permutation and return it.\n self.state[0]\n }\n\n fn hash_internal(\n input: [Field; N],\n in_len: u32,\n is_variable_length: bool,\n ) -> 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\npub struct Poseidon2Hasher {\n _state: [Field],\n}\n\nimpl Hasher for Poseidon2Hasher {\n fn finish(self) -> Field {\n let iv: Field = (self._state.len() as Field) * 18446744073709551616; // iv = (self._state.len() << 64)\n let mut sponge = Poseidon2::new(iv);\n for i in 0..self._state.len() {\n sponge.absorb(self._state[i]);\n }\n sponge.squeeze()\n }\n\n fn write(&mut self, input: Field) {\n self._state = self._state.push_back(input);\n }\n}\n\nimpl Default for Poseidon2Hasher {\n fn default() -> Self {\n Poseidon2Hasher { _state: &[] }\n }\n}\n" + }, + "269": { + "path": "/home/ubuntu/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.20251212/noir-projects/noir-protocol-circuits/crates/types/src/abis/function_selector.nr", + "source": "use crate::traits::{Deserialize, Empty, FromField, Serialize, ToField};\nuse std::meta::derive;\n\n#[derive(Deserialize, Eq, Serialize)]\npub struct FunctionSelector {\n // 1st 4-bytes (big-endian leftmost) of abi-encoding of an event.\n pub inner: u32,\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(signature: str) -> Self {\n let bytes = signature.as_bytes();\n let hash = crate::hash::poseidon2_hash_bytes(bytes);\n\n // `hash` is automatically truncated to fit within 32 bits.\n FunctionSelector::from_field(hash)\n }\n\n pub fn zero() -> Self {\n Self { inner: 0 }\n }\n}\n\n#[test]\nfn test_is_valid_selector() {\n let selector = FunctionSelector::from_signature(\"IS_VALID()\");\n assert_eq(selector.to_field(), 0x73cdda47);\n}\n\n#[test]\nfn test_long_selector() {\n let selector =\n FunctionSelector::from_signature(\"foo_and_bar_and_baz_and_foo_bar_baz_and_bar_foo\");\n assert_eq(selector.to_field(), 0x7590a997);\n}\n" + }, + "3": { + "path": "std/array/mod.nr", + "source": "use crate::cmp::{Eq, Ord};\nuse crate::convert::From;\nuse crate::runtime::is_unconstrained;\n\nmod check_shuffle;\nmod quicksort;\n\nimpl [T; N] {\n /// Returns the length of this array.\n ///\n /// ```noir\n /// fn len(self) -> Field\n /// ```\n ///\n /// example\n ///\n /// ```noir\n /// fn main() {\n /// let array = [42, 42];\n /// assert(array.len() == 2);\n /// }\n /// ```\n #[builtin(array_len)]\n pub fn len(self) -> u32 {}\n\n /// Returns this array as a slice.\n ///\n /// ```noir\n /// let array = [1, 2];\n /// let slice = array.as_slice();\n /// assert_eq(slice, &[1, 2]);\n /// ```\n #[builtin(as_slice)]\n pub fn as_slice(self) -> [T] {}\n\n /// Applies a function to each element of this array, returning a new array containing the mapped elements.\n ///\n /// Example:\n ///\n /// ```rust\n /// let a = [1, 2, 3];\n /// let b = a.map(|a| a * 2);\n /// assert_eq(b, [2, 4, 6]);\n /// ```\n pub fn map(self, f: fn[Env](T) -> U) -> [U; N] {\n let uninitialized = crate::mem::zeroed();\n let mut ret = [uninitialized; N];\n\n for i in 0..self.len() {\n ret[i] = f(self[i]);\n }\n\n ret\n }\n\n /// Applies a function to each element of this array along with its index,\n /// returning a new array containing the mapped elements.\n ///\n /// Example:\n ///\n /// ```rust\n /// let a = [1, 2, 3];\n /// let b = a.mapi(|i, a| i + a * 2);\n /// assert_eq(b, [2, 5, 8]);\n /// ```\n pub fn mapi(self, f: fn[Env](u32, T) -> U) -> [U; N] {\n let uninitialized = crate::mem::zeroed();\n let mut ret = [uninitialized; N];\n\n for i in 0..self.len() {\n ret[i] = f(i, self[i]);\n }\n\n ret\n }\n\n /// Applies a function to each element of this array.\n ///\n /// Example:\n ///\n /// ```rust\n /// let a = [1, 2, 3];\n /// let mut b = [0; 3];\n /// let mut i = 0;\n /// a.for_each(|x| {\n /// b[i] = x;\n /// i += 1;\n /// });\n /// assert_eq(a, b);\n /// ```\n pub fn for_each(self, f: fn[Env](T) -> ()) {\n for i in 0..self.len() {\n f(self[i]);\n }\n }\n\n /// Applies a function to each element of this array along with its index.\n ///\n /// Example:\n ///\n /// ```rust\n /// let a = [1, 2, 3];\n /// let mut b = [0; 3];\n /// a.for_eachi(|i, x| {\n /// b[i] = x;\n /// });\n /// assert_eq(a, b);\n /// ```\n pub fn for_eachi(self, f: fn[Env](u32, T) -> ()) {\n for i in 0..self.len() {\n f(i, self[i]);\n }\n }\n\n /// Applies a function to each element of the array, returning the final accumulated value. The first\n /// parameter is the initial value.\n ///\n /// This is a left fold, so the given function will be applied to the accumulator and first element of\n /// the array, then the second, and so on. For a given call the expected result would be equivalent to:\n ///\n /// ```rust\n /// let a1 = [1];\n /// let a2 = [1, 2];\n /// let a3 = [1, 2, 3];\n ///\n /// let f = |a, b| a - b;\n /// a1.fold(10, f); //=> f(10, 1)\n /// a2.fold(10, f); //=> f(f(10, 1), 2)\n /// a3.fold(10, f); //=> f(f(f(10, 1), 2), 3)\n ///\n /// assert_eq(a3.fold(10, f), 10 - 1 - 2 - 3);\n /// ```\n pub fn fold(self, mut accumulator: U, f: fn[Env](U, T) -> U) -> U {\n for elem in self {\n accumulator = f(accumulator, elem);\n }\n accumulator\n }\n\n /// Same as fold, but uses the first element as the starting element.\n ///\n /// Requires the input array to be non-empty.\n ///\n /// Example:\n ///\n /// ```noir\n /// fn main() {\n /// let arr = [1, 2, 3, 4];\n /// let reduced = arr.reduce(|a, b| a + b);\n /// assert(reduced == 10);\n /// }\n /// ```\n pub fn reduce(self, f: fn[Env](T, T) -> T) -> T {\n let mut accumulator = self[0];\n for i in 1..self.len() {\n accumulator = f(accumulator, self[i]);\n }\n accumulator\n }\n\n /// Returns true if all the elements in this array satisfy the given predicate.\n ///\n /// Example:\n ///\n /// ```noir\n /// fn main() {\n /// let arr = [2, 2, 2, 2, 2];\n /// let all = arr.all(|a| a == 2);\n /// assert(all);\n /// }\n /// ```\n pub fn all(self, predicate: fn[Env](T) -> bool) -> bool {\n let mut ret = true;\n for elem in self {\n ret &= predicate(elem);\n }\n ret\n }\n\n /// Returns true if any of the elements in this array satisfy the given predicate.\n ///\n /// Example:\n ///\n /// ```noir\n /// fn main() {\n /// let arr = [2, 2, 2, 2, 5];\n /// let any = arr.any(|a| a == 5);\n /// assert(any);\n /// }\n /// ```\n pub fn any(self, predicate: fn[Env](T) -> bool) -> bool {\n let mut ret = false;\n for elem in self {\n ret |= predicate(elem);\n }\n ret\n }\n\n /// Concatenates this array with another array.\n ///\n /// Example:\n ///\n /// ```noir\n /// fn main() {\n /// let arr1 = [1, 2, 3, 4];\n /// let arr2 = [6, 7, 8, 9, 10, 11];\n /// let concatenated_arr = arr1.concat(arr2);\n /// assert(concatenated_arr == [1, 2, 3, 4, 6, 7, 8, 9, 10, 11]);\n /// }\n /// ```\n pub fn concat(self, array2: [T; M]) -> [T; N + M] {\n let mut result = [crate::mem::zeroed(); N + M];\n for i in 0..N {\n result[i] = self[i];\n }\n for i in 0..M {\n result[i + N] = array2[i];\n }\n result\n }\n}\n\nimpl [T; N]\nwhere\n T: Ord + Eq,\n{\n /// Returns a new sorted array. The original array remains untouched. Notice that this function will\n /// only work for arrays of fields or integers, not for any arbitrary type. This is because the sorting\n /// logic it uses internally is optimized specifically for these values. If you need a sort function to\n /// sort any type, you should use the [`Self::sort_via`] function.\n ///\n /// Example:\n ///\n /// ```rust\n /// fn main() {\n /// let arr = [42, 32];\n /// let sorted = arr.sort();\n /// assert(sorted == [32, 42]);\n /// }\n /// ```\n pub fn sort(self) -> Self {\n self.sort_via(|a, b| a <= b)\n }\n}\n\nimpl [T; N]\nwhere\n T: Eq,\n{\n /// Returns a new sorted array by sorting it with a custom comparison function.\n /// The original array remains untouched.\n /// The ordering function must return true if the first argument should be sorted to be before the second argument or is equal to the second argument.\n ///\n /// Using this method with an operator like `<` that does not return `true` for equal values will result in an assertion failure for arrays with equal elements.\n ///\n /// Example:\n ///\n /// ```rust\n /// fn main() {\n /// let arr = [42, 32]\n /// let sorted_ascending = arr.sort_via(|a, b| a <= b);\n /// assert(sorted_ascending == [32, 42]); // verifies\n ///\n /// let sorted_descending = arr.sort_via(|a, b| a >= b);\n /// assert(sorted_descending == [32, 42]); // does not verify\n /// }\n /// ```\n pub fn sort_via(self, ordering: fn[Env](T, T) -> bool) -> Self {\n // Safety: `sorted` array is checked to be:\n // a. a permutation of `input`'s elements\n // b. satisfying the predicate `ordering`\n let sorted = unsafe { quicksort::quicksort(self, ordering) };\n\n if !is_unconstrained() {\n for i in 0..N - 1 {\n assert(\n ordering(sorted[i], sorted[i + 1]),\n \"Array has not been sorted correctly according to `ordering`.\",\n );\n }\n check_shuffle::check_shuffle(self, sorted);\n }\n sorted\n }\n}\n\nimpl [u8; N] {\n /// Converts a byte array of type `[u8; N]` to a string. Note that this performs no UTF-8 validation -\n /// the given array is interpreted as-is as a string.\n ///\n /// Example:\n ///\n /// ```rust\n /// fn main() {\n /// let hi = [104, 105].as_str_unchecked();\n /// assert_eq(hi, \"hi\");\n /// }\n /// ```\n #[builtin(array_as_str_unchecked)]\n pub fn as_str_unchecked(self) -> str {}\n}\n\nimpl From> for [u8; N] {\n /// Returns an array of the string bytes.\n fn from(s: str) -> Self {\n s.as_bytes()\n }\n}\n\nmod test {\n #[test]\n fn map_empty() {\n assert_eq([].map(|x| x + 1), []);\n }\n\n global arr_with_100_values: [u32; 100] = [\n 42, 123, 87, 93, 48, 80, 50, 5, 104, 84, 70, 47, 119, 66, 71, 121, 3, 29, 42, 118, 2, 54,\n 89, 44, 81, 0, 26, 106, 68, 96, 84, 48, 95, 54, 45, 32, 89, 100, 109, 19, 37, 41, 19, 98,\n 53, 114, 107, 66, 6, 74, 13, 19, 105, 64, 123, 28, 44, 50, 89, 58, 123, 126, 21, 43, 86, 35,\n 21, 62, 82, 0, 108, 120, 72, 72, 62, 80, 12, 71, 70, 86, 116, 73, 38, 15, 127, 81, 30, 8,\n 125, 28, 26, 69, 114, 63, 27, 28, 61, 42, 13, 32,\n ];\n global expected_with_100_values: [u32; 100] = [\n 0, 0, 2, 3, 5, 6, 8, 12, 13, 13, 15, 19, 19, 19, 21, 21, 26, 26, 27, 28, 28, 28, 29, 30, 32,\n 32, 35, 37, 38, 41, 42, 42, 42, 43, 44, 44, 45, 47, 48, 48, 50, 50, 53, 54, 54, 58, 61, 62,\n 62, 63, 64, 66, 66, 68, 69, 70, 70, 71, 71, 72, 72, 73, 74, 80, 80, 81, 81, 82, 84, 84, 86,\n 86, 87, 89, 89, 89, 93, 95, 96, 98, 100, 104, 105, 106, 107, 108, 109, 114, 114, 116, 118,\n 119, 120, 121, 123, 123, 123, 125, 126, 127,\n ];\n fn sort_u32(a: u32, b: u32) -> bool {\n a <= b\n }\n\n #[test]\n fn test_sort() {\n let mut arr: [u32; 7] = [3, 6, 8, 10, 1, 2, 1];\n\n let sorted = arr.sort();\n\n let expected: [u32; 7] = [1, 1, 2, 3, 6, 8, 10];\n assert(sorted == expected);\n }\n\n #[test]\n fn test_sort_100_values() {\n let mut arr: [u32; 100] = [\n 42, 123, 87, 93, 48, 80, 50, 5, 104, 84, 70, 47, 119, 66, 71, 121, 3, 29, 42, 118, 2,\n 54, 89, 44, 81, 0, 26, 106, 68, 96, 84, 48, 95, 54, 45, 32, 89, 100, 109, 19, 37, 41,\n 19, 98, 53, 114, 107, 66, 6, 74, 13, 19, 105, 64, 123, 28, 44, 50, 89, 58, 123, 126, 21,\n 43, 86, 35, 21, 62, 82, 0, 108, 120, 72, 72, 62, 80, 12, 71, 70, 86, 116, 73, 38, 15,\n 127, 81, 30, 8, 125, 28, 26, 69, 114, 63, 27, 28, 61, 42, 13, 32,\n ];\n\n let sorted = arr.sort();\n\n let expected: [u32; 100] = [\n 0, 0, 2, 3, 5, 6, 8, 12, 13, 13, 15, 19, 19, 19, 21, 21, 26, 26, 27, 28, 28, 28, 29, 30,\n 32, 32, 35, 37, 38, 41, 42, 42, 42, 43, 44, 44, 45, 47, 48, 48, 50, 50, 53, 54, 54, 58,\n 61, 62, 62, 63, 64, 66, 66, 68, 69, 70, 70, 71, 71, 72, 72, 73, 74, 80, 80, 81, 81, 82,\n 84, 84, 86, 86, 87, 89, 89, 89, 93, 95, 96, 98, 100, 104, 105, 106, 107, 108, 109, 114,\n 114, 116, 118, 119, 120, 121, 123, 123, 123, 125, 126, 127,\n ];\n assert(sorted == expected);\n }\n\n #[test]\n fn test_sort_100_values_comptime() {\n let sorted = arr_with_100_values.sort();\n assert(sorted == expected_with_100_values);\n }\n\n #[test]\n fn test_sort_via() {\n let mut arr: [u32; 7] = [3, 6, 8, 10, 1, 2, 1];\n\n let sorted = arr.sort_via(sort_u32);\n\n let expected: [u32; 7] = [1, 1, 2, 3, 6, 8, 10];\n assert(sorted == expected);\n }\n\n #[test]\n fn test_sort_via_100_values() {\n let mut arr: [u32; 100] = [\n 42, 123, 87, 93, 48, 80, 50, 5, 104, 84, 70, 47, 119, 66, 71, 121, 3, 29, 42, 118, 2,\n 54, 89, 44, 81, 0, 26, 106, 68, 96, 84, 48, 95, 54, 45, 32, 89, 100, 109, 19, 37, 41,\n 19, 98, 53, 114, 107, 66, 6, 74, 13, 19, 105, 64, 123, 28, 44, 50, 89, 58, 123, 126, 21,\n 43, 86, 35, 21, 62, 82, 0, 108, 120, 72, 72, 62, 80, 12, 71, 70, 86, 116, 73, 38, 15,\n 127, 81, 30, 8, 125, 28, 26, 69, 114, 63, 27, 28, 61, 42, 13, 32,\n ];\n\n let sorted = arr.sort_via(sort_u32);\n\n let expected: [u32; 100] = [\n 0, 0, 2, 3, 5, 6, 8, 12, 13, 13, 15, 19, 19, 19, 21, 21, 26, 26, 27, 28, 28, 28, 29, 30,\n 32, 32, 35, 37, 38, 41, 42, 42, 42, 43, 44, 44, 45, 47, 48, 48, 50, 50, 53, 54, 54, 58,\n 61, 62, 62, 63, 64, 66, 66, 68, 69, 70, 70, 71, 71, 72, 72, 73, 74, 80, 80, 81, 81, 82,\n 84, 84, 86, 86, 87, 89, 89, 89, 93, 95, 96, 98, 100, 104, 105, 106, 107, 108, 109, 114,\n 114, 116, 118, 119, 120, 121, 123, 123, 123, 125, 126, 127,\n ];\n assert(sorted == expected);\n }\n\n #[test]\n fn mapi_empty() {\n assert_eq([].mapi(|i, x| i * x + 1), []);\n }\n\n #[test]\n fn for_each_empty() {\n let empty_array: [Field; 0] = [];\n empty_array.for_each(|_x| assert(false));\n }\n\n #[test]\n fn for_eachi_empty() {\n let empty_array: [Field; 0] = [];\n empty_array.for_eachi(|_i, _x| assert(false));\n }\n\n #[test]\n fn map_example() {\n let a = [1, 2, 3];\n let b = a.map(|a| a * 2);\n assert_eq(b, [2, 4, 6]);\n }\n\n #[test]\n fn mapi_example() {\n let a = [1, 2, 3];\n let b = a.mapi(|i, a| i + a * 2);\n assert_eq(b, [2, 5, 8]);\n }\n\n #[test]\n fn for_each_example() {\n let a = [1, 2, 3];\n let mut b = [0, 0, 0];\n let b_ref = &mut b;\n let mut i = 0;\n let i_ref = &mut i;\n a.for_each(|x| {\n b_ref[*i_ref] = x * 2;\n *i_ref += 1;\n });\n assert_eq(b, [2, 4, 6]);\n assert_eq(i, 3);\n }\n\n #[test]\n fn for_eachi_example() {\n let a = [1, 2, 3];\n let mut b = [0, 0, 0];\n let b_ref = &mut b;\n a.for_eachi(|i, a| { b_ref[i] = i + a * 2; });\n assert_eq(b, [2, 5, 8]);\n }\n\n #[test]\n fn concat() {\n let arr1 = [1, 2, 3, 4];\n let arr2 = [6, 7, 8, 9, 10, 11];\n let concatenated_arr = arr1.concat(arr2);\n assert_eq(concatenated_arr, [1, 2, 3, 4, 6, 7, 8, 9, 10, 11]);\n }\n\n #[test]\n fn concat_zero_length_with_something() {\n let arr1 = [];\n let arr2 = [1];\n let concatenated_arr = arr1.concat(arr2);\n assert_eq(concatenated_arr, [1]);\n }\n\n #[test]\n fn concat_something_with_zero_length() {\n let arr1 = [1];\n let arr2 = [];\n let concatenated_arr = arr1.concat(arr2);\n assert_eq(concatenated_arr, [1]);\n }\n\n #[test]\n fn concat_zero_lengths() {\n let arr1: [Field; 0] = [];\n let arr2: [Field; 0] = [];\n let concatenated_arr = arr1.concat(arr2);\n assert_eq(concatenated_arr, []);\n }\n}\n" + }, + "307": { + "path": "/home/ubuntu/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.20251212/noir-projects/noir-protocol-circuits/crates/types/src/address/aztec_address.nr", + "source": "use crate::{\n address::{\n partial_address::PartialAddress, salted_initialization_hash::SaltedInitializationHash,\n },\n constants::{\n AZTEC_ADDRESS_LENGTH, GENERATOR_INDEX__CONTRACT_ADDRESS_V1, MAX_FIELD_VALUE,\n MAX_PROTOCOL_CONTRACTS,\n },\n contract_class_id::ContractClassId,\n hash::poseidon2_hash_with_separator,\n public_keys::{IvpkM, NpkM, OvpkM, PublicKeys, ToPoint, TpkM},\n traits::{Deserialize, Empty, FromField, Packable, Serialize, ToField},\n utils::field::{pow, sqrt},\n};\n\n// We do below because `use crate::point::Point;` does not work\nuse dep::std::embedded_curve_ops::EmbeddedCurvePoint as Point;\n\nuse crate::public_keys::AddressPoint;\nuse std::{\n embedded_curve_ops::{EmbeddedCurveScalar, fixed_base_scalar_mul as derive_public_key},\n ops::Add,\n};\nuse std::meta::derive;\n\n// Aztec address\n#[derive(Deserialize, Eq, Packable, Serialize)]\npub struct AztecAddress {\n pub inner: Field,\n}\n\nimpl Empty for AztecAddress {\n fn empty() -> Self {\n Self { inner: 0 }\n }\n}\n\nimpl ToField for AztecAddress {\n fn to_field(self) -> Field {\n self.inner\n }\n}\n\nimpl FromField for AztecAddress {\n fn from_field(value: Field) -> AztecAddress {\n AztecAddress { inner: value }\n }\n}\n\nimpl AztecAddress {\n pub fn zero() -> Self {\n Self { inner: 0 }\n }\n\n /// Returns an address's `AddressPoint`, which can be used to create shared secrets with the owner\n /// of the address. If the address is invalid (i.e. it is not a properly derived Aztec address), then this\n /// returns `Option::none()`, and no shared secrets can be created.\n pub fn to_address_point(self) -> Option {\n // We compute the address point by taking our address, setting it to x, and then solving for y in the\n // equation which defines our bn curve:\n // y^2 = x^3 - 17; x = address\n let x = self.inner;\n let y_squared = pow(x, 3) - 17;\n\n // An invalid AztecAddress is one for which no y coordinate satisfies the curve equation, which we'll\n // identify by proving that the square root of y_squared does not exist.\n let mut y_opt = sqrt(y_squared);\n if y_opt.is_none() {\n Option::none()\n } else {\n let mut y = y_opt.unwrap();\n\n // If we get a negative y coordinate (any y where y > MAX_FIELD_VALUE / 2), we pin it to the\n // positive one (any value where y <= MAX_FIELD_VALUE / 2) by subtracting it from the Field modulus\n // note: The field modulus is MAX_FIELD_VALUE + 1\n if (!(y.lt(MAX_FIELD_VALUE / 2) | y.eq(MAX_FIELD_VALUE / 2))) {\n y = (MAX_FIELD_VALUE + 1) - y;\n }\n\n Option::some(\n AddressPoint { inner: Point { x: self.inner, y, is_infinite: false } },\n )\n }\n }\n\n pub fn compute(public_keys: PublicKeys, partial_address: PartialAddress) -> AztecAddress {\n let public_keys_hash = public_keys.hash();\n\n let pre_address = poseidon2_hash_with_separator(\n [public_keys_hash.to_field(), partial_address.to_field()],\n GENERATOR_INDEX__CONTRACT_ADDRESS_V1,\n );\n\n let address_point = derive_public_key(EmbeddedCurveScalar::from_field(pre_address)).add(\n public_keys.ivpk_m.to_point(),\n );\n\n // Note that our address is only the x-coordinate of the full address_point. This is okay because when people want to encrypt something and send it to us\n // they can recover our full point using the x-coordinate (our address itself). To do this, they recompute the y-coordinate according to the equation y^2 = x^3 - 17.\n // When they do this, they may get a positive y-coordinate (a value that is less than or equal to MAX_FIELD_VALUE / 2) or\n // a negative y-coordinate (a value that is more than MAX_FIELD_VALUE), and we cannot dictate which one they get and hence the recovered point may sometimes be different than the one\n // our secret can decrypt. Regardless though, they should and will always encrypt using point with the positive y-coordinate by convention.\n // This ensures that everyone encrypts to the same point given an arbitrary x-coordinate (address). This is allowed because even though our original point may not have a positive y-coordinate,\n // with our original secret, we will be able to derive the secret to the point with the flipped (and now positive) y-coordinate that everyone encrypts to.\n AztecAddress::from_field(address_point.x)\n }\n\n pub fn compute_from_class_id(\n contract_class_id: ContractClassId,\n salted_initialization_hash: SaltedInitializationHash,\n public_keys: PublicKeys,\n ) -> Self {\n let partial_address = PartialAddress::compute_from_salted_initialization_hash(\n contract_class_id,\n salted_initialization_hash,\n );\n\n AztecAddress::compute(public_keys, partial_address)\n }\n\n pub fn is_protocol_contract(self) -> bool {\n self.inner.lt(MAX_PROTOCOL_CONTRACTS as Field)\n }\n\n pub fn is_zero(self) -> bool {\n self.inner == 0\n }\n\n pub fn assert_is_zero(self) {\n assert(self.to_field() == 0);\n }\n}\n\n#[test]\nfn compute_address_from_partial_and_pub_keys() {\n let public_keys = PublicKeys {\n npk_m: NpkM {\n inner: Point {\n x: 0x22f7fcddfa3ce3e8f0cc8e82d7b94cdd740afa3e77f8e4a63ea78a239432dcab,\n y: 0x0471657de2b6216ade6c506d28fbc22ba8b8ed95c871ad9f3e3984e90d9723a7,\n is_infinite: false,\n },\n },\n ivpk_m: IvpkM {\n inner: Point {\n x: 0x111223493147f6785514b1c195bb37a2589f22a6596d30bb2bb145fdc9ca8f1e,\n y: 0x273bbffd678edce8fe30e0deafc4f66d58357c06fd4a820285294b9746c3be95,\n is_infinite: false,\n },\n },\n ovpk_m: OvpkM {\n inner: Point {\n x: 0x09115c96e962322ffed6522f57194627136b8d03ac7469109707f5e44190c484,\n y: 0x0c49773308a13d740a7f0d4f0e6163b02c5a408b6f965856b6a491002d073d5b,\n is_infinite: false,\n },\n },\n tpk_m: TpkM {\n inner: Point {\n x: 0x00d3d81beb009873eb7116327cf47c612d5758ef083d4fda78e9b63980b2a762,\n y: 0x2f567d22d2b02fe1f4ad42db9d58a36afd1983e7e2909d1cab61cafedad6193a,\n is_infinite: false,\n },\n },\n };\n\n let partial_address = PartialAddress::from_field(\n 0x0a7c585381b10f4666044266a02405bf6e01fa564c8517d4ad5823493abd31de,\n );\n\n let address = AztecAddress::compute(public_keys, partial_address);\n\n // The following value was generated by `derivation.test.ts`.\n // --> Run the test with AZTEC_GENERATE_TEST_DATA=1 flag to update test data.\n let expected_computed_address_from_partial_and_pubkeys =\n 0x24e4646f58b9fbe7d38e317db8d5636c423fbbdfbe119fc190fe9c64747e0c62;\n assert(address.to_field() == expected_computed_address_from_partial_and_pubkeys);\n}\n\n#[test]\nfn compute_preaddress_from_partial_and_pub_keys() {\n let pre_address = poseidon2_hash_with_separator([1, 2], GENERATOR_INDEX__CONTRACT_ADDRESS_V1);\n let expected_computed_preaddress_from_partial_and_pubkey =\n 0x23ce9be3fa3c846b0f9245cc796902e731d04f086e8a42473bb29e405fc98075;\n assert(pre_address == expected_computed_preaddress_from_partial_and_pubkey);\n}\n\n#[test]\nfn from_field_to_field() {\n let address = AztecAddress { inner: 37 };\n assert_eq(FromField::from_field(address.to_field()), address);\n}\n\n#[test]\nfn serde() {\n let address = AztecAddress { inner: 37 };\n // We use the AZTEC_ADDRESS_LENGTH constant to ensure that there is a match between the derived trait\n // implementation and the constant.\n let serialized: [Field; AZTEC_ADDRESS_LENGTH] = address.serialize();\n let deserialized = AztecAddress::deserialize(serialized);\n assert_eq(address, deserialized);\n}\n\n#[test]\nfn to_address_point_valid() {\n // x = 8 where x^3 - 17 = 512 - 17 = 495, which is a residue in this field\n let address = AztecAddress { inner: 8 };\n let maybe_point = address.to_address_point();\n assert(maybe_point.is_some());\n\n let point = maybe_point.unwrap().inner;\n // check that x is preserved\n assert_eq(point.x, Field::from(8));\n\n // check that the curve equation holds: y^2 == x^3 - 17\n assert_eq(pow(point.y, 2), pow(point.x, 3) - 17);\n}\n\n#[test]\nunconstrained fn to_address_point_invalid() {\n // x = 3 where x^3 - 17 = 27 - 17 = 10, which is a non-residue in this field\n let address = AztecAddress { inner: 3 }; //\n let maybe_point = address.to_address_point();\n assert(maybe_point.is_none());\n}\n" + }, + "328": { + "path": "/home/ubuntu/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.20251212/noir-projects/noir-protocol-circuits/crates/types/src/debug_log.nr", + "source": "// TODO: Expose other wrapped functions than debug (info, warn)\n// ['silent', 'fatal', 'error', 'warn', 'info', 'verbose', 'debug', 'trace']\n\npub global SILENT_LOG_LEVEL: u8 = 0;\npub global FATAL_LOG_LEVEL: u8 = 1;\npub global ERROR_LOG_LEVEL: u8 = 2;\npub global WARN_LOG_LEVEL: u8 = 3;\npub global INFO_LOG_LEVEL: u8 = 4;\npub global VERBOSE_LOG_LEVEL: u8 = 5;\npub global DEBUG_LOG_LEVEL: u8 = 6;\npub global TRACE_LOG_LEVEL: u8 = 7;\n\n/// Utility function to console.log data in the acir simulator.\n/// Example:\n/// debug_log(\"blah blah this is a debug string\");\npub fn debug_log(msg: str) {\n debug_log_format(msg, []);\n}\n\n/// Same as debug_log, but allows to customize the log level.\n/// Consider changing just to 'log'\npub fn debug_log_with_level(log_level: u8, msg: str) {\n debug_log_format_with_level(log_level, msg, []);\n}\n\n/// Utility function to console.log data in the acir simulator. This variant receives a format string in which the\n/// `${k}` tokens will be replaced with the k-eth value in the `args` array.\n/// Examples:\n/// debug_log_format(\"get_2(slot:{0}) =>\\n\\t0:{1}\\n\\t1:{2}\", [storage_slot, note0_hash, note1_hash]);\n/// debug_log_format(\"whole array: {}\", [e1, e2, e3, e4]);\npub fn debug_log_format(msg: str, args: [Field; N]) {\n // Safety: This oracle call returns nothing: we only call it for its side effects. It is therefore always safe\n // to call.\n unsafe { debug_log_array_oracle_wrapper(DEBUG_LOG_LEVEL, msg, args) };\n}\n\n/// Same as debug_log_format, but allows to customize the log level.\n/// Consider changing just to 'log_format'\npub fn debug_log_format_with_level(\n log_level: u8,\n msg: str,\n args: [Field; N],\n) {\n // Safety: This oracle call returns nothing: we only call it for its side effects. It is therefore always safe\n // to call.\n unsafe { debug_log_array_oracle_wrapper(log_level, msg, args) };\n}\n\n/// Utility function to console.log data in the acir simulator. This variant receives a format string in which the\n/// `${k}` tokens will be replaced with the k-eth value in the `args` slice.\n/// Examples:\n/// debug_log_format(\"get_2(slot:{0}) =>\\n\\t0:{1}\\n\\t1:{2}\", [storage_slot, note0_hash, note1_hash]);\n/// debug_log_format(\"whole slice: {}\", [e1, e2, e3, e4]);\npub fn debug_log_format_slice(log_level: u8, msg: str, args: [Field]) {\n // Safety: This oracle call returns nothing: we only call it for its side effects. It is therefore always safe\n // to call.\n unsafe { debug_log_slice_oracle_wrapper(log_level, msg, args) };\n}\n\n// We provide two versions of the debug log oracle: one that takes args as a slice and another one that takes args as an array.\n// We do this since conversion from array to slice generates overhead in public functions, since opcodes need to be emitted for the conversion.\n// By exposing the two flavors, we avoid conversions since the AVM is able to handle both arrays an slices in this oracle.\n\nunconstrained fn debug_log_slice_oracle_wrapper(\n log_level: u8,\n msg: str,\n args: [Field],\n) {\n debug_log_slice_oracle(log_level, msg, args);\n}\n\n// WARNING: sometimes when using debug logs the ACVM errors with: `thrown: \"solver opcode resolution error: cannot solve opcode: expression has too many unknowns x155\"`\n#[oracle(utilityDebugLog)]\nunconstrained fn debug_log_slice_oracle(log_level: u8, msg: str, args: [Field]) {}\n\nunconstrained fn debug_log_array_oracle_wrapper(\n log_level: u8,\n msg: str,\n args: [Field; N],\n) {\n debug_log_array_oracle(log_level, msg, N, args);\n}\n\n#[oracle(utilityDebugLog)]\nunconstrained fn debug_log_array_oracle(\n log_level: u8,\n msg: str,\n length: u32,\n args: [Field; N],\n) {}\n" + }, + "338": { + "path": "/home/ubuntu/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.20251212/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr", + "source": "mod poseidon2_chunks;\n\nuse crate::{\n abis::{\n contract_class_function_leaf_preimage::ContractClassFunctionLeafPreimage,\n function_selector::FunctionSelector,\n note_hash::NoteHash,\n nullifier::Nullifier,\n private_log::{PrivateLog, PrivateLogData},\n transaction::tx_request::TxRequest,\n },\n address::{AztecAddress, EthAddress},\n constants::{\n CONTRACT_CLASS_LOG_SIZE_IN_FIELDS, FUNCTION_TREE_HEIGHT, GENERATOR_INDEX__NOTE_HASH_NONCE,\n GENERATOR_INDEX__OUTER_NULLIFIER, GENERATOR_INDEX__SILOED_NOTE_HASH,\n GENERATOR_INDEX__UNIQUE_NOTE_HASH, NULL_MSG_SENDER_CONTRACT_ADDRESS, TWO_POW_64,\n },\n merkle_tree::root_from_sibling_path,\n messaging::l2_to_l1_message::L2ToL1Message,\n poseidon2::Poseidon2Sponge,\n side_effect::{Counted, Scoped},\n traits::{FromField, Hash, ToField},\n utils::field::{field_from_bytes, field_from_bytes_32_trunc},\n};\n\npub use poseidon2_chunks::poseidon2_absorb_in_chunks_existing_sponge;\nuse poseidon2_chunks::poseidon2_absorb_in_chunks;\nuse std::embedded_curve_ops::EmbeddedCurveScalar;\n\npub fn sha256_to_field(bytes_to_hash: [u8; N]) -> Field {\n let sha256_hashed = sha256::digest(bytes_to_hash);\n let hash_in_a_field = field_from_bytes_32_trunc(sha256_hashed);\n\n hash_in_a_field\n}\n\npub fn private_functions_root_from_siblings(\n selector: FunctionSelector,\n vk_hash: Field,\n function_leaf_index: Field,\n function_leaf_sibling_path: [Field; FUNCTION_TREE_HEIGHT],\n) -> Field {\n let function_leaf_preimage = ContractClassFunctionLeafPreimage { selector, vk_hash };\n let function_leaf = function_leaf_preimage.hash();\n root_from_sibling_path(\n function_leaf,\n function_leaf_index,\n function_leaf_sibling_path,\n )\n}\n\npub fn compute_note_hash_nonce(first_nullifier_in_tx: Field, note_index_in_tx: u32) -> Field {\n // Hashing the first nullifier with note index in tx is guaranteed to be unique (because all nullifiers are also\n // unique).\n poseidon2_hash_with_separator(\n [first_nullifier_in_tx, note_index_in_tx as Field],\n GENERATOR_INDEX__NOTE_HASH_NONCE,\n )\n}\n\npub fn compute_unique_note_hash(note_nonce: Field, siloed_note_hash: Field) -> Field {\n let inputs = [note_nonce, siloed_note_hash];\n poseidon2_hash_with_separator(inputs, GENERATOR_INDEX__UNIQUE_NOTE_HASH)\n}\n\npub fn compute_nonce_and_unique_note_hash(\n siloed_note_hash: Field,\n first_nullifier: Field,\n note_index_in_tx: u32,\n) -> Field {\n let note_nonce = compute_note_hash_nonce(first_nullifier, note_index_in_tx);\n compute_unique_note_hash(note_nonce, siloed_note_hash)\n}\n\npub fn compute_siloed_note_hash(app: AztecAddress, note_hash: Field) -> Field {\n poseidon2_hash_with_separator(\n [app.to_field(), note_hash],\n GENERATOR_INDEX__SILOED_NOTE_HASH,\n )\n}\n\n/// Computes unique note hashes from siloed note hashes\npub fn compute_unique_siloed_note_hash(\n siloed_note_hash: Field,\n first_nullifier: Field,\n note_index_in_tx: u32,\n) -> Field {\n if siloed_note_hash == 0 {\n 0\n } else {\n compute_nonce_and_unique_note_hash(siloed_note_hash, first_nullifier, note_index_in_tx)\n }\n}\n\n/// Siloing in the context of Aztec refers to the process of hashing a note hash with a contract address (this way\n/// the note hash is scoped to a specific contract). This is used to prevent intermingling of notes between contracts.\npub fn silo_note_hash(note_hash: Scoped>) -> Field {\n if note_hash.contract_address.is_zero() {\n 0\n } else {\n compute_siloed_note_hash(note_hash.contract_address, note_hash.innermost())\n }\n}\n\npub fn compute_siloed_nullifier(app: AztecAddress, nullifier: Field) -> Field {\n poseidon2_hash_with_separator(\n [app.to_field(), nullifier],\n GENERATOR_INDEX__OUTER_NULLIFIER,\n )\n}\n\npub fn silo_nullifier(nullifier: Scoped>) -> Field {\n let value = nullifier.innermost().value;\n // Q: shouldn't we be checking whether the _whole_ nullifier is empty?\n // A: We don't have to. The init and inner circuits add contract address to non-empty nullifiers.\n // So we know we should silo it if the contract address is not empty.\n if nullifier.contract_address.is_zero() {\n value // Return `value` instead of 0 because an already-siloed nullifier's contract address is zero.\n } else {\n compute_siloed_nullifier(nullifier.contract_address, value)\n }\n}\n\npub fn create_protocol_nullifier(tx_request: TxRequest) -> Scoped> {\n Nullifier { value: tx_request.hash(), note_hash: 0 }.count(1).scope(\n NULL_MSG_SENDER_CONTRACT_ADDRESS,\n )\n}\n\npub fn compute_siloed_private_log_field(contract_address: AztecAddress, field: Field) -> Field {\n poseidon2_hash([contract_address.to_field(), field])\n}\n\npub fn silo_private_log(private_log: Scoped>) -> PrivateLog {\n let log = private_log.innermost().log;\n if private_log.contract_address.is_zero() {\n log\n } else {\n let mut fields = log.fields;\n fields[0] = compute_siloed_private_log_field(private_log.contract_address, fields[0]);\n PrivateLog::new(fields, log.length)\n }\n}\n\npub fn compute_contract_class_log_hash(log: [Field; CONTRACT_CLASS_LOG_SIZE_IN_FIELDS]) -> Field {\n poseidon2_hash(log)\n}\n\npub fn compute_app_secret_key(\n master_secret_key: EmbeddedCurveScalar,\n app_address: AztecAddress,\n app_secret_generator: Field,\n) -> Field {\n poseidon2_hash_with_separator(\n [master_secret_key.hi, master_secret_key.lo, app_address.to_field()],\n app_secret_generator,\n )\n}\n\npub fn merkle_hash(left: Field, right: Field) -> Field {\n poseidon2_hash([left, right])\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 contract_address_bytes: [u8; 32] = contract_address.to_field().to_be_bytes();\n let recipient_bytes: [u8; 20] = recipient.to_be_bytes();\n let content_bytes: [u8; 32] = content.to_be_bytes();\n let rollup_version_id_bytes: [u8; 32] = rollup_version_id.to_be_bytes();\n let chain_id_bytes: [u8; 32] = chain_id.to_be_bytes();\n\n let mut bytes: [u8; 148] = std::mem::zeroed();\n for i in 0..32 {\n bytes[i] = contract_address_bytes[i];\n bytes[i + 32] = rollup_version_id_bytes[i];\n // 64 - 84 are for recipient.\n bytes[i + 84] = chain_id_bytes[i];\n bytes[i + 116] = content_bytes[i];\n }\n\n for i in 0..20 {\n bytes[64 + i] = recipient_bytes[i];\n }\n\n sha256_to_field(bytes)\n}\n\npub fn silo_l2_to_l1_message(\n msg: Scoped,\n rollup_version_id: Field,\n chain_id: Field,\n) -> Field {\n if msg.contract_address.is_zero() {\n 0\n } else {\n compute_l2_to_l1_hash(\n msg.contract_address,\n msg.inner.recipient,\n msg.inner.content,\n rollup_version_id,\n chain_id,\n )\n }\n}\n\n/// Computes sha256 hash of 2 input fields.\n///\n/// @returns A truncated field (i.e., the first byte is always 0).\npub fn accumulate_sha256(v0: Field, v1: Field) -> Field {\n // Concatenate two fields into 32 x 2 = 64 bytes\n let v0_as_bytes: [u8; 32] = v0.to_be_bytes();\n let v1_as_bytes: [u8; 32] = v1.to_be_bytes();\n let hash_input_flattened = v0_as_bytes.concat(v1_as_bytes);\n\n sha256_to_field(hash_input_flattened)\n}\n\n#[inline_always]\npub fn pedersen_hash(inputs: [Field; N], hash_index: u32) -> Field {\n std::hash::pedersen_hash_with_separator(inputs, hash_index)\n}\n\npub fn poseidon2_hash(inputs: [Field; N]) -> Field {\n poseidon::poseidon2::Poseidon2::hash(inputs, N)\n}\n\n#[no_predicates]\npub fn poseidon2_hash_with_separator(inputs: [Field; N], separator: T) -> Field\nwhere\n T: ToField,\n{\n let inputs_with_separator = [separator.to_field()].concat(inputs);\n poseidon2_hash(inputs_with_separator)\n}\n\n/// Computes a Poseidon2 hash over a dynamic-length subarray of the given input.\n/// Only the first `in_len` fields of `input` are absorbed; any remaining fields are ignored.\n/// The caller is responsible for ensuring that the input is padded with zeros if required.\n#[no_predicates]\npub fn poseidon2_hash_subarray(input: [Field; N], in_len: u32) -> Field {\n let mut sponge = poseidon2_absorb_in_chunks(input, in_len);\n sponge.squeeze()\n}\n\n// NB the below is the same as poseidon::poseidon2::Poseidon2::hash(), but replacing a range check with a bit check,\n// and absorbing in chunks of 3 below.\n#[no_predicates]\npub fn poseidon2_cheaper_variable_hash(input: [Field; N], in_len: u32) -> Field {\n let mut sponge = poseidon2_absorb_in_chunks(input, in_len);\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 in_len != N {\n sponge.absorb(1);\n }\n sponge.squeeze()\n}\n\n// This function is unconstrained because it is intended to be used in unconstrained context only as\n// in constrained contexts it would be too inefficient.\npub unconstrained fn poseidon2_hash_with_separator_bounded_vec(\n inputs: BoundedVec,\n separator: T,\n) -> Field\nwhere\n T: ToField,\n{\n let in_len = inputs.len() + 1;\n let iv: Field = (in_len as Field) * TWO_POW_64;\n let mut sponge = Poseidon2Sponge::new(iv);\n sponge.absorb(separator.to_field());\n\n for i in 0..inputs.len() {\n sponge.absorb(inputs.get(i));\n }\n\n sponge.squeeze()\n}\n\n#[no_predicates]\npub fn poseidon2_hash_bytes(inputs: [u8; N]) -> Field {\n let mut fields = [0; (N + 30) / 31];\n let mut field_index = 0;\n let mut current_field = [0; 31];\n for i in 0..inputs.len() {\n let index = i % 31;\n current_field[index] = inputs[i];\n if index == 30 {\n fields[field_index] = field_from_bytes(current_field, false);\n current_field = [0; 31];\n field_index += 1;\n }\n }\n if field_index != fields.len() {\n fields[field_index] = field_from_bytes(current_field, false);\n }\n poseidon2_hash(fields)\n}\n\n#[test]\nfn poseidon_chunks_matches_fixed() {\n let in_len = 501;\n let mut input: [Field; 4096] = [0; 4096];\n let mut fixed_input = [3; 501];\n assert(in_len == fixed_input.len()); // sanity check\n for i in 0..in_len {\n input[i] = 3;\n }\n let sub_chunk_hash = poseidon2_hash_subarray(input, in_len);\n let fixed_len_hash = poseidon::poseidon2::Poseidon2::hash(fixed_input, fixed_input.len());\n assert(sub_chunk_hash == fixed_len_hash);\n}\n\n#[test]\nfn poseidon_chunks_matches_variable() {\n let in_len = 501;\n let mut input: [Field; 4096] = [0; 4096];\n for i in 0..in_len {\n input[i] = 3;\n }\n let variable_chunk_hash = poseidon2_cheaper_variable_hash(input, in_len);\n let variable_len_hash = poseidon::poseidon2::Poseidon2::hash(input, in_len);\n assert(variable_chunk_hash == variable_len_hash);\n}\n\n#[test]\nfn smoke_sha256_to_field() {\n let full_buffer = [\n 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,\n 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,\n 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70,\n 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93,\n 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112,\n 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130,\n 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148,\n 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,\n ];\n let result = sha256_to_field(full_buffer);\n\n assert(result == 0x448ebbc9e1a31220a2f3830c18eef61b9bd070e5084b7fa2a359fe729184c7);\n\n // to show correctness of the current ver (truncate one byte) vs old ver (mod full bytes):\n let result_bytes = sha256::digest(full_buffer);\n let truncated_field = crate::utils::field::field_from_bytes_32_trunc(result_bytes);\n assert(truncated_field == result);\n let mod_res = result + (result_bytes[31] as Field);\n assert(mod_res == 0x448ebbc9e1a31220a2f3830c18eef61b9bd070e5084b7fa2a359fe729184e0);\n}\n\n#[test]\nfn compute_l2_l1_hash() {\n // All zeroes\n let hash_result =\n compute_l2_to_l1_hash(AztecAddress::from_field(0), EthAddress::zero(), 0, 0, 0);\n assert(hash_result == 0x3b18c58c739716e76429634a61375c45b3b5cd470c22ab6d3e14cee23dd992);\n\n // Non-zero case\n let hash_result = compute_l2_to_l1_hash(\n AztecAddress::from_field(1),\n EthAddress::from_field(3),\n 5,\n 2,\n 4,\n );\n assert(hash_result == 0xaab2a5828156782b12a1dc6f336e2bc627eb1b9514b02d511f66296990c050);\n}\n\n#[test]\nfn silo_l2_to_l1_message_matches_typescript() {\n let version = 4;\n let chainId = 5;\n\n let hash = silo_l2_to_l1_message(\n L2ToL1Message { recipient: EthAddress::from_field(1), content: 2 }.scope(\n AztecAddress::from_field(3),\n ),\n version,\n chainId,\n );\n\n // The following value was generated by `yarn-project/stdlib/src/hash/hash.test.ts`\n let hash_from_typescript = 0x0081edf209e087ad31b3fd24263698723d57190bd1d6e9fe056fc0c0a68ee661;\n\n assert_eq(hash, hash_from_typescript);\n}\n\n#[test]\nunconstrained fn poseidon2_hash_with_separator_bounded_vec_matches_non_bounded_vec_version() {\n let inputs = BoundedVec::::from_array([1, 2, 3]);\n let separator = 42;\n\n // Hash using bounded vec version\n let bounded_result = poseidon2_hash_with_separator_bounded_vec(inputs, separator);\n\n // Hash using regular version\n let regular_result = poseidon2_hash_with_separator([1, 2, 3], separator);\n\n // Results should match\n assert_eq(bounded_result, regular_result);\n}\n" + }, + "351": { + "path": "/home/ubuntu/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.20251212/noir-projects/noir-protocol-circuits/crates/types/src/meta/mod.nr", + "source": "use utils::derive_serialization_quotes;\n\npub mod utils;\n\n/// Generates the generic parameter declarations for a struct's trait implementation.\n///\n/// This function takes a struct type definition and generates the generic parameter declarations\n/// that go after the `impl` keyword. For example, given a struct with generics `N: u32` and `T`,\n/// it generates ``.\n///\n/// # Parameters\n/// - `s`: The struct type definition to generate generic declarations for\n///\n/// # Returns\n/// A quoted code block containing the generic parameter declarations, or an empty quote if the struct\n/// has no generic parameters\n///\n/// # Example\n/// For a struct defined as:\n/// ```\n/// struct Container {\n/// items: [T; N],\n/// count: u32\n/// }\n/// ```\n///\n/// This function generates:\n/// ```\n/// \n/// ```\ncomptime fn get_generics_declarations(s: TypeDefinition) -> Quoted {\n let generics = s.generics();\n\n if generics.len() > 0 {\n let generics_declarations_items = generics\n .map(|(name, maybe_integer_typ)| {\n // The second item in the generics tuple is an Option of an integer type that is Some only if\n // the generic is numeric.\n if maybe_integer_typ.is_some() {\n // The generic is numeric, so we return a quote defined as e.g. \"let N: u32\"\n let integer_type = maybe_integer_typ.unwrap();\n quote {let $name: $integer_type}\n } else {\n // The generic is not numeric, so we return a quote containing the name of the generic (e.g. \"T\")\n quote {$name}\n }\n })\n .join(quote {,});\n quote {<$generics_declarations_items>}\n } else {\n // The struct doesn't have any generics defined, so we just return an empty quote.\n quote {}\n }\n}\n\n/// Generates the `where` clause for a trait implementation that constrains non-numeric generic type parameters.\n///\n/// This function takes a struct type definition and a trait name, and generates a `where` clause that\n/// requires all non-numeric generic type parameters to implement the specified trait.\n///\n/// # Parameters\n/// - `s`: The struct type definition to generate the where clause for\n/// - `trait_name`: The name of the trait that non-numeric generic parameters must implement\n///\n/// # Returns\n/// A quoted code block containing the where clause, or an empty quote if the struct has no non-numeric\n/// generic parameters\n///\n/// # Example\n/// For a struct defined as:\n/// ```\n/// struct Container {\n/// items: [T; N],\n/// count: u32\n/// }\n/// ```\n///\n/// And trait name \"Serialize\", this function generates:\n/// ```\n/// where T: Serialize\n/// ```\ncomptime fn get_where_trait_clause(s: TypeDefinition, trait_name: Quoted) -> Quoted {\n let generics = s.generics();\n\n // The second item in the generics tuple is an Option of an integer type that is Some only if the generic is\n // numeric.\n let non_numeric_generics =\n generics.filter(|(_, maybe_integer_typ)| maybe_integer_typ.is_none());\n\n if non_numeric_generics.len() > 0 {\n let non_numeric_generics_declarations =\n non_numeric_generics.map(|(name, _)| quote {$name: $trait_name}).join(quote {,});\n quote {where $non_numeric_generics_declarations}\n } else {\n // There are no non-numeric generics, so we return an empty quote.\n quote {}\n }\n}\n\n/// Generates a `Serialize` trait implementation for a struct type.\n///\n/// # Parameters\n/// - `s`: The struct type definition to generate the implementation for\n///\n/// # Returns\n/// A quoted code block containing the trait implementation\n///\n/// # Example\n/// For a struct defined as:\n/// ```\n/// struct Log {\n/// fields: [Field; N],\n/// length: u32\n/// }\n/// ```\n///\n/// This function generates code equivalent to:\n/// ```\n/// impl Serialize for Log {\n/// let N: u32 = <[Field; N] as Serialize>::N + ::N;\n///\n/// #[inline_always]\n/// fn serialize(self) -> [Field; Self::N] {\n/// let mut serialized_params = [0; _];\n/// let mut offset = 0;\n///\n/// let serialized_member = Serialize::serialize(self.fields);\n/// let serialized_member_len = <[Field; N] as Serialize>::N;\n/// for i in 0..serialized_member_len {\n/// serialized_params[i + offset] = serialized_member[i];\n/// }\n/// offset += serialized_member_len;\n///\n/// let serialized_member = Serialize::serialize(self.length);\n/// let serialized_member_len = ::N;\n/// for i in 0..serialized_member_len {\n/// serialized_params[i + offset] = serialized_member[i];\n/// }\n/// offset += serialized_member_len;\n///\n/// serialized_params\n/// }\n/// }\n/// ```\npub comptime fn derive_serialize(s: TypeDefinition) -> Quoted {\n let typ = s.as_type();\n let nested_struct = typ.as_data_type().unwrap();\n\n // We care only about the name and type so we drop the last item of the tuple\n let params = nested_struct.0.fields(nested_struct.1).map(|(name, typ, _)| (name, typ));\n\n // Generates the generic parameter declarations (to be placed after the `impl` keyword) and the `where` clause\n // for the `Serialize` trait.\n let generics_declarations = get_generics_declarations(s);\n let where_serialize_clause = get_where_trait_clause(s, quote {Serialize});\n\n let (function_body, params_len_quote, serialized_params_name) =\n derive_serialization_quotes(params, true);\n\n quote {\n impl$generics_declarations $crate::traits::Serialize for $typ\n $where_serialize_clause\n {\n let N: u32 = $params_len_quote;\n\n #[inline_always]\n fn serialize(self) -> [Field; Self::N] {\n $function_body\n\n $serialized_params_name\n }\n }\n }\n}\n\n/// Generates a `Deserialize` trait implementation for a given struct `s`.\n///\n/// # Arguments\n/// * `s` - The struct type definition to generate the implementation for\n///\n/// # Returns\n/// A `Quoted` block containing the generated trait implementation\n///\n/// # Requirements\n/// Each struct member type must implement the `Deserialize` trait (it gets used in the generated code).\n///\n/// # Example\n/// For a struct like:\n/// ```\n/// struct MyStruct {\n/// x: AztecAddress,\n/// y: Field,\n/// }\n/// ```\n///\n/// This generates:\n/// ```\n/// impl Deserialize for MyStruct {\n/// let N: u32 = ::N + ::N;\n///\n/// fn deserialize(serialized: [Field; Self::N]) -> Self {\n/// let mut offset = 0;\n/// let mut member_fields = [0; ::N];\n/// for i in 0..::N {\n/// member_fields[i] = serialized[i + offset];\n/// }\n/// let x = ::deserialize(member_fields);\n/// offset += ::N;\n///\n/// let mut member_fields = [0; ::N];\n/// for i in 0..::N {\n/// member_fields[i] = serialized[i + offset];\n/// }\n/// let y = ::deserialize(member_fields);\n/// offset += ::N;\n///\n/// Self { x, y }\n/// }\n/// }\n/// ```\npub(crate) comptime fn derive_deserialize(s: TypeDefinition) -> Quoted {\n let typ = s.as_type();\n let nested_struct = typ.as_data_type().unwrap();\n let params = nested_struct.0.fields(nested_struct.1);\n\n // Generates the generic parameter declarations (to be placed after the `impl` keyword) and the `where` clause\n // for the `Deserialize` trait.\n let generics_declarations = get_generics_declarations(s);\n let where_deserialize_clause = get_where_trait_clause(s, quote {Deserialize});\n\n // The following will give us:\n // ::N + ::N + ...\n // (or 0 if the struct has no members)\n let right_hand_side_of_definition_of_n = if params.len() > 0 {\n params\n .map(|(_, param_type, _): (Quoted, Type, Quoted)| {\n quote {\n <$param_type as $crate::traits::Deserialize>::N\n }\n })\n .join(quote {+})\n } else {\n quote {0}\n };\n\n // For structs containing a single member, we can enhance performance by directly deserializing the input array,\n // bypassing the need for loop-based array construction. While this optimization yields significant benefits in\n // Brillig where the loops are expected to not be optimized, it is not relevant in ACIR where the loops are\n // expected to be optimized away.\n let function_body = if params.len() > 1 {\n // This generates deserialization code for each struct member and concatenates them together.\n let deserialization_of_struct_members = params\n .map(|(param_name, param_type, _): (Quoted, Type, Quoted)| {\n quote {\n let mut member_fields = [0; <$param_type as Deserialize>::N];\n for i in 0..<$param_type as Deserialize>::N {\n member_fields[i] = serialized[i + offset];\n }\n let $param_name = <$param_type as Deserialize>::deserialize(member_fields);\n offset += <$param_type as Deserialize>::N;\n }\n })\n .join(quote {});\n\n // We join the struct member names with a comma to be used in the `Self { ... }` syntax\n // This will give us e.g. `a, b, c` for a struct with three fields named `a`, `b`, and `c`.\n let struct_members = params\n .map(|(param_name, _, _): (Quoted, Type, Quoted)| quote { $param_name })\n .join(quote {,});\n\n quote {\n let mut offset = 0;\n\n $deserialization_of_struct_members\n\n Self { $struct_members }\n }\n } else if params.len() == 1 {\n let param_name = params[0].0;\n quote {\n Self { $param_name: $crate::traits::Deserialize::deserialize(serialized) }\n }\n } else {\n quote {\n Self {}\n }\n };\n\n quote {\n impl$generics_declarations $crate::traits::Deserialize for $typ\n $where_deserialize_clause\n {\n let N: u32 = $right_hand_side_of_definition_of_n;\n\n #[inline_always]\n fn deserialize(serialized: [Field; Self::N]) -> Self {\n $function_body\n }\n }\n }\n}\n\n/// Generates a `Packable` trait implementation for a given struct `s`.\n///\n/// # Arguments\n/// * `s` - The struct type definition to generate the implementation for\n///\n/// # Returns\n/// A `Quoted` block containing the generated trait implementation\n///\n/// # Requirements\n/// Each struct member type must implement the `Packable` trait (it gets used in the generated code).\n///\n/// # Example\n/// For a struct like:\n/// ```\n/// struct MyStruct {\n/// x: AztecAddress,\n/// y: Field,\n/// }\n/// ```\n///\n/// This generates:\n/// ```\n/// impl Packable for MyStruct {\n/// let N: u32 = 2;\n///\n/// fn pack(self) -> [Field; 2] {\n/// let mut result: [Field; 2] = [0_Field; 2];\n/// let mut offset: u32 = 0_u32;\n/// let packed_member: [Field; 1] = self.x.pack();\n/// let packed_member_len: u32 = ::N;\n/// for i in 0_u32..packed_member_len {\n/// {\n/// result[i + offset] = packed_member[i];\n/// }\n/// }\n/// offset = offset + packed_member_len;\n/// let packed_member: [Field; 1] = self.y.pack();\n/// let packed_member_len: u32 = ::N;\n/// for i in 0_u32..packed_member_len {\n/// {\n/// result[i + offset] = packed_member[i];\n/// }\n/// }\n/// offset = offset + packed_member_len;\n/// result\n/// }\n///\n/// fn unpack(packed: [Field; 2]) -> Self {\n/// let mut offset: u32 = 0_u32;\n/// let mut member_fields: [Field; 1] = [0_Field; 1];\n/// for i in 0_u32..::N {\n/// member_fields[i] = packed[i + offset];\n/// }\n/// let x: AztecAddress = ::unpack(member_fields);\n/// offset = offset + ::N;\n/// let mut member_fields: [Field; 1] = [0_Field; 1];\n/// for i in 0_u32..::N {\n/// member_fields[i] = packed[i + offset];\n/// }\n/// let y: Field = ::unpack(member_fields);\n/// offset = offset + ::N;\n/// Self { x: x, y: y }\n/// }\n/// }\n/// ```\npub comptime fn derive_packable(s: TypeDefinition) -> Quoted {\n let typ = s.as_type();\n let nested_struct = typ.as_data_type().unwrap();\n let params = nested_struct.0.fields(nested_struct.1);\n\n // Generates the generic parameter declarations (to be placed after the `impl` keyword) and the `where` clause\n // for the `Packable` trait.\n let generics_declarations = get_generics_declarations(s);\n let where_packable_clause = get_where_trait_clause(s, quote {Packable});\n\n // The following will give us:\n // ::N + ::N + ...\n // (or 0 if the struct has no members)\n let right_hand_side_of_definition_of_n = if params.len() > 0 {\n params\n .map(|(_, param_type, _): (Quoted, Type, Quoted)| {\n quote {\n <$param_type as $crate::traits::Packable>::N\n }\n })\n .join(quote {+})\n } else {\n quote {0}\n };\n\n // For structs containing a single member, we can enhance performance by directly returning the packed member,\n // bypassing the need for loop-based array construction. While this optimization yields significant benefits in\n // Brillig where the loops are expected to not be optimized, it is not relevant in ACIR where the loops are\n // expected to be optimized away.\n let pack_function_body = if params.len() > 1 {\n // For multiple struct members, generate packing code that:\n // 1. Packs each member\n // 2. Copies the packed fields into the result array at the correct offset\n // 3. Updates the offset for the next member\n let packing_of_struct_members = params\n .map(|(param_name, param_type, _): (Quoted, Type, Quoted)| {\n quote {\n let packed_member = $crate::traits::Packable::pack(self.$param_name);\n let packed_member_len = <$param_type as $crate::traits::Packable>::N;\n for i in 0..packed_member_len {\n result[i + offset] = packed_member[i];\n }\n offset += packed_member_len;\n }\n })\n .join(quote {});\n\n quote {\n let mut result = [0; Self::N];\n let mut offset = 0;\n\n $packing_of_struct_members\n\n result\n }\n } else if params.len() == 1 {\n let param_name = params[0].0;\n quote {\n $crate::traits::Packable::pack(self.$param_name)\n }\n } else {\n quote {\n [0; Self::N]\n }\n };\n\n // For structs containing a single member, we can enhance performance by directly unpacking the input array,\n // bypassing the need for loop-based array construction. While this optimization yields significant benefits in\n // Brillig where the loops are expected to not be optimized, it is not relevant in ACIR where the loops are\n // expected to be optimized away.\n let unpack_function_body = if params.len() > 1 {\n // For multiple struct members, generate unpacking code that:\n // 1. Unpacks each member\n // 2. Copies packed fields into member array at correct offset\n // 3. Updates offset for next member\n let unpacking_of_struct_members = params\n .map(|(param_name, param_type, _): (Quoted, Type, Quoted)| {\n quote {\n let mut member_fields = [0; <$param_type as $crate::traits::Packable>::N];\n for i in 0..<$param_type as $crate::traits::Packable>::N {\n member_fields[i] = packed[i + offset];\n }\n let $param_name = <$param_type as $crate::traits::Packable>::unpack(member_fields);\n offset += <$param_type as $crate::traits::Packable>::N;\n }\n })\n .join(quote {});\n\n // We join the struct member names with a comma to be used in the `Self { ... }` syntax\n let struct_members = params\n .map(|(param_name, _, _): (Quoted, Type, Quoted)| quote { $param_name })\n .join(quote {,});\n\n quote {\n let mut offset = 0;\n $unpacking_of_struct_members\n Self { $struct_members }\n }\n } else if params.len() == 1 {\n let param_name = params[0].0;\n quote {\n Self { $param_name: $crate::traits::Packable::unpack(packed) }\n }\n } else {\n quote {\n Self {}\n }\n };\n\n quote {\n impl$generics_declarations $crate::traits::Packable for $typ\n $where_packable_clause\n {\n let N: u32 = $right_hand_side_of_definition_of_n;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n $pack_function_body\n }\n\n #[inline_always]\n fn unpack(packed: [Field; Self::N]) -> Self {\n $unpack_function_body\n }\n }\n }\n}\n\nmod test {\n use crate::traits::{Deserialize, Packable, Serialize};\n\n #[derive(Deserialize, Eq, Packable, Serialize)]\n pub struct Empty {}\n\n #[derive(Deserialize, Eq, Packable, Serialize)]\n pub struct Smol {\n a: Field,\n b: Field,\n }\n\n #[derive(Deserialize, Eq, Serialize)]\n pub struct HasArray {\n a: [Field; 2],\n b: bool,\n }\n\n #[derive(Deserialize, Eq, Serialize)]\n pub struct Fancier {\n a: Smol,\n b: [Field; 2],\n c: [u8; 3],\n d: str<16>,\n }\n\n #[derive(Deserialize, Eq, Packable, Serialize)]\n pub struct HasArrayWithGenerics {\n pub fields: [T; N],\n pub length: u32,\n }\n\n #[test]\n fn serde_on_empty() {\n let original = Empty {};\n let serialized = original.serialize();\n assert_eq(serialized, [], \"Serialized does not match empty array\");\n let deserialized = Empty::deserialize(serialized);\n assert_eq(deserialized, original, \"Deserialized does not match original\");\n }\n\n #[test]\n fn packable_on_empty() {\n let original = Empty {};\n let packed = original.pack();\n assert_eq(packed, [], \"Packed does not match empty array\");\n let unpacked = Empty::unpack(packed);\n assert_eq(unpacked, original, \"Unpacked does not match original\");\n }\n\n #[test]\n fn serde_on_smol() {\n let smol = Smol { a: 1, b: 2 };\n let serialized = smol.serialize();\n assert(serialized == [1, 2], serialized);\n let deserialized = Smol::deserialize(serialized);\n assert(deserialized == smol);\n\n // None of the struct members implements the `Packable` trait so the packed and serialized data should be the same\n let packed = smol.pack();\n assert_eq(packed, serialized, \"Packed does not match serialized\");\n }\n\n #[test]\n fn serde_on_has_array() {\n let has_array = HasArray { a: [1, 2], b: true };\n let serialized = has_array.serialize();\n assert(serialized == [1, 2, 1], serialized);\n let deserialized = HasArray::deserialize(serialized);\n assert(deserialized == has_array);\n }\n\n #[test]\n fn serde_on_fancier() {\n let fancier =\n Fancier { a: Smol { a: 1, b: 2 }, b: [0, 1], c: [1, 2, 3], d: \"metaprogramming!\" };\n let serialized = fancier.serialize();\n assert(\n serialized\n == [\n 1, 2, 0, 1, 1, 2, 3, 0x6d, 0x65, 0x74, 0x61, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61,\n 0x6d, 0x6d, 0x69, 0x6e, 0x67, 0x21,\n ],\n serialized,\n );\n let deserialized = Fancier::deserialize(serialized);\n assert(deserialized == fancier);\n }\n\n #[test]\n fn serde_on_contains_array_with_generics() {\n let struct_with_array_of_generics = HasArrayWithGenerics { fields: [1, 2, 3], length: 3 };\n let serialized = struct_with_array_of_generics.serialize();\n assert(serialized == [1, 2, 3, 3], serialized);\n let deserialized = HasArrayWithGenerics::deserialize(serialized);\n assert(deserialized == struct_with_array_of_generics);\n }\n\n #[test]\n fn packable_on_contains_array_with_generics() {\n let struct_with_array_of_generics = HasArrayWithGenerics { fields: [1, 2, 3], length: 3 };\n let packed = struct_with_array_of_generics.pack();\n assert(packed == [1, 2, 3, 3], packed);\n\n let unpacked = HasArrayWithGenerics::unpack(packed);\n assert(unpacked == struct_with_array_of_generics);\n }\n\n}\n" + }, + "352": { + "path": "/home/ubuntu/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.20251212/noir-projects/noir-protocol-circuits/crates/types/src/meta/utils.nr", + "source": "/// Generates serialization code for a list of parameters and the total length of the serialized array\n///\n/// # Parameters\n/// - `params`: A list of (name, type) tuples to serialize\n/// - `use_self_prefix`: If true, parameters are accessed as `self.$param_name` (for struct members).\n/// If false, parameters are accessed directly as `$param_name` (for function parameters).\n///\n/// # Returns\n/// A tuple containing:\n/// - Quoted code that serializes the parameters into an array named `serialized_params`\n/// - Quoted code that evaluates to the total length of the serialized array\n/// - Quoted code containing the name of the serialized array\npub comptime fn derive_serialization_quotes(\n params: [(Quoted, Type)],\n use_self_prefix: bool,\n) -> (Quoted, Quoted, Quoted) {\n let prefix_quote = if use_self_prefix {\n quote { self. }\n } else {\n quote {}\n };\n\n let params_len_quote = get_params_len_quote(params);\n let serialized_params_name = quote { serialized_params };\n\n let body = if params.len() == 0 {\n quote {\n let $serialized_params_name: [Field; 0] = [];\n }\n } else if params.len() == 1 {\n // When we have only a single parameter on the input, we can enhance performance by directly returning\n // the serialized member, bypassing the need for loop-based array construction. While this optimization yields\n // significant benefits in Brillig where the loops are expected to not be optimized, it is not relevant in ACIR\n // where the loops are expected to be optimized away.\n\n let param_name = params[0].0;\n quote {\n let $serialized_params_name = $crate::traits::Serialize::serialize($prefix_quote$param_name);\n }\n } else {\n // For multiple struct members, generate serialization code that:\n // 1. Serializes each member\n // 2. Copies the serialized fields into the serialize array at the correct offset\n // 3. Updates the offset for the next member\n let serialization_of_struct_members = params\n .map(|(param_name, param_type): (Quoted, Type)| {\n quote {\n let serialized_member = $crate::traits::Serialize::serialize($prefix_quote$param_name);\n let serialized_member_len = <$param_type as $crate::traits::Serialize>::N;\n for i in 0..serialized_member_len {\n $serialized_params_name[i + offset] = serialized_member[i];\n }\n offset += serialized_member_len;\n }\n })\n .join(quote {});\n\n quote {\n let mut $serialized_params_name = [0; $params_len_quote];\n let mut offset = 0;\n\n $serialization_of_struct_members\n }\n };\n\n (body, params_len_quote, serialized_params_name)\n}\n\n/// Generates a quoted expression that computes the total serialized length of function parameters.\n///\n/// # Parameters\n/// * `params` - An array of tuples where each tuple contains a quoted parameter name and its Type. The type needs\n/// to implement the Serialize trait.\n///\n/// # Returns\n/// A quoted expression that evaluates to:\n/// * `0` if there are no parameters\n/// * `(::N + ::N + ...)` for one or more parameters\npub comptime fn get_params_len_quote(params: [(Quoted, Type)]) -> Quoted {\n if params.len() == 0 {\n quote { 0 }\n } else {\n let params_quote_without_parentheses = params\n .map(|(_, param_type): (Quoted, Type)| {\n quote {\n <$param_type as $crate::traits::Serialize>::N\n }\n })\n .join(quote {+});\n quote { ($params_quote_without_parentheses) }\n }\n}\n" + }, + "353": { + "path": "/home/ubuntu/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.20251212/noir-projects/noir-protocol-circuits/crates/types/src/point.nr", + "source": "pub use dep::std::embedded_curve_ops::EmbeddedCurvePoint as Point;\nuse crate::{hash::poseidon2_hash, traits::{Deserialize, Empty, Hash, Packable, Serialize}};\n\npub global POINT_LENGTH: u32 = 3;\n\n// Note: Not deriving this because it's not supported to call derive_serialize on a \"remote\" struct (and it will never\n// be supported).\nimpl Serialize for Point {\n let N: u32 = POINT_LENGTH;\n\n fn serialize(self: Self) -> [Field; Self::N] {\n [self.x, self.y, self.is_infinite as Field]\n }\n}\n\nimpl Hash for Point {\n fn hash(self) -> Field {\n poseidon2_hash(self.serialize())\n }\n}\n\nimpl Empty for Point {\n /// Note: Does not return a valid point on curve - instead represents an empty/\"unpopulated\" point struct (e.g.\n /// empty/unpopulated value in an array of points).\n fn empty() -> Self {\n Point { x: 0, y: 0, is_infinite: false }\n }\n}\n\nimpl Deserialize for Point {\n let N: u32 = POINT_LENGTH;\n\n fn deserialize(serialized: [Field; Self::N]) -> Self {\n Point { x: serialized[0], y: serialized[1], is_infinite: serialized[2] != 0 }\n }\n}\n\n// TODO(#11356): use compact representation here.\nimpl Packable for Point {\n let N: u32 = POINT_LENGTH;\n\n fn pack(self) -> [Field; Self::N] {\n self.serialize()\n }\n\n fn unpack(packed: [Field; Self::N]) -> Self {\n Self::deserialize(packed)\n }\n}\n" + }, + "354": { + "path": "/home/ubuntu/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.20251212/noir-projects/noir-protocol-circuits/crates/types/src/poseidon2.nr", + "source": "use crate::constants::TWO_POW_64;\nuse crate::traits::{Deserialize, Serialize};\nuse std::meta::derive;\n// NB: This is a clone of noir/noir-repo/noir_stdlib/src/hash/poseidon2.nr\n// It exists as we sometimes need to perform custom absorption, but the stdlib version\n// has a private absorb() method (it's also designed to just be a hasher)\n// Can be removed when standalone noir poseidon lib exists: See noir#6679\n\ncomptime global RATE: u32 = 3;\n\n#[derive(Deserialize, Eq, Serialize)]\npub struct Poseidon2Sponge {\n pub cache: [Field; 3],\n pub state: [Field; 4],\n pub cache_size: u32,\n pub squeeze_mode: bool, // 0 => absorb, 1 => squeeze\n}\n\nimpl Poseidon2Sponge {\n #[no_predicates]\n pub fn hash(input: [Field; N], message_size: u32) -> Field {\n Poseidon2Sponge::hash_internal(input, message_size, message_size != N)\n }\n\n pub(crate) fn new(iv: Field) -> Poseidon2Sponge {\n let mut result =\n Poseidon2Sponge { cache: [0; 3], state: [0; 4], cache_size: 0, squeeze_mode: false };\n result.state[RATE] = iv;\n result\n }\n\n fn perform_duplex(&mut self) {\n // add the cache into sponge state\n for i in 0..RATE {\n // We effectively zero-pad the cache by only adding to the state\n // cache that is less than the specified `cache_size`\n if i < self.cache_size {\n self.state[i] += self.cache[i];\n }\n }\n self.state = std::hash::poseidon2_permutation(self.state, 4);\n }\n\n pub fn absorb(&mut self, input: Field) {\n assert(!self.squeeze_mode);\n if self.cache_size == RATE {\n // If we're absorbing, and the cache is full, apply the sponge permutation to compress the cache\n self.perform_duplex();\n self.cache[0] = input;\n self.cache_size = 1;\n } else {\n // If we're absorbing, and the cache is not full, add the input into the cache\n self.cache[self.cache_size] = input;\n self.cache_size += 1;\n }\n }\n\n pub fn squeeze(&mut self) -> Field {\n assert(!self.squeeze_mode);\n // If we're in absorb mode, apply sponge permutation to compress the cache.\n self.perform_duplex();\n self.squeeze_mode = true;\n\n // Pop one item off the top of the permutation and return it.\n self.state[0]\n }\n\n fn hash_internal(\n input: [Field; N],\n in_len: u32,\n is_variable_length: bool,\n ) -> Field {\n let iv: Field = (in_len as Field) * TWO_POW_64;\n let mut sponge = Poseidon2Sponge::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" + }, + "361": { + "path": "/home/ubuntu/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.20251212/noir-projects/noir-protocol-circuits/crates/types/src/public_keys.nr", + "source": "use crate::{\n address::public_keys_hash::PublicKeysHash,\n constants::{\n DEFAULT_IVPK_M_X, DEFAULT_IVPK_M_Y, DEFAULT_NPK_M_X, DEFAULT_NPK_M_Y, DEFAULT_OVPK_M_X,\n DEFAULT_OVPK_M_Y, DEFAULT_TPK_M_X, DEFAULT_TPK_M_Y, GENERATOR_INDEX__PUBLIC_KEYS_HASH,\n },\n hash::poseidon2_hash_with_separator,\n traits::{Deserialize, Hash, Serialize},\n};\n\nuse dep::std::embedded_curve_ops::EmbeddedCurvePoint as Point;\nuse std::{default::Default, meta::derive};\n\npub trait ToPoint {\n fn to_point(self) -> Point;\n}\n\n#[derive(Deserialize, Eq, Serialize)]\npub struct NpkM {\n pub inner: Point,\n}\n\nimpl ToPoint for NpkM {\n fn to_point(self) -> Point {\n self.inner\n }\n}\n\n// Note: If we store npk_m_hash directly we can remove this trait implementation. See #8091\nimpl Hash for NpkM {\n fn hash(self) -> Field {\n self.inner.hash()\n }\n}\n\n#[derive(Deserialize, Eq, Serialize)]\npub struct IvpkM {\n pub inner: Point,\n}\n\nimpl ToPoint for IvpkM {\n fn to_point(self) -> Point {\n self.inner\n }\n}\n\n#[derive(Deserialize, Eq, Serialize)]\npub struct OvpkM {\n pub inner: Point,\n}\n\nimpl Hash for OvpkM {\n fn hash(self) -> Field {\n self.inner.hash()\n }\n}\n\nimpl ToPoint for OvpkM {\n fn to_point(self) -> Point {\n self.inner\n }\n}\n\n#[derive(Deserialize, Eq, Serialize)]\npub struct TpkM {\n pub inner: Point,\n}\n\nimpl ToPoint for TpkM {\n fn to_point(self) -> Point {\n self.inner\n }\n}\n\n#[derive(Deserialize, Eq, Serialize)]\npub struct PublicKeys {\n pub npk_m: NpkM,\n pub ivpk_m: IvpkM,\n pub ovpk_m: OvpkM,\n pub tpk_m: TpkM,\n}\n\nimpl Default for PublicKeys {\n fn default() -> Self {\n PublicKeys {\n npk_m: NpkM {\n inner: Point { x: DEFAULT_NPK_M_X, y: DEFAULT_NPK_M_Y, is_infinite: false },\n },\n ivpk_m: IvpkM {\n inner: Point { x: DEFAULT_IVPK_M_X, y: DEFAULT_IVPK_M_Y, is_infinite: false },\n },\n ovpk_m: OvpkM {\n inner: Point { x: DEFAULT_OVPK_M_X, y: DEFAULT_OVPK_M_Y, is_infinite: false },\n },\n tpk_m: TpkM {\n inner: Point { x: DEFAULT_TPK_M_X, y: DEFAULT_TPK_M_Y, is_infinite: false },\n },\n }\n }\n}\n\nimpl PublicKeys {\n pub fn hash(self) -> PublicKeysHash {\n PublicKeysHash::from_field(poseidon2_hash_with_separator(\n self.serialize(),\n GENERATOR_INDEX__PUBLIC_KEYS_HASH as Field,\n ))\n }\n}\n\npub struct AddressPoint {\n pub inner: Point,\n}\n\nimpl ToPoint for AddressPoint {\n fn to_point(self) -> Point {\n self.inner\n }\n}\n\nmod test {\n use crate::{\n point::POINT_LENGTH,\n public_keys::{IvpkM, NpkM, OvpkM, PublicKeys, TpkM},\n traits::{Deserialize, Serialize},\n };\n use dep::std::embedded_curve_ops::EmbeddedCurvePoint as Point;\n\n #[test]\n unconstrained fn compute_public_keys_hash() {\n let keys = PublicKeys {\n npk_m: NpkM { inner: Point { x: 1, y: 2, is_infinite: false } },\n ivpk_m: IvpkM { inner: Point { x: 3, y: 4, is_infinite: false } },\n ovpk_m: OvpkM { inner: Point { x: 5, y: 6, is_infinite: false } },\n tpk_m: TpkM { inner: Point { x: 7, y: 8, is_infinite: false } },\n };\n\n let actual = keys.hash();\n let expected_public_keys_hash =\n 0x0fecd9a32db731fec1fded1b9ff957a1625c069245a3613a2538bd527068b0ad;\n\n assert(actual.to_field() == expected_public_keys_hash);\n }\n\n #[test]\n unconstrained fn compute_default_hash() {\n let keys = PublicKeys::default();\n\n let actual = keys.hash();\n let test_data_default_hash =\n 0x1d3bf1fb93ae0e9cda83b203dd91c3bfb492a9aecf30ec90e1057eced0f0e62d;\n\n assert(actual.to_field() == test_data_default_hash);\n }\n\n #[test]\n unconstrained fn serde() {\n let keys = PublicKeys {\n npk_m: NpkM { inner: Point { x: 1, y: 2, is_infinite: false } },\n ivpk_m: IvpkM { inner: Point { x: 3, y: 4, is_infinite: false } },\n ovpk_m: OvpkM { inner: Point { x: 5, y: 6, is_infinite: false } },\n tpk_m: TpkM { inner: Point { x: 7, y: 8, is_infinite: false } },\n };\n\n // We use the PUBLIC_KEYS_LENGTH constant to ensure that there is a match between the derived trait\n let serialized: [Field; POINT_LENGTH * 4] = keys.serialize();\n let deserialized = PublicKeys::deserialize(serialized);\n\n assert_eq(keys, deserialized);\n }\n}\n" + }, + "366": { + "path": "/home/ubuntu/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.20251212/noir-projects/noir-protocol-circuits/crates/types/src/storage/map.nr", + "source": "use crate::{hash::poseidon2_hash, traits::ToField};\n\npub fn derive_storage_slot_in_map(storage_slot: Field, key: K) -> Field\nwhere\n K: ToField,\n{\n poseidon2_hash([storage_slot, key.to_field()])\n}\n\nmod test {\n use crate::{address::AztecAddress, storage::map::derive_storage_slot_in_map, traits::FromField};\n\n #[test]\n fn test_derive_storage_slot_in_map_matches_typescript() {\n let map_slot = 0x132258fb6962c4387ba659d9556521102d227549a386d39f0b22d1890d59c2b5;\n let key = AztecAddress::from_field(\n 0x302dbc2f9b50a73283d5fb2f35bc01eae8935615817a0b4219a057b2ba8a5a3f,\n );\n\n let slot = derive_storage_slot_in_map(map_slot, key);\n\n // The following value was generated by `map_slot.test.ts`\n let slot_from_typescript =\n 0x15b9fe39449affd8b377461263e9d2b610b9ad40580553500b4e41d9cbd887ac;\n\n assert_eq(slot, slot_from_typescript);\n }\n}\n" + }, + "382": { + "path": "/home/ubuntu/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.20251212/noir-projects/noir-protocol-circuits/crates/types/src/traits.nr", + "source": "use crate::meta::{derive_deserialize, derive_packable, derive_serialize};\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.\npub trait Empty: Eq {\n fn empty() -> Self;\n\n fn is_empty(self) -> bool {\n self.eq(Self::empty())\n }\n\n // Requires this Noir fix: https://github.com/noir-lang/noir/issues/9002\n // fn assert_not_empty(self, msg: str) { // This msg version was failing with weird compiler errors.\n // // We provide a default impl but it's likely inefficient.\n // // The reason we include this function is because there's a lot of\n // // opportunity for optimisation on a per-struct basis.\n // // You only need to show one element is not empty to know that the whole thing\n // // is not empty.\n // // If you know an element of your struct which should always be nonempty,\n // // you can write an impl that solely checks that that element is nonempty.\n // assert(!self.is_empty(), msg);\n // }\n\n // This default impl is overwritten by types like arrays, because there's a much\n // more efficient approach.\n fn assert_empty(self, msg: str) {\n assert(self.is_empty(), msg);\n }\n}\n\nimpl Empty for Field {\n #[inline_always]\n fn empty() -> Self {\n 0\n }\n}\n\nimpl Empty for bool {\n #[inline_always]\n fn empty() -> Self {\n false\n }\n}\n\nimpl Empty for u1 {\n #[inline_always]\n fn empty() -> Self {\n 0\n }\n}\nimpl Empty for u8 {\n #[inline_always]\n fn empty() -> Self {\n 0\n }\n}\nimpl Empty for u16 {\n fn empty() -> Self {\n 0\n }\n}\nimpl Empty for u32 {\n #[inline_always]\n fn empty() -> Self {\n 0\n }\n}\nimpl Empty for u64 {\n #[inline_always]\n fn empty() -> Self {\n 0\n }\n}\nimpl Empty for u128 {\n #[inline_always]\n fn empty() -> Self {\n 0\n }\n}\n\nimpl Empty for [T; N]\nwhere\n T: Empty,\n{\n #[inline_always]\n fn empty() -> Self {\n [T::empty(); N]\n }\n\n fn is_empty(self) -> bool {\n self.all(|elem| elem.is_empty())\n }\n\n fn assert_empty(self, msg: str) -> () {\n self.for_each(|elem| elem.assert_empty(msg))\n }\n}\n\nimpl Empty for [T]\nwhere\n T: Empty,\n{\n #[inline_always]\n fn empty() -> Self {\n [T::empty()]\n }\n\n fn is_empty(self) -> bool {\n self.all(|elem| elem.is_empty())\n }\n\n fn assert_empty(self, msg: str) -> () {\n self.for_each(|elem| elem.assert_empty(msg))\n }\n}\nimpl Empty for (A, B)\nwhere\n A: Empty,\n B: Empty,\n{\n #[inline_always]\n fn empty() -> Self {\n (A::empty(), B::empty())\n }\n}\n\nimpl Empty for Option\nwhere\n T: Eq,\n{\n #[inline_always]\n fn empty() -> Self {\n Option::none()\n }\n}\n\n// pub fn is_empty(item: T) -> bool\n// where\n// T: Empty,\n// {\n// item.eq(T::empty())\n// }\n\n// pub fn is_empty_array(array: [T; N]) -> bool\n// where\n// T: Empty,\n// {\n// array.all(|elem| is_empty(elem))\n// }\n\n// pub fn assert_empty(item: T) -> ()\n// where\n// T: Empty,\n// {\n// assert(item.eq(T::empty()))\n// }\n\n// pub fn assert_empty_array(array: [T; N]) -> ()\n// where\n// T: Empty,\n// {\n// // A cheaper option than `is_empty_array` for if you don't need to gracefully\n// // handle a bool result.\n// // Avoids the `&` operator of `is_empty_array`'s `.all()` call.\n// for i in 0..N {\n// assert(is_empty(array[i]));\n// }\n// }\n\npub trait Hash {\n fn hash(self) -> Field;\n}\n\npub trait ToField {\n fn to_field(self) -> Field;\n}\n\nimpl ToField for Field {\n #[inline_always]\n fn to_field(self) -> Field {\n self\n }\n}\n\nimpl ToField for bool {\n #[inline_always]\n fn to_field(self) -> Field {\n self as Field\n }\n}\nimpl ToField for u1 {\n #[inline_always]\n fn to_field(self) -> Field {\n self as Field\n }\n}\nimpl ToField for u8 {\n #[inline_always]\n fn to_field(self) -> Field {\n self as Field\n }\n}\nimpl ToField for u16 {\n fn to_field(self) -> Field {\n self as Field\n }\n}\nimpl ToField for u32 {\n #[inline_always]\n fn to_field(self) -> Field {\n self as Field\n }\n}\nimpl ToField for u64 {\n #[inline_always]\n fn to_field(self) -> Field {\n self as Field\n }\n}\nimpl ToField for u128 {\n #[inline_always]\n fn to_field(self) -> Field {\n self as Field\n }\n}\nimpl ToField for str {\n #[inline_always]\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\npub trait FromField {\n fn from_field(value: Field) -> Self;\n}\n\nimpl FromField for Field {\n #[inline_always]\n fn from_field(value: Field) -> Self {\n value\n }\n}\n\nimpl FromField for bool {\n #[inline_always]\n fn from_field(value: Field) -> Self {\n value != 0\n }\n}\nimpl FromField for u1 {\n #[inline_always]\n fn from_field(value: Field) -> Self {\n value as u1\n }\n}\nimpl FromField for u8 {\n #[inline_always]\n fn from_field(value: Field) -> Self {\n value as u8\n }\n}\nimpl FromField for u16 {\n fn from_field(value: Field) -> Self {\n value as u16\n }\n}\nimpl FromField for u32 {\n #[inline_always]\n fn from_field(value: Field) -> Self {\n value as u32\n }\n}\nimpl FromField for u64 {\n #[inline_always]\n fn from_field(value: Field) -> Self {\n value as u64\n }\n}\nimpl FromField for u128 {\n #[inline_always]\n fn from_field(value: Field) -> Self {\n value as u128\n }\n}\n\n// docs:start:serialize\n/// Trait for serializing Noir types into arrays of Fields.\n///\n/// An implementation of the Serialize trait has to follow Noir's intrinsic serialization (each member of a struct\n/// converted directly into one or more Fields without any packing or compression). This trait (and Deserialize) are\n/// typically used to communicate between Noir and TypeScript (via oracles and function arguments).\n///\n/// # On Following Noir's Intrinsic Serialization\n/// When calling a Noir function from TypeScript (TS), first the function arguments are serialized into an array\n/// of fields. This array is then included in the initial witness. Noir's intrinsic serialization is then used\n/// to deserialize the arguments from the witness. When the same Noir function is called from Noir this Serialize trait\n/// is used instead of the serialization in TS. For this reason we need to have a match between TS serialization,\n/// Noir's intrinsic serialization and the implementation of this trait. If there is a mismatch, the function calls\n/// fail with an arguments hash mismatch error message.\n///\n/// # Associated Constants\n/// * `N` - The length of the output Field array, known at compile time\n///\n/// # Example\n/// ```\n/// impl Serialize for str {\n/// let N: u32 = N;\n///\n/// fn serialize(self) -> [Field; Self::N] {\n/// let bytes = self.as_bytes();\n/// let mut fields = [0; Self::N];\n/// for i in 0..bytes.len() {\n/// fields[i] = bytes[i] as Field; // Each byte gets its own Field\n/// }\n/// fields\n/// }\n/// }\n/// ```\n#[derive_via(derive_serialize)]\npub trait Serialize {\n let N: u32;\n\n fn serialize(self) -> [Field; N];\n}\n// docs:end:serialize\n\nimpl Serialize for str {\n let N: u32 = M;\n\n #[inline_always]\n fn serialize(self) -> [Field; Self::N] {\n let bytes = self.as_bytes();\n let mut fields = [0; Self::N];\n for i in 0..bytes.len() {\n fields[i] = bytes[i] as Field;\n }\n fields\n }\n}\n\n/// Implementation of Deserialize for BoundedVec.\n///\n/// This implementation deserializes a BoundedVec from an array of Fields. The array contains:\n/// 1. The serialized items, each taking up T::N Fields\n/// 2. The length of the BoundedVec as the last Field\n///\n/// # Type Parameters\n/// * `T` - The type of items stored in the BoundedVec, must implement Deserialize\n/// * `M` - The maximum length of the BoundedVec\n///\n/// # Fields Array Layout\n/// [item1_field1, item1_field2, ..., item2_field1, item2_field2, ..., length]\n/// Where:\n/// - itemN_fieldM: The M-th Field of the N-th item (T::N Fields per item)\n/// - length: The number of items in the BoundedVec (1 Field)\n///\n/// Total length N = T::N * M + 1, where:\n/// - T::N is the number of Fields needed to deserialize one item\n/// - M is the maximum length of the BoundedVec\n/// - +1 is for storing the length\n///\n/// # Note\n/// Not deriving this because it's not supported to call derive_deserialize on a \"remote\" struct (and it will never\n/// be supported).\nimpl Deserialize for BoundedVec\nwhere\n T: Deserialize,\n{\n let N: u32 = ::N * M + 1;\n\n #[inline_always]\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut new_bounded_vec: BoundedVec = BoundedVec::new();\n\n // Length is stored in the last field as we need to match intrinsic Noir serialization and the `len` struct\n // field is after `storage` struct field (see `bounded_vec.nr` in noir-stdlib)\n let len = fields[::N * M] as u32;\n\n for i in 0..len {\n let mut nested_fields = [0; ::N];\n for j in 0..::N {\n nested_fields[j] = fields[i * ::N + j];\n }\n\n let item = T::deserialize(nested_fields);\n new_bounded_vec.push(item);\n }\n\n new_bounded_vec\n }\n}\n\n// This may cause issues if used as program input, because noir disallows empty arrays for program input.\n// I think this is okay because I don't foresee a unit type being used as input. But leaving this comment as a hint\n// if someone does run into this in the future.\nimpl Deserialize for () {\n let N: u32 = 0;\n\n fn deserialize(_fields: [Field; Self::N]) -> Self {\n ()\n }\n}\n\n// Note: Not deriving this because it's not supported to call derive_serialize on a \"remote\" struct (and it will never\n// be supported).\nimpl Serialize for BoundedVec\nwhere\n T: Serialize,\n{\n let N: u32 = ::N * M + 1; // +1 for the length of the BoundedVec\n\n #[inline_always]\n fn serialize(self) -> [Field; Self::N] {\n let mut fields = [0; Self::N];\n\n let storage = self.storage();\n\n for i in 0..M {\n let serialized_item = storage[i].serialize();\n\n for j in 0..::N {\n fields[i * ::N + j] = serialized_item[j];\n }\n }\n\n // Length is stored in the last field as we need to match intrinsic Noir serialization and the `len` struct\n // field is after `storage` struct field (see `bounded_vec.nr` in noir-stdlib)\n fields[::N * M] = self.len() as Field;\n\n fields\n }\n}\n\n// docs:start:deserialize\n/// Trait for deserializing Noir types from arrays of Fields.\n///\n/// An implementation of the Deserialize trait has to follow Noir's intrinsic serialization (each member of a struct\n/// converted directly into one or more Fields without any packing or compression). This trait is typically used when\n/// deserializing return values from function calls in Noir. Since the same function could be called from TypeScript\n/// (TS), in which case the TS deserialization would get used, we need to have a match between the 2.\n///\n/// # Associated Constants\n/// * `N` - The length of the input Field array, known at compile time\n///\n/// # Example\n/// ```\n/// impl Deserialize for str {\n/// let N: u32 = M;\n///\n/// #[inline_always]\n/// fn deserialize(fields: [Field; Self::N]) -> Self {\n/// str::::from(fields.map(|value| value as u8))\n/// }\n/// }\n/// ```\n#[derive_via(derive_deserialize)]\npub trait Deserialize {\n let N: u32;\n\n fn deserialize(fields: [Field; N]) -> Self;\n}\n// docs:end:deserialize\n\nimpl Deserialize for str {\n let N: u32 = M;\n\n #[inline_always]\n fn deserialize(fields: [Field; Self::N]) -> Self {\n str::::from(fields.map(|value| value as u8))\n }\n}\n\n/// Trait for efficiently packing and unpacking Noir types into and from arrays of Fields.\n///\n/// The `Packable` trait allows types to be serialized and deserialized with a focus on minimizing the size of\n/// the resulting Field array. This trait is used when storage efficiency is critical (e.g. when storing data\n/// in the contract's public storage).\n///\n/// # Associated Constants\n/// * `N` - The length of the Field array, known at compile time\n#[derive_via(derive_packable)]\npub trait Packable {\n let N: u32;\n\n /// Packs the current value into a compact array of `Field` elements.\n fn pack(self) -> [Field; N];\n\n /// Unpacks a compact array of `Field` elements into the original value.\n fn unpack(fields: [Field; N]) -> Self;\n}\n\n#[test]\nunconstrained fn bounded_vec_serialization() {\n // Test empty BoundedVec\n let empty_vec: BoundedVec = BoundedVec::from_array([]);\n let serialized = empty_vec.serialize();\n let deserialized = BoundedVec::::deserialize(serialized);\n assert_eq(empty_vec, deserialized);\n assert_eq(deserialized.len(), 0);\n\n // Test partially filled BoundedVec\n let partial_vec: BoundedVec<[u32; 2], 3> = BoundedVec::from_array([[1, 2]]);\n let serialized = partial_vec.serialize();\n let deserialized = BoundedVec::<[u32; 2], 3>::deserialize(serialized);\n assert_eq(partial_vec, deserialized);\n assert_eq(deserialized.len(), 1);\n assert_eq(deserialized.get(0), [1, 2]);\n\n // Test full BoundedVec\n let full_vec: BoundedVec<[u32; 2], 3> = BoundedVec::from_array([[1, 2], [3, 4], [5, 6]]);\n let serialized = full_vec.serialize();\n let deserialized = BoundedVec::<[u32; 2], 3>::deserialize(serialized);\n assert_eq(full_vec, deserialized);\n assert_eq(deserialized.len(), 3);\n assert_eq(deserialized.get(0), [1, 2]);\n assert_eq(deserialized.get(1), [3, 4]);\n assert_eq(deserialized.get(2), [5, 6]);\n}\n" + }, + "384": { + "path": "/home/ubuntu/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.20251212/noir-projects/noir-protocol-circuits/crates/types/src/type_packing.nr", + "source": "use crate::traits::Packable;\n\nglobal BOOL_PACKED_LEN: u32 = 1;\nglobal U8_PACKED_LEN: u32 = 1;\nglobal U16_PACKED_LEN: u32 = 1;\nglobal U32_PACKED_LEN: u32 = 1;\nglobal U64_PACKED_LEN: u32 = 1;\nglobal U128_PACKED_LEN: u32 = 1;\nglobal FIELD_PACKED_LEN: u32 = 1;\nglobal I8_PACKED_LEN: u32 = 1;\nglobal I16_PACKED_LEN: u32 = 1;\nglobal I32_PACKED_LEN: u32 = 1;\nglobal I64_PACKED_LEN: u32 = 1;\n\nimpl Packable for bool {\n let N: u32 = BOOL_PACKED_LEN;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n [self as Field]\n }\n\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> bool {\n (fields[0] as u1) != 0\n }\n}\n\nimpl Packable for u8 {\n let N: u32 = U8_PACKED_LEN;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n [self as Field]\n }\n\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> Self {\n fields[0] as u8\n }\n}\n\nimpl Packable for u16 {\n let N: u32 = U16_PACKED_LEN;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n [self as Field]\n }\n\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> Self {\n fields[0] as u16\n }\n}\n\nimpl Packable for u32 {\n let N: u32 = U32_PACKED_LEN;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n [self as Field]\n }\n\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> Self {\n fields[0] as u32\n }\n}\n\nimpl Packable for u64 {\n let N: u32 = U64_PACKED_LEN;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n [self as Field]\n }\n\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> Self {\n fields[0] as u64\n }\n}\n\nimpl Packable for u128 {\n let N: u32 = U128_PACKED_LEN;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n [self as Field]\n }\n\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> Self {\n fields[0] as u128\n }\n}\n\nimpl Packable for Field {\n let N: u32 = FIELD_PACKED_LEN;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n [self]\n }\n\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> Self {\n fields[0]\n }\n}\n\nimpl Packable for i8 {\n let N: u32 = I8_PACKED_LEN;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n [self as u8 as Field]\n }\n\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> Self {\n fields[0] as u8 as i8\n }\n}\n\nimpl Packable for i16 {\n let N: u32 = I16_PACKED_LEN;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n [self as u16 as Field]\n }\n\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> Self {\n fields[0] as u16 as i16\n }\n}\n\nimpl Packable for i32 {\n let N: u32 = I32_PACKED_LEN;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n [self as u32 as Field]\n }\n\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> Self {\n fields[0] as u32 as i32\n }\n}\n\nimpl Packable for i64 {\n let N: u32 = I64_PACKED_LEN;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n [self as u64 as Field]\n }\n\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> Self {\n fields[0] as u64 as i64\n }\n}\n\nimpl Packable for [T; M]\nwhere\n T: Packable,\n{\n let N: u32 = M * ::N;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n let mut result: [Field; Self::N] = std::mem::zeroed();\n for i in 0..M {\n let serialized = self[i].pack();\n for j in 0..::N {\n result[i * ::N + j] = serialized[j];\n }\n }\n result\n }\n\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> Self {\n let mut reader = crate::utils::reader::Reader::new(fields);\n let mut result: [T; M] = std::mem::zeroed();\n reader.read_struct_array::::N, M>(Packable::unpack, result)\n }\n}\n\n#[test]\nfn test_u16_packing() {\n let a: u16 = 10;\n assert_eq(a, u16::unpack(a.pack()));\n}\n\n#[test]\nfn test_i8_packing() {\n let a: i8 = -10;\n assert_eq(a, i8::unpack(a.pack()));\n}\n\n#[test]\nfn test_i16_packing() {\n let a: i16 = -10;\n assert_eq(a, i16::unpack(a.pack()));\n}\n\n#[test]\nfn test_i32_packing() {\n let a: i32 = -10;\n assert_eq(a, i32::unpack(a.pack()));\n}\n\n#[test]\nfn test_i64_packing() {\n let a: i64 = -10;\n assert_eq(a, i64::unpack(a.pack()));\n}\n" + }, + "385": { + "path": "/home/ubuntu/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.20251212/noir-projects/noir-protocol-circuits/crates/types/src/type_serialization.nr", + "source": "use crate::traits::{Deserialize, Serialize};\n\nglobal U1_SERIALIZED_LEN: u32 = 1;\nglobal BOOL_SERIALIZED_LEN: u32 = 1;\nglobal U8_SERIALIZED_LEN: u32 = 1;\nglobal U16_SERIALIZED_LEN: u32 = 1;\nglobal U32_SERIALIZED_LEN: u32 = 1;\nglobal U64_SERIALIZED_LEN: u32 = 1;\nglobal U128_SERIALIZED_LEN: u32 = 1;\nglobal FIELD_SERIALIZED_LEN: u32 = 1;\nglobal I8_SERIALIZED_LEN: u32 = 1;\nglobal I16_SERIALIZED_LEN: u32 = 1;\nglobal I32_SERIALIZED_LEN: u32 = 1;\nglobal I64_SERIALIZED_LEN: u32 = 1;\n\nimpl Serialize for bool {\n let N: u32 = BOOL_SERIALIZED_LEN;\n\n #[inline_always]\n fn serialize(self) -> [Field; Self::N] {\n [self as Field]\n }\n}\n\nimpl Deserialize for bool {\n let N: u32 = BOOL_SERIALIZED_LEN;\n\n #[inline_always]\n fn deserialize(fields: [Field; Self::N]) -> bool {\n fields[0] != 0\n }\n}\n\nimpl Serialize for u1 {\n let N: u32 = U1_SERIALIZED_LEN;\n\n #[inline_always]\n fn serialize(self) -> [Field; Self::N] {\n [self as Field]\n }\n}\n\nimpl Deserialize for u1 {\n let N: u32 = U1_SERIALIZED_LEN;\n\n #[inline_always]\n fn deserialize(fields: [Field; Self::N]) -> Self {\n fields[0] as u1\n }\n}\n\nimpl Serialize for u8 {\n let N: u32 = U8_SERIALIZED_LEN;\n\n #[inline_always]\n fn serialize(self) -> [Field; Self::N] {\n [self as Field]\n }\n}\n\nimpl Deserialize for u8 {\n let N: u32 = U8_SERIALIZED_LEN;\n\n #[inline_always]\n fn deserialize(fields: [Field; Self::N]) -> Self {\n fields[0] as u8\n }\n}\n\nimpl Serialize for u16 {\n let N: u32 = U16_SERIALIZED_LEN;\n\n #[inline_always]\n fn serialize(self) -> [Field; Self::N] {\n [self as Field]\n }\n}\n\nimpl Deserialize for u16 {\n let N: u32 = U16_SERIALIZED_LEN;\n\n #[inline_always]\n fn deserialize(fields: [Field; Self::N]) -> Self {\n fields[0] as u16\n }\n}\n\nimpl Serialize for u32 {\n let N: u32 = U32_SERIALIZED_LEN;\n\n #[inline_always]\n fn serialize(self) -> [Field; Self::N] {\n [self as Field]\n }\n}\n\nimpl Deserialize for u32 {\n let N: u32 = U32_SERIALIZED_LEN;\n\n #[inline_always]\n fn deserialize(fields: [Field; Self::N]) -> Self {\n fields[0] as u32\n }\n}\n\nimpl Serialize for u64 {\n let N: u32 = U64_SERIALIZED_LEN;\n\n #[inline_always]\n fn serialize(self) -> [Field; Self::N] {\n [self as Field]\n }\n}\n\nimpl Deserialize for u64 {\n let N: u32 = U64_SERIALIZED_LEN;\n\n #[inline_always]\n fn deserialize(fields: [Field; Self::N]) -> Self {\n fields[0] as u64\n }\n}\n\nimpl Serialize for u128 {\n let N: u32 = U128_SERIALIZED_LEN;\n\n #[inline_always]\n fn serialize(self) -> [Field; Self::N] {\n [self as Field]\n }\n}\n\nimpl Deserialize for u128 {\n let N: u32 = U128_SERIALIZED_LEN;\n\n #[inline_always]\n fn deserialize(fields: [Field; Self::N]) -> Self {\n fields[0] as u128\n }\n}\n\nimpl Serialize for Field {\n let N: u32 = FIELD_SERIALIZED_LEN;\n\n #[inline_always]\n fn serialize(self) -> [Field; Self::N] {\n [self]\n }\n}\n\nimpl Deserialize for Field {\n let N: u32 = FIELD_SERIALIZED_LEN;\n\n #[inline_always]\n fn deserialize(fields: [Field; Self::N]) -> Self {\n fields[0]\n }\n}\n\nimpl Serialize for i8 {\n let N: u32 = I8_SERIALIZED_LEN;\n\n #[inline_always]\n fn serialize(self) -> [Field; Self::N] {\n [self as u8 as Field]\n }\n}\n\nimpl Deserialize for i8 {\n let N: u32 = I8_SERIALIZED_LEN;\n\n #[inline_always]\n fn deserialize(fields: [Field; Self::N]) -> Self {\n fields[0] as u8 as i8\n }\n}\n\nimpl Serialize for i16 {\n let N: u32 = I16_SERIALIZED_LEN;\n\n #[inline_always]\n fn serialize(self) -> [Field; Self::N] {\n [self as u16 as Field]\n }\n}\n\nimpl Deserialize for i16 {\n let N: u32 = I16_SERIALIZED_LEN;\n\n #[inline_always]\n fn deserialize(fields: [Field; Self::N]) -> Self {\n fields[0] as u16 as i16\n }\n}\n\nimpl Serialize for i32 {\n let N: u32 = I32_SERIALIZED_LEN;\n\n #[inline_always]\n fn serialize(self) -> [Field; Self::N] {\n [self as u32 as Field]\n }\n}\n\nimpl Deserialize for i32 {\n let N: u32 = I32_SERIALIZED_LEN;\n\n #[inline_always]\n fn deserialize(fields: [Field; Self::N]) -> Self {\n fields[0] as u32 as i32\n }\n}\n\nimpl Serialize for i64 {\n let N: u32 = I64_SERIALIZED_LEN;\n\n #[inline_always]\n fn serialize(self) -> [Field; Self::N] {\n [self as u64 as Field]\n }\n}\n\nimpl Deserialize for i64 {\n let N: u32 = I64_SERIALIZED_LEN;\n\n #[inline_always]\n fn deserialize(fields: [Field; Self::N]) -> Self {\n fields[0] as u64 as i64\n }\n}\n\nimpl Serialize for [T; M]\nwhere\n T: Serialize,\n{\n let N: u32 = ::N * M;\n #[inline_always]\n fn serialize(self) -> [Field; Self::N] {\n let mut result: [Field; _] = std::mem::zeroed();\n for i in 0..M {\n let serialized_t = self[i].serialize();\n for j in 0..::N {\n result[i * ::N + j] = serialized_t[j];\n }\n }\n result\n }\n}\n\nimpl Deserialize for [T; M]\nwhere\n T: Deserialize,\n{\n let N: u32 = ::N * M;\n\n #[inline_always]\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = crate::utils::reader::Reader::new(fields);\n let mut result: [T; M] = std::mem::zeroed();\n reader.read_struct_array::::N, M>(Deserialize::deserialize, result)\n }\n}\n\nimpl Serialize for Option\nwhere\n T: Serialize,\n{\n let N: u32 = ::N + 1;\n\n #[inline_always]\n fn serialize(self) -> [Field; Self::N] {\n let mut result: [Field; Self::N] = std::mem::zeroed();\n\n result[0] = if self.is_some() { 1 } else { 0 };\n\n let value_serialized = self.unwrap_unchecked().serialize();\n for i in 0..::N {\n result[1 + i] = value_serialized[i];\n }\n\n result\n }\n}\n\nimpl Deserialize for Option\nwhere\n T: Deserialize,\n{\n let N: u32 = ::N + 1;\n\n #[inline_always]\n fn deserialize(fields: [Field; Self::N]) -> Self {\n if fields[0] == 1 {\n let mut value_fields = [0; ::N];\n for i in 0..::N {\n value_fields[i] = fields[1 + i];\n }\n\n Option::some(T::deserialize(value_fields))\n } else {\n Option::none()\n }\n }\n}\n\nmod test {\n use crate::traits::{Deserialize, Serialize};\n\n #[test]\n fn u16_serialization() {\n let a: u16 = 10;\n assert_eq(a, u16::deserialize(a.serialize()));\n }\n\n #[test]\n fn i8_serialization() {\n let a: i8 = -10;\n assert_eq(a, i8::deserialize(a.serialize()));\n }\n\n #[test]\n fn i16_serialization() {\n let a: i16 = -10;\n assert_eq(a, i16::deserialize(a.serialize()));\n }\n\n #[test]\n fn i32_serialization() {\n let a: i32 = -10;\n assert_eq(a, i32::deserialize(a.serialize()));\n }\n\n #[test]\n fn i64_serialization() {\n let a: i64 = -10;\n assert_eq(a, i64::deserialize(a.serialize()));\n }\n\n #[test]\n fn option_field_serialization() {\n let opt_some = Option::some(5);\n assert_eq(Option::<_>::deserialize(opt_some.serialize()), opt_some);\n\n let opt_none = Option::none();\n assert_eq(Option::::deserialize(opt_none.serialize()), opt_none);\n }\n\n #[test]\n fn array_serialization() {\n let array = [1, 2, 3, 4];\n\n let serialized: [Field; 4] = array.serialize();\n let deserialized: [Field; 4] = Deserialize::deserialize(serialized);\n assert_eq(deserialized, array);\n }\n\n #[test]\n fn nested_array_serialization() {\n let nested_array = [[1, 2, 3, 4], [5, 6, 7, 8]];\n\n let serialized: [Field; 8] = nested_array.serialize();\n let deserialized: [[Field; 4]; 2] = Deserialize::deserialize(serialized);\n\n assert_eq(deserialized, nested_array);\n }\n\n #[test]\n fn option_array_serialization() {\n let opt_some = Option::some([2, 5]);\n assert_eq(Option::<_>::deserialize(opt_some.serialize()), opt_some);\n\n let opt_none = Option::none();\n assert_eq(Option::::deserialize(opt_none.serialize()), opt_none);\n }\n}\n" + }, + "390": { + "path": "/home/ubuntu/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.20251212/noir-projects/noir-protocol-circuits/crates/types/src/utils/field.nr", + "source": "global KNOWN_NON_RESIDUE: Field = 5; // This is a non-residue in Noir's native Field.\n\npub fn field_from_bytes(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\npub fn min(f1: Field, f2: Field) -> Field {\n if f1.lt(f2) {\n f1\n } else {\n f2\n }\n}\n\nglobal C1: u32 = 28;\nglobal C3: Field = 40770029410420498293352137776570907027550720424234931066070132305055;\nglobal C5: Field = 19103219067921713944291392827692070036145651957329286315305642004821462161904;\n\npub fn pow(x: Field, y: Field) -> Field {\n let mut r = 1 as Field;\n let b: [u1; 254] = y.to_le_bits();\n\n for i in 0..254 {\n r *= r;\n r *= (b[254 - 1 - i] as Field) * x + (1 - b[254 - 1 - i] as Field);\n }\n\n r\n}\n\n/// Returns Option::some(sqrt) if there is a square root, and Option::none() if there isn't.\npub fn sqrt(x: Field) -> Option {\n // Safety: if the hint returns the square root of x, then we simply square it\n // check the result equals x. If x is not square, we return a value that\n // enables us to prove that fact (see the `else` clause below).\n let (is_sq, maybe_sqrt) = unsafe { __sqrt(x) };\n\n if is_sq {\n let sqrt = maybe_sqrt;\n validate_sqrt_hint(x, sqrt);\n Option::some(sqrt)\n } else {\n let not_sqrt_hint = maybe_sqrt;\n validate_not_sqrt_hint(x, not_sqrt_hint);\n Option::none()\n }\n}\n\n// Boolean indicating whether Field element is a square, i.e. whether there exists a y in Field s.t. x = y*y.\nunconstrained fn is_square(x: Field) -> bool {\n let v = pow(x, -1 / 2);\n v * (v - 1) == 0\n}\n\n// Tonelli-Shanks algorithm for computing the square root of a Field element.\n// Requires C1 = max{c: 2^c divides (p-1)}, where p is the order of Field\n// as well as C3 = (C2 - 1)/2, where C2 = (p-1)/(2^c1),\n// and C5 = ZETA^C2, where ZETA is a non-square element of Field.\n// These are pre-computed above as globals.\nunconstrained fn tonelli_shanks_sqrt(x: Field) -> Field {\n let mut z = pow(x, C3);\n let mut t = z * z * x;\n z *= x;\n let mut b = t;\n let mut c = C5;\n\n for i in 0..(C1 - 1) {\n for _j in 1..(C1 - i - 1) {\n b *= b;\n }\n\n z *= if b == 1 { 1 } else { c };\n\n c *= c;\n\n t *= if b == 1 { 1 } else { c };\n\n b = t;\n }\n\n z\n}\n\n// NB: this doesn't return an option, because in the case of there _not_ being a square root, we still want to return a field element that allows us to then assert in the _constrained_ sqrt function that there is no sqrt.\nunconstrained fn __sqrt(x: Field) -> (bool, Field) {\n let is_sq = is_square(x);\n if is_sq {\n let sqrt = tonelli_shanks_sqrt(x);\n (true, sqrt)\n } else {\n // Demonstrate that x is not a square (a.k.a. a \"quadratic non-residue\").\n // Facts:\n // The Legendre symbol (\"LS\") of x, is x^((p-1)/2) (mod p).\n // - If x is a square, LS(x) = 1\n // - If x is not a square, LS(x) = -1\n // - If x = 0, LS(x) = 0.\n //\n // Hence:\n // sq * sq = sq // 1 * 1 = 1\n // non-sq * non-sq = sq // -1 * -1 = 1\n // sq * non-sq = non-sq // -1 * 1 = -1\n //\n // See: https://en.wikipedia.org/wiki/Legendre_symbol\n let demo_x_not_square = x * KNOWN_NON_RESIDUE;\n let not_sqrt = tonelli_shanks_sqrt(demo_x_not_square);\n (false, not_sqrt)\n }\n}\n\nfn validate_sqrt_hint(x: Field, hint: Field) {\n assert(hint * hint == x, f\"The claimed_sqrt {hint} is not the sqrt of x {x}\");\n}\n\nfn validate_not_sqrt_hint(x: Field, hint: Field) {\n // We need this assertion, because x = 0 would pass the other assertions in this\n // function, and we don't want people to be able to prove that 0 is not square!\n assert(x != 0, \"0 has a square root; you cannot claim it is not square\");\n // Demonstrate that x is not a square (a.k.a. a \"quadratic non-residue\").\n //\n // Facts:\n // The Legendre symbol (\"LS\") of x, is x^((p-1)/2) (mod p).\n // - If x is a square, LS(x) = 1\n // - If x is not a square, LS(x) = -1\n // - If x = 0, LS(x) = 0.\n //\n // Hence:\n // 1. sq * sq = sq // 1 * 1 = 1\n // 2. non-sq * non-sq = sq // -1 * -1 = 1\n // 3. sq * non-sq = non-sq // -1 * 1 = -1\n //\n // See: https://en.wikipedia.org/wiki/Legendre_symbol\n //\n // We want to demonstrate that this below multiplication falls under bullet-point (2):\n let demo_x_not_square = x * KNOWN_NON_RESIDUE;\n // I.e. we want to demonstrate that `demo_x_not_square` has Legendre symbol 1\n // (i.e. that it is a square), so we prove that it is square below.\n // Why do we want to prove that it has LS 1?\n // Well, since it was computed with a known-non-residue, its squareness implies we're\n // in case 2 (something multiplied by a known-non-residue yielding a result which\n // has a LS of 1), which implies that x must be a non-square. The unconstrained\n // function gave us the sqrt of demo_x_not_square, so all we need to do is\n // assert its squareness:\n assert(\n hint * hint == demo_x_not_square,\n f\"The hint {hint} does not demonstrate that {x} is not a square\",\n );\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,\n 151, 202, 67, 55, 77, 233, 80, 187, 224, 167,\n ];\n let field = field_from_bytes(inputs, true);\n let return_bytes: [u8; 31] = field.to_be_bytes();\n assert_eq(inputs, return_bytes);\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,\n 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: [u8; 31] = field.to_be_bytes();\n\n assert_eq(return_bytes2, return_bytes);\n assert_eq(field2, field);\n}\n\n#[test]\nunconstrained fn max_field_test() {\n // Tests the hardcoded value in constants.nr vs underlying modulus\n // NB: We can't use 0-1 in constants.nr as it will be transpiled incorrectly to ts and sol constants files\n let max_value = crate::constants::MAX_FIELD_VALUE;\n assert_eq(max_value, 0 - 1);\n // modulus == 0 is tested elsewhere, so below is more of a sanity check\n let max_bytes: [u8; 32] = max_value.to_be_bytes();\n let mod_bytes = std::field::modulus_be_bytes();\n for i in 0..31 {\n assert_eq(max_bytes[i], mod_bytes[i]);\n }\n assert_eq(max_bytes[31], mod_bytes[31] - 1);\n}\n\n#[test]\nunconstrained fn sqrt_valid_test() {\n let x = 16; // examples: 16, 9, 25, 81\n let result = sqrt(x);\n assert(result.is_some());\n assert_eq(result.unwrap() * result.unwrap(), x);\n}\n\n#[test]\nunconstrained fn sqrt_invalid_test() {\n let x = KNOWN_NON_RESIDUE; // has no square root in the field\n let result = sqrt(x);\n assert(result.is_none());\n}\n" + }, + "394": { + "path": "/home/ubuntu/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.20251212/noir-projects/noir-protocol-circuits/crates/types/src/utils/reader.nr", + "source": "pub struct Reader {\n data: [Field; N],\n offset: u32,\n}\n\nimpl Reader {\n pub fn new(data: [Field; N]) -> Self {\n Self { data, offset: 0 }\n }\n\n pub fn read(&mut self) -> Field {\n let result = self.data[self.offset];\n self.offset += 1;\n result\n }\n\n pub fn read_u32(&mut self) -> u32 {\n self.read() as u32\n }\n\n pub fn read_u64(&mut self) -> u64 {\n self.read() as u64\n }\n\n pub fn read_bool(&mut self) -> bool {\n self.read() != 0\n }\n\n pub fn read_array(&mut self) -> [Field; K] {\n let mut result = [0; K];\n for i in 0..K {\n result[i] = self.data[self.offset + i];\n }\n self.offset += K;\n result\n }\n\n pub fn read_struct(&mut self, deserialise: fn([Field; K]) -> T) -> T {\n let result = deserialise(self.read_array());\n result\n }\n\n pub fn read_struct_array(\n &mut self,\n deserialise: fn([Field; K]) -> T,\n mut result: [T; C],\n ) -> [T; C] {\n for i in 0..C {\n result[i] = self.read_struct(deserialise);\n }\n result\n }\n\n pub fn finish(self) {\n assert_eq(self.offset, self.data.len(), \"Reader did not read all data\");\n }\n}\n" + }, + "412": { + "path": "/home/ubuntu/nargo/github.com/noir-lang/sha256/v0.2.1/src/sha256.nr", + "source": "use std::hash::sha256_compression;\nuse std::runtime::is_unconstrained;\n\nuse constants::{\n BLOCK_BYTE_PTR, BLOCK_SIZE, HASH, INITIAL_STATE, INT_BLOCK, INT_BLOCK_SIZE, INT_SIZE,\n INT_SIZE_PTR, MSG_BLOCK, MSG_SIZE_PTR, STATE, TWO_POW_16, TWO_POW_24, TWO_POW_32, TWO_POW_8,\n};\n\npub(crate) mod constants;\nmod tests;\n\n// Implementation of SHA-256 mapping a byte array of variable length to\n// 32 bytes.\n\n// Deprecated in favour of `sha256_var`\n// docs:start:sha256\npub fn sha256(input: [u8; N]) -> HASH\n// docs:end:sha256\n{\n digest(input)\n}\n\n// SHA-256 hash function\n#[no_predicates]\npub fn digest(msg: [u8; N]) -> HASH {\n sha256_var(msg, N as u64)\n}\n\n// Variable size SHA-256 hash\npub fn sha256_var(msg: [u8; N], message_size: u64) -> HASH {\n let message_size = message_size as u32;\n assert(message_size <= N);\n\n if std::runtime::is_unconstrained() {\n // Safety: SHA256 is running as an unconstrained function.\n unsafe {\n __sha256_var(msg, message_size)\n }\n } else {\n let (mut h, mut msg_block) = process_full_blocks(msg, message_size, INITIAL_STATE);\n\n finalize_sha256_blocks::(message_size, h, msg_block)\n }\n}\n\npub(crate) unconstrained fn __sha_var(\n msg: [u8; N],\n message_size: u32,\n initial_state: STATE,\n) -> HASH {\n let num_full_blocks = message_size / BLOCK_SIZE;\n // Intermediate hash, starting with the canonical initial value\n let mut h: STATE = initial_state;\n // Pointer into msg_block on a 64 byte scale\n for i in 0..num_full_blocks {\n let msg_block = build_msg_block(msg, message_size, BLOCK_SIZE * i);\n h = sha256_compression(msg_block, h);\n }\n\n // Handle setup of the final msg block.\n // This case is only hit if the msg is less than the block size,\n // or our message cannot be evenly split into blocks.\n\n finalize_last_sha256_block(h, message_size, msg)\n}\n\n// Helper function to finalize the message block with padding and length\npub(crate) unconstrained fn finalize_last_sha256_block(\n mut h: STATE,\n message_size: u32,\n msg: [u8; N],\n) -> HASH {\n let modulo = message_size % BLOCK_SIZE;\n let (mut msg_block, mut msg_byte_ptr): (INT_BLOCK, u32) = if modulo != 0 {\n let num_full_blocks = message_size / BLOCK_SIZE;\n let msg_start = BLOCK_SIZE * num_full_blocks;\n let new_msg_block = build_msg_block(msg, message_size, msg_start);\n (new_msg_block, modulo)\n } else {\n // If we had modulo == 0 then it means the last block was full,\n // and we can reset the pointer to zero to overwrite it.\n ([0; INT_BLOCK_SIZE], 0)\n };\n\n // Pad the rest such that we have a [u32; 2] block at the end representing the length\n // of the message, and a block of 1 0 ... 0 following the message (i.e. [1 << 7, 0, ..., 0]).\n // Here we rely on the fact that everything beyond the available input is set to 0.\n let index = msg_byte_ptr / INT_SIZE;\n msg_block[index] = set_item_byte_then_zeros(msg_block[index], msg_byte_ptr, 1 << 7);\n\n // If we don't have room to write the size, compress the block and reset it.\n let (h, mut msg_byte_ptr): (STATE, u32) = if msg_byte_ptr >= MSG_SIZE_PTR {\n // `attach_len_to_msg_block` will zero out everything after the `msg_byte_ptr`.\n (sha256_compression(msg_block, h), 0)\n } else {\n (h, msg_byte_ptr + 1)\n };\n msg_block = attach_len_to_msg_block(msg_block, msg_byte_ptr, message_size);\n\n hash_final_block(msg_block, h)\n}\n\n// Variable size SHA-256 hash\nunconstrained fn __sha256_var(msg: [u8; N], message_size: u32) -> HASH {\n __sha_var(msg, message_size, INITIAL_STATE)\n}\n\npub(crate) fn process_full_blocks(\n msg: [u8; N],\n message_size: u32,\n h: STATE,\n) -> (STATE, MSG_BLOCK) {\n let num_blocks = N / BLOCK_SIZE;\n\n // We store the intermediate hash states and message blocks in these two arrays which allows us to select the correct state\n // for the given message size with a lookup.\n //\n // These can be reasoned about as followed:\n // Consider a message with an unknown number of bytes, `msg_size. It can be seen that this will have `msg_size / BLOCK_SIZE` full blocks.\n // - `states[i]` should then be the state after processing the first `i` blocks.\n // - `blocks[i]` should then be the next message block after processing the first `i` blocks.\n // blocks[first_partially_filled_block_index] is the last block that is partially filled or all 0 if the message is a multiple of the block size.\n //\n // In other words:\n //\n // blocks = [block 1, block 2, ..., block N / BLOCK_SIZE, block N / BLOCK_SIZE + 1]\n // states = [INITIAL_STATE, state after block 1, state after block 2, ..., state after block N / BLOCK_SIZE]\n //\n // We place the initial state in `states[0]` as in the case where the `message_size < BLOCK_SIZE` then there are no full blocks to process and no compressions should occur.\n let mut blocks: [MSG_BLOCK; N / BLOCK_SIZE + 1] = std::mem::zeroed();\n let mut states: [STATE; N / BLOCK_SIZE + 1] = [h; N / BLOCK_SIZE + 1];\n\n // Optimization for small messages. If the largest possible message is smaller than a block then we know that the first block is partially filled\n // no matter the value of `message_size`.\n //\n // Note that the condition `N >= BLOCK_SIZE` is known during monomorphization so this has no runtime cost.\n let first_partially_filled_block_index = if N >= BLOCK_SIZE {\n message_size / BLOCK_SIZE\n } else {\n 0\n };\n\n for i in 0..num_blocks {\n let msg_start = BLOCK_SIZE * i;\n let new_msg_block =\n // Safety: separate verification function\n unsafe { build_msg_block(msg, message_size, msg_start) };\n\n // Verify the block we are compressing was appropriately constructed\n verify_msg_block(msg, message_size, new_msg_block, msg_start);\n\n blocks[i] = new_msg_block;\n states[i + 1] = sha256_compression(new_msg_block, states[i]);\n }\n // If message_size/BLOCK_SIZE == N/BLOCK_SIZE, and there is a remainder, we need to process the last block.\n if N % BLOCK_SIZE != 0 {\n let new_msg_block =\n // Safety: separate verification function\n unsafe { build_msg_block(msg, message_size, BLOCK_SIZE * num_blocks) };\n\n // Verify the block we are compressing was appropriately constructed\n verify_msg_block(msg, message_size, new_msg_block, BLOCK_SIZE * num_blocks);\n\n blocks[num_blocks] = new_msg_block;\n }\n\n // verify the 0 padding is correct for the last block\n let final_block = blocks[first_partially_filled_block_index];\n verify_msg_block_zeros(final_block, message_size % BLOCK_SIZE, INT_BLOCK_SIZE);\n (states[first_partially_filled_block_index], final_block)\n}\n\n// Take `BLOCK_SIZE` number of bytes from `msg` starting at `msg_start` and pack them into a `MSG_BLOCK`.\npub(crate) unconstrained fn build_msg_block(\n msg: [u8; N],\n message_size: u32,\n msg_start: u32,\n) -> MSG_BLOCK {\n let mut msg_block: MSG_BLOCK = [0; INT_BLOCK_SIZE];\n\n // We insert `BLOCK_SIZE` bytes (or up to the end of the message)\n let block_input = if message_size < msg_start {\n // This function is sometimes called with `msg_start` past the end of the message.\n // In this case we return an empty block and zero pointer to signal that the result should be ignored.\n 0\n } else if message_size < msg_start + BLOCK_SIZE {\n message_size - msg_start\n } else {\n BLOCK_SIZE\n };\n\n // Figure out the number of items in the int array that we have to pack.\n // e.g. if the input is [0,1,2,3,4,5] then we need to pack it as 2 items: [0123, 4500]\n let int_input = (block_input + INT_SIZE - 1) / INT_SIZE;\n\n for i in 0..int_input {\n let mut msg_item: u32 = 0;\n // Always construct the integer as 4 bytes, even if it means going beyond the input.\n for j in 0..INT_SIZE {\n let k = i * INT_SIZE + j;\n let msg_byte = if k < block_input {\n msg[msg_start + k]\n } else {\n 0\n };\n msg_item = (msg_item << 8) + msg_byte as u32;\n }\n msg_block[i] = msg_item;\n }\n\n // Returning the index as if it was a 64 byte array.\n // We have to project it down to 16 items and bit shifting to get a byte back if we need it.\n msg_block\n}\n\n// Verify the block we are compressing was appropriately constructed by `build_msg_block`\n// and matches the input data.\n// If `message_size` is less than `msg_start` then this is called with the old non-empty block;\n// in that case we can skip verification, ie. no need to check that everything is zero.\nfn verify_msg_block(\n msg: [u8; N],\n message_size: u32,\n msg_block: MSG_BLOCK,\n msg_start: u32,\n) {\n let mut msg_end = msg_start + BLOCK_SIZE;\n if msg_end > N {\n msg_end = N;\n }\n // We might have to go beyond the input to pad the fields.\n if msg_end % INT_SIZE != 0 {\n msg_end = msg_end + INT_SIZE - msg_end % INT_SIZE;\n }\n\n // Reconstructed packed item.\n let mut msg_item: u32 = 0;\n\n // Inclusive at the end so that we can compare the last item.\n let mut i: u32 = 0;\n for k in msg_start..=msg_end {\n if k % INT_SIZE == 0 {\n // If we consumed some input we can compare against the block.\n if (msg_start < message_size) & (k > msg_start) {\n assert_eq(msg_block[i], msg_item as u32);\n i = i + 1;\n msg_item = 0;\n }\n }\n // Shift the accumulator\n msg_item = msg_item << 8;\n // If we have input to consume, add it at the rightmost position.\n if k < message_size & k < msg_end {\n msg_item = msg_item + msg[k] as u32;\n }\n }\n}\n\n// Verify that a region of ints in the message block are (partially) zeroed,\n// up to an (exclusive) maximum which can either be the end of the block\n// or just where the size is to be written.\nfn verify_msg_block_zeros(\n msg_block: MSG_BLOCK,\n mut msg_byte_ptr: BLOCK_BYTE_PTR,\n max_int_byte_ptr: u32,\n) {\n // First integer which is supposed to be (partially) zero.\n let mut int_byte_ptr = msg_byte_ptr / INT_SIZE;\n\n // Check partial zeros.\n let modulo = msg_byte_ptr % INT_SIZE;\n if modulo != 0 {\n let zeros = INT_SIZE - modulo;\n let mask = if zeros == 3 {\n TWO_POW_24\n } else if zeros == 2 {\n TWO_POW_16\n } else {\n TWO_POW_8\n };\n assert_eq(msg_block[int_byte_ptr] % mask, 0);\n int_byte_ptr = int_byte_ptr + 1;\n }\n\n // Check the rest of the items.\n for i in 0..max_int_byte_ptr {\n if i >= int_byte_ptr {\n assert_eq(msg_block[i], 0);\n }\n }\n}\n\n// Verify that up to the byte pointer the two blocks are equal.\n// At the byte pointer the new block can be partially zeroed.\nfn verify_msg_block_equals_last(\n msg_block: MSG_BLOCK,\n last_block: MSG_BLOCK,\n mut msg_byte_ptr: BLOCK_BYTE_PTR,\n) {\n // msg_byte_ptr is the position at which they are no longer have to be the same.\n // First integer which is supposed to be (partially) zero contains that pointer.\n let mut int_byte_ptr = msg_byte_ptr / INT_SIZE;\n\n // Check partial zeros.\n let modulo = msg_byte_ptr % INT_SIZE;\n if modulo != 0 {\n // Reconstruct the partially zero item from the last block.\n let last_field = last_block[int_byte_ptr];\n let mut msg_item: u32 = 0;\n // Reset to where they are still equal.\n msg_byte_ptr = msg_byte_ptr - modulo;\n for i in 0..INT_SIZE {\n msg_item = msg_item << 8;\n if i < modulo {\n msg_item = msg_item + get_item_byte(last_field, msg_byte_ptr) as u32;\n msg_byte_ptr = msg_byte_ptr + 1;\n }\n }\n assert_eq(msg_block[int_byte_ptr], msg_item);\n }\n\n for i in 0..INT_SIZE_PTR {\n if i < int_byte_ptr {\n assert_eq(msg_block[i], last_block[i]);\n }\n }\n}\n\n// Set the rightmost `zeros` number of bytes to 0.\n#[inline_always]\nfn set_item_zeros(item: u32, zeros: u32) -> u32 {\n lshift8(rshift8(item, zeros), zeros)\n}\n\n// Replace one byte in the item with a value, and set everything after it to zero.\nfn set_item_byte_then_zeros(msg_item: u32, msg_byte_ptr: BLOCK_BYTE_PTR, msg_byte: u8) -> u32 {\n let zeros = INT_SIZE - msg_byte_ptr % INT_SIZE;\n let zeroed_item = set_item_zeros(msg_item, zeros);\n let new_item = byte_into_item(msg_byte, msg_byte_ptr);\n zeroed_item + new_item\n}\n\n// Get a byte of a message item according to its overall position in the `BLOCK_SIZE` space.\nfn get_item_byte(mut msg_item: u32, msg_byte_ptr: BLOCK_BYTE_PTR) -> u8 {\n // How many times do we have to shift to the right to get to the position we want?\n let max_shifts = INT_SIZE - 1;\n let shifts = max_shifts - msg_byte_ptr % INT_SIZE;\n msg_item = rshift8(msg_item, shifts);\n // At this point the byte we want is in the rightmost position.\n msg_item as u8\n}\n\n// Project a byte into a position in a field based on the overall block pointer.\n// For example putting 1 into pointer 5 would be 100, because overall we would\n// have [____, 0100] with indexes [0123,4567].\n#[inline_always]\nfn byte_into_item(msg_byte: u8, msg_byte_ptr: BLOCK_BYTE_PTR) -> u32 {\n let mut msg_item = msg_byte as u32;\n // How many times do we have to shift to the left to get to the position we want?\n let max_shifts = INT_SIZE - 1;\n let shifts = max_shifts - msg_byte_ptr % INT_SIZE;\n lshift8(msg_item, shifts)\n}\n\n// Construct a field out of 4 bytes.\n#[inline_always]\nfn make_item(b0: u8, b1: u8, b2: u8, b3: u8) -> u32 {\n let mut item = b0 as u32;\n item = (item << 8) + b1 as u32;\n item = (item << 8) + b2 as u32;\n item = (item << 8) + b3 as u32;\n item\n}\n\nglobal BIT_SHIFT_TABLE: [u32; 4] = [1, TWO_POW_8, TWO_POW_16, TWO_POW_24];\n\n// Shift by 8 bits to the left between 0 and 4 times.\n// Checks `is_unconstrained()` to just use a bitshift if we're running in an unconstrained context,\n// otherwise multiplies by 256.\n#[inline_always]\nfn lshift8(item: u32, shifts: u32) -> u32 {\n if is_unconstrained() {\n // Brillig wouldn't shift 0<<4 without overflow.\n if shifts >= 4 {\n 0\n } else {\n item << (8 * shifts)\n }\n } else {\n if shifts == 4 {\n 0\n } else {\n item * BIT_SHIFT_TABLE[shifts]\n }\n }\n}\n\n// Shift by 8 bits to the right between 0 and 4 times.\n// Checks `is_unconstrained()` to just use a bitshift if we're running in an unconstrained context,\n// otherwise divides by 256.\n#[inline_always]\nfn rshift8(item: u32, shifts: u32) -> u32 {\n if is_unconstrained() {\n if shifts >= 4 {\n 0\n } else {\n item >> (8 * shifts)\n }\n } else {\n if shifts == 4 {\n 0\n } else {\n item / BIT_SHIFT_TABLE[shifts]\n }\n }\n}\n\n// Zero out all bytes between the end of the message and where the length is appended,\n// then write the length into the last 8 bytes of the block.\nunconstrained fn attach_len_to_msg_block(\n mut msg_block: MSG_BLOCK,\n mut msg_byte_ptr: BLOCK_BYTE_PTR,\n message_size: u32,\n) -> MSG_BLOCK {\n // We assume that `msg_byte_ptr` is less than 57 because if not then it is reset to zero before calling this function.\n // In any case, fill blocks up with zeros until the last 64 bits (i.e. until msg_byte_ptr = 56).\n // There can be one item which has to be partially zeroed.\n let modulo = msg_byte_ptr % INT_SIZE;\n if modulo != 0 {\n // Index of the block in which we find the item we need to partially zero.\n let i = msg_byte_ptr / INT_SIZE;\n let zeros = INT_SIZE - modulo;\n msg_block[i] = set_item_zeros(msg_block[i], zeros);\n msg_byte_ptr = msg_byte_ptr + zeros;\n }\n\n // The rest can be zeroed without bit shifting anything.\n for i in (msg_byte_ptr / INT_SIZE)..INT_SIZE_PTR {\n msg_block[i] = 0;\n }\n\n // Set the last two 4 byte ints as the first/second half of the 8 bytes of the length.\n let len = 8 * message_size;\n let len_bytes: [u8; 8] = (len as Field).to_be_bytes();\n msg_block[INT_SIZE_PTR] = (len_bytes[0] as u32) << 24\n | (len_bytes[1] as u32) << 16\n | (len_bytes[2] as u32) << 8\n | (len_bytes[3] as u32);\n\n msg_block[INT_SIZE_PTR + 1] = (len_bytes[4] as u32) << 24\n | (len_bytes[5] as u32) << 16\n | (len_bytes[6] as u32) << 8\n | (len_bytes[7] as u32);\n\n msg_block\n}\n\n// Verify that the message length was correctly written by `attach_len_to_msg_block`,\n// and that everything between the byte pointer and the size pointer was zeroed,\n// and that everything before the byte pointer was untouched.\nfn verify_msg_len(\n msg_block: MSG_BLOCK,\n last_block: MSG_BLOCK,\n msg_byte_ptr: BLOCK_BYTE_PTR,\n message_size: u32,\n) {\n // Check zeros up to the size pointer.\n verify_msg_block_zeros(msg_block, msg_byte_ptr, INT_SIZE_PTR);\n\n // Check that up to the pointer we match the last block.\n verify_msg_block_equals_last(msg_block, last_block, msg_byte_ptr);\n\n // We verify the message length was inserted correctly by reversing the byte decomposition.\n std::static_assert(\n INT_SIZE_PTR + 2 == INT_BLOCK_SIZE,\n \"INT_SIZE_PTR + 2 must equal INT_BLOCK_SIZE\",\n );\n let reconstructed_len_hi = msg_block[INT_SIZE_PTR] as Field;\n let reconstructed_len_lo = msg_block[INT_SIZE_PTR + 1] as Field;\n\n let reconstructed_len: Field =\n reconstructed_len_hi * TWO_POW_32 as Field + reconstructed_len_lo;\n let len = 8 * (message_size as Field);\n assert_eq(reconstructed_len, len);\n}\n\n// Perform the final compression, then transform the `STATE` into `HASH`.\nfn hash_final_block(msg_block: MSG_BLOCK, mut state: STATE) -> HASH {\n let mut out_h: HASH = [0; 32]; // Digest as sequence of bytes\n // Hash final padded block\n state = sha256_compression(msg_block, state);\n\n // Return final hash as byte array\n for j in 0..8 {\n let h_bytes: [u8; 4] = (state[j] as Field).to_be_bytes();\n for k in 0..4 {\n out_h[4 * j + k] = h_bytes[k];\n }\n }\n\n out_h\n}\n\npub(crate) fn finalize_sha256_blocks(\n message_size: u32,\n mut h: STATE,\n mut msg_block: MSG_BLOCK,\n) -> HASH {\n let mut msg_byte_ptr = message_size % BLOCK_SIZE;\n\n // If we had modulo == 0 then it means the last block was full,\n // and we can reset the pointer to zero to overwrite it.\n if msg_byte_ptr == BLOCK_SIZE {\n msg_byte_ptr = 0;\n }\n\n // Pad the rest such that we have a [u32; 2] block at the end representing the length\n // of the message, and a block of 1 0 ... 0 following the message (i.e. [1 << 7, 0, ..., 0]).\n // Here we rely on the fact that everything beyond the available input is set to 0.\n let index = msg_byte_ptr / INT_SIZE;\n msg_block[index] = set_item_byte_then_zeros(msg_block[index], msg_byte_ptr, 1 << 7);\n\n msg_byte_ptr = msg_byte_ptr + 1;\n let last_block = msg_block;\n\n // If we don't have room to write the size, compress the block and reset it.\n if msg_byte_ptr > MSG_SIZE_PTR {\n h = sha256_compression(msg_block, h);\n\n // `attach_len_to_msg_block` will zero out everything after the `msg_byte_ptr`.\n msg_byte_ptr = 0;\n }\n\n // Safety: separate verification function\n msg_block = unsafe { attach_len_to_msg_block(msg_block, msg_byte_ptr, message_size) };\n\n verify_msg_len(msg_block, last_block, msg_byte_ptr, message_size);\n\n hash_final_block(msg_block, h)\n}\n\n/**\n * Given some state of a partially computed sha256 hash and part of the preimage, continue hashing\n * @notice used for complex/ recursive offloading of post-partial hashing\n *\n * @param N - the maximum length of the message to hash\n * @param h - the intermediate hash state\n * @param msg - the preimage to hash\n * @param message_size - the actual length of the preimage to hash\n * @return the intermediate hash state after compressing in msg to h\n */\npub fn partial_sha256_var_interstitial(\n mut h: [u32; 8],\n msg: [u8; N],\n message_size: u32,\n) -> [u32; 8] {\n assert(message_size % BLOCK_SIZE == 0, \"Message size must be a multiple of the block size\");\n if std::runtime::is_unconstrained() {\n // Safety: running as an unconstrained function\n unsafe {\n __sha_partial_var_interstitial(h, msg, message_size)\n }\n } else {\n let (mut h, _) = process_full_blocks(msg, message_size, h);\n\n h\n }\n}\n\n/**\n * Given some state of a partially computed sha256 hash and remaining preimage, complete the hash\n * @notice used for traditional partial hashing\n *\n * @param N - the maximum length of the message to hash\n * @param h - the intermediate hash state\n * @param msg - the remaining preimage to hash\n * @param message_size - the size of the current chunk\n * @param real_message_size - the total size of the original preimage\n * @return finalized sha256 hash\n */\npub fn partial_sha256_var_end(\n mut h: [u32; 8],\n msg: [u8; N],\n message_size: u32,\n real_message_size: u32,\n) -> [u8; 32] {\n assert(message_size % BLOCK_SIZE == 0, \"Message size must be a multiple of the block size\");\n if std::runtime::is_unconstrained() {\n // Safety: running as an unconstrained function\n unsafe {\n h = __sha_partial_var_interstitial(h, msg, message_size);\n\n // Handle setup of the final msg block.\n // This case is only hit if the msg is less than the block size,\n // or our message cannot be evenly split into blocks.\n\n finalize_last_sha256_block(h, real_message_size, msg)\n }\n } else {\n let (mut h, mut msg_block) = process_full_blocks(msg, message_size, h);\n finalize_sha256_blocks::(real_message_size, h, msg_block)\n }\n}\n\nunconstrained fn __sha_partial_var_interstitial(\n mut h: [u32; 8],\n msg: [u8; N],\n message_size: u32,\n) -> [u32; 8] {\n let num_full_blocks = message_size / BLOCK_SIZE;\n // Intermediate hash, starting with the canonical initial value\n // Pointer into msg_block on a 64 byte scale\n for i in 0..num_full_blocks {\n let msg_block = build_msg_block(msg, message_size, BLOCK_SIZE * i);\n h = sha256_compression(msg_block, h);\n }\n h\n}\n\nmod equivalence_test {\n\n #[test]\n fn test_implementations_agree(msg: [u8; 100], message_size: u64) {\n let message_size = message_size % 100;\n // Safety: test function\n let unconstrained_sha = unsafe { super::__sha256_var(msg, message_size as u32) };\n let sha = super::sha256_var(msg, message_size);\n assert_eq(sha, unconstrained_sha);\n }\n}\n" + }, + "42": { + "path": "std/option.nr", + "source": "use crate::cmp::{Eq, Ord, Ordering};\nuse crate::default::Default;\nuse crate::hash::{Hash, Hasher};\n\npub struct Option {\n _is_some: bool,\n _value: T,\n}\n\nimpl Option {\n /// Constructs a None value\n pub fn none() -> Self {\n Self { _is_some: false, _value: crate::mem::zeroed() }\n }\n\n /// Constructs a Some wrapper around the given value\n pub fn some(_value: T) -> Self {\n Self { _is_some: true, _value }\n }\n\n /// True if this Option is None\n pub fn is_none(self) -> bool {\n !self._is_some\n }\n\n /// True if this Option is Some\n pub fn is_some(self) -> bool {\n self._is_some\n }\n\n /// Asserts `self.is_some()` and returns the wrapped value.\n pub fn unwrap(self) -> T {\n assert(self._is_some);\n self._value\n }\n\n /// Returns the inner value without asserting `self.is_some()`\n /// Note that if `self` is `None`, there is no guarantee what value will be returned,\n /// only that it will be of type `T`.\n pub fn unwrap_unchecked(self) -> T {\n self._value\n }\n\n /// Returns the wrapped value if `self.is_some()`. Otherwise, returns the given default value.\n pub fn unwrap_or(self, default: T) -> T {\n if self._is_some {\n self._value\n } else {\n default\n }\n }\n\n /// Returns the wrapped value if `self.is_some()`. Otherwise, calls the given function to return\n /// a default value.\n pub fn unwrap_or_else(self, default: fn[Env]() -> T) -> T {\n if self._is_some {\n self._value\n } else {\n default()\n }\n }\n\n /// Asserts `self.is_some()` with a provided custom message and returns the contained `Some` value\n pub fn expect(self, message: fmtstr) -> T {\n assert(self.is_some(), message);\n self._value\n }\n\n /// If self is `Some(x)`, this returns `Some(f(x))`. Otherwise, this returns `None`.\n pub fn map(self, f: fn[Env](T) -> U) -> Option {\n if self._is_some {\n Option::some(f(self._value))\n } else {\n Option::none()\n }\n }\n\n /// If self is `Some(x)`, this returns `f(x)`. Otherwise, this returns the given default value.\n pub fn map_or(self, default: U, f: fn[Env](T) -> U) -> U {\n if self._is_some {\n f(self._value)\n } else {\n default\n }\n }\n\n /// If self is `Some(x)`, this returns `f(x)`. Otherwise, this returns `default()`.\n pub fn map_or_else(self, default: fn[Env1]() -> U, f: fn[Env2](T) -> U) -> U {\n if self._is_some {\n f(self._value)\n } else {\n default()\n }\n }\n\n /// Returns None if self is None. Otherwise, this returns `other`.\n pub fn and(self, other: Self) -> Self {\n if self.is_none() {\n Option::none()\n } else {\n other\n }\n }\n\n /// If self is None, this returns None. Otherwise, this calls the given function\n /// with the Some value contained within self, and returns the result of that call.\n ///\n /// In some languages this function is called `flat_map` or `bind`.\n pub fn and_then(self, f: fn[Env](T) -> Option) -> Option {\n if self._is_some {\n f(self._value)\n } else {\n Option::none()\n }\n }\n\n /// If self is Some, return self. Otherwise, return `other`.\n pub fn or(self, other: Self) -> Self {\n if self._is_some {\n self\n } else {\n other\n }\n }\n\n /// If self is Some, return self. Otherwise, return `default()`.\n pub fn or_else(self, default: fn[Env]() -> Self) -> Self {\n if self._is_some {\n self\n } else {\n default()\n }\n }\n\n // If only one of the two Options is Some, return that option.\n // Otherwise, if both options are Some or both are None, None is returned.\n pub fn xor(self, other: Self) -> Self {\n if self._is_some {\n if other._is_some {\n Option::none()\n } else {\n self\n }\n } else if other._is_some {\n other\n } else {\n Option::none()\n }\n }\n\n /// Returns `Some(x)` if self is `Some(x)` and `predicate(x)` is true.\n /// Otherwise, this returns `None`\n pub fn filter(self, predicate: fn[Env](T) -> bool) -> Self {\n if self._is_some {\n if predicate(self._value) {\n self\n } else {\n Option::none()\n }\n } else {\n Option::none()\n }\n }\n\n /// Flattens an Option> into a Option.\n /// This returns None if the outer Option is None. Otherwise, this returns the inner Option.\n pub fn flatten(option: Option>) -> Option {\n if option._is_some {\n option._value\n } else {\n Option::none()\n }\n }\n}\n\nimpl Default for Option {\n fn default() -> Self {\n Option::none()\n }\n}\n\nimpl Eq for Option\nwhere\n T: Eq,\n{\n fn eq(self, other: Self) -> bool {\n if self._is_some == other._is_some {\n if self._is_some {\n self._value == other._value\n } else {\n true\n }\n } else {\n false\n }\n }\n}\n\nimpl Hash for Option\nwhere\n T: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n self._is_some.hash(state);\n if self._is_some {\n self._value.hash(state);\n }\n }\n}\n\n// For this impl we're declaring Option::none < Option::some\nimpl Ord for Option\nwhere\n T: Ord,\n{\n fn cmp(self, other: Self) -> Ordering {\n if self._is_some {\n if other._is_some {\n self._value.cmp(other._value)\n } else {\n Ordering::greater()\n }\n } else if other._is_some {\n Ordering::less()\n } else {\n Ordering::equal()\n }\n }\n}\n" + }, + "43": { + "path": "std/panic.nr", + "source": "pub fn panic(message: fmtstr) -> U {\n assert(false, message);\n crate::mem::zeroed()\n}\n" + }, + "430": { + "path": "/home/ubuntu/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.20251212/noir-projects/aztec-nr/uint-note/src/uint_note.nr", + "source": "use dep::aztec::{\n context::{PrivateContext, PublicContext},\n history::nullifier_inclusion::ProveNullifierInclusion,\n keys::getters::{get_nsk_app, get_public_keys},\n macros::notes::custom_note,\n messages::logs::note,\n note::note_interface::{NoteHash, NoteType},\n oracle::random::random,\n protocol_types::{\n address::AztecAddress,\n constants::{\n GENERATOR_INDEX__NOTE_HASH, GENERATOR_INDEX__NOTE_NULLIFIER,\n GENERATOR_INDEX__PARTIAL_NOTE_VALIDITY_COMMITMENT, PRIVATE_LOG_SIZE_IN_FIELDS,\n },\n hash::{compute_siloed_nullifier, poseidon2_hash_with_separator},\n traits::{Deserialize, FromField, Hash, Packable, Serialize, ToField},\n },\n};\n\n// UintNote supports partial notes, i.e. the ability to create an incomplete note in private, hiding certain values (the\n// owner, storage slot and randomness), and then completing the note in public with the ones missing (the amount).\n// Partial notes are being actively developed and are not currently fully supported via macros, and so we rely on the\n// #[custom_note] macro to implement it manually, resulting in some boilerplate. This is expected to be unnecessary once\n// macro support is expanded.\n\n/// A private note representing a numeric value associated to an account (e.g. a token balance).\n// docs:start:uint_note_def\n#[derive(Deserialize, Eq, Serialize, Packable)]\n#[custom_note]\npub struct UintNote {\n /// The number stored in the note.\n pub value: u128,\n}\n// docs:end:uint_note_def\n\nimpl NoteHash for UintNote {\n // docs:start:compute_note_hash\n fn compute_note_hash(\n self,\n owner: AztecAddress,\n storage_slot: Field,\n randomness: Field,\n ) -> Field {\n // Partial notes can be implemented by having the note hash be either the result of multiscalar multiplication\n // (MSM), or two rounds of poseidon. MSM results in more constraints and is only required when multiple variants\n // of partial notes are supported. Because UintNote has just one variant (where the value is public), we use\n // poseidon instead.\n\n // We must compute the same note hash as would be produced by a partial note created and completed with the same\n // values, so that notes all behave the same way regardless of how they were created. To achieve this, we\n // perform both steps of the partial note computation.\n\n // First we create the partial note from a commitment to the private content (including storage slot).\n let partial_note = PartialUintNote {\n commitment: compute_partial_commitment(owner, storage_slot, randomness),\n };\n\n // Then compute the completion note hash. In a real partial note this step would be performed in public.\n partial_note.compute_complete_note_hash(self.value)\n }\n // docs:end:compute_note_hash\n\n // The nullifiers are nothing special - this is just the canonical implementation that would be injected by the\n // #[note] macro.\n\n fn compute_nullifier(\n self,\n context: &mut PrivateContext,\n owner: AztecAddress,\n note_hash_for_nullification: Field,\n ) -> Field {\n let owner_npk_m = get_public_keys(owner).npk_m;\n let owner_npk_m_hash = owner_npk_m.hash();\n let secret = context.request_nsk_app(owner_npk_m_hash);\n poseidon2_hash_with_separator(\n [note_hash_for_nullification, secret],\n GENERATOR_INDEX__NOTE_NULLIFIER,\n )\n }\n\n unconstrained fn compute_nullifier_unconstrained(\n self,\n owner: AztecAddress,\n note_hash_for_nullification: Field,\n ) -> Field {\n let owner_npk_m = get_public_keys(owner).npk_m;\n let owner_npk_m_hash = owner_npk_m.hash();\n let secret = get_nsk_app(owner_npk_m_hash);\n poseidon2_hash_with_separator(\n [note_hash_for_nullification, secret],\n GENERATOR_INDEX__NOTE_NULLIFIER,\n )\n }\n}\n\nimpl UintNote {\n /// Creates a partial note that will hide the owner and storage slot but not the value, since the note will be later\n /// completed in public. This is a powerful technique for scenarios in which the value cannot be known in private\n /// (e.g. because it depends on some public state, such as a DEX).\n ///\n /// This function inserts a partial note validity commitment into the nullifier tree to be later on able to verify\n /// that the partial note and completer are legitimate. See function docs of `compute_validity_commitment` for more\n /// details.\n ///\n /// Each partial note should only be used once, since otherwise multiple notes would be linked together and known to\n /// belong to the same owner.\n ///\n /// As part of the partial note creation process, a log will be sent to `recipient` so that they can discover the\n /// note. `recipient` will typically be the same as `owner`.\n pub fn partial(\n owner: AztecAddress,\n storage_slot: Field,\n context: &mut PrivateContext,\n recipient: AztecAddress,\n completer: AztecAddress,\n ) -> PartialUintNote {\n // Safety: We use the randomness to preserve the privacy of the note recipient by preventing brute-forcing,\n // so a malicious sender could use non-random values to make the note less private. But they already know\n // the full note pre-image anyway, and so the recipient already trusts them to not disclose this\n // information. We can therefore assume that the sender will cooperate in the random value generation.\n let randomness = unsafe { random() };\n\n // We create a commitment to the private data, which we then use to construct the log we send to the recipient.\n let commitment = compute_partial_commitment(owner, storage_slot, randomness);\n\n // Our partial note log encoding scheme includes a field with the tag of the public completion log, and we use\n // the commitment as the tag. This is good for multiple reasons:\n // - the commitment is uniquely tied to this partial note\n // - the commitment is already public information, so we're not revealing anything else\n // - we don't need to create any additional information, private or public, for the tag\n // - other contracts cannot impersonate us and emit logs with the same tag due to public log siloing\n let private_log_content = UintPartialNotePrivateLogContent { public_log_tag: commitment };\n\n let encrypted_log = note::compute_partial_note_private_content_log(\n private_log_content,\n owner,\n storage_slot,\n randomness,\n recipient,\n );\n // Regardless of the original content size, the log is padded with random bytes up to\n // `PRIVATE_LOG_SIZE_IN_FIELDS` to prevent leaking information about the actual size.\n let length = encrypted_log.len();\n context.emit_private_log(encrypted_log, length);\n\n let partial_note = PartialUintNote { commitment };\n\n // Now we compute the validity commitment and push it to the nullifier tree. It can be safely pushed to\n // the nullifier tree since it uses its own separator, making collisions with actual note nullifiers\n // practically impossible.\n let validity_commitment = partial_note.compute_validity_commitment(completer);\n context.push_nullifier(validity_commitment);\n\n partial_note\n }\n}\n\n/// Computes a commitment to the private content of a partial UintNote, i.e. the fields that will remain private. All\n/// other note fields will be made public.\n// docs:start:compute_partial_commitment\nfn compute_partial_commitment(\n owner: AztecAddress,\n storage_slot: Field,\n randomness: Field,\n) -> Field {\n poseidon2_hash_with_separator(\n [owner.to_field(), storage_slot, randomness],\n GENERATOR_INDEX__NOTE_HASH,\n )\n}\n// docs:end:compute_partial_commitment\n\n#[derive(Packable)]\nstruct UintPartialNotePrivateLogContent {\n public_log_tag: Field,\n}\n\nimpl NoteType for UintPartialNotePrivateLogContent {\n fn get_id() -> Field {\n UintNote::get_id()\n }\n}\n\n/// A partial instance of a UintNote. This value represents a private commitment to the owner, randomness and storage\n/// slot, but the value field has not yet been set. A partial note can be completed in public with the `complete`\n/// function (revealing the value to the public), resulting in a UintNote that can be used like any other one (except\n/// of course that its value is known).\n// docs:start:partial_uint_note_def\n#[derive(Packable, Serialize, Deserialize, Eq)]\npub struct PartialUintNote {\n commitment: Field,\n}\n// docs:end:partial_uint_note_def\n\nglobal NOTE_COMPLETION_LOG_LENGTH: u32 = 2;\n\nimpl PartialUintNote {\n /// Completes the partial note, creating a new note that can be used like any other UintNote.\n pub fn complete(self, context: PublicContext, completer: AztecAddress, value: u128) {\n // A note with a value of zero is valid, but we cannot currently complete a partial note with such a value\n // because this will result in the completion log having its last field set to 0. Public logs currently do not\n // track their length, and so trailing zeros are simply trimmed. This results in the completion log missing its\n // last field (the value), and note discovery failing.\n // TODO(#11636): remove this\n assert(value != 0, \"Cannot complete a PartialUintNote with a value of 0\");\n\n // We verify that the partial note we're completing is valid (i.e. completer is correct, it uses the correct\n // state variable's storage slot, and it is internally consistent).\n let validity_commitment = self.compute_validity_commitment(completer);\n assert(\n context.nullifier_exists(validity_commitment, context.this_address()),\n \"Invalid partial note or completer\",\n );\n\n // We need to do two things:\n // - emit a public log containing the public fields (the value). The contract will later find it by searching\n // for the expected tag (which is simply the partial note commitment).\n // - insert the completion note hash (i.e. the hash of the note) into the note hash tree. This is typically\n // only done in private to hide the preimage of the hash that is inserted, but completed partial notes are\n // inserted in public as the public values are provided and the note hash computed.\n context.emit_public_log(self.compute_note_completion_log(value));\n context.push_note_hash(self.compute_complete_note_hash(value));\n }\n\n /// Completes the partial note, creating a new note that can be used like any other UintNote. Same as `complete`\n /// function but works from private context.\n pub fn complete_from_private(\n self,\n context: &mut PrivateContext,\n completer: AztecAddress,\n value: u128,\n ) {\n // We verify that the partial note we're completing is valid (i.e. completer is correct, it uses the correct\n // state variable's storage slot, and it is internally consistent).\n let validity_commitment = self.compute_validity_commitment(completer);\n // `prove_nullifier_inclusion` function expects the nullifier to be siloed (hashed with the address of\n // the contract that emitted the nullifier) as it checks the value directly against the nullifier tree and all\n // the nullifiers in the tree are siloed by the protocol.\n let siloed_validity_commitment =\n compute_siloed_nullifier(context.this_address(), validity_commitment);\n context.get_anchor_block_header().prove_nullifier_inclusion(siloed_validity_commitment);\n\n // We need to do two things:\n // - emit an unencrypted log containing the public fields (the value) via the private log channel. The\n // contract will later find it by searching for the expected tag (which is simply the partial note\n // commitment).\n // - insert the completion note hash (i.e. the hash of the note) into the note hash tree. This is typically\n // only done in private to hide the preimage of the hash that is inserted, but completed partial notes are\n // inserted in public as the public values are provided and the note hash computed.\n context.emit_private_log(\n self.compute_note_completion_log_padded_for_private_log(value),\n NOTE_COMPLETION_LOG_LENGTH,\n );\n context.push_note_hash(self.compute_complete_note_hash(value));\n }\n\n /// Computes a validity commitment for this partial note. The commitment cryptographically binds the note's private\n /// data with the designated completer address. When the note is later completed in public execution, we can load\n /// this commitment from the nullifier tree and verify that both the partial note (e.g. that the storage slot\n /// corresponds to the correct owner, and that we're using the correct state variable) and completer are\n /// legitimate.\n pub fn compute_validity_commitment(self, completer: AztecAddress) -> Field {\n poseidon2_hash_with_separator(\n [self.commitment, completer.to_field()],\n GENERATOR_INDEX__PARTIAL_NOTE_VALIDITY_COMMITMENT,\n )\n }\n\n fn compute_note_completion_log(self, value: u128) -> [Field; NOTE_COMPLETION_LOG_LENGTH] {\n // The first field of this log must be the tag that the recipient of the partial note private field logs\n // expects, which is equal to the partial note commitment.\n [self.commitment, value.to_field()]\n }\n\n fn compute_note_completion_log_padded_for_private_log(\n self,\n value: u128,\n ) -> [Field; PRIVATE_LOG_SIZE_IN_FIELDS] {\n let note_completion_log = self.compute_note_completion_log(value);\n let padding = [0; PRIVATE_LOG_SIZE_IN_FIELDS - NOTE_COMPLETION_LOG_LENGTH];\n note_completion_log.concat(padding)\n }\n\n // docs:start:compute_complete_note_hash\n fn compute_complete_note_hash(self, value: u128) -> Field {\n // Here we finalize the note hash by including the (public) value into the partial note commitment. Note that we\n // use the same generator index as we used for the first round of poseidon - this is not an issue.\n poseidon2_hash_with_separator(\n [self.commitment, value.to_field()],\n GENERATOR_INDEX__NOTE_HASH,\n )\n }\n // docs:end:compute_complete_note_hash\n}\n\nimpl ToField for PartialUintNote {\n fn to_field(self) -> Field {\n self.commitment\n }\n}\n\nimpl FromField for PartialUintNote {\n fn from_field(field: Field) -> Self {\n Self { commitment: field }\n }\n}\n\nmod test {\n use super::{\n compute_partial_commitment, PartialUintNote, UintNote, UintPartialNotePrivateLogContent,\n };\n use dep::aztec::{\n note::note_interface::NoteHash,\n protocol_types::{address::AztecAddress, traits::{Deserialize, FromField, Packable}},\n utils::array::subarray,\n };\n\n global value: u128 = 17;\n global randomness: Field = 42;\n global owner: AztecAddress = AztecAddress::from_field(50);\n global storage_slot: Field = 13;\n\n #[test]\n fn note_hash_matches_completed_partial_note_hash() {\n // Tests that a UintNote has the same note hash as a PartialUintNote created and then completed with the same\n // private values. This requires for the same hash function to be used in both flows, with the fields in the\n // same order.\n let note = UintNote { value };\n let note_hash = note.compute_note_hash(owner, storage_slot, randomness);\n\n let partial_note = PartialUintNote {\n commitment: compute_partial_commitment(owner, storage_slot, randomness),\n };\n let completed_partial_note_hash = partial_note.compute_complete_note_hash(value);\n\n assert_eq(note_hash, completed_partial_note_hash);\n }\n\n #[test]\n fn unpack_from_partial_note_encoding() {\n // Tests that the packed representation of a regular UintNote can be reconstructed given the partial note\n // private fields log and the public completion log, ensuring the recipient will be able to compute the\n // completed note as if it were a regular UintNote.\n let note = UintNote { value };\n\n let commitment = compute_partial_commitment(owner, storage_slot, randomness);\n\n let private_log_content = UintPartialNotePrivateLogContent { public_log_tag: commitment };\n // The following is a misuse of the `deserialize` function, but this is just a test and it's better than\n // letting devs manually construct it when they shouldn't be able to.\n let partial_note = PartialUintNote::deserialize([commitment]);\n\n // The first field of the partial note private content is the public completion log tag, so it should match the\n // first field of the public log.\n assert_eq(\n private_log_content.pack()[0],\n partial_note.compute_note_completion_log(value)[0],\n );\n\n // The completion log without the tag should match the note's packed representation.\n let public_log_without_tag: [_; 1] =\n subarray(partial_note.compute_note_completion_log(value), 1);\n assert_eq(public_log_without_tag, note.pack());\n }\n}\n" + }, + "47": { + "path": "std/slice.nr", + "source": "use crate::append::Append;\n\nimpl [T] {\n /// Returns the length of the slice.\n #[builtin(array_len)]\n pub fn len(self) -> u32 {}\n\n /// Push a new element to the end of the slice, returning a\n /// new slice with a length one greater than the\n /// original unmodified slice.\n #[builtin(slice_push_back)]\n pub fn push_back(self, elem: T) -> Self {}\n\n /// Push a new element to the front of the slice, returning a\n /// new slice with a length one greater than the\n /// original unmodified slice.\n #[builtin(slice_push_front)]\n pub fn push_front(self, elem: T) -> Self {}\n\n /// Remove the last element of the slice, returning the\n /// popped slice and the element in a tuple\n #[builtin(slice_pop_back)]\n pub fn pop_back(self) -> (Self, T) {}\n\n /// Remove the first element of the slice, returning the\n /// element and the popped slice in a tuple\n #[builtin(slice_pop_front)]\n pub fn pop_front(self) -> (T, Self) {}\n\n /// Insert an element at a specified index, shifting all elements\n /// after it to the right\n #[builtin(slice_insert)]\n pub fn insert(self, index: u32, elem: T) -> Self {}\n\n /// Remove an element at a specified index, shifting all elements\n /// after it to the left, returning the altered slice and\n /// the removed element\n #[builtin(slice_remove)]\n pub fn remove(self, index: u32) -> (Self, T) {}\n\n /// Append each element of the `other` slice to the end of `self`.\n /// This returns a new slice and leaves both input slices unchanged.\n pub fn append(mut self, other: Self) -> Self {\n for elem in other {\n self = self.push_back(elem);\n }\n self\n }\n\n pub fn as_array(self) -> [T; N] {\n assert(self.len() == N);\n\n let mut array = [crate::mem::zeroed(); N];\n for i in 0..N {\n array[i] = self[i];\n }\n array\n }\n\n // Apply a function to each element of the slice, returning a new slice\n // containing the mapped elements.\n pub fn map(self, f: fn[Env](T) -> U) -> [U] {\n let mut ret = &[];\n for elem in self {\n ret = ret.push_back(f(elem));\n }\n ret\n }\n\n // Apply a function to each element of the slice with its index, returning a\n // new slice containing the mapped elements.\n pub fn mapi(self, f: fn[Env](u32, T) -> U) -> [U] {\n let mut ret = &[];\n let mut index = 0;\n for elem in self {\n ret = ret.push_back(f(index, elem));\n index += 1;\n }\n ret\n }\n\n // Apply a function to each element of the slice\n pub fn for_each(self, f: fn[Env](T) -> ()) {\n for elem in self {\n f(elem);\n }\n }\n\n // Apply a function to each element of the slice with its index\n pub fn for_eachi(self, f: fn[Env](u32, T) -> ()) {\n let mut index = 0;\n for elem in self {\n f(index, elem);\n index += 1;\n }\n }\n\n // Apply a function to each element of the slice and an accumulator value,\n // returning the final accumulated value. This function is also sometimes\n // called `foldl`, `fold_left`, `reduce`, or `inject`.\n pub fn fold(self, mut accumulator: U, f: fn[Env](U, T) -> U) -> U {\n for elem in self {\n accumulator = f(accumulator, elem);\n }\n accumulator\n }\n\n // Apply a function to each element of the slice and an accumulator value,\n // returning the final accumulated value. Unlike fold, reduce uses the first\n // element of the given slice as its starting accumulator value.\n pub fn reduce(self, f: fn[Env](T, T) -> T) -> T {\n let mut accumulator = self[0];\n for i in 1..self.len() {\n accumulator = f(accumulator, self[i]);\n }\n accumulator\n }\n\n // Returns a new slice containing only elements for which the given predicate\n // returns true.\n pub fn filter(self, predicate: fn[Env](T) -> bool) -> Self {\n let mut ret = &[];\n for elem in self {\n if predicate(elem) {\n ret = ret.push_back(elem);\n }\n }\n ret\n }\n\n // Flatten each element in the slice into one value, separated by `separator`.\n pub fn join(self, separator: T) -> T\n where\n T: Append,\n {\n let mut ret = T::empty();\n\n if self.len() != 0 {\n ret = self[0];\n\n for i in 1..self.len() {\n ret = ret.append(separator).append(self[i]);\n }\n }\n\n ret\n }\n\n // Returns true if all elements in the slice satisfy the predicate\n pub fn all(self, predicate: fn[Env](T) -> bool) -> bool {\n let mut ret = true;\n for elem in self {\n ret &= predicate(elem);\n }\n ret\n }\n\n // Returns true if any element in the slice satisfies the predicate\n pub fn any(self, predicate: fn[Env](T) -> bool) -> bool {\n let mut ret = false;\n for elem in self {\n ret |= predicate(elem);\n }\n ret\n }\n}\n\nmod test {\n #[test]\n fn map_empty() {\n assert_eq(&[].map(|x| x + 1), &[]);\n }\n\n #[test]\n fn mapi_empty() {\n assert_eq(&[].mapi(|i, x| i * x + 1), &[]);\n }\n\n #[test]\n fn for_each_empty() {\n let empty_slice: [Field] = &[];\n empty_slice.for_each(|_x| assert(false));\n assert(empty_slice == &[]);\n }\n\n #[test]\n fn for_eachi_empty() {\n let empty_slice: [Field] = &[];\n empty_slice.for_eachi(|_i, _x| assert(false));\n assert(empty_slice == &[]);\n }\n\n #[test]\n fn map_example() {\n let a = &[1, 2, 3];\n let b = a.map(|a| a * 2);\n assert_eq(b, &[2, 4, 6]);\n assert_eq(a, &[1, 2, 3]);\n }\n\n #[test]\n fn mapi_example() {\n let a = &[1, 2, 3];\n let b = a.mapi(|i, a| i + a * 2);\n assert_eq(b, &[2, 5, 8]);\n assert_eq(a, &[1, 2, 3]);\n }\n\n #[test]\n fn for_each_example() {\n let a = &[1, 2, 3];\n let mut b = &[];\n let b_ref = &mut b;\n a.for_each(|a| { *b_ref = b_ref.push_back(a * 2); });\n assert_eq(b, &[2, 4, 6]);\n }\n\n #[test]\n fn for_eachi_example() {\n let a = &[1, 2, 3];\n let mut b = &[];\n let b_ref = &mut b;\n a.for_eachi(|i, a| { *b_ref = b_ref.push_back(i + a * 2); });\n assert_eq(b, &[2, 5, 8]);\n }\n\n #[test]\n fn len_empty() {\n let empty: [Field] = &[];\n assert_eq(empty.len(), 0);\n }\n\n #[test]\n fn len_single() {\n assert_eq(&[42].len(), 1);\n }\n\n #[test]\n fn len_multiple() {\n assert_eq(&[1, 2, 3, 4, 5].len(), 5);\n }\n\n #[test]\n fn push_back_empty() {\n let empty: [Field] = &[];\n let result = empty.push_back(42);\n assert_eq(result.len(), 1);\n assert_eq(result[0], 42);\n }\n\n #[test]\n fn push_back_non_empty() {\n let slice = &[1, 2, 3];\n let result = slice.push_back(4);\n assert_eq(result.len(), 4);\n assert_eq(result, &[1, 2, 3, 4]);\n }\n\n #[test]\n fn push_front_empty() {\n let empty = &[];\n let result = empty.push_front(42);\n assert_eq(result.len(), 1);\n assert_eq(result[0], 42);\n }\n\n #[test]\n fn push_front_non_empty() {\n let slice = &[1, 2, 3];\n let result = slice.push_front(0);\n assert_eq(result.len(), 4);\n assert_eq(result, &[0, 1, 2, 3]);\n }\n\n #[test(should_fail_with = \"Index out of bounds\")]\n fn pop_back_empty() {\n let slice: [Field] = &[];\n let (_, _) = slice.pop_back();\n }\n\n #[test]\n fn pop_back_one() {\n let slice = &[42];\n let (result, elem) = slice.pop_back();\n assert_eq(result.len(), 0);\n assert_eq(elem, 42);\n }\n\n #[test]\n fn pop_back_multiple() {\n let slice = &[1, 2, 3];\n let (result, elem) = slice.pop_back();\n assert_eq(result.len(), 2);\n assert_eq(result, &[1, 2]);\n assert_eq(elem, 3);\n }\n\n #[test(should_fail_with = \"Index out of bounds\")]\n fn pop_front_empty() {\n let slice: [Field] = &[];\n let (_, _) = slice.pop_front();\n }\n\n #[test]\n fn pop_front_one() {\n let slice = &[42];\n let (elem, result) = slice.pop_front();\n assert_eq(result.len(), 0);\n assert_eq(elem, 42);\n }\n\n #[test]\n fn pop_front_multiple() {\n let slice = &[1, 2, 3];\n let (elem, result) = slice.pop_front();\n assert_eq(result.len(), 2);\n assert_eq(result, &[2, 3]);\n assert_eq(elem, 1);\n }\n\n #[test]\n fn insert_beginning() {\n let slice = &[1, 2, 3];\n let result = slice.insert(0, 0);\n assert_eq(result.len(), 4);\n assert_eq(result, &[0, 1, 2, 3]);\n }\n\n #[test]\n fn insert_middle() {\n let slice = &[1, 2, 3];\n let result = slice.insert(1, 99);\n assert_eq(result.len(), 4);\n assert_eq(result, &[1, 99, 2, 3]);\n }\n\n #[test]\n fn insert_end() {\n let slice = &[1, 2, 3];\n let result = slice.insert(3, 4);\n assert_eq(result.len(), 4);\n assert_eq(result, &[1, 2, 3, 4]);\n }\n\n #[test(should_fail_with = \"Index out of bounds\")]\n fn insert_end_out_of_bounds() {\n let slice = &[1, 2];\n let _ = slice.insert(3, 4);\n }\n\n #[test(should_fail_with = \"Index out of bounds\")]\n fn remove_empty() {\n let slice: [Field] = &[];\n let (_, _) = slice.remove(0);\n }\n\n #[test]\n fn remove_beginning() {\n let slice = &[1, 2, 3];\n let (result, elem) = slice.remove(0);\n assert_eq(result.len(), 2);\n assert_eq(result, &[2, 3]);\n assert_eq(elem, 1);\n }\n\n #[test]\n fn remove_middle() {\n let slice = &[1, 2, 3];\n let (result, elem) = slice.remove(1);\n assert_eq(result.len(), 2);\n assert_eq(result, &[1, 3]);\n assert_eq(elem, 2);\n }\n\n #[test]\n fn remove_end() {\n let slice = &[1, 2, 3];\n let (result, elem) = slice.remove(2);\n assert_eq(result.len(), 2);\n assert_eq(result, &[1, 2]);\n assert_eq(elem, 3);\n }\n\n #[test(should_fail_with = \"Index out of bounds\")]\n fn remove_end_out_of_bounds() {\n let slice = &[1, 2];\n let (_, _) = slice.remove(2);\n }\n\n #[test]\n fn fold_empty() {\n let empty = &[];\n let result = empty.fold(10, |acc, x| acc + x);\n assert_eq(result, 10);\n }\n\n #[test]\n fn fold_single() {\n let slice = &[5];\n let result = slice.fold(10, |acc, x| acc + x);\n assert_eq(result, 15);\n }\n\n #[test]\n fn fold_multiple() {\n let slice = &[1, 2, 3, 4];\n let result = slice.fold(0, |acc, x| acc + x);\n assert_eq(result, 10);\n }\n\n #[test(should_fail_with = \"Index out of bounds\")]\n fn reduce_empty() {\n let empty: [Field] = &[];\n let _ = empty.reduce(|a, b| a + b);\n }\n\n #[test]\n fn reduce_single() {\n let slice = &[42];\n let result = slice.reduce(|a, b| a + b);\n assert_eq(result, 42);\n }\n\n #[test]\n fn reduce_multiple() {\n let slice = &[1, 2, 3, 4];\n let result = slice.reduce(|a, b| a + b);\n assert_eq(result, 10);\n }\n\n #[test]\n fn filter_empty() {\n let empty = &[];\n let result = empty.filter(|x| x > 0);\n assert_eq(result.len(), 0);\n }\n\n #[test]\n fn filter_all_true() {\n let slice = &[1, 2, 3, 4];\n let result = slice.filter(|x| x > 0);\n assert_eq(result, slice);\n }\n\n #[test]\n fn filter_all_false() {\n let slice = &[1, 2, 3, 4];\n let result = slice.filter(|x| x > 10);\n assert_eq(result.len(), 0);\n }\n\n #[test]\n fn filter_some() {\n let slice = &[1, 2, 3, 4, 5];\n let result = slice.filter(|x| x % 2 == 0);\n assert_eq(result, &[2, 4]);\n }\n\n #[test]\n fn all_empty() {\n let empty = &[];\n let result = empty.all(|x| x > 0);\n assert_eq(result, true);\n }\n\n #[test]\n fn all_true() {\n let slice = &[1, 2, 3, 4];\n let result = slice.all(|x| x > 0);\n assert_eq(result, true);\n }\n\n #[test]\n fn all_false() {\n let slice = &[1, 2, 3, 4];\n let result = slice.all(|x| x > 2);\n assert_eq(result, false);\n }\n\n #[test]\n fn any_empty() {\n let empty = &[];\n let result = empty.any(|x| x > 0);\n assert_eq(result, false);\n }\n\n #[test]\n fn any_true() {\n let slice = &[1, 2, 3, 4];\n let result = slice.any(|x| x > 3);\n assert_eq(result, true);\n }\n\n #[test]\n fn any_false() {\n let slice = &[1, 2, 3, 4];\n let result = slice.any(|x| x > 10);\n assert_eq(result, false);\n }\n\n // utility method tests\n #[test]\n fn append_empty_to_empty() {\n let empty1: [Field] = &[];\n let empty2: [Field] = &[];\n let result = empty1.append(empty2);\n assert_eq(result.len(), 0);\n }\n\n #[test]\n fn append_empty_to_non_empty() {\n let slice = &[1, 2, 3];\n let empty = &[];\n let result = slice.append(empty);\n assert_eq(result, slice);\n }\n\n #[test]\n fn append_non_empty_to_empty() {\n let empty = &[];\n let slice = &[1, 2, 3];\n let result = empty.append(slice);\n assert_eq(result, slice);\n }\n\n #[test]\n fn append_two_non_empty() {\n let slice1 = &[1, 2];\n let slice2 = &[3, 4, 5];\n let result = slice1.append(slice2);\n assert_eq(result, &[1, 2, 3, 4, 5]);\n }\n\n #[test]\n fn as_array_single() {\n let slice = &[42];\n let array: [Field; 1] = slice.as_array();\n assert_eq(array[0], 42);\n }\n\n #[test]\n fn as_array_multiple() {\n let slice = &[1, 2, 3];\n let array: [Field; 3] = slice.as_array();\n assert_eq(array[0], 1);\n assert_eq(array[1], 2);\n assert_eq(array[2], 3);\n }\n\n // complex scenarios\n #[test]\n fn chain_operations() {\n let slice = &[1, 2, 3, 4, 5];\n let result = slice.filter(|x| x % 2 == 0).map(|x| x * 2).fold(0, |acc, x| acc + x);\n assert_eq(result, 12); // (2*2) + (4*2) = 4 + 8 = 12\n }\n\n #[test]\n fn nested_operations() {\n let slice = &[1, 2, 3, 4];\n let filtered = slice.filter(|x| x > 1);\n let mapped = filtered.map(|x| x * x);\n let sum = mapped.fold(0, |acc, x| acc + x);\n assert_eq(sum, 29); // 2^2 + 3^2 + 4^2 = 4 + 9 + 16 = 29\n }\n\n #[test]\n fn single_element_operations() {\n let single = &[42];\n\n // Test all operations on single element\n assert_eq(single.len(), 1);\n\n let pushed_back = single.push_back(99);\n assert_eq(pushed_back, &[42, 99]);\n\n let pushed_front = single.push_front(0);\n assert_eq(pushed_front, &[0, 42]);\n\n let (popped_back_slice, popped_back_elem) = single.pop_back();\n assert_eq(popped_back_slice.len(), 0);\n assert_eq(popped_back_elem, 42);\n\n let (popped_front_elem, popped_front_slice) = single.pop_front();\n assert_eq(popped_front_slice.len(), 0);\n assert_eq(popped_front_elem, 42);\n\n let inserted = single.insert(0, 0);\n assert_eq(inserted, &[0, 42]);\n\n let (removed_slice, removed_elem) = single.remove(0);\n assert_eq(removed_slice.len(), 0);\n assert_eq(removed_elem, 42);\n }\n\n #[test]\n fn boundary_conditions() {\n let slice = &[1, 2, 3];\n\n // insert at boundaries\n let at_start = slice.insert(0, 0);\n assert_eq(at_start, &[0, 1, 2, 3]);\n\n let at_end = slice.insert(3, 4);\n assert_eq(at_end, &[1, 2, 3, 4]);\n\n // remove at boundaries\n let (removed_start, elem_start) = slice.remove(0);\n assert_eq(removed_start, &[2, 3]);\n assert_eq(elem_start, 1);\n\n let (removed_end, elem_end) = slice.remove(2);\n assert_eq(removed_end, &[1, 2]);\n assert_eq(elem_end, 3);\n }\n\n #[test]\n fn complex_predicates() {\n let slice = &[1, 2, 3, 4, 5, 6, 7, 8, 9, 10];\n\n let even_greater_than_5 = slice.filter(|x| (x % 2 == 0) & (x > 5));\n assert_eq(even_greater_than_5, &[6, 8, 10]);\n\n let all_positive_and_less_than_20 = slice.all(|x| (x > 0) & (x < 20));\n assert_eq(all_positive_and_less_than_20, true);\n\n let any_divisible_by_7 = slice.any(|x| x % 7 == 0);\n assert_eq(any_divisible_by_7, true);\n }\n\n #[test]\n fn identity_operations() {\n let slice = &[1, 2, 3, 4, 5];\n\n let mapped_identity = slice.map(|x| x);\n assert_eq(mapped_identity, slice);\n\n let filtered_all = slice.filter(|_| true);\n assert_eq(filtered_all, slice);\n\n let filtered_none = slice.filter(|_| false);\n assert_eq(filtered_none.len(), 0);\n }\n\n #[test(should_fail)]\n fn as_array_size_mismatch() {\n let slice = &[1, 2, 3];\n let _: [Field; 5] = slice.as_array(); // size doesn't match\n }\n}\n" + }, + "5": { + "path": "std/cmp.nr", + "source": "use crate::meta::derive_via;\n\n#[derive_via(derive_eq)]\n// docs:start:eq-trait\npub trait Eq {\n fn eq(self, other: Self) -> bool;\n}\n// docs:end:eq-trait\n\n// docs:start:derive_eq\ncomptime fn derive_eq(s: TypeDefinition) -> Quoted {\n let signature = quote { fn eq(_self: Self, _other: Self) -> bool };\n let for_each_field = |name| quote { (_self.$name == _other.$name) };\n let body = |fields| {\n if s.fields_as_written().len() == 0 {\n quote { true }\n } else {\n fields\n }\n };\n crate::meta::make_trait_impl(\n s,\n quote { $crate::cmp::Eq },\n signature,\n for_each_field,\n quote { & },\n body,\n )\n}\n// docs:end:derive_eq\n\nimpl Eq for Field {\n fn eq(self, other: Field) -> bool {\n self == other\n }\n}\n\nimpl Eq for u128 {\n fn eq(self, other: u128) -> bool {\n self == other\n }\n}\nimpl Eq for u64 {\n fn eq(self, other: u64) -> bool {\n self == other\n }\n}\nimpl Eq for u32 {\n fn eq(self, other: u32) -> bool {\n self == other\n }\n}\nimpl Eq for u16 {\n fn eq(self, other: u16) -> bool {\n self == other\n }\n}\nimpl Eq for u8 {\n fn eq(self, other: u8) -> bool {\n self == other\n }\n}\nimpl Eq for u1 {\n fn eq(self, other: u1) -> bool {\n self == other\n }\n}\n\nimpl Eq for i8 {\n fn eq(self, other: i8) -> bool {\n self == other\n }\n}\nimpl Eq for i16 {\n fn eq(self, other: i16) -> bool {\n self == other\n }\n}\nimpl Eq for i32 {\n fn eq(self, other: i32) -> bool {\n self == other\n }\n}\nimpl Eq for i64 {\n fn eq(self, other: i64) -> bool {\n self == other\n }\n}\n\nimpl Eq for () {\n fn eq(_self: Self, _other: ()) -> bool {\n true\n }\n}\nimpl Eq for bool {\n fn eq(self, other: bool) -> bool {\n self == other\n }\n}\n\nimpl Eq for [T; N]\nwhere\n T: Eq,\n{\n fn eq(self, other: [T; N]) -> bool {\n let mut result = true;\n for i in 0..self.len() {\n result &= self[i].eq(other[i]);\n }\n result\n }\n}\n\nimpl Eq for [T]\nwhere\n T: Eq,\n{\n fn eq(self, other: [T]) -> bool {\n let mut result = self.len() == other.len();\n if result {\n for i in 0..self.len() {\n result &= self[i].eq(other[i]);\n }\n }\n result\n }\n}\n\nimpl Eq for str {\n fn eq(self, other: str) -> bool {\n let self_bytes = self.as_bytes();\n let other_bytes = other.as_bytes();\n self_bytes == other_bytes\n }\n}\n\nimpl Eq for (A, B)\nwhere\n A: Eq,\n B: Eq,\n{\n fn eq(self, other: (A, B)) -> bool {\n self.0.eq(other.0) & self.1.eq(other.1)\n }\n}\n\nimpl Eq for (A, B, C)\nwhere\n A: Eq,\n B: Eq,\n C: Eq,\n{\n fn eq(self, other: (A, B, C)) -> bool {\n self.0.eq(other.0) & self.1.eq(other.1) & self.2.eq(other.2)\n }\n}\n\nimpl Eq for (A, B, C, D)\nwhere\n A: Eq,\n B: Eq,\n C: Eq,\n D: Eq,\n{\n fn eq(self, other: (A, B, C, D)) -> bool {\n self.0.eq(other.0) & self.1.eq(other.1) & self.2.eq(other.2) & self.3.eq(other.3)\n }\n}\n\nimpl Eq for (A, B, C, D, E)\nwhere\n A: Eq,\n B: Eq,\n C: Eq,\n D: Eq,\n E: Eq,\n{\n fn eq(self, other: (A, B, C, D, E)) -> bool {\n self.0.eq(other.0)\n & self.1.eq(other.1)\n & self.2.eq(other.2)\n & self.3.eq(other.3)\n & self.4.eq(other.4)\n }\n}\n\nimpl Eq for Ordering {\n fn eq(self, other: Ordering) -> bool {\n self.result == other.result\n }\n}\n\n// Noir doesn't have enums yet so we emulate (Lt | Eq | Gt) with a struct\n// that has 3 public functions for constructing the struct.\npub struct Ordering {\n result: Field,\n}\n\nimpl Ordering {\n // Implementation note: 0, 1, and 2 for Lt, Eq, and Gt are built\n // into the compiler, do not change these without also updating\n // the compiler itself!\n pub fn less() -> Ordering {\n Ordering { result: 0 }\n }\n\n pub fn equal() -> Ordering {\n Ordering { result: 1 }\n }\n\n pub fn greater() -> Ordering {\n Ordering { result: 2 }\n }\n}\n\n#[derive_via(derive_ord)]\n// docs:start:ord-trait\npub trait Ord {\n fn cmp(self, other: Self) -> Ordering;\n}\n// docs:end:ord-trait\n\n// docs:start:derive_ord\ncomptime fn derive_ord(s: TypeDefinition) -> Quoted {\n let name = quote { $crate::cmp::Ord };\n let signature = quote { fn cmp(_self: Self, _other: Self) -> $crate::cmp::Ordering };\n let for_each_field = |name| quote {\n if result == $crate::cmp::Ordering::equal() {\n result = _self.$name.cmp(_other.$name);\n }\n };\n let body = |fields| quote {\n let mut result = $crate::cmp::Ordering::equal();\n $fields\n result\n };\n crate::meta::make_trait_impl(s, name, signature, for_each_field, quote {}, body)\n}\n// docs:end:derive_ord\n\n// Note: Field deliberately does not implement Ord\n\nimpl Ord for u128 {\n fn cmp(self, other: u128) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\nimpl Ord for u64 {\n fn cmp(self, other: u64) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for u32 {\n fn cmp(self, other: u32) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for u16 {\n fn cmp(self, other: u16) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for u8 {\n fn cmp(self, other: u8) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for i8 {\n fn cmp(self, other: i8) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for i16 {\n fn cmp(self, other: i16) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for i32 {\n fn cmp(self, other: i32) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for i64 {\n fn cmp(self, other: i64) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for () {\n fn cmp(_self: Self, _other: ()) -> Ordering {\n Ordering::equal()\n }\n}\n\nimpl Ord for bool {\n fn cmp(self, other: bool) -> Ordering {\n if self {\n if other {\n Ordering::equal()\n } else {\n Ordering::greater()\n }\n } else if other {\n Ordering::less()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for [T; N]\nwhere\n T: Ord,\n{\n // The first non-equal element of both arrays determines\n // the ordering for the whole array.\n fn cmp(self, other: [T; N]) -> Ordering {\n let mut result = Ordering::equal();\n for i in 0..self.len() {\n if result == Ordering::equal() {\n result = self[i].cmp(other[i]);\n }\n }\n result\n }\n}\n\nimpl Ord for [T]\nwhere\n T: Ord,\n{\n // The first non-equal element of both arrays determines\n // the ordering for the whole array.\n fn cmp(self, other: [T]) -> Ordering {\n let self_len = self.len();\n let other_len = other.len();\n let min_len = if self_len < other_len {\n self_len\n } else {\n other_len\n };\n\n let mut result = Ordering::equal();\n for i in 0..min_len {\n if result == Ordering::equal() {\n result = self[i].cmp(other[i]);\n }\n }\n\n if result != Ordering::equal() {\n result\n } else {\n self_len.cmp(other_len)\n }\n }\n}\n\nimpl Ord for (A, B)\nwhere\n A: Ord,\n B: Ord,\n{\n fn cmp(self, other: (A, B)) -> Ordering {\n let result = self.0.cmp(other.0);\n\n if result != Ordering::equal() {\n result\n } else {\n self.1.cmp(other.1)\n }\n }\n}\n\nimpl Ord for (A, B, C)\nwhere\n A: Ord,\n B: Ord,\n C: Ord,\n{\n fn cmp(self, other: (A, B, C)) -> Ordering {\n let mut result = self.0.cmp(other.0);\n\n if result == Ordering::equal() {\n result = self.1.cmp(other.1);\n }\n\n if result == Ordering::equal() {\n result = self.2.cmp(other.2);\n }\n\n result\n }\n}\n\nimpl Ord for (A, B, C, D)\nwhere\n A: Ord,\n B: Ord,\n C: Ord,\n D: Ord,\n{\n fn cmp(self, other: (A, B, C, D)) -> Ordering {\n let mut result = self.0.cmp(other.0);\n\n if result == Ordering::equal() {\n result = self.1.cmp(other.1);\n }\n\n if result == Ordering::equal() {\n result = self.2.cmp(other.2);\n }\n\n if result == Ordering::equal() {\n result = self.3.cmp(other.3);\n }\n\n result\n }\n}\n\nimpl Ord for (A, B, C, D, E)\nwhere\n A: Ord,\n B: Ord,\n C: Ord,\n D: Ord,\n E: Ord,\n{\n fn cmp(self, other: (A, B, C, D, E)) -> Ordering {\n let mut result = self.0.cmp(other.0);\n\n if result == Ordering::equal() {\n result = self.1.cmp(other.1);\n }\n\n if result == Ordering::equal() {\n result = self.2.cmp(other.2);\n }\n\n if result == Ordering::equal() {\n result = self.3.cmp(other.3);\n }\n\n if result == Ordering::equal() {\n result = self.4.cmp(other.4);\n }\n\n result\n }\n}\n\n// Compares and returns the maximum of two values.\n//\n// Returns the second argument if the comparison determines them to be equal.\n//\n// # Examples\n//\n// ```\n// use std::cmp;\n//\n// assert_eq(cmp::max(1, 2), 2);\n// assert_eq(cmp::max(2, 2), 2);\n// ```\npub fn max(v1: T, v2: T) -> T\nwhere\n T: Ord,\n{\n if v1 > v2 {\n v1\n } else {\n v2\n }\n}\n\n// Compares and returns the minimum of two values.\n//\n// Returns the first argument if the comparison determines them to be equal.\n//\n// # Examples\n//\n// ```\n// use std::cmp;\n//\n// assert_eq(cmp::min(1, 2), 1);\n// assert_eq(cmp::min(2, 2), 2);\n// ```\npub fn min(v1: T, v2: T) -> T\nwhere\n T: Ord,\n{\n if v1 > v2 {\n v2\n } else {\n v1\n }\n}\n\nmod cmp_tests {\n use super::{Eq, max, min, Ord};\n\n #[test]\n fn sanity_check_min() {\n assert_eq(min(0_u64, 1), 0);\n assert_eq(min(0_u64, 0), 0);\n assert_eq(min(1_u64, 1), 1);\n assert_eq(min(255_u8, 0), 0);\n }\n\n #[test]\n fn sanity_check_max() {\n assert_eq(max(0_u64, 1), 1);\n assert_eq(max(0_u64, 0), 0);\n assert_eq(max(1_u64, 1), 1);\n assert_eq(max(255_u8, 0), 255);\n }\n\n #[test]\n fn correctly_handles_unequal_length_slices() {\n let slice_1 = &[0, 1, 2, 3];\n let slice_2 = &[0, 1, 2];\n assert(!slice_1.eq(slice_2));\n }\n\n #[test]\n fn lexicographic_ordering_for_slices() {\n assert(&[2_u32].cmp(&[1_u32, 1_u32, 1_u32]) == super::Ordering::greater());\n assert(&[1_u32, 2_u32].cmp(&[1_u32, 2_u32, 3_u32]) == super::Ordering::less());\n }\n}\n" + }, + "51": { + "path": "/home/ubuntu/Dropbox/WEB/aztec/nft-portal-example/train-contracts/chains/aztec/contracts/train/src/lib.nr", + "source": "pub fn bytes_to_u128_limbs(bytes: [u8; 32]) -> (u128, u128) {\n let mut high: u128 = 0;\n let mut low: u128 = 0;\n for i in 0..16 {\n high = (high << 8) + (bytes[i] as u128);\n }\n for i in 16..32 {\n low = (low << 8) + (bytes[i] as u128);\n }\n (high, low)\n}\n\npub fn u128_limbs_to_bytes(high: u128, low: u128) -> [u8; 32] {\n let mut bytes: [u8; 32] = [0; 32];\n\n let mut temp = high;\n for i in 0..16 {\n bytes[15 - i] = (temp & 0xff) as u8;\n temp >>= 8;\n }\n\n temp = low;\n for i in 0..16 {\n bytes[31 - i] = (temp & 0xff) as u8;\n temp >>= 8;\n }\n\n bytes\n}\n" + }, + "52": { + "path": "/home/ubuntu/Dropbox/WEB/aztec/nft-portal-example/train-contracts/chains/aztec/contracts/train/src/main.nr", + "source": "// @@ @@@\n// @@@\n// @@@ @@ @@@@ @@@@@ @ @ @@@@@\n// @@@@@@@@@ @@@@@@ @@@@ @@@@@ @@@ @@@@@@ @@@@\n// @@@ @@@ @@@ @@@ @@@ @@@ @@@\n// @@@ @@@ @@@ @@@ @@@ @@@ @@@\n// @@@ @@@ @@@ @@@ @@@ @@@ @@@\n// @@@ @@@ @@@@ @@@@@ @@@ @@@ @@@\n// @@@@@ @@@ @@@@@@@@@ @@@ @@@ @@@ @@@\n\nmod lib;\nuse dep::aztec::macros::aztec;\n\n#[aztec]\npub contract Train {\n use std::meta::derive;\n\n use aztec::macros::{\n events::event,\n functions::{external, initializer, view},\n storage::storage,\n };\n\n use dep::aztec::{\n protocol_types::{address::AztecAddress, traits::{Deserialize, Packable, Serialize}},\n state_vars::{PublicMutable, map::Map},\n };\n use dep::sha256;\n use dep::token::Token;\n\n use crate::lib::{bytes_to_u128_limbs, u128_limbs_to_bytes};\n\n // Events\n #[event]\n pub struct SrcLocked {\n pub swap_id: Field,\n pub hashlock: [u8; 32],\n pub dst_chain: str<30>,\n pub dst_address: str<90>,\n pub dst_asset: str<30>,\n pub sender: AztecAddress,\n pub src_receiver: AztecAddress,\n pub src_asset: str<30>,\n pub amount: u128,\n pub timelock: u64,\n }\n\n #[event]\n pub struct DstLocked {\n pub swap_id: Field,\n pub htlc_id: Field,\n pub hashlock: [u8; 32],\n pub dst_chain: str<30>,\n pub dst_address: str<90>,\n pub dst_asset: str<30>,\n pub sender: AztecAddress,\n pub src_receiver: AztecAddress,\n pub src_asset: str<30>,\n pub amount: u128,\n pub reward: u128,\n pub reward_timelock: u64,\n pub timelock: u64,\n }\n\n #[event]\n pub struct TokenRefunded {\n pub swap_id: Field,\n pub htlc_id: Field,\n }\n\n #[event]\n pub struct TokenRedeemed {\n pub swap_id: Field,\n pub htlc_id: Field,\n pub redeem_address: AztecAddress,\n pub secret_high: u128,\n pub secret_low: u128,\n pub hashlock: [u8; 32],\n }\n\n #[derive(Eq, Packable, Serialize, Deserialize)]\n pub struct HTLC_Public {\n amount: u128,\n token: AztecAddress,\n hashlock_high: u128,\n hashlock_low: u128,\n secret_high: u128,\n secret_low: u128,\n sender: AztecAddress,\n src_receiver: AztecAddress,\n timelock: u64,\n claimed: u8,\n reward: u128,\n reward_timelock: u64,\n }\n\n #[external(\"public\")]\n #[initializer]\n fn constructor() {}\n\n #[storage]\n struct Storage {\n contracts: Map, Context>, Context>,\n user_swaps_count: Map, Context>,\n user_swaps: Map, Context>, Context>,\n }\n\n #[external(\"public\")]\n fn lock_src(\n swap_id: Field,\n hashlock_high: u128,\n hashlock_low: u128,\n timelock: u64,\n src_receiver: AztecAddress,\n token: AztecAddress,\n amount: u128,\n src_asset: str<30>,\n dst_chain: str<30>,\n dst_asset: str<30>,\n dst_address: str<90>,\n ) {\n assert(amount > 0, \"FundsNotSent\");\n\n let htlc_public_current = self.storage.contracts.at(swap_id).at(0).read();\n assert(htlc_public_current.sender == AztecAddress::zero(), \"SwapAlreadyInitialized\");\n assert(self.context.timestamp() + 1800 < timelock, \"InvalidTimelock\");\n\n let hashlock_tuple = (hashlock_high, hashlock_low);\n let sender = self.msg_sender().expect(f\"Sender must not be none!\");\n let htlc_public = HTLC_Public {\n amount: amount,\n token: token,\n hashlock_high: hashlock_tuple.0,\n hashlock_low: hashlock_tuple.1,\n secret_high: 0 as u128,\n secret_low: 0 as u128,\n sender: sender,\n src_receiver: src_receiver,\n timelock: timelock,\n claimed: 1 as u8,\n reward: 0 as u128,\n reward_timelock: 0 as u64,\n };\n self.storage.contracts.at(swap_id).at(0).write(htlc_public);\n\n // Transfer tokens from sender to contract\n self.call(Token::at(token).transfer_in_public(sender, self.address, amount, 0));\n\n // Track this swap for the user\n let current_count = self.storage.user_swaps_count.at(sender).read();\n self.storage.user_swaps.at(sender).at(current_count).write(swap_id);\n self.storage.user_swaps_count.at(sender).write(current_count + 1);\n\n let hashlock = u128_limbs_to_bytes(hashlock_high, hashlock_low);\n let log_msg = SrcLocked {\n swap_id: swap_id,\n hashlock: hashlock,\n dst_chain: dst_chain,\n dst_address: dst_address,\n dst_asset: dst_asset,\n sender: sender,\n src_receiver: src_receiver,\n src_asset: src_asset,\n amount: amount,\n timelock: timelock,\n };\n\n self.emit(log_msg);\n }\n\n #[external(\"public\")]\n fn refund(swap_id: Field, htlc_id: Field) {\n let htlc_public = self.storage.contracts.at(swap_id).at(htlc_id).read();\n assert(htlc_public.claimed == 1, \"AlreadyClaimed\");\n assert(htlc_public.timelock < self.context.timestamp(), \"NotPassedTimelock\");\n\n let refund_amount = if htlc_public.reward != 0 {\n htlc_public.amount + htlc_public.reward\n } else {\n htlc_public.amount\n };\n\n // Transfer tokens back to sender\n self.call(Token::at(htlc_public.token).transfer_in_public(\n self.address,\n htlc_public.sender,\n refund_amount,\n 0\n ));\n\n let modified_htlc_public = HTLC_Public {\n amount: htlc_public.amount,\n token: htlc_public.token,\n hashlock_high: htlc_public.hashlock_high,\n hashlock_low: htlc_public.hashlock_low,\n secret_high: htlc_public.secret_high,\n secret_low: htlc_public.secret_low,\n sender: htlc_public.sender,\n src_receiver: htlc_public.src_receiver,\n timelock: htlc_public.timelock,\n claimed: 2 as u8,\n reward: htlc_public.reward,\n reward_timelock: htlc_public.reward_timelock,\n };\n\n self.storage.contracts.at(swap_id).at(htlc_id).write(modified_htlc_public);\n let log_msg = TokenRefunded { swap_id, htlc_id };\n self.emit(log_msg);\n }\n\n #[external(\"public\")]\n fn lock_dst(\n swap_id: Field,\n htlc_id: Field,\n hashlock_high: u128,\n hashlock_low: u128,\n reward: u128,\n reward_timelock: u64,\n timelock: u64,\n src_receiver: AztecAddress,\n token: AztecAddress,\n total_amount: u128,\n src_asset: str<30>,\n dst_chain: str<30>,\n dst_asset: str<30>,\n dst_address: str<90>,\n ) {\n assert(total_amount > 0, \"FundsNotSent\");\n assert(reward > 0, \"InvalidRewardAmount\");\n\n let amount = total_amount - reward;\n assert(amount > 0, \"InvalidRewardAmount\");\n // Enforce reward >= 10% of amount: reward * 10 >= amount\n assert(reward * 10 >= amount, \"InvalidRewardAmount\");\n\n let htlc_public_current = self.storage.contracts.at(swap_id).at(htlc_id).read();\n assert(htlc_public_current.sender == AztecAddress::zero(), \"HTLCAlreadyExists\");\n assert(self.context.timestamp() + 900 < timelock, \"InvalidTimelock\");\n assert(reward_timelock <= timelock, \"InvalidRewardTimelock\");\n assert(reward_timelock > self.context.timestamp(), \"InvalidRewardTimelock\");\n\n let hashlock_tuple = (hashlock_high, hashlock_low);\n let sender = self.msg_sender().expect(f\"Sender must not be none!\");\n let htlc_public = HTLC_Public {\n amount: amount,\n token: token,\n hashlock_high: hashlock_tuple.0,\n hashlock_low: hashlock_tuple.1,\n secret_high: 0 as u128,\n secret_low: 0 as u128,\n sender: sender,\n src_receiver: src_receiver,\n timelock: timelock,\n claimed: 1 as u8,\n reward: reward,\n reward_timelock: reward_timelock,\n };\n self.storage.contracts.at(swap_id).at(htlc_id).write(htlc_public);\n\n // Transfer tokens from sender to contract\n self.call(Token::at(token).transfer_in_public(sender, self.address, total_amount, 0));\n\n let hashlock = u128_limbs_to_bytes(hashlock_high, hashlock_low);\n let log_msg = DstLocked {\n swap_id: swap_id,\n htlc_id: htlc_id,\n hashlock: hashlock,\n dst_chain: dst_chain,\n dst_address: dst_address,\n dst_asset: dst_asset,\n sender: sender,\n src_receiver: src_receiver,\n src_asset: src_asset,\n amount: amount,\n reward: reward,\n reward_timelock: reward_timelock,\n timelock: timelock,\n };\n\n self.emit(log_msg);\n }\n\n #[external(\"public\")]\n fn redeem(swap_id: Field, htlc_id: Field, secret_high: u128, secret_low: u128) {\n let secret = u128_limbs_to_bytes(secret_high, secret_low);\n let caller = self.msg_sender().expect(f\"Sender must not be none!\");\n\n let htlc_public = self.storage.contracts.at(swap_id).at(htlc_id).read();\n assert(htlc_public.amount > 0, \"HTLCNotExists\");\n let hashed_secret = sha256::sha256_var(secret, secret.len() as u64);\n let hashed_secret_tuple = bytes_to_u128_limbs(hashed_secret);\n assert(htlc_public.hashlock_high == hashed_secret_tuple.0, \"HashlockNotMatch\");\n assert(htlc_public.hashlock_low == hashed_secret_tuple.1, \"HashlockNotMatch\");\n assert(htlc_public.claimed == 1, \"AlreadyClaimed\");\n\n let secret_limbs = bytes_to_u128_limbs(secret);\n\n let modified_htlc_public = HTLC_Public {\n amount: htlc_public.amount,\n token: htlc_public.token,\n hashlock_high: htlc_public.hashlock_high,\n hashlock_low: htlc_public.hashlock_low,\n secret_high: secret_limbs.0,\n secret_low: secret_limbs.1,\n sender: htlc_public.sender,\n src_receiver: htlc_public.src_receiver,\n timelock: htlc_public.timelock,\n claimed: 3 as u8,\n reward: htlc_public.reward,\n reward_timelock: htlc_public.reward_timelock,\n };\n\n self.storage.contracts.at(swap_id).at(htlc_id).write(modified_htlc_public);\n\n // Handle token transfers based on reward logic\n if htlc_public.reward == 0 {\n // No reward: transfer amount to src_receiver\n self.call(Token::at(htlc_public.token).transfer_in_public(\n self.address,\n htlc_public.src_receiver,\n htlc_public.amount,\n 0\n ));\n } else if htlc_public.reward_timelock > self.context.timestamp() {\n // Before reward timelock: amount to src_receiver, reward back to sender\n self.call(Token::at(htlc_public.token).transfer_in_public(\n self.address,\n htlc_public.src_receiver,\n htlc_public.amount,\n 0\n ));\n self.call(Token::at(htlc_public.token).transfer_in_public(\n self.address,\n htlc_public.sender,\n htlc_public.reward,\n 0\n ));\n } else {\n // After reward timelock\n if caller == htlc_public.src_receiver {\n // src_receiver gets amount + reward\n self.call(Token::at(htlc_public.token).transfer_in_public(\n self.address,\n htlc_public.src_receiver,\n htlc_public.amount + htlc_public.reward,\n 0\n ));\n } else {\n // amount to src_receiver, reward to caller\n self.call(Token::at(htlc_public.token).transfer_in_public(\n self.address,\n htlc_public.src_receiver,\n htlc_public.amount,\n 0\n ));\n self.call(Token::at(htlc_public.token).transfer_in_public(\n self.address,\n caller,\n htlc_public.reward,\n 0\n ));\n }\n }\n\n let log_msg = TokenRedeemed {\n swap_id: swap_id,\n htlc_id: htlc_id,\n redeem_address: caller,\n secret_high: secret_limbs.0,\n secret_low: secret_limbs.1,\n hashlock: u128_limbs_to_bytes(htlc_public.hashlock_high, htlc_public.hashlock_low),\n };\n\n self.emit(log_msg);\n }\n\n #[external(\"public\")]\n #[view]\n fn has_htlc(swap_id: Field, htlc_id: Field) -> pub bool {\n let htlc = self.storage.contracts.at(swap_id).at(htlc_id).read();\n htlc.sender != AztecAddress::zero()\n }\n\n #[external(\"public\")]\n #[view]\n fn get_htlc(swap_id: Field, htlc_id: Field) -> pub HTLC_Public {\n self.storage.contracts.at(swap_id).at(htlc_id).read()\n }\n\n #[external(\"public\")]\n #[view]\n fn get_user_swaps_count(user: AztecAddress) -> pub Field {\n self.storage.user_swaps_count.at(user).read()\n }\n}\n" + }, + "6": { + "path": "std/collections/bounded_vec.nr", + "source": "use crate::{cmp::Eq, convert::From, runtime::is_unconstrained, static_assert};\n\n/// A `BoundedVec` is a growable storage similar to a [`Vec`][crate::collections::vec::Vec]`` except that it\n/// is bounded with a maximum possible length. Unlike `Vec`, `BoundedVec` is not implemented\n/// via slices and thus is not subject to the same restrictions slices are (notably, nested\n/// slices - and thus nested vectors as well - are disallowed).\n///\n/// Since a BoundedVec is backed by a normal array under the hood, growing the BoundedVec by\n/// pushing an additional element is also more efficient - the length only needs to be increased\n/// by one.\n///\n/// For these reasons `BoundedVec` should generally be preferred over `Vec` when there\n/// is a reasonable maximum bound that can be placed on the vector.\n///\n/// Example:\n///\n/// ```noir\n/// let mut vector: BoundedVec = BoundedVec::new();\n/// for i in 0..5 {\n/// vector.push(i);\n/// }\n/// assert(vector.len() == 5);\n/// assert(vector.max_len() == 10);\n/// ```\npub struct BoundedVec {\n storage: [T; MaxLen],\n len: u32,\n}\n\nimpl BoundedVec {\n /// Creates a new, empty vector of length zero.\n ///\n /// Since this container is backed by an array internally, it still needs an initial value\n /// to give each element. To resolve this, each element is zeroed internally. This value\n /// is guaranteed to be inaccessible unless `get_unchecked` is used.\n ///\n /// Example:\n ///\n /// ```noir\n /// let empty_vector: BoundedVec = BoundedVec::new();\n /// assert(empty_vector.len() == 0);\n /// ```\n ///\n /// Note that whenever calling `new` the maximum length of the vector should always be specified\n /// via a type signature:\n ///\n /// ```noir\n /// fn good() -> BoundedVec {\n /// // Ok! MaxLen is specified with a type annotation\n /// let v1: BoundedVec = BoundedVec::new();\n /// let v2 = BoundedVec::new();\n ///\n /// // Ok! MaxLen is known from the type of `good`'s return value\n /// v2\n /// }\n ///\n /// fn bad() {\n /// // Error: Type annotation needed\n /// // The compiler can't infer `MaxLen` from the following code:\n /// let mut v3 = BoundedVec::new();\n /// v3.push(5);\n /// }\n /// ```\n ///\n /// This defaulting of `MaxLen` (and numeric generics in general) to zero may change in future noir versions\n /// but for now make sure to use type annotations when using bounded vectors. Otherwise, you will receive a\n /// constraint failure at runtime when the vec is pushed to.\n pub fn new() -> Self {\n let zeroed = crate::mem::zeroed();\n BoundedVec { storage: [zeroed; MaxLen], len: 0 }\n }\n\n /// Retrieves an element from the vector at the given index, starting from zero.\n ///\n /// If the given index is equal to or greater than the length of the vector, this\n /// will issue a constraint failure.\n ///\n /// Example:\n ///\n /// ```noir\n /// fn foo(v: BoundedVec) {\n /// let first = v.get(0);\n /// let last = v.get(v.len() - 1);\n /// assert(first != last);\n /// }\n /// ```\n pub fn get(self, index: u32) -> T {\n assert(index < self.len, \"Attempted to read past end of BoundedVec\");\n self.get_unchecked(index)\n }\n\n /// Retrieves an element from the vector at the given index, starting from zero, without\n /// performing a bounds check.\n ///\n /// Since this function does not perform a bounds check on length before accessing the element,\n /// it is unsafe! Use at your own risk!\n ///\n /// Example:\n ///\n /// ```noir\n /// fn sum_of_first_three(v: BoundedVec) -> u32 {\n /// // Always ensure the length is larger than the largest\n /// // index passed to get_unchecked\n /// assert(v.len() > 2);\n /// let first = v.get_unchecked(0);\n /// let second = v.get_unchecked(1);\n /// let third = v.get_unchecked(2);\n /// first + second + third\n /// }\n /// ```\n pub fn get_unchecked(self, index: u32) -> T {\n self.storage[index]\n }\n\n /// Writes an element to the vector at the given index, starting from zero.\n ///\n /// If the given index is equal to or greater than the length of the vector, this will issue a constraint failure.\n ///\n /// Example:\n ///\n /// ```noir\n /// fn foo(v: BoundedVec) {\n /// let first = v.get(0);\n /// assert(first != 42);\n /// v.set(0, 42);\n /// let new_first = v.get(0);\n /// assert(new_first == 42);\n /// }\n /// ```\n pub fn set(&mut self, index: u32, value: T) {\n assert(index < self.len, \"Attempted to write past end of BoundedVec\");\n self.set_unchecked(index, value)\n }\n\n /// Writes an element to the vector at the given index, starting from zero, without performing a bounds check.\n ///\n /// Since this function does not perform a bounds check on length before accessing the element, it is unsafe! Use at your own risk!\n ///\n /// Example:\n ///\n /// ```noir\n /// fn set_unchecked_example() {\n /// let mut vec: BoundedVec = BoundedVec::new();\n /// vec.extend_from_array([1, 2]);\n ///\n /// // Here we're safely writing within the valid range of `vec`\n /// // `vec` now has the value [42, 2]\n /// vec.set_unchecked(0, 42);\n ///\n /// // We can then safely read this value back out of `vec`.\n /// // Notice that we use the checked version of `get` which would prevent reading unsafe values.\n /// assert_eq(vec.get(0), 42);\n ///\n /// // We've now written past the end of `vec`.\n /// // As this index is still within the maximum potential length of `v`,\n /// // it won't cause a constraint failure.\n /// vec.set_unchecked(2, 42);\n /// println(vec);\n ///\n /// // This will write past the end of the maximum potential length of `vec`,\n /// // it will then trigger a constraint failure.\n /// vec.set_unchecked(5, 42);\n /// println(vec);\n /// }\n /// ```\n pub fn set_unchecked(&mut self, index: u32, value: T) {\n self.storage[index] = value;\n }\n\n /// Pushes an element to the end of the vector. This increases the length\n /// of the vector by one.\n ///\n /// Panics if the new length of the vector will be greater than the max length.\n ///\n /// Example:\n ///\n /// ```noir\n /// let mut v: BoundedVec = BoundedVec::new();\n ///\n /// v.push(1);\n /// v.push(2);\n ///\n /// // Panics with failed assertion \"push out of bounds\"\n /// v.push(3);\n /// ```\n pub fn push(&mut self, elem: T) {\n assert(self.len < MaxLen, \"push out of bounds\");\n\n self.storage[self.len] = elem;\n self.len += 1;\n }\n\n /// Returns the current length of this vector\n ///\n /// Example:\n ///\n /// ```noir\n /// let mut v: BoundedVec = BoundedVec::new();\n /// assert(v.len() == 0);\n ///\n /// v.push(100);\n /// assert(v.len() == 1);\n ///\n /// v.push(200);\n /// v.push(300);\n /// v.push(400);\n /// assert(v.len() == 4);\n ///\n /// let _ = v.pop();\n /// let _ = v.pop();\n /// assert(v.len() == 2);\n /// ```\n pub fn len(self) -> u32 {\n self.len\n }\n\n /// Returns the maximum length of this vector. This is always\n /// equal to the `MaxLen` parameter this vector was initialized with.\n ///\n /// Example:\n ///\n /// ```noir\n /// let mut v: BoundedVec = BoundedVec::new();\n ///\n /// assert(v.max_len() == 5);\n /// v.push(10);\n /// assert(v.max_len() == 5);\n /// ```\n pub fn max_len(_self: BoundedVec) -> u32 {\n MaxLen\n }\n\n /// Returns the internal array within this vector.\n ///\n /// Since arrays in Noir are immutable, mutating the returned storage array will not mutate\n /// the storage held internally by this vector.\n ///\n /// Note that uninitialized elements may be zeroed out!\n ///\n /// Example:\n ///\n /// ```noir\n /// let mut v: BoundedVec = BoundedVec::new();\n ///\n /// assert(v.storage() == [0, 0, 0, 0, 0]);\n ///\n /// v.push(57);\n /// assert(v.storage() == [57, 0, 0, 0, 0]);\n /// ```\n pub fn storage(self) -> [T; MaxLen] {\n self.storage\n }\n\n /// Pushes each element from the given array to this vector.\n ///\n /// Panics if pushing each element would cause the length of this vector\n /// to exceed the maximum length.\n ///\n /// Example:\n ///\n /// ```noir\n /// let mut vec: BoundedVec = BoundedVec::new();\n /// vec.extend_from_array([2, 4]);\n ///\n /// assert(vec.len == 2);\n /// assert(vec.get(0) == 2);\n /// assert(vec.get(1) == 4);\n /// ```\n pub fn extend_from_array(&mut self, array: [T; Len]) {\n let new_len = self.len + array.len();\n assert(new_len <= MaxLen, \"extend_from_array out of bounds\");\n for i in 0..array.len() {\n self.storage[self.len + i] = array[i];\n }\n self.len = new_len;\n }\n\n /// Pushes each element from the given slice to this vector.\n ///\n /// Panics if pushing each element would cause the length of this vector\n /// to exceed the maximum length.\n ///\n /// Example:\n ///\n /// ```noir\n /// let mut vec: BoundedVec = BoundedVec::new();\n /// vec.extend_from_slice(&[2, 4]);\n ///\n /// assert(vec.len == 2);\n /// assert(vec.get(0) == 2);\n /// assert(vec.get(1) == 4);\n /// ```\n pub fn extend_from_slice(&mut self, slice: [T]) {\n let new_len = self.len + slice.len();\n assert(new_len <= MaxLen, \"extend_from_slice out of bounds\");\n for i in 0..slice.len() {\n self.storage[self.len + i] = slice[i];\n }\n self.len = new_len;\n }\n\n /// Pushes each element from the other vector to this vector. The length of\n /// the other vector is left unchanged.\n ///\n /// Panics if pushing each element would cause the length of this vector\n /// to exceed the maximum length.\n ///\n /// ```noir\n /// let mut v1: BoundedVec = BoundedVec::new();\n /// let mut v2: BoundedVec = BoundedVec::new();\n ///\n /// v2.extend_from_array([1, 2, 3]);\n /// v1.extend_from_bounded_vec(v2);\n ///\n /// assert(v1.storage() == [1, 2, 3, 0, 0]);\n /// assert(v2.storage() == [1, 2, 3, 0, 0, 0, 0]);\n /// ```\n pub fn extend_from_bounded_vec(&mut self, vec: BoundedVec) {\n let append_len = vec.len();\n let new_len = self.len + append_len;\n assert(new_len <= MaxLen, \"extend_from_bounded_vec out of bounds\");\n\n if is_unconstrained() {\n for i in 0..append_len {\n self.storage[self.len + i] = vec.get_unchecked(i);\n }\n } else {\n let mut exceeded_len = false;\n for i in 0..Len {\n exceeded_len |= i == append_len;\n if !exceeded_len {\n self.storage[self.len + i] = vec.get_unchecked(i);\n }\n }\n }\n self.len = new_len;\n }\n\n /// Creates a new vector, populating it with values derived from an array input.\n /// The maximum length of the vector is determined based on the type signature.\n ///\n /// Example:\n ///\n /// ```noir\n /// let bounded_vec: BoundedVec = BoundedVec::from_array([1, 2, 3])\n /// ```\n pub fn from_array(array: [T; Len]) -> Self {\n static_assert(Len <= MaxLen, \"from array out of bounds\");\n let mut vec: BoundedVec = BoundedVec::new();\n vec.extend_from_array(array);\n vec\n }\n\n /// Pops the element at the end of the vector. This will decrease the length\n /// of the vector by one.\n ///\n /// Panics if the vector is empty.\n ///\n /// Example:\n ///\n /// ```noir\n /// let mut v: BoundedVec = BoundedVec::new();\n /// v.push(1);\n /// v.push(2);\n ///\n /// let two = v.pop();\n /// let one = v.pop();\n ///\n /// assert(two == 2);\n /// assert(one == 1);\n ///\n /// // error: cannot pop from an empty vector\n /// let _ = v.pop();\n /// ```\n pub fn pop(&mut self) -> T {\n assert(self.len > 0, \"cannot pop from an empty vector\");\n self.len -= 1;\n\n let elem = self.storage[self.len];\n self.storage[self.len] = crate::mem::zeroed();\n elem\n }\n\n /// Returns true if the given predicate returns true for any element\n /// in this vector.\n ///\n /// Example:\n ///\n /// ```noir\n /// let mut v: BoundedVec = BoundedVec::new();\n /// v.extend_from_array([2, 4, 6]);\n ///\n /// let all_even = !v.any(|elem: u32| elem % 2 != 0);\n /// assert(all_even);\n /// ```\n pub fn any(self, predicate: fn[Env](T) -> bool) -> bool {\n let mut ret = false;\n if is_unconstrained() {\n for i in 0..self.len {\n ret |= predicate(self.storage[i]);\n }\n } else {\n let mut exceeded_len = false;\n for i in 0..MaxLen {\n exceeded_len |= i == self.len;\n if !exceeded_len {\n ret |= predicate(self.storage[i]);\n }\n }\n }\n ret\n }\n\n /// Creates a new vector of equal size by calling a closure on each element in this vector.\n ///\n /// Example:\n ///\n /// ```noir\n /// let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);\n /// let result = vec.map(|value| value * 2);\n ///\n /// let expected = BoundedVec::from_array([2, 4, 6, 8]);\n /// assert_eq(result, expected);\n /// ```\n pub fn map(self, f: fn[Env](T) -> U) -> BoundedVec {\n let mut ret = BoundedVec::new();\n ret.len = self.len();\n\n if is_unconstrained() {\n for i in 0..self.len() {\n ret.storage[i] = f(self.get_unchecked(i));\n }\n } else {\n for i in 0..MaxLen {\n if i < self.len() {\n ret.storage[i] = f(self.get_unchecked(i));\n }\n }\n }\n\n ret\n }\n\n /// Creates a new vector of equal size by calling a closure on each element\n /// in this vector, along with its index.\n ///\n /// Example:\n ///\n /// ```noir\n /// let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);\n /// let result = vec.mapi(|i, value| i + value * 2);\n ///\n /// let expected = BoundedVec::from_array([2, 5, 8, 11]);\n /// assert_eq(result, expected);\n /// ```\n pub fn mapi(self, f: fn[Env](u32, T) -> U) -> BoundedVec {\n let mut ret = BoundedVec::new();\n ret.len = self.len();\n\n if is_unconstrained() {\n for i in 0..self.len() {\n ret.storage[i] = f(i, self.get_unchecked(i));\n }\n } else {\n for i in 0..MaxLen {\n if i < self.len() {\n ret.storage[i] = f(i, self.get_unchecked(i));\n }\n }\n }\n\n ret\n }\n\n /// Calls a closure on each element in this vector.\n ///\n /// Example:\n ///\n /// ```noir\n /// let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);\n /// let mut result = BoundedVec::::new();\n /// vec.for_each(|value| result.push(value * 2));\n ///\n /// let expected = BoundedVec::from_array([2, 4, 6, 8]);\n /// assert_eq(result, expected);\n /// ```\n pub fn for_each(self, f: fn[Env](T) -> ()) {\n if is_unconstrained() {\n for i in 0..self.len() {\n f(self.get_unchecked(i));\n }\n } else {\n for i in 0..MaxLen {\n if i < self.len() {\n f(self.get_unchecked(i));\n }\n }\n }\n }\n\n /// Calls a closure on each element in this vector, along with its index.\n ///\n /// Example:\n ///\n /// ```noir\n /// let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);\n /// let mut result = BoundedVec::::new();\n /// vec.for_eachi(|i, value| result.push(i + value * 2));\n ///\n /// let expected = BoundedVec::from_array([2, 5, 8, 11]);\n /// assert_eq(result, expected);\n /// ```\n pub fn for_eachi(self, f: fn[Env](u32, T) -> ()) {\n if is_unconstrained() {\n for i in 0..self.len() {\n f(i, self.get_unchecked(i));\n }\n } else {\n for i in 0..MaxLen {\n if i < self.len() {\n f(i, self.get_unchecked(i));\n }\n }\n }\n }\n\n /// Creates a new BoundedVec from the given array and length.\n /// The given length must be less than or equal to the length of the array.\n ///\n /// This function will zero out any elements at or past index `len` of `array`.\n /// This incurs an extra runtime cost of O(MaxLen). If you are sure your array is\n /// zeroed after that index, you can use [`from_parts_unchecked`][Self::from_parts_unchecked] to remove the extra loop.\n ///\n /// Example:\n ///\n /// ```noir\n /// let vec: BoundedVec = BoundedVec::from_parts([1, 2, 3, 0], 3);\n /// assert_eq(vec.len(), 3);\n /// ```\n pub fn from_parts(mut array: [T; MaxLen], len: u32) -> Self {\n assert(len <= MaxLen);\n let zeroed = crate::mem::zeroed();\n\n if is_unconstrained() {\n for i in len..MaxLen {\n array[i] = zeroed;\n }\n } else {\n for i in 0..MaxLen {\n if i >= len {\n array[i] = zeroed;\n }\n }\n }\n\n BoundedVec { storage: array, len }\n }\n\n /// Creates a new BoundedVec from the given array and length.\n /// The given length must be less than or equal to the length of the array.\n ///\n /// This function is unsafe because it expects all elements past the `len` index\n /// of `array` to be zeroed, but does not check for this internally. Use `from_parts`\n /// for a safe version of this function which does zero out any indices past the\n /// given length. Invalidating this assumption can notably cause `BoundedVec::eq`\n /// to give incorrect results since it will check even elements past `len`.\n ///\n /// Example:\n ///\n /// ```noir\n /// let vec: BoundedVec = BoundedVec::from_parts_unchecked([1, 2, 3, 0], 3);\n /// assert_eq(vec.len(), 3);\n ///\n /// // invalid use!\n /// let vec1: BoundedVec = BoundedVec::from_parts_unchecked([1, 2, 3, 1], 3);\n /// let vec2: BoundedVec = BoundedVec::from_parts_unchecked([1, 2, 3, 2], 3);\n ///\n /// // both vecs have length 3 so we'd expect them to be equal, but this\n /// // fails because elements past the length are still checked in eq\n /// assert_eq(vec1, vec2); // fails\n /// ```\n pub fn from_parts_unchecked(array: [T; MaxLen], len: u32) -> Self {\n assert(len <= MaxLen);\n BoundedVec { storage: array, len }\n }\n}\n\nimpl Eq for BoundedVec\nwhere\n T: Eq,\n{\n fn eq(self, other: BoundedVec) -> bool {\n // TODO: https://github.com/noir-lang/noir/issues/4837\n //\n // We make the assumption that the user has used the proper interface for working with `BoundedVec`s\n // rather than directly manipulating the internal fields as this can result in an inconsistent internal state.\n if self.len == other.len {\n self.storage == other.storage\n } else {\n false\n }\n }\n}\n\nimpl From<[T; Len]> for BoundedVec {\n fn from(array: [T; Len]) -> BoundedVec {\n BoundedVec::from_array(array)\n }\n}\n\nmod bounded_vec_tests {\n\n mod get {\n use crate::collections::bounded_vec::BoundedVec;\n\n #[test(should_fail_with = \"Attempted to read past end of BoundedVec\")]\n fn panics_when_reading_elements_past_end_of_vec() {\n let vec: BoundedVec = BoundedVec::new();\n\n let _ = vec.get(0);\n }\n\n #[test(should_fail_with = \"Attempted to read past end of BoundedVec\")]\n fn panics_when_reading_beyond_length() {\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3]);\n let _ = vec.get(3);\n }\n\n #[test]\n fn get_works_within_bounds() {\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4, 5]);\n assert_eq(vec.get(0), 1);\n assert_eq(vec.get(2), 3);\n assert_eq(vec.get(4), 5);\n }\n\n #[test]\n fn get_unchecked_works() {\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3]);\n assert_eq(vec.get_unchecked(0), 1);\n assert_eq(vec.get_unchecked(2), 3);\n }\n\n #[test]\n fn get_unchecked_works_past_len() {\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3]);\n assert_eq(vec.get_unchecked(4), 0);\n }\n }\n\n mod set {\n use crate::collections::bounded_vec::BoundedVec;\n\n #[test]\n fn set_updates_values_properly() {\n let mut vec = BoundedVec::from_array([0, 0, 0, 0, 0]);\n\n vec.set(0, 42);\n assert_eq(vec.storage, [42, 0, 0, 0, 0]);\n\n vec.set(1, 43);\n assert_eq(vec.storage, [42, 43, 0, 0, 0]);\n\n vec.set(2, 44);\n assert_eq(vec.storage, [42, 43, 44, 0, 0]);\n\n vec.set(1, 10);\n assert_eq(vec.storage, [42, 10, 44, 0, 0]);\n\n vec.set(0, 0);\n assert_eq(vec.storage, [0, 10, 44, 0, 0]);\n }\n\n #[test(should_fail_with = \"Attempted to write past end of BoundedVec\")]\n fn panics_when_writing_elements_past_end_of_vec() {\n let mut vec: BoundedVec = BoundedVec::new();\n vec.set(0, 42);\n }\n\n #[test(should_fail_with = \"Attempted to write past end of BoundedVec\")]\n fn panics_when_setting_beyond_length() {\n let mut vec: BoundedVec = BoundedVec::from_array([1, 2, 3]);\n vec.set(3, 4);\n }\n\n #[test]\n fn set_unchecked_operations() {\n let mut vec: BoundedVec = BoundedVec::new();\n vec.push(1);\n vec.push(2);\n\n vec.set_unchecked(0, 10);\n assert_eq(vec.get(0), 10);\n }\n\n #[test(should_fail_with = \"Attempted to read past end of BoundedVec\")]\n fn set_unchecked_operations_past_len() {\n let mut vec: BoundedVec = BoundedVec::new();\n vec.push(1);\n vec.push(2);\n\n vec.set_unchecked(3, 40);\n assert_eq(vec.get(3), 40);\n }\n\n #[test]\n fn set_preserves_other_elements() {\n let mut vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4, 5]);\n\n vec.set(2, 30);\n assert_eq(vec.get(0), 1);\n assert_eq(vec.get(1), 2);\n assert_eq(vec.get(2), 30);\n assert_eq(vec.get(3), 4);\n assert_eq(vec.get(4), 5);\n }\n }\n\n mod any {\n use crate::collections::bounded_vec::BoundedVec;\n\n #[test]\n fn returns_false_if_predicate_not_satisfied() {\n let vec: BoundedVec = BoundedVec::from_array([false, false, false, false]);\n let result = vec.any(|value| value);\n\n assert(!result);\n }\n\n #[test]\n fn returns_true_if_predicate_satisfied() {\n let vec: BoundedVec = BoundedVec::from_array([false, false, true, true]);\n let result = vec.any(|value| value);\n\n assert(result);\n }\n\n #[test]\n fn returns_false_on_empty_boundedvec() {\n let vec: BoundedVec = BoundedVec::new();\n let result = vec.any(|value| value);\n\n assert(!result);\n }\n\n #[test]\n fn any_with_complex_predicates() {\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4, 5]);\n\n assert(vec.any(|x| x > 3));\n assert(!vec.any(|x| x > 10));\n assert(vec.any(|x| x % 2 == 0)); // has a even number\n assert(vec.any(|x| x == 3)); // has a specific value\n }\n\n #[test]\n fn any_with_partial_vector() {\n let mut vec: BoundedVec = BoundedVec::new();\n vec.push(1);\n vec.push(2);\n\n assert(vec.any(|x| x == 1));\n assert(vec.any(|x| x == 2));\n assert(!vec.any(|x| x == 3));\n }\n }\n\n mod map {\n use crate::collections::bounded_vec::BoundedVec;\n\n #[test]\n fn applies_function_correctly() {\n // docs:start:bounded-vec-map-example\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);\n let result = vec.map(|value| value * 2);\n // docs:end:bounded-vec-map-example\n let expected = BoundedVec::from_array([2, 4, 6, 8]);\n\n assert_eq(result, expected);\n }\n\n #[test]\n fn applies_function_that_changes_return_type() {\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);\n let result = vec.map(|value| (value * 2) as Field);\n let expected: BoundedVec = BoundedVec::from_array([2, 4, 6, 8]);\n\n assert_eq(result, expected);\n }\n\n #[test]\n fn does_not_apply_function_past_len() {\n let vec: BoundedVec = BoundedVec::from_array([0, 1]);\n let result = vec.map(|value| if value == 0 { 5 } else { value });\n let expected = BoundedVec::from_array([5, 1]);\n\n assert_eq(result, expected);\n assert_eq(result.get_unchecked(2), 0);\n }\n\n #[test]\n fn map_with_conditional_logic() {\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);\n\n let result = vec.map(|x| if x % 2 == 0 { x * 2 } else { x });\n let expected = BoundedVec::from_array([1, 4, 3, 8]);\n assert_eq(result, expected);\n }\n\n #[test]\n fn map_preserves_length() {\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);\n let result = vec.map(|x| x * 2);\n\n assert_eq(result.len(), vec.len());\n assert_eq(result.max_len(), vec.max_len());\n }\n\n #[test]\n fn map_on_empty_vector() {\n let vec: BoundedVec = BoundedVec::new();\n let result = vec.map(|x| x * 2);\n assert_eq(result, vec);\n assert_eq(result.len(), 0);\n assert_eq(result.max_len(), 5);\n }\n }\n\n mod mapi {\n use crate::collections::bounded_vec::BoundedVec;\n\n #[test]\n fn applies_function_correctly() {\n // docs:start:bounded-vec-mapi-example\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);\n let result = vec.mapi(|i, value| i + value * 2);\n // docs:end:bounded-vec-mapi-example\n let expected = BoundedVec::from_array([2, 5, 8, 11]);\n\n assert_eq(result, expected);\n }\n\n #[test]\n fn applies_function_that_changes_return_type() {\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);\n let result = vec.mapi(|i, value| (i + value * 2) as Field);\n let expected: BoundedVec = BoundedVec::from_array([2, 5, 8, 11]);\n\n assert_eq(result, expected);\n }\n\n #[test]\n fn does_not_apply_function_past_len() {\n let vec: BoundedVec = BoundedVec::from_array([0, 1]);\n let result = vec.mapi(|_, value| if value == 0 { 5 } else { value });\n let expected = BoundedVec::from_array([5, 1]);\n\n assert_eq(result, expected);\n assert_eq(result.get_unchecked(2), 0);\n }\n\n #[test]\n fn mapi_with_index_branching_logic() {\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);\n\n let result = vec.mapi(|i, x| if i % 2 == 0 { x * 2 } else { x });\n let expected = BoundedVec::from_array([2, 2, 6, 4]);\n assert_eq(result, expected);\n }\n }\n\n mod for_each {\n use crate::collections::bounded_vec::BoundedVec;\n\n // map in terms of for_each\n fn for_each_map(\n input: BoundedVec,\n f: fn[Env](T) -> U,\n ) -> BoundedVec {\n let mut output = BoundedVec::::new();\n let output_ref = &mut output;\n input.for_each(|x| output_ref.push(f(x)));\n output\n }\n\n #[test]\n fn smoke_test() {\n let mut acc = 0;\n let acc_ref = &mut acc;\n // docs:start:bounded-vec-for-each-example\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3]);\n vec.for_each(|value| { *acc_ref += value; });\n // docs:end:bounded-vec-for-each-example\n assert_eq(acc, 6);\n }\n\n #[test]\n fn applies_function_correctly() {\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);\n let result = for_each_map(vec, |value| value * 2);\n let expected = BoundedVec::from_array([2, 4, 6, 8]);\n\n assert_eq(result, expected);\n }\n\n #[test]\n fn applies_function_that_changes_return_type() {\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);\n let result = for_each_map(vec, |value| (value * 2) as Field);\n let expected: BoundedVec = BoundedVec::from_array([2, 4, 6, 8]);\n\n assert_eq(result, expected);\n }\n\n #[test]\n fn does_not_apply_function_past_len() {\n let vec: BoundedVec = BoundedVec::from_array([0, 1]);\n let result = for_each_map(vec, |value| if value == 0 { 5 } else { value });\n let expected = BoundedVec::from_array([5, 1]);\n\n assert_eq(result, expected);\n assert_eq(result.get_unchecked(2), 0);\n }\n\n #[test]\n fn for_each_on_empty_vector() {\n let vec: BoundedVec = BoundedVec::new();\n let mut count = 0;\n let count_ref = &mut count;\n vec.for_each(|_| { *count_ref += 1; });\n assert_eq(count, 0);\n }\n\n #[test]\n fn for_each_with_side_effects() {\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3]);\n let mut seen = BoundedVec::::new();\n let seen_ref = &mut seen;\n vec.for_each(|x| seen_ref.push(x));\n assert_eq(seen, vec);\n }\n }\n\n mod for_eachi {\n use crate::collections::bounded_vec::BoundedVec;\n\n // mapi in terms of for_eachi\n fn for_eachi_mapi(\n input: BoundedVec,\n f: fn[Env](u32, T) -> U,\n ) -> BoundedVec {\n let mut output = BoundedVec::::new();\n let output_ref = &mut output;\n input.for_eachi(|i, x| output_ref.push(f(i, x)));\n output\n }\n\n #[test]\n fn smoke_test() {\n let mut acc = 0;\n let acc_ref = &mut acc;\n // docs:start:bounded-vec-for-eachi-example\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3]);\n vec.for_eachi(|i, value| { *acc_ref += i * value; });\n // docs:end:bounded-vec-for-eachi-example\n\n // 0 * 1 + 1 * 2 + 2 * 3\n assert_eq(acc, 8);\n }\n\n #[test]\n fn applies_function_correctly() {\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);\n let result = for_eachi_mapi(vec, |i, value| i + value * 2);\n let expected = BoundedVec::from_array([2, 5, 8, 11]);\n\n assert_eq(result, expected);\n }\n\n #[test]\n fn applies_function_that_changes_return_type() {\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);\n let result = for_eachi_mapi(vec, |i, value| (i + value * 2) as Field);\n let expected: BoundedVec = BoundedVec::from_array([2, 5, 8, 11]);\n\n assert_eq(result, expected);\n }\n\n #[test]\n fn does_not_apply_function_past_len() {\n let vec: BoundedVec = BoundedVec::from_array([0, 1]);\n let result = for_eachi_mapi(vec, |_, value| if value == 0 { 5 } else { value });\n let expected = BoundedVec::from_array([5, 1]);\n\n assert_eq(result, expected);\n assert_eq(result.get_unchecked(2), 0);\n }\n\n #[test]\n fn for_eachi_on_empty_vector() {\n let vec: BoundedVec = BoundedVec::new();\n let mut count = 0;\n let count_ref = &mut count;\n vec.for_eachi(|_, _| { *count_ref += 1; });\n assert_eq(count, 0);\n }\n\n #[test]\n fn for_eachi_with_index_tracking() {\n let vec: BoundedVec = BoundedVec::from_array([10, 20, 30]);\n let mut indices = BoundedVec::::new();\n let indices_ref = &mut indices;\n vec.for_eachi(|i, _| indices_ref.push(i));\n\n let expected = BoundedVec::from_array([0, 1, 2]);\n assert_eq(indices, expected);\n }\n\n }\n\n mod from_array {\n use crate::collections::bounded_vec::BoundedVec;\n\n #[test]\n fn empty() {\n let empty_array: [Field; 0] = [];\n let bounded_vec = BoundedVec::from_array([]);\n\n assert_eq(bounded_vec.max_len(), 0);\n assert_eq(bounded_vec.len(), 0);\n assert_eq(bounded_vec.storage(), empty_array);\n }\n\n #[test]\n fn equal_len() {\n let array = [1, 2, 3];\n let bounded_vec = BoundedVec::from_array(array);\n\n assert_eq(bounded_vec.max_len(), 3);\n assert_eq(bounded_vec.len(), 3);\n assert_eq(bounded_vec.storage(), array);\n }\n\n #[test]\n fn max_len_greater_then_array_len() {\n let array = [1, 2, 3];\n let bounded_vec: BoundedVec = BoundedVec::from_array(array);\n\n assert_eq(bounded_vec.max_len(), 10);\n assert_eq(bounded_vec.len(), 3);\n assert_eq(bounded_vec.get(0), 1);\n assert_eq(bounded_vec.get(1), 2);\n assert_eq(bounded_vec.get(2), 3);\n }\n\n #[test(should_fail_with = \"from array out of bounds\")]\n fn max_len_lower_then_array_len() {\n let _: BoundedVec = BoundedVec::from_array([0; 3]);\n }\n\n #[test]\n fn from_array_preserves_order() {\n let array = [5, 3, 1, 4, 2];\n let vec: BoundedVec = BoundedVec::from_array(array);\n for i in 0..array.len() {\n assert_eq(vec.get(i), array[i]);\n }\n }\n\n #[test]\n fn from_array_with_different_types() {\n let bool_array = [true, false, true];\n let bool_vec: BoundedVec = BoundedVec::from_array(bool_array);\n assert_eq(bool_vec.len(), 3);\n assert_eq(bool_vec.get(0), true);\n assert_eq(bool_vec.get(1), false);\n }\n }\n\n mod trait_from {\n use crate::collections::bounded_vec::BoundedVec;\n use crate::convert::From;\n\n #[test]\n fn simple() {\n let array = [1, 2];\n let bounded_vec: BoundedVec = BoundedVec::from(array);\n\n assert_eq(bounded_vec.max_len(), 10);\n assert_eq(bounded_vec.len(), 2);\n assert_eq(bounded_vec.get(0), 1);\n assert_eq(bounded_vec.get(1), 2);\n }\n }\n\n mod trait_eq {\n use crate::collections::bounded_vec::BoundedVec;\n\n #[test]\n fn empty_equality() {\n let mut bounded_vec1: BoundedVec = BoundedVec::new();\n let mut bounded_vec2: BoundedVec = BoundedVec::new();\n\n assert_eq(bounded_vec1, bounded_vec2);\n }\n\n #[test]\n fn inequality() {\n let mut bounded_vec1: BoundedVec = BoundedVec::new();\n let mut bounded_vec2: BoundedVec = BoundedVec::new();\n bounded_vec1.push(1);\n bounded_vec2.push(2);\n\n assert(bounded_vec1 != bounded_vec2);\n }\n }\n\n mod from_parts {\n use crate::collections::bounded_vec::BoundedVec;\n\n #[test]\n fn from_parts() {\n // docs:start:from-parts\n let vec: BoundedVec = BoundedVec::from_parts([1, 2, 3, 0], 3);\n assert_eq(vec.len(), 3);\n\n // Any elements past the given length are zeroed out, so these\n // two BoundedVecs will be completely equal\n let vec1: BoundedVec = BoundedVec::from_parts([1, 2, 3, 1], 3);\n let vec2: BoundedVec = BoundedVec::from_parts([1, 2, 3, 2], 3);\n assert_eq(vec1, vec2);\n // docs:end:from-parts\n }\n\n #[test]\n fn from_parts_unchecked() {\n // docs:start:from-parts-unchecked\n let vec: BoundedVec = BoundedVec::from_parts_unchecked([1, 2, 3, 0], 3);\n assert_eq(vec.len(), 3);\n\n // invalid use!\n let vec1: BoundedVec = BoundedVec::from_parts_unchecked([1, 2, 3, 1], 3);\n let vec2: BoundedVec = BoundedVec::from_parts_unchecked([1, 2, 3, 2], 3);\n\n // both vecs have length 3 so we'd expect them to be equal, but this\n // fails because elements past the length are still checked in eq\n assert(vec1 != vec2);\n // docs:end:from-parts-unchecked\n }\n }\n\n mod push_pop {\n use crate::collections::bounded_vec::BoundedVec;\n\n #[test]\n fn push_and_pop_operations() {\n let mut vec: BoundedVec = BoundedVec::new();\n\n assert_eq(vec.len(), 0);\n\n vec.push(1);\n assert_eq(vec.len(), 1);\n assert_eq(vec.get(0), 1);\n\n vec.push(2);\n assert_eq(vec.len(), 2);\n assert_eq(vec.get(1), 2);\n\n let popped = vec.pop();\n assert_eq(popped, 2);\n assert_eq(vec.len(), 1);\n\n let popped2 = vec.pop();\n assert_eq(popped2, 1);\n assert_eq(vec.len(), 0);\n }\n\n #[test(should_fail_with = \"push out of bounds\")]\n fn push_to_full_vector() {\n let mut vec: BoundedVec = BoundedVec::new();\n vec.push(1);\n vec.push(2);\n vec.push(3); // should panic\n }\n\n #[test(should_fail_with = \"cannot pop from an empty vector\")]\n fn pop_from_empty_vector() {\n let mut vec: BoundedVec = BoundedVec::new();\n let _ = vec.pop(); // should panic\n }\n\n #[test]\n fn push_pop_cycle() {\n let mut vec: BoundedVec = BoundedVec::new();\n\n // push to full\n vec.push(1);\n vec.push(2);\n vec.push(3);\n assert_eq(vec.len(), 3);\n\n // pop all\n assert_eq(vec.pop(), 3);\n assert_eq(vec.pop(), 2);\n assert_eq(vec.pop(), 1);\n assert_eq(vec.len(), 0);\n\n // push again\n vec.push(4);\n assert_eq(vec.len(), 1);\n assert_eq(vec.get(0), 4);\n }\n }\n\n mod extend {\n use crate::collections::bounded_vec::BoundedVec;\n\n #[test]\n fn extend_from_array() {\n let mut vec: BoundedVec = BoundedVec::new();\n vec.push(1);\n vec.extend_from_array([2, 3]);\n\n assert_eq(vec.len(), 3);\n assert_eq(vec.get(0), 1);\n assert_eq(vec.get(1), 2);\n assert_eq(vec.get(2), 3);\n }\n\n #[test]\n fn extend_from_slice() {\n let mut vec: BoundedVec = BoundedVec::new();\n vec.push(1);\n vec.extend_from_slice(&[2, 3]);\n\n assert_eq(vec.len(), 3);\n assert_eq(vec.get(0), 1);\n assert_eq(vec.get(1), 2);\n assert_eq(vec.get(2), 3);\n }\n\n #[test]\n fn extend_from_bounded_vec() {\n let mut vec1: BoundedVec = BoundedVec::new();\n let mut vec2: BoundedVec = BoundedVec::new();\n\n vec1.push(1);\n vec2.push(2);\n vec2.push(3);\n\n vec1.extend_from_bounded_vec(vec2);\n\n assert_eq(vec1.len(), 3);\n assert_eq(vec1.get(0), 1);\n assert_eq(vec1.get(1), 2);\n assert_eq(vec1.get(2), 3);\n }\n\n #[test(should_fail_with = \"extend_from_array out of bounds\")]\n fn extend_array_beyond_max_len() {\n let mut vec: BoundedVec = BoundedVec::new();\n vec.push(1);\n vec.extend_from_array([2, 3, 4]); // should panic\n }\n\n #[test(should_fail_with = \"extend_from_slice out of bounds\")]\n fn extend_slice_beyond_max_len() {\n let mut vec: BoundedVec = BoundedVec::new();\n vec.push(1);\n vec.extend_from_slice(&[2, 3, 4]); // S]should panic\n }\n\n #[test(should_fail_with = \"extend_from_bounded_vec out of bounds\")]\n fn extend_bounded_vec_beyond_max_len() {\n let mut vec: BoundedVec = BoundedVec::new();\n let other: BoundedVec = BoundedVec::from_array([1, 2, 3, 4, 5]);\n vec.extend_from_bounded_vec(other); // should panic\n }\n\n #[test]\n fn extend_with_empty_collections() {\n let mut vec: BoundedVec = BoundedVec::new();\n let original_len = vec.len();\n\n vec.extend_from_array([]);\n assert_eq(vec.len(), original_len);\n\n vec.extend_from_slice(&[]);\n assert_eq(vec.len(), original_len);\n\n let empty: BoundedVec = BoundedVec::new();\n vec.extend_from_bounded_vec(empty);\n assert_eq(vec.len(), original_len);\n }\n }\n\n mod storage {\n use crate::collections::bounded_vec::BoundedVec;\n\n #[test]\n fn storage_consistency() {\n let mut vec: BoundedVec = BoundedVec::new();\n\n // test initial storage state\n assert_eq(vec.storage(), [0, 0, 0, 0, 0]);\n\n vec.push(1);\n vec.push(2);\n\n // test storage after modifications\n assert_eq(vec.storage(), [1, 2, 0, 0, 0]);\n\n // storage doesn't change length\n assert_eq(vec.len(), 2);\n assert_eq(vec.max_len(), 5);\n }\n\n #[test]\n fn storage_after_pop() {\n let mut vec: BoundedVec = BoundedVec::from_array([1, 2, 3]);\n\n let _ = vec.pop();\n // after pop, the last element should be zeroed\n assert_eq(vec.storage(), [1, 2, 0]);\n assert_eq(vec.len(), 2);\n }\n\n #[test]\n fn vector_immutable() {\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3]);\n let storage = vec.storage();\n\n assert_eq(storage, [1, 2, 3]);\n\n // Verify that the original vector is unchanged\n assert_eq(vec.len(), 3);\n assert_eq(vec.get(0), 1);\n assert_eq(vec.get(1), 2);\n assert_eq(vec.get(2), 3);\n }\n }\n}\n" + }, + "61": { + "path": "/home/ubuntu/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.20251212/noir-projects/aztec-nr/aztec/src/capsules/mod.nr", + "source": "use crate::oracle::capsules;\nuse protocol_types::{address::AztecAddress, traits::{Deserialize, Serialize}};\n\n/// A dynamically sized array backed by PXE's non-volatile database (called capsules). Values are persisted until\n/// deleted, so they can be e.g. stored during simulation of a transaction and later retrieved during witness\n/// generation. All values are scoped per contract address, so external contracts cannot access them.\npub struct CapsuleArray {\n contract_address: AztecAddress,\n /// The base slot is where the array length is stored in capsules. Array elements are stored in consecutive slots\n /// after the base slot. For example, with base slot 5: the length is at slot 5, the first element (index 0) is at\n /// slot 6, the second element (index 1) is at slot 7, and so on.\n base_slot: Field,\n}\n\nimpl CapsuleArray {\n /// Returns a CapsuleArray connected to a contract's capsules at a base slot. Array elements are stored in\n /// contiguous slots following the base slot, so there should be sufficient space between array base slots to\n /// accommodate elements. A reasonable strategy is to make the base slot a hash of a unique value.\n pub unconstrained fn at(contract_address: AztecAddress, base_slot: Field) -> Self {\n Self { contract_address, base_slot }\n }\n\n /// Returns the number of elements stored in the array.\n pub unconstrained fn len(self) -> u32 {\n // An uninitialized array defaults to a length of 0.\n capsules::load(self.contract_address, self.base_slot).unwrap_or(0) as u32\n }\n\n /// Stores a value at the end of the array.\n pub unconstrained fn push(self, value: T)\n where\n T: Serialize,\n {\n let current_length = self.len();\n\n // The slot corresponding to the index `current_length` is the first slot immediately after the end of the\n // array, which is where we want to place the new value.\n capsules::store(self.contract_address, self.slot_at(current_length), value);\n\n // Then we simply update the length.\n let new_length = current_length + 1;\n capsules::store(self.contract_address, self.base_slot, new_length);\n }\n\n /// Retrieves the value stored in the array at `index`. Throws if the index is out of bounds.\n pub unconstrained fn get(self, index: u32) -> T\n where\n T: Deserialize,\n {\n assert(index < self.len(), \"Attempted to read past the length of a CapsuleArray\");\n\n capsules::load(self.contract_address, self.slot_at(index)).unwrap()\n }\n\n /// Deletes the value stored in the array at `index`. Throws if the index is out of bounds.\n pub unconstrained fn remove(self, index: u32) {\n let current_length = self.len();\n assert(index < current_length, \"Attempted to delete past the length of a CapsuleArray\");\n\n // In order to be able to remove elements at arbitrary indices, we need to shift the entire contents of the\n // array past the removed element one slot backward so that we don't end up with a gap and preserve the\n // contiguous slots. We can skip this when deleting the last element however.\n if index != current_length - 1 {\n // The source and destination regions overlap, but `copy` supports this.\n capsules::copy(\n self.contract_address,\n self.slot_at(index + 1),\n self.slot_at(index),\n current_length - index - 1,\n );\n }\n\n // We can now delete the last element (which has either been copied to the slot immediately before it, or was\n // the element we meant to delete in the first place) and update the length.\n capsules::delete(self.contract_address, self.slot_at(current_length - 1));\n capsules::store(self.contract_address, self.base_slot, current_length - 1);\n }\n\n /// Iterates over the entire array, calling the callback with all values and their array index. The order in which\n /// values are processed is arbitrary.\n ///\n /// It is safe to delete the current element (and only the current element) from inside the callback via `remove`:\n /// ```noir\n /// array.for_each(|index, value| {\n /// if some_condition(value) {\n /// array.remove(index); // safe only for this index\n /// }\n /// }\n /// ```\n ///\n /// If all elements in the array need to iterated over and then removed, then using `for_each` results in optimal\n /// efficiency.\n ///\n /// It is **not** safe to push new elements into the array from inside the callback.\n pub unconstrained fn for_each(self, f: unconstrained fn[Env](u32, T) -> ())\n where\n T: Deserialize,\n {\n // Iterating over all elements is simple, but we want to do it in such a way that a) deleting the current\n // element is safe to do, and b) deleting *all* elements is optimally efficient. This is because CapsuleArrays\n // are typically used to hold pending tasks, so iterating them while clearing completed tasks (sometimes\n // unconditionally, resulting in a full clear) is a very common access pattern.\n //\n // The way we achieve this is by iterating backwards: each element can always be deleted since it won't change\n // any preceding (lower) indices, and if every element is deleted then every element will (in turn) be the last\n // element. This results in an optimal full clear since `remove` will be able to skip the `capsules::copy` call\n // to shift any elements past the deleted one (because there will be none).\n let mut i = self.len();\n while i > 0 {\n i -= 1;\n f(i, self.get(i));\n }\n }\n\n unconstrained fn slot_at(self, index: u32) -> Field {\n // Elements are stored immediately after the base slot, so we add 1 to it to compute the slot for the first\n // element.\n self.base_slot + 1 + index as Field\n }\n}\n\nmod test {\n use crate::test::helpers::test_environment::TestEnvironment;\n use super::CapsuleArray;\n\n global SLOT: Field = 1230;\n\n #[test]\n unconstrained fn empty_array() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n\n let array: CapsuleArray = CapsuleArray::at(contract_address, SLOT);\n assert_eq(array.len(), 0);\n });\n }\n\n #[test(should_fail_with = \"Attempted to read past the length of a CapsuleArray\")]\n unconstrained fn empty_array_read() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n\n let array = CapsuleArray::at(contract_address, SLOT);\n let _: Field = array.get(0);\n });\n }\n\n #[test]\n unconstrained fn array_push() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n\n let array = CapsuleArray::at(contract_address, SLOT);\n array.push(5);\n\n assert_eq(array.len(), 1);\n assert_eq(array.get(0), 5);\n });\n }\n\n #[test(should_fail_with = \"Attempted to read past the length of a CapsuleArray\")]\n unconstrained fn read_past_len() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n\n let array = CapsuleArray::at(contract_address, SLOT);\n array.push(5);\n\n let _ = array.get(1);\n });\n }\n\n #[test]\n unconstrained fn array_remove_last() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n\n let array = CapsuleArray::at(contract_address, SLOT);\n\n array.push(5);\n array.remove(0);\n\n assert_eq(array.len(), 0);\n });\n }\n\n #[test]\n unconstrained fn array_remove_some() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n\n let array = CapsuleArray::at(contract_address, SLOT);\n\n array.push(7);\n array.push(8);\n array.push(9);\n\n assert_eq(array.len(), 3);\n assert_eq(array.get(0), 7);\n assert_eq(array.get(1), 8);\n assert_eq(array.get(2), 9);\n\n array.remove(1);\n\n assert_eq(array.len(), 2);\n assert_eq(array.get(0), 7);\n assert_eq(array.get(1), 9);\n });\n }\n\n #[test]\n unconstrained fn array_remove_all() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n\n let array = CapsuleArray::at(contract_address, SLOT);\n\n array.push(7);\n array.push(8);\n array.push(9);\n\n array.remove(1);\n array.remove(1);\n array.remove(0);\n\n assert_eq(array.len(), 0);\n });\n }\n\n #[test]\n unconstrained fn for_each_called_with_all_elements() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n let array = CapsuleArray::at(contract_address, SLOT);\n\n array.push(4);\n array.push(5);\n array.push(6);\n\n // We store all values that we were called with and check that all (value, index) tuples are present. Note that\n // we do not care about the order in which each tuple was passed to the closure.\n let called_with = &mut BoundedVec::<(u32, Field), 3>::new();\n array.for_each(|index, value| { called_with.push((index, value)); });\n\n assert_eq(called_with.len(), 3);\n assert(called_with.any(|(index, value)| (index == 0) & (value == 4)));\n assert(called_with.any(|(index, value)| (index == 1) & (value == 5)));\n assert(called_with.any(|(index, value)| (index == 2) & (value == 6)));\n });\n }\n\n #[test]\n unconstrained fn for_each_remove_some() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n let array = CapsuleArray::at(contract_address, SLOT);\n\n array.push(4);\n array.push(5);\n array.push(6);\n\n array.for_each(|index, _| {\n if index == 1 {\n array.remove(index);\n }\n });\n\n assert_eq(array.len(), 2);\n assert_eq(array.get(0), 4);\n assert_eq(array.get(1), 6);\n });\n }\n\n #[test]\n unconstrained fn for_each_remove_all() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n let array = CapsuleArray::at(contract_address, SLOT);\n\n array.push(4);\n array.push(5);\n array.push(6);\n\n array.for_each(|index, _| { array.remove(index); });\n\n assert_eq(array.len(), 0);\n });\n }\n\n #[test]\n unconstrained fn for_each_remove_all_no_copy() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n let array = CapsuleArray::at(contract_address, SLOT);\n\n array.push(4);\n array.push(5);\n array.push(6);\n\n // We test that the utilityCopyCapsule was never called, which is the expensive operation we want to avoid.\n let mock = std::test::OracleMock::mock(\"utilityCopyCapsule\");\n\n array.for_each(|index, _| { array.remove(index); });\n\n assert_eq(mock.times_called(), 0);\n });\n }\n}\n" + }, + "62": { + "path": "/home/ubuntu/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.20251212/noir-projects/aztec-nr/aztec/src/context/calls.nr", + "source": "use dep::protocol_types::{\n abis::function_selector::FunctionSelector,\n address::AztecAddress,\n traits::{Deserialize, ToField},\n};\n\nuse crate::context::{gas::GasOpts, private_context::PrivateContext, public_context::PublicContext};\nuse crate::hash::{hash_args, hash_calldata_array};\nuse crate::oracle::execution_cache;\n\n// PrivateCall\n\n#[must_use = \"Your private call needs to be passed into the `self.call(...)` method to be executed (e.g. `self.call(MyContract::at(address).my_private_function(...args))`\"]\npub struct PrivateCall {\n pub target_contract: AztecAddress,\n pub selector: FunctionSelector,\n pub name: str,\n args_hash: Field,\n pub args: [Field; N],\n return_type: T,\n}\n\nimpl PrivateCall {\n pub fn new(\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args: [Field; N],\n ) -> Self {\n let args_hash = hash_args(args);\n Self { target_contract, selector, name, args_hash, args, return_type: std::mem::zeroed() }\n }\n}\n\nimpl PrivateCall\nwhere\n T: Deserialize,\n{\n /// **[DEPRECATED]**\n /// This function is deprecated. Please use the new contract API:\n /// `self.call(MyContract::at(address).my_private_function(...args))`\n /// instead of manually constructing and calling `PrivateCall`.\n pub fn call(self, context: &mut PrivateContext) -> T {\n execution_cache::store(self.args, self.args_hash);\n let returns_hash = context.call_private_function_with_args_hash(\n self.target_contract,\n self.selector,\n self.args_hash,\n false,\n );\n\n // If T is () (i.e. if the function does not return anything) then `get_preimage` will constrain that the\n // returns hash is empty as per the protocol rules.\n returns_hash.get_preimage()\n }\n}\n\n// PrivateStaticCall\n\n#[must_use = \"Your private static call needs to be passed into the `self.view(...)` method to be executed (e.g. `self.view(MyContract::at(address).my_private_static_function(...args))`\"]\npub struct PrivateStaticCall {\n pub target_contract: AztecAddress,\n pub selector: FunctionSelector,\n pub name: str,\n args_hash: Field,\n pub args: [Field; N],\n return_type: T,\n}\n\nimpl PrivateStaticCall {\n pub fn new(\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args: [Field; N],\n ) -> Self {\n let args_hash = hash_args(args);\n Self { target_contract, selector, name, args_hash, args, return_type: std::mem::zeroed() }\n }\n\n /// **[DEPRECATED]**\n /// This function is deprecated. Please use the new contract API:\n /// `self.view(MyContract::at(address).my_private_static_function(...args))`\n /// instead of manually constructing and calling `PrivateCall`.\n pub fn view(self, context: &mut PrivateContext) -> T\n where\n T: Deserialize,\n {\n execution_cache::store(self.args, self.args_hash);\n let returns = context.call_private_function_with_args_hash(\n self.target_contract,\n self.selector,\n self.args_hash,\n true,\n );\n returns.get_preimage()\n }\n}\n\n// PublicCall\n\n#[must_use = \"Your public call needs to be passed into the `self.call(...)`, `self.enqueue(...)` or `self.enqueue_incognito(...)` method to be executed (e.g. `self.call(MyContract::at(address).my_public_function(...args))`\"]\npub struct PublicCall {\n pub target_contract: AztecAddress,\n pub selector: FunctionSelector,\n pub name: str,\n pub args: [Field; N],\n gas_opts: GasOpts,\n return_type: T,\n}\n\nimpl PublicCall {\n pub fn new(\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args: [Field; N],\n ) -> Self {\n Self {\n target_contract,\n selector,\n name,\n args,\n gas_opts: GasOpts::default(),\n return_type: std::mem::zeroed(),\n }\n }\n\n pub fn with_gas(mut self, gas_opts: GasOpts) -> Self {\n self.gas_opts = gas_opts;\n self\n }\n\n /// **[DEPRECATED]**\n /// This function is deprecated. Please use the new contract API:\n /// `self.call(MyContract::at(address).my_public_function(...args))`\n /// instead of manually constructing and calling `PublicCall`.\n pub unconstrained fn call(self, context: PublicContext) -> T\n where\n T: Deserialize,\n {\n let returns = context.call_public_function(\n self.target_contract,\n self.selector,\n self.args,\n self.gas_opts,\n );\n // If T is () (i.e. if the function does not return anything) then `as_array` will constrain that `returns` has\n // a length of 0 (since that is ()'s deserialization length).\n Deserialize::deserialize(returns.as_array())\n }\n\n /// **[DEPRECATED]**\n /// This function is deprecated. Please use the new contract API:\n /// `self.enqueue(MyContract::at(address).my_public_function(...args))`\n /// instead of manually constructing and calling `PublicCall`.\n pub fn enqueue(self, context: &mut PrivateContext) {\n self.enqueue_impl(context, false, false)\n }\n\n /// **[DEPRECATED]**\n /// This function is deprecated. Please use the new contract API:\n /// `self.enqueue_incognito(MyContract::at(address).my_public_function(...args))`\n /// instead of manually constructing and calling `PublicCall`.\n pub fn enqueue_incognito(self, context: &mut PrivateContext) {\n self.enqueue_impl(context, false, true)\n }\n\n fn enqueue_impl(\n self,\n context: &mut PrivateContext,\n is_static_call: bool,\n hide_msg_sender: bool,\n ) {\n let calldata = [self.selector.to_field()].concat(self.args);\n let calldata_hash = hash_calldata_array(calldata);\n execution_cache::store(calldata, calldata_hash);\n context.call_public_function_with_calldata_hash(\n self.target_contract,\n calldata_hash,\n is_static_call,\n hide_msg_sender,\n )\n }\n\n /// **[DEPRECATED]**\n /// This function is deprecated. Please use the new contract API:\n /// `self.set_as_teardown(MyContract::at(address).my_public_function(...args))`\n /// instead of manually constructing and setting the teardown function `PublicCall`.\n pub fn set_as_teardown(self, context: &mut PrivateContext) {\n self.set_as_teardown_impl(context, false);\n }\n\n /// **[DEPRECATED]**\n /// This function is deprecated. Please use the new contract API:\n /// `self.set_as_teardown_incognito(MyContract::at(address).my_public_function(...args))`\n /// instead of manually constructing and setting the teardown function `PublicCall`.\n pub fn set_as_teardown_incognito(self, context: &mut PrivateContext) {\n self.set_as_teardown_impl(context, true);\n }\n\n fn set_as_teardown_impl(self, context: &mut PrivateContext, hide_msg_sender: bool) {\n let calldata = [self.selector.to_field()].concat(self.args);\n let calldata_hash = hash_calldata_array(calldata);\n execution_cache::store(calldata, calldata_hash);\n context.set_public_teardown_function_with_calldata_hash(\n self.target_contract,\n calldata_hash,\n false,\n hide_msg_sender,\n )\n }\n}\n\n// PublicStaticCall\n\n#[must_use = \"Your public static call needs to be passed into the `self.view(...)`, `self.enqueue_view(...)` or `self.enqueue_view_incognito(...)` method to be executed (e.g. `self.view(MyContract::at(address).my_public_static_function(...args))`\"]\npub struct PublicStaticCall {\n pub target_contract: AztecAddress,\n pub selector: FunctionSelector,\n pub name: str,\n pub args: [Field; N],\n return_type: T,\n gas_opts: GasOpts,\n}\n\nimpl PublicStaticCall {\n pub fn new(\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args: [Field; N],\n ) -> Self {\n Self {\n target_contract,\n selector,\n name,\n args,\n return_type: std::mem::zeroed(),\n gas_opts: GasOpts::default(),\n }\n }\n\n pub fn with_gas(mut self, gas_opts: GasOpts) -> Self {\n self.gas_opts = gas_opts;\n self\n }\n\n /// **[DEPRECATED]**\n /// This function is deprecated. Please use the new contract API:\n /// `self.view(MyContract::at(address).my_public_static_function(...args))`\n /// instead of manually constructing and calling `PublicStaticCall`.\n pub unconstrained fn view(self, context: PublicContext) -> T\n where\n T: Deserialize,\n {\n let returns = context.static_call_public_function(\n self.target_contract,\n self.selector,\n self.args,\n self.gas_opts,\n );\n Deserialize::deserialize(returns.as_array())\n }\n\n /// **[DEPRECATED]**\n /// This function is deprecated. Please use the new contract API:\n /// `self.enqueue_view(MyContract::at(address).my_public_static_function(...args))`\n /// instead of manually constructing and calling `PublicStaticCall`.\n pub fn enqueue_view(self, context: &mut PrivateContext) {\n let calldata = [self.selector.to_field()].concat(self.args);\n let calldata_hash = hash_calldata_array(calldata);\n execution_cache::store(calldata, calldata_hash);\n context.call_public_function_with_calldata_hash(\n self.target_contract,\n calldata_hash,\n /*static=*/\n true,\n false,\n )\n }\n\n /// **[DEPRECATED]**\n /// This function is deprecated. Please use the new contract API:\n /// `self.enqueue_view_incognito(MyContract::at(address).my_public_static_function(...args))`\n /// instead of manually constructing and calling `PublicStaticCall`.\n pub fn enqueue_view_incognito(self, context: &mut PrivateContext) {\n let calldata = [self.selector.to_field()].concat(self.args);\n let calldata_hash = hash_calldata_array(calldata);\n execution_cache::store(calldata, calldata_hash);\n context.call_public_function_with_calldata_hash(\n self.target_contract,\n calldata_hash,\n /*static=*/\n true,\n true,\n )\n }\n}\n\n// UtilityCall\n\npub struct UtilityCall {\n pub target_contract: AztecAddress,\n pub selector: FunctionSelector,\n pub name: str,\n args_hash: Field,\n pub args: [Field; N],\n return_type: T,\n}\n\nimpl UtilityCall {\n pub fn new(\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args: [Field; N],\n ) -> Self {\n let args_hash = hash_args(args);\n Self { target_contract, selector, name, args_hash, args, return_type: std::mem::zeroed() }\n }\n}\n" + }, + "69": { + "path": "/home/ubuntu/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.20251212/noir-projects/aztec-nr/aztec/src/context/note_hash_read.nr", + "source": "use protocol_types::address::aztec_address::AztecAddress;\n\npub struct NoteHashRead {\n note_hash: Field,\n contract_address: Option,\n}\n\nimpl NoteHashRead {\n pub fn new_transient(note_hash: Field, contract_address: AztecAddress) -> Self {\n assert(\n !contract_address.is_zero(),\n \"Can't read a transient note with a zero contract address\",\n );\n Self { note_hash, contract_address: Option::some(contract_address) }\n }\n\n pub fn new_settled(note_hash: Field) -> Self {\n Self { note_hash, contract_address: Option::none() }\n }\n\n pub fn note_hash(self) -> Field {\n self.note_hash\n }\n\n pub fn contract_address(self) -> Option {\n self.contract_address\n }\n}\n" + }, + "71": { + "path": "/home/ubuntu/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.20251212/noir-projects/aztec-nr/aztec/src/context/public_context.nr", + "source": "use crate::context::gas::GasOpts;\nuse crate::hash::{\n compute_l1_to_l2_message_hash, compute_l1_to_l2_message_nullifier, compute_secret_hash,\n};\nuse dep::protocol_types::abis::function_selector::FunctionSelector;\nuse dep::protocol_types::address::{AztecAddress, EthAddress};\nuse dep::protocol_types::constants::{MAX_U32_VALUE, NULL_MSG_SENDER_CONTRACT_ADDRESS};\nuse dep::protocol_types::traits::{Empty, FromField, Packable, Serialize, ToField};\n\n/// # PublicContext\n///\n/// The **main interface** between an #[external(\"public\")] function and the Aztec blockchain.\n///\n/// An instance of the PublicContext is initialized automatically at the outset\n/// of every public function, within the #[external(\"public\")] macro, so you'll never\n/// need to consciously instantiate this yourself.\n///\n/// The instance is always named `context`, and it will always be available\n/// within the body of every #[external(\"public\")] function in your smart contract.\n///\n/// Typical usage for a smart contract developer will be to call getter\n/// methods of the PublicContext.\n///\n/// _Pushing_ data and requests to the context is mostly handled within\n/// aztec-nr's own functions, so typically a smart contract developer won't\n/// need to call any setter methods directly.\n///\n/// ## Responsibilities\n/// - Exposes contextual data to a public function:\n/// - Data relating to how this public function was called:\n/// - msg_sender, this_address\n/// - Data relating to the current blockchain state:\n/// - timestamp, block_number, chain_id, version\n/// - Gas and fee information\n/// - Provides state access:\n/// - Read/write public storage (key-value mapping)\n/// - Check existence of notes and nullifiers\n/// (Some patterns use notes & nullifiers to store public (not private)\n/// information)\n/// - Enables consumption of L1->L2 messages.\n/// - Enables calls to other public smart contract functions:\n/// - Writes data to the blockchain:\n/// - Updates to public state variables\n/// - New public logs (for events)\n/// - New L2->L1 messages\n/// - New notes & nullifiers\n/// (E.g. pushing public info to notes/nullifiers, or for completing\n/// \"partial notes\")\n///\n/// ## Key Differences from Private Execution\n///\n/// Unlike private functions -- which are executed on the user's device and which\n/// can only reference historic state -- public functions are executed by a block\n/// proposer and are executed \"live\" on the _current_ tip of the chain.\n/// This means public functions can:\n/// - Read and write _current_ public state\n/// - Immediately see the effects of earlier transactions in the same block\n///\n/// Also, public functions are executed within a zkVM (the \"AVM\"), so that they\n/// can _revert_ whilst still ensuring payment to the proposer and prover.\n/// (Private functions cannot revert: they either succeed, or they cannot be\n/// included).\n///\n/// ## Optimising Public Functions\n///\n/// Using the AVM to execute public functions means they compile down to \"AVM\n/// bytecode\" instead of the ACIR that private functions (standalone circuits)\n/// compile to. Therefore the approach to optimising a public function is\n/// fundamentally different from optimising a public function.\n///\npub struct PublicContext {\n pub args_hash: Option,\n pub compute_args_hash: fn() -> Field,\n}\n\nimpl Eq for PublicContext {\n fn eq(self, other: Self) -> bool {\n (self.args_hash == other.args_hash)\n // Can't compare the function compute_args_hash\n }\n}\n\nimpl PublicContext {\n /// Creates a new PublicContext instance.\n ///\n /// Low-level function: This is called automatically by the #[external(\"public\")]\n /// macro, so you shouldn't need to be called directly by smart contract\n /// developers.\n ///\n /// # Arguments\n /// * `compute_args_hash` - Function to compute the args_hash\n ///\n /// # Returns\n /// * A new PublicContext instance\n ///\n pub fn new(compute_args_hash: fn() -> Field) -> Self {\n PublicContext { args_hash: Option::none(), compute_args_hash }\n }\n\n /// Emits a _public_ log that will be visible onchain to everyone.\n ///\n /// # Arguments\n /// * `log` - The data to log, must implement Serialize trait\n ///\n pub fn emit_public_log(_self: Self, log: T)\n where\n T: Serialize,\n {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe { emit_public_log(Serialize::serialize(log).as_slice()) };\n }\n\n /// Checks if a given note hash exists in the note hash tree at a particular\n /// leaf_index.\n ///\n /// # Arguments\n /// * `note_hash` - The note hash to check for existence\n /// * `leaf_index` - The index where the note hash should be located\n ///\n /// # Returns\n /// * `bool` - True if the note hash exists at the specified index\n ///\n pub fn note_hash_exists(_self: Self, note_hash: Field, leaf_index: u64) -> bool {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe { note_hash_exists(note_hash, leaf_index) } == 1\n }\n\n /// Checks if a specific L1-to-L2 message exists in the L1-to-L2 message\n /// tree at a particular leaf index.\n ///\n /// Common use cases include token bridging, cross-chain governance, and\n /// triggering L2 actions based on L1 events.\n ///\n /// This function should be called before attempting to consume an L1-to-L2\n /// message.\n ///\n /// # Arguments\n /// * `msg_hash` - Hash of the L1-to-L2 message to check\n /// * `msg_leaf_index` - The index where the message should be located\n ///\n /// # Returns\n /// * `bool` - True if the message exists at the specified index\n ///\n /// # Advanced\n /// * Uses the AVM l1_to_l2_msg_exists opcode for tree lookup\n /// * Messages are copied from L1 Inbox to L2 by block proposers\n ///\n pub fn l1_to_l2_msg_exists(_self: Self, msg_hash: Field, msg_leaf_index: Field) -> bool {\n // Safety: AVM opcodes are constrained by the AVM itself\n // TODO(alvaro): Make l1l2msg leaf index a u64 upstream\n unsafe { l1_to_l2_msg_exists(msg_hash, msg_leaf_index as u64) } == 1\n }\n\n /// Checks if a specific nullifier has been emitted by a given contract.\n ///\n /// Whilst nullifiers are primarily intended as a _privacy-preserving_\n /// record of a one-time action, they can also be used to efficiently\n /// record _public_ one-time actions too. An example is to check\n /// whether a contract has been published: we emit a nullifier that is\n /// deterministic, but whose preimage is _not_ private. This is more\n /// efficient than using mutable storage, and can be done directly\n /// from a private function.\n ///\n /// Nullifiers can be tested for non-existence in public, which is not the\n /// case in private. Because private functions do not have access to\n /// the tip of the blockchain (but only the anchor block they are built\n /// at) they can only prove nullifier non-existence in the past. But between\n /// an anchor block and the block in which a tx is included, the nullifier\n /// might have been inserted into the nullifier tree by some other\n /// transaction.\n /// Public functions _do_ have access to the tip of the state, and so\n /// this pattern is safe.\n ///\n /// # Arguments\n /// * `unsiloed_nullifier` - The raw nullifier value (before siloing with\n /// the contract address that emitted it).\n /// * `address` - The claimed contract address that emitted the nullifier\n ///\n /// # Returns\n /// * `bool` - True if the nullifier has been emitted by the specified contract\n ///\n pub fn nullifier_exists(_self: Self, unsiloed_nullifier: Field, address: AztecAddress) -> bool {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe { nullifier_exists(unsiloed_nullifier, address.to_field()) } == 1\n }\n\n /// Consumes a message sent from Ethereum (L1) to Aztec (L2) -- effectively\n /// marking it as \"read\".\n ///\n /// Use this function if you only want the message to ever be \"referred to\"\n /// once. Once consumed using this method, the message cannot be consumed\n /// again, because a nullifier is emitted.\n /// If your use case wants for the message to be read unlimited times, then\n /// you can always read any historic message from the L1-to-L2 messages tree,\n /// using the `l1_to_l2_msg_exists` method. Messages never technically get\n /// deleted from that tree.\n ///\n /// The message will first be inserted into an Aztec \"Inbox\" smart contract\n /// on L1. It will not be available for consumption immediately. Messages\n /// get copied-over from the L1 Inbox to L2 by the next Proposer in batches.\n /// So you will need to wait until the messages are copied before you can\n /// consume them.\n ///\n /// # Arguments\n /// * `content` - The message content that was sent from L1\n /// * `secret` - Secret value used for message privacy (if needed)\n /// * `sender` - Ethereum address that sent the message\n /// * `leaf_index` - Index of the message in the L1-to-L2 message tree\n ///\n /// # Advanced\n /// * Validates message existence in the L1-to-L2 message tree\n /// * Prevents double-consumption by emitting a nullifier\n /// * Message hash is computed from all parameters + chain context\n /// * Will revert if message doesn't exist or was already consumed\n ///\n pub fn consume_l1_to_l2_message(\n self: 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_l1_to_l2_message_hash(\n sender,\n self.chain_id(),\n /*recipient=*/\n self.this_address(),\n self.version(),\n content,\n secret_hash,\n leaf_index,\n );\n let nullifier = compute_l1_to_l2_message_nullifier(message_hash, secret);\n\n assert(\n !self.nullifier_exists(nullifier, self.this_address()),\n \"L1-to-L2 message is already nullified\",\n );\n assert(\n self.l1_to_l2_msg_exists(message_hash, leaf_index),\n \"Tried to consume nonexistent L1-to-L2 message\",\n );\n\n self.push_nullifier(nullifier);\n }\n\n /// Sends an \"L2 -> L1 message\" from this function (Aztec, L2) to a smart\n /// contract on Ethereum (L1). L1 contracts which are designed to\n /// send/receive messages to/from Aztec are called \"Portal Contracts\".\n ///\n /// Common use cases include withdrawals, cross-chain asset transfers, and\n /// triggering L1 actions based on L2 state changes.\n ///\n /// The message will be inserted into an Aztec \"Outbox\" contract on L1,\n /// when this transaction's block is proposed to L1.\n /// Sending the message will not result in any immediate state changes in\n /// the target portal contract. The message will need to be manually\n /// consumed from the Outbox through a separate Ethereum transaction: a user\n /// will need to call a function of the portal contract -- a function\n /// specifically designed to make a call to the Outbox to consume the\n /// message.\n /// The message will only be available for consumption once the _epoch_\n /// proof has been submitted. Given that there are multiple Aztec blocks\n /// within an epoch, it might take some time for this epoch proof to be\n /// submitted -- especially if the block was near the start of an epoch.\n ///\n /// # Arguments\n /// * `recipient` - Ethereum address that will receive the message\n /// * `content` - Message content (32 bytes as a Field element)\n ///\n pub fn message_portal(_self: Self, recipient: EthAddress, content: Field) {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe { send_l2_to_l1_msg(recipient, content) };\n }\n\n /// Calls a public function on another contract.\n ///\n /// Will revert if the called function reverts or runs out of gas.\n ///\n /// # Arguments\n /// * `contract_address` - Address of the contract to call\n /// * `function_selector` - Function to call on the target contract\n /// * `args` - Arguments to pass to the function\n /// * `gas_opts` - An optional allocation of gas to the called function.\n ///\n /// # Returns\n /// * `[Field]` - Return data from the called function\n ///\n pub unconstrained fn call_public_function(\n _self: Self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; N],\n gas_opts: GasOpts,\n ) -> [Field] {\n let calldata = [function_selector.to_field()].concat(args);\n\n call(\n gas_opts.l2_gas.unwrap_or(MAX_U32_VALUE),\n gas_opts.da_gas.unwrap_or(MAX_U32_VALUE),\n contract_address,\n calldata,\n );\n // Use success_copy to determine whether the call succeeded\n let success = success_copy();\n\n let result_data = returndata_copy(0, returndata_size());\n if !success {\n // Rethrow the revert data.\n avm_revert(result_data);\n }\n result_data\n }\n\n /// Makes a read-only call to a public function on another contract.\n ///\n /// This is similar to Solidity's `staticcall`. The called function\n /// cannot modify state or emit events. Any nested calls are constrained to\n /// also be staticcalls.\n ///\n /// Useful for querying data from other contracts safely.\n ///\n /// Will revert if the called function reverts or runs out of gas.\n ///\n /// # Arguments\n /// * `contract_address` - Address of the contract to call\n /// * `function_selector` - Function to call on the target contract\n /// * `args` - Array of arguments to pass to the called function\n /// * `gas_opts` - An optional allocation of gas to the called function.\n ///\n /// # Returns\n /// * `[Field]` - Return data from the called function\n ///\n pub unconstrained fn static_call_public_function(\n _self: Self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; N],\n gas_opts: GasOpts,\n ) -> [Field] {\n let calldata = [function_selector.to_field()].concat(args);\n\n call_static(\n gas_opts.l2_gas.unwrap_or(MAX_U32_VALUE),\n gas_opts.da_gas.unwrap_or(MAX_U32_VALUE),\n contract_address,\n calldata,\n );\n // Use success_copy to determine whether the call succeeded\n let success = success_copy();\n\n let result_data = returndata_copy(0, returndata_size());\n if !success {\n // Rethrow the revert data.\n avm_revert(result_data);\n }\n result_data\n }\n\n /// Adds a new note hash to the Aztec blockchain's global Note Hash Tree.\n ///\n /// Notes are ordinarily constructed and emitted by _private_ functions, to\n /// ensure that both the content of the note, and the contract that emitted\n /// the note, stay private.\n ///\n /// There are however some useful patterns whereby a note needs to contain\n /// _public_ data. The ability to push a new note_hash from a _public_\n /// function means that notes can be injected with public data immediately\n /// -- as soon as the public value is known. The slower alternative would\n /// be to submit a follow-up transaction so that a private function can\n /// inject the data. Both are possible on Aztec.\n ///\n /// Search \"Partial Note\" for a very common pattern which enables a note\n /// to be \"partially\" populated with some data in a _private_ function, and\n /// then later \"completed\" with some data in a public function.\n ///\n /// # Arguments\n /// * `note_hash` - The hash of the note to add to the tree\n ///\n /// # Advanced\n /// * The note hash will be siloed with the contract address by the protocol\n ///\n pub fn push_note_hash(_self: Self, note_hash: Field) {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe { emit_note_hash(note_hash) };\n }\n\n /// Adds a new nullifier to the Aztec blockchain's global Nullifier Tree.\n ///\n /// Whilst nullifiers are primarily intended as a _privacy-preserving_\n /// record of a one-time action, they can also be used to efficiently\n /// record _public_ one-time actions too. Hence why you're seeing this\n /// function within the PublicContext.\n /// An example is to check whether a contract has been published: we emit\n /// a nullifier that is deterministic, but whose preimage is _not_ private.\n ///\n /// # Arguments\n /// * `nullifier` - A unique field element that represents the consumed\n /// state\n ///\n /// # Advanced\n /// * Nullifier is immediately added to the global nullifier tree\n /// * Emitted nullifiers are immediately visible to all\n /// subsequent transactions in the same block\n /// * Automatically siloed with the contract address by the protocol\n /// * Used for preventing double-spending and ensuring one-time actions\n ///\n pub fn push_nullifier(_self: Self, nullifier: Field) {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe { emit_nullifier(nullifier) };\n }\n\n /// Returns the address of the current contract being executed.\n ///\n /// This is equivalent to `address(this)` in Solidity (hence the name).\n /// Use this to identify the current contract's address, commonly needed for\n /// access control or when interacting with other contracts.\n ///\n /// # Returns\n /// * `AztecAddress` - The contract address of the current function being\n /// executed.\n ///\n pub fn this_address(_self: Self) -> AztecAddress {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n address()\n }\n }\n\n /// Returns the contract address that initiated this function call.\n ///\n /// This is similar to `msg.sender` in Solidity (hence the name).\n ///\n /// Important Note: If the calling function is a _private_ function, then\n /// it had the option of hiding its address when enqueuing this public\n /// function call. In such cases, this `context.msg_sender()` method will\n /// return `Option::none`.\n /// If the calling function is a _public_ function, it will always return\n /// an `Option::some` (i.e. a non-null value).\n ///\n /// # Returns\n /// * `Option` - The address of the smart contract that called\n /// this function (be it an app contract or a user's account contract).\n ///\n /// # Advanced\n /// * Value is provided by the AVM sender opcode\n /// * In nested calls, this is the immediate caller, not the original\n /// transaction sender\n ///\n pub fn msg_sender(_self: Self) -> Option {\n // Safety: AVM opcodes are constrained by the AVM itself\n let maybe_msg_sender = unsafe { sender() };\n if maybe_msg_sender == NULL_MSG_SENDER_CONTRACT_ADDRESS {\n Option::none()\n } else {\n Option::some(maybe_msg_sender)\n }\n }\n\n /// \"Unsafe\" versus calling `context.msg_sender()`, because it doesn't\n /// translate `NULL_MSG_SENDER_CONTRACT_ADDRESS` as\n /// `Option::none`.\n /// Used by some internal aztecnr functions.\n pub fn msg_sender_unsafe(_self: Self) -> AztecAddress {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n sender()\n }\n }\n\n /// Returns the function selector of the currently-executing function.\n ///\n /// This is similar to `msg.sig` in Solidity, returning the first 4\n /// bytes of the function signature.\n ///\n /// # Returns\n /// * `FunctionSelector` - The 4-byte function identifier\n ///\n /// # Advanced\n /// * Extracted from the first element of calldata\n /// * Used internally for function dispatch in the AVM\n ///\n pub fn selector(_self: Self) -> FunctionSelector {\n // The selector is the first element of the calldata when calling a public function through dispatch.\n // Safety: AVM opcodes are constrained by the AVM itself\n let raw_selector: [Field; 1] = unsafe { calldata_copy(0, 1) };\n FunctionSelector::from_field(raw_selector[0])\n }\n\n /// Returns the hash of the arguments passed to the current function.\n ///\n /// Very low-level function: The #[external(\"public\")] macro uses this internally.\n /// Smart contract developers typically won't need to access this\n /// directly as arguments are automatically made available.\n ///\n /// # Returns\n /// * `Field` - Hash of the function arguments\n ///\n pub fn get_args_hash(mut self) -> Field {\n if !self.args_hash.is_some() {\n self.args_hash = Option::some((self.compute_args_hash)());\n }\n\n self.args_hash.unwrap_unchecked()\n }\n\n /// Returns the \"transaction fee\" for the current transaction.\n /// This is the final tx fee that will be deducted from the fee_payer's\n /// \"fee-juice\" balance (in the protocol's Base Rollup circuit).\n ///\n /// # Returns\n /// * `Field` - The actual, final cost of the transaction, taking into account:\n /// the actual gas used during the setup and app-logic phases,\n /// and the fixed amount of gas that's been allocated by the user\n /// for the teardown phase.\n /// I.e. effectiveL2FeePerGas * l2GasUsed + effectiveDAFeePerGas * daGasUsed\n ///\n /// This will return `0` during the \"setup\" and \"app-logic\" phases of\n /// tx execution (because the final tx fee is not known at that time).\n /// This will only return a nonzero value during the \"teardown\" phase of\n /// execution, where the final tx fee can actually be computed.\n ///\n /// Regardless of _when_ this function is called during the teardown phase,\n /// it will always return the same final tx fee value. The teardown phase\n /// does not consume a variable amount of gas: it always consumes a\n /// pre-allocated amount of gas, as specified by the user when they generate\n /// their tx.\n ///\n pub fn transaction_fee(_self: Self) -> Field {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n transaction_fee()\n }\n }\n\n /// Returns the chain ID of the current network.\n ///\n /// This is similar to `block.chainid` in Solidity. Returns the unique\n /// identifier for the blockchain network this transaction is executing on.\n ///\n /// Helps prevent cross-chain replay attacks. Useful if implementing\n /// multi-chain contract logic.\n ///\n /// # Returns\n /// * `Field` - The chain ID as a field element\n ///\n pub fn chain_id(_self: Self) -> Field {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n chain_id()\n }\n }\n\n /// Returns the Aztec protocol version that this transaction is executing\n /// under. Different versions may have different rules, opcodes, or\n /// cryptographic primitives.\n ///\n /// This is similar to how Ethereum has different EVM versions.\n ///\n /// Useful for forward/backward compatibility checks\n ///\n /// Not to be confused with contract versions; this is the protocol version.\n ///\n /// # Returns\n /// * `Field` - The protocol version as a field element\n ///\n pub fn version(_self: Self) -> Field {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n version()\n }\n }\n /// Returns the current block number.\n ///\n /// This is similar to `block.number` in Solidity.\n ///\n /// Note: the current block number is only available within a public function\n /// (as opposed to a private function).\n ///\n /// Note: the time intervals between blocks should not be relied upon as\n /// being consistent:\n /// - Timestamps of blocks fall within a range, rather than at exact regular\n /// intervals.\n /// - Slots can be missed.\n /// - Protocol upgrades can completely change the intervals between blocks\n /// (and indeed the current roadmap plans to reduce the time between\n /// blocks, eventually).\n /// Use `context.timestamp()` for more-reliable time-based logic.\n ///\n /// # Returns\n /// * `u32` - The current block number\n ///\n pub fn block_number(_self: Self) -> u32 {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n block_number()\n }\n }\n\n /// Returns the timestamp of the current block.\n ///\n /// This is similar to `block.timestamp` in Solidity.\n ///\n /// All functions of all transactions in a block share the exact same\n /// timestamp (even though technically each transaction is executed\n /// one-after-the-other).\n ///\n /// Important note: Timestamps of Aztec blocks are not at reliably-fixed\n /// intervals. The proposer of the block has some flexibility to choose a\n /// timestamp which is in a valid _range_: Obviously the timestamp of this\n /// block must be strictly greater than that of the previous block, and must\n /// must be less than the timestamp of whichever ethereum block the aztec\n /// block is proposed to. Furthermore, if the timestamp is not deemed close\n /// enough to the actual current time, the committee of validators will not\n /// attest to the block.\n ///\n /// # Returns\n /// * `u64` - Unix timestamp in seconds\n ///\n pub fn timestamp(_self: Self) -> u64 {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n timestamp()\n }\n }\n\n /// Returns the fee per unit of L2 gas for this transaction (aka the \"L2 gas\n /// price\"), as chosen by the user.\n ///\n /// L2 gas covers the cost of executing public functions and handling\n /// side-effects within the AVM.\n ///\n /// # Returns\n /// * `u128` - Fee per unit of L2 gas\n ///\n /// Wallet developers should be mindful that the choice of gas price (which\n /// is publicly visible) can leak information about the user, e.g.:\n /// - which wallet software the user is using;\n /// - the amount of time which has elapsed from the time the user's wallet\n /// chose a gas price (at the going rate), to the time of tx submission.\n /// This can give clues about the proving time, and hence the nature of\n /// the tx.\n /// - the urgency of the transaction (which is kind of unavoidable, if the\n /// tx is indeed urgent).\n /// - the wealth of the user.\n /// - the exact user (if the gas price is explicitly chosen by the user to\n /// be some unique number like 0.123456789, or their favorite number).\n /// Wallet devs might wish to consider fuzzing the choice of gas price.\n ///\n pub fn base_fee_per_l2_gas(_self: Self) -> u128 {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n base_fee_per_l2_gas()\n }\n }\n\n /// Returns the fee per unit of DA (Data Availability) gas (aka the \"DA gas\n /// price\").\n ///\n /// DA gas covers the cost of making transaction data available on L1.\n ///\n /// See the warning in `fee_pre_l2_gas` for how gas prices can be leaky.\n ///\n /// # Returns\n /// * `u128` - Fee per unit of DA gas\n ///\n pub fn base_fee_per_da_gas(_self: Self) -> u128 {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n base_fee_per_da_gas()\n }\n }\n\n /// Returns the remaining L2 gas available for this transaction.\n ///\n /// Different AVM opcodes consume different amounts of gas.\n ///\n /// # Returns\n /// * `u32` - Remaining L2 gas units\n ///\n pub fn l2_gas_left(_self: Self) -> u32 {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n l2_gas_left()\n }\n }\n\n /// Returns the remaining DA (Data Availability) gas available for this\n /// transaction.\n ///\n /// DA gas is consumed when emitting data that needs to be made available\n /// on L1, such as public logs or state updates.\n /// All of the side-effects from the private part of the tx also consume\n /// DA gas before execution of any public functions even begins.\n ///\n /// # Returns\n /// * `u32` - Remaining DA gas units\n ///\n pub fn da_gas_left(_self: Self) -> u32 {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n da_gas_left()\n }\n }\n\n /// Checks if the current execution is within a staticcall context, where\n /// no state changes or logs are allowed to be emitted (by this function\n /// or any nested function calls).\n ///\n /// # Returns\n /// * `bool` - True if in staticcall context, false otherwise\n ///\n pub fn is_static_call(_self: Self) -> bool {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe { is_static_call() } == 1\n }\n\n /// Reads raw field values from public storage.\n /// Reads N consecutive storage slots starting from the given slot.\n ///\n /// Very low-level function. Users should typically use the public state\n /// variable abstractions to perform reads: PublicMutable & PublicImmutable.\n ///\n /// # Arguments\n /// * `storage_slot` - The starting storage slot to read from\n ///\n /// # Returns\n /// * `[Field; N]` - Array of N field values from consecutive storage slots\n ///\n /// # Generic Parameters\n /// * `N` - the number of consecutive slots to return, starting from the\n /// `storage_slot`.\n ///\n pub fn raw_storage_read(_self: Self, storage_slot: Field) -> [Field; N] {\n let mut out = [0; N];\n for i in 0..N {\n // Safety: AVM opcodes are constrained by the AVM itself\n out[i] = unsafe { storage_read(storage_slot + i as Field) };\n }\n out\n }\n\n /// Reads a typed value from public storage.\n ///\n /// Low-level function. Users should typically use the public state\n /// variable abstractions to perform reads: PublicMutable & PublicImmutable.\n ///\n /// # Arguments\n /// * `storage_slot` - The storage slot to read from\n ///\n /// # Returns\n /// * `T` - The deserialized value from storage\n ///\n /// # Generic Parameters\n /// * `T` - The type that the caller expects to read from the `storage_slot`.\n ///\n pub fn storage_read(self, storage_slot: Field) -> T\n where\n T: Packable,\n {\n T::unpack(self.raw_storage_read(storage_slot))\n }\n\n /// Writes raw field values to public storage.\n /// Writes to N consecutive storage slots starting from the given slot.\n ///\n /// Very low-level function. Users should typically use the public state\n /// variable abstractions to perform writes: PublicMutable & PublicImmutable.\n ///\n /// Public storage writes take effect immediately.\n ///\n /// # Arguments\n /// * `storage_slot` - The starting storage slot to write to\n /// * `values` - Array of N Fields to write to storage\n ///\n pub fn raw_storage_write(_self: Self, storage_slot: Field, values: [Field; N]) {\n for i in 0..N {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe { storage_write(storage_slot + i as Field, values[i]) };\n }\n }\n\n /// Writes a typed value to public storage.\n ///\n /// Low-level function. Users should typically use the public state\n /// variable abstractions to perform writes: PublicMutable & PublicImmutable.\n ///\n /// # Arguments\n /// * `storage_slot` - The storage slot to write to\n /// * `value` - The typed value to write to storage\n ///\n /// # Generic Parameters\n /// * `T` - The type to write to storage.\n ///\n pub fn storage_write(self, storage_slot: Field, value: T)\n where\n T: Packable,\n {\n self.raw_storage_write(storage_slot, value.pack());\n }\n}\n\n// TODO: consider putting this oracle code in its own file.\n// Unconstrained opcode wrappers (do not use directly).\nunconstrained fn address() -> AztecAddress {\n address_opcode()\n}\nunconstrained fn sender() -> AztecAddress {\n sender_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() -> u32 {\n block_number_opcode()\n}\nunconstrained fn timestamp() -> u64 {\n timestamp_opcode()\n}\nunconstrained fn base_fee_per_l2_gas() -> u128 {\n base_fee_per_l2_gas_opcode()\n}\nunconstrained fn base_fee_per_da_gas() -> u128 {\n base_fee_per_da_gas_opcode()\n}\nunconstrained fn l2_gas_left() -> u32 {\n l2_gas_left_opcode()\n}\nunconstrained fn da_gas_left() -> u32 {\n da_gas_left_opcode()\n}\nunconstrained fn is_static_call() -> u1 {\n is_static_call_opcode()\n}\nunconstrained fn note_hash_exists(note_hash: Field, leaf_index: u64) -> u1 {\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) -> u1 {\n nullifier_exists_opcode(nullifier, address)\n}\nunconstrained fn emit_nullifier(nullifier: Field) {\n emit_nullifier_opcode(nullifier)\n}\nunconstrained fn emit_public_log(message: [Field]) {\n emit_public_log_opcode(message)\n}\nunconstrained fn l1_to_l2_msg_exists(msg_hash: Field, msg_leaf_index: u64) -> u1 {\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}\n\nunconstrained fn call(\n l2_gas_allocation: u32,\n da_gas_allocation: u32,\n address: AztecAddress,\n args: [Field; N],\n) {\n call_opcode(l2_gas_allocation, da_gas_allocation, address, N, args)\n}\n\nunconstrained fn call_static(\n l2_gas_allocation: u32,\n da_gas_allocation: u32,\n address: AztecAddress,\n args: [Field; N],\n) {\n call_static_opcode(l2_gas_allocation, da_gas_allocation, address, N, args)\n}\n\npub unconstrained fn calldata_copy(cdoffset: u32, copy_size: u32) -> [Field; N] {\n calldata_copy_opcode(cdoffset, copy_size)\n}\n\n// `success_copy` is placed immediately after the CALL opcode to get the success value\nunconstrained fn success_copy() -> bool {\n success_copy_opcode()\n}\n\nunconstrained fn returndata_size() -> u32 {\n returndata_size_opcode()\n}\n\nunconstrained fn returndata_copy(rdoffset: u32, copy_size: u32) -> [Field] {\n returndata_copy_opcode(rdoffset, copy_size)\n}\n\npub unconstrained fn avm_return(returndata: [Field]) {\n return_opcode(returndata)\n}\n\n// This opcode reverts using the exact data given. In general it should only be used\n// to do rethrows, where the revert data is the same as the original revert data.\n// For normal reverts, use Noir's `assert` which, on top of reverting, will also add\n// an error selector to the revert data.\nunconstrained fn avm_revert(revertdata: [Field]) {\n revert_opcode(revertdata)\n}\n\nunconstrained fn storage_read(storage_slot: Field) -> Field {\n storage_read_opcode(storage_slot)\n}\n\nunconstrained fn storage_write(storage_slot: Field, value: Field) {\n storage_write_opcode(storage_slot, value);\n}\n\nimpl Empty for PublicContext {\n fn empty() -> Self {\n PublicContext::new(|| 0)\n }\n}\n\n// TODO: consider putting this oracle code in its own file.\n// AVM oracles (opcodes) follow, do not use directly.\n#[oracle(avmOpcodeAddress)]\nunconstrained fn address_opcode() -> AztecAddress {}\n\n#[oracle(avmOpcodeSender)]\nunconstrained fn sender_opcode() -> AztecAddress {}\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() -> u32 {}\n\n#[oracle(avmOpcodeTimestamp)]\nunconstrained fn timestamp_opcode() -> u64 {}\n\n#[oracle(avmOpcodeBaseFeePerL2Gas)]\nunconstrained fn base_fee_per_l2_gas_opcode() -> u128 {}\n\n#[oracle(avmOpcodeBaseFeePerDaGas)]\nunconstrained fn base_fee_per_da_gas_opcode() -> u128 {}\n\n#[oracle(avmOpcodeL2GasLeft)]\nunconstrained fn l2_gas_left_opcode() -> u32 {}\n\n#[oracle(avmOpcodeDaGasLeft)]\nunconstrained fn da_gas_left_opcode() -> u32 {}\n\n#[oracle(avmOpcodeIsStaticCall)]\nunconstrained fn is_static_call_opcode() -> u1 {}\n\n#[oracle(avmOpcodeNoteHashExists)]\nunconstrained fn note_hash_exists_opcode(note_hash: Field, leaf_index: u64) -> u1 {}\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) -> u1 {}\n\n#[oracle(avmOpcodeEmitNullifier)]\nunconstrained fn emit_nullifier_opcode(nullifier: Field) {}\n\n// TODO(#11124): rename unencrypted to public in avm\n#[oracle(avmOpcodeEmitUnencryptedLog)]\nunconstrained fn emit_public_log_opcode(message: [Field]) {}\n\n#[oracle(avmOpcodeL1ToL2MsgExists)]\nunconstrained fn l1_to_l2_msg_exists_opcode(msg_hash: Field, msg_leaf_index: u64) -> u1 {}\n\n#[oracle(avmOpcodeSendL2ToL1Msg)]\nunconstrained fn send_l2_to_l1_msg_opcode(recipient: EthAddress, content: Field) {}\n\n#[oracle(avmOpcodeCalldataCopy)]\nunconstrained fn calldata_copy_opcode(cdoffset: u32, copy_size: u32) -> [Field; N] {}\n\n#[oracle(avmOpcodeReturndataSize)]\nunconstrained fn returndata_size_opcode() -> u32 {}\n\n#[oracle(avmOpcodeReturndataCopy)]\nunconstrained fn returndata_copy_opcode(rdoffset: u32, copy_size: u32) -> [Field] {}\n\n#[oracle(avmOpcodeReturn)]\nunconstrained fn return_opcode(returndata: [Field]) {}\n\n// This opcode reverts using the exact data given. In general it should only be used\n// to do rethrows, where the revert data is the same as the original revert data.\n// For normal reverts, use Noir's `assert` which, on top of reverting, will also add\n// an error selector to the revert data.\n#[oracle(avmOpcodeRevert)]\nunconstrained fn revert_opcode(revertdata: [Field]) {}\n\n// While the length parameter might seem unnecessary given that we have N we keep it around because at the AVM bytecode\n// level, we want to support non-comptime-known lengths for such opcodes, even if Noir code will not generally take that\n// route.\n#[oracle(avmOpcodeCall)]\nunconstrained fn call_opcode(\n l2_gas_allocation: u32,\n da_gas_allocation: u32,\n address: AztecAddress,\n length: u32,\n args: [Field; N],\n) {}\n\n// While the length parameter might seem unnecessary given that we have N we keep it around because at the AVM bytecode\n// level, we want to support non-comptime-known lengths for such opcodes, even if Noir code will not generally take that\n// route.\n#[oracle(avmOpcodeStaticCall)]\nunconstrained fn call_static_opcode(\n l2_gas_allocation: u32,\n da_gas_allocation: u32,\n address: AztecAddress,\n length: u32,\n args: [Field; N],\n) {}\n\n#[oracle(avmOpcodeSuccessCopy)]\nunconstrained fn success_copy_opcode() -> bool {}\n\n#[oracle(avmOpcodeStorageRead)]\nunconstrained fn storage_read_opcode(storage_slot: Field) -> Field {}\n\n#[oracle(avmOpcodeStorageWrite)]\nunconstrained fn storage_write_opcode(storage_slot: Field, value: Field) {}\n" + }, + "73": { + "path": "/home/ubuntu/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.20251212/noir-projects/aztec-nr/aztec/src/context/utility_context.nr", + "source": "use crate::oracle::{execution::get_utility_context, storage::storage_read};\nuse protocol_types::{address::AztecAddress, traits::Packable};\n\n// If you'll modify this struct don't forget to update utility_context.ts as well.\npub struct UtilityContext {\n block_number: u32,\n timestamp: u64,\n contract_address: AztecAddress,\n version: Field,\n chain_id: Field,\n}\n\nimpl UtilityContext {\n pub unconstrained fn new() -> Self {\n get_utility_context()\n }\n\n pub unconstrained fn at(contract_address: AztecAddress) -> Self {\n // We get a context with default contract address, and then we construct the final context with the provided\n // contract address.\n let default_context = get_utility_context();\n\n Self {\n block_number: default_context.block_number,\n timestamp: default_context.timestamp,\n contract_address,\n version: default_context.version,\n chain_id: default_context.chain_id,\n }\n }\n\n pub unconstrained fn at_historical(contract_address: AztecAddress, block_number: u32) -> Self {\n // We get a context with default contract address and block number, and then we construct the final context\n // with the provided contract address and block number.\n let default_context = get_utility_context();\n\n Self {\n block_number,\n timestamp: default_context.timestamp,\n contract_address,\n version: default_context.version,\n chain_id: default_context.chain_id,\n }\n }\n\n pub fn block_number(self) -> u32 {\n self.block_number\n }\n\n pub fn timestamp(self) -> u64 {\n self.timestamp\n }\n\n pub fn this_address(self) -> AztecAddress {\n self.contract_address\n }\n\n pub fn version(self) -> Field {\n self.version\n }\n\n pub fn chain_id(self) -> Field {\n self.chain_id\n }\n\n pub unconstrained fn raw_storage_read(\n self: Self,\n storage_slot: Field,\n ) -> [Field; N] {\n storage_read(self.this_address(), storage_slot, self.block_number())\n }\n\n pub unconstrained fn storage_read(self, storage_slot: Field) -> T\n where\n T: Packable,\n {\n T::unpack(self.raw_storage_read(storage_slot))\n }\n}\n" + }, + "74": { + "path": "/home/ubuntu/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.20251212/noir-projects/aztec-nr/aztec/src/contract_self.nr", + "source": "use crate::{\n context::{\n calls::{PrivateCall, PrivateStaticCall, PublicCall, PublicStaticCall},\n private_context::PrivateContext,\n public_context::PublicContext,\n utility_context::UtilityContext,\n },\n event::{\n event_emission::{emit_event_in_private, emit_event_in_public},\n event_interface::EventInterface,\n event_message::EventMessage,\n },\n};\nuse protocol_types::{\n address::AztecAddress,\n constants::NULL_MSG_SENDER_CONTRACT_ADDRESS,\n traits::{Deserialize, Serialize},\n};\n\n/// `ContractSelf` is the core interface for interacting with an Aztec contract's own state and context.\n///\n/// This struct is automatically injected into every #[external(...)] contract function by the Aztec macro system and is\n/// accessible through the `self` variable.\n///\n/// # Usage in Contract Functions\n///\n/// Once injected, you can use `self` to:\n/// - Access storage: `self.storage.balances.at(owner).read()`\n/// - Call contracts: `self.call(Token::at(address).transfer(recipient, amount))`\n/// - Emit events: `self.emit(event).deliver_to(recipient, delivery_mode)` (private) or `self.emit(event)` (public)\n/// - Get the contract address: `self.address`\n/// - Get the caller: `self.msg_sender()`\n/// - Access low-level Aztec.nr APIs through the context: `self.context`\n///\n/// # Example\n///\n/// ```noir\n/// #[external(\"private\")]\n/// fn withdraw(amount: u128, recipient: AztecAddress) {\n/// // Get the caller of this function\n/// let sender = self.msg_sender().unwrap();\n///\n/// // Access storage\n/// let token = self.storage.donation_token.get_note().get_address();\n///\n/// // Call contracts\n/// self.call(Token::at(token).transfer(recipient, amount));\n/// }\n/// ```\n///\n/// # Type Parameters\n///\n/// - `Context`: The execution context type - either `&mut PrivateContext`, `PublicContext`, or `UtilityContext`\n/// - `Storage`: The contract's storage struct (defined with `#[storage]`), or `()` if the contract has no storage\n/// - `CallSelf`: Macro-generated type for calling contract's own non-view functions\n/// - `EnqueueSelf`: Macro-generated type for enqueuing calls to the contract's own non-view functions\n/// - `CallSelfStatic`: Macro-generated type for calling contract's own view functions\n/// - `EnqueueSelfStatic`: Macro-generated type for enqueuing calls to the contract's own view functions\npub struct ContractSelf {\n /// The address of this contract\n pub address: AztecAddress,\n /// The contract's storage instance, representing the struct to which the `#[storage]` macro was applied in your\n /// contract. If the contract has no storage, the type of this will be `()`.\n ///\n /// This storage instance is specialized for the current execution context (private, public, or utility) and\n /// provides access to the contract's state variables. Each state variable accepts the context as a generic\n /// parameter, which determines its available functionality. For example, a PublicImmutable variable can be read\n /// from any context (public, private, or utility) but can only be written to from public contexts.\n ///\n /// # Developer Note\n /// If you've arrived here while trying to access your contract's storage while the `Storage` generic type is set to\n /// unit type `()`, it means you haven't yet defined a Storage struct using the #[storage] macro in your contract.\n /// For guidance on setting this up, please refer to our docs:\n /// https://docs.aztec.network/developers/docs/guides/smart_contracts/storage\n pub storage: Storage,\n /// The execution context whose type is determined by the #[external(...)] attribute of the contract function based\n /// on the external function type (private, public, or utility).\n pub context: Context,\n\n /// Provides type-safe methods for calling this contract's own non-view functions.\n ///\n /// In private and public contexts this will be a struct with appropriate methods;\n /// in utility context it will be the unit type `()`.\n ///\n /// Example API:\n /// ```noir\n /// self.call_self.some_private_function(args)\n /// ```\n pub call_self: CallSelf,\n /// Provides type-safe methods for enqueuing calls to this contract's own non-view functions.\n ///\n /// In private context this will be a struct with appropriate methods;\n /// in public and utility contexts it will be the unit type `()`.\n ///\n /// Example API:\n /// ```noir\n /// self.enqueue_self.some_public_function(args)\n /// ```\n pub enqueue_self: EnqueueSelf,\n /// Provides type-safe methods for calling this contract's own view functions.\n ///\n /// In private and public contexts this will be a struct with appropriate methods;\n /// in utility context it will be the unit type `()`.\n ///\n /// Example API:\n /// ```noir\n /// self.call_self_static.some_view_function(args)\n /// ```\n pub call_self_static: CallSelfStatic,\n /// Provides type-safe methods for enqueuing calls to this contract's own view functions.\n ///\n /// In private context this will be a struct with appropriate methods;\n /// in public and utility contexts it will be the unit type `()`.\n ///\n /// Example API:\n /// ```noir\n /// self.enqueue_self_static.some_public_view_function(args)\n /// ```\n pub enqueue_self_static: EnqueueSelfStatic,\n /// Provides type-safe methods for calling internal functions.\n ///\n /// In private and public contexts this will be a struct with appropriate methods;\n /// in utility context it will be the unit type `()`.\n ///\n /// Example API:\n /// ```noir\n /// self.internal.some_internal_function(args)\n /// ```\n pub internal: CallInternal,\n}\n\n/// Implementation for `ContractSelf` in private execution contexts.\n///\n/// This implementation is used when a contract function is marked with `#[external(\"private\")]`.\n/// Private functions execute client-side and generate zero-knowledge proofs of their execution.\nimpl ContractSelf<&mut PrivateContext, Storage, CallSelf, EnqueueSelf, CallSelfStatic, EnqueueSelfStatic, CallInternal> {\n /// Creates a new `ContractSelf` instance for a private function.\n ///\n /// This constructor is called automatically by the macro system and should not be called directly.\n pub fn new_private(\n context: &mut PrivateContext,\n storage: Storage,\n call_self: CallSelf,\n enqueue_self: EnqueueSelf,\n call_self_static: CallSelfStatic,\n enqueue_self_static: EnqueueSelfStatic,\n internal: CallInternal,\n ) -> Self {\n Self {\n context,\n storage,\n address: context.this_address(),\n call_self,\n enqueue_self,\n call_self_static,\n enqueue_self_static,\n internal,\n }\n }\n\n /// Returns the contract address that initiated this function call. This is similar to `msg.sender` in Solidity.\n ///\n /// Important Note: Since Aztec doesn't have a concept of an EoA ( Externally-owned Account), the msg_sender is\n /// \"null\" for the first function call of every transaction. The first function call of a tx is likely to be a call\n /// to the user's account contract, so this quirk will most often be handled by account contract developers.\n ///\n /// # Returns\n /// * `Option` - The address of the smart contract that called this function (be it an app contract or\n /// a user's account contract). Returns `Option::none` for the first function call of the tx. No\n /// other _private_ function calls in the tx will have a `none` msg_sender, but _public_ function calls might (see\n /// the PublicContext).\n ///\n pub fn msg_sender(self) -> Option {\n let maybe_msg_sender = self.context.msg_sender_unsafe();\n if maybe_msg_sender == NULL_MSG_SENDER_CONTRACT_ADDRESS {\n Option::none()\n } else {\n Option::some(maybe_msg_sender)\n }\n }\n\n /// Emits an event privately.\n ///\n /// Unlike public events, private events do not reveal their contents publicly. They instead create an\n /// [EventMessage] containing the private event information, which **MUST** be delivered to a recipient via\n /// [EventMessage::deliver_to] in order for them to learn about the event. Multiple recipients can have the same\n /// message be delivered to them.\n ///\n /// # Example\n /// ```noir\n /// #[event]\n /// struct Transfer { from: AztecAddress, to: AztecAddress, amount: u128 }\n ///\n /// #[external(\"private\")]\n /// fn transfer(to: AztecAddress, amount: u128) {\n /// let from = self.msg_sender().unwrap();\n ///\n /// let message: EventMessage = self.emit(Transfer { from, to, amount });\n /// message.deliver_to(from, MessageDelivery.UNCONSTRAINED_OFFCHAIN);\n /// message.deliver_to(to, MessageDelivery.CONSTRAINED_ONCHAIN);\n /// }\n /// ```\n ///\n /// # Cost\n ///\n /// Private event emission always results in the creation of a nullifer, which acts as a commitment to the event and\n /// is used by third parties to verify its authenticity. See [EventMessage::deliver_to] for the costs associated to\n /// delivery.\n ///\n /// # Privacy\n ///\n /// The nullifier created when emitting a private event leaks nothing about the content of the event - it's a\n /// commitment that includes a random value, so even with full knowledge of the event preimage determining if an\n /// event was emitted or not requires brute-forcing the entire `Field` space.\n pub fn emit(&mut self, event: Event) -> EventMessage\n where\n Event: EventInterface + Serialize,\n {\n emit_event_in_private(self.context, event)\n }\n\n /// Makes a call to the private function defined by the `call` parameter.\n ///\n /// # Arguments\n /// * `call` - The object representing the private function to invoke.\n ///\n /// # Returns\n /// * `T` - Whatever data the called function has returned.\n ///\n /// # Example\n /// ```noir\n /// self.call(Token::at(address).transfer_in_private(recipient, amount));\n /// ```\n ///\n /// This enables contracts to interact with each other while maintaining\n /// privacy. This \"composability\" of private contract functions is a key\n /// feature of the Aztec network.\n ///\n /// If a user's transaction includes multiple private function calls, then\n /// by the design of Aztec, the following information will remain private[1]:\n /// - The function selectors and contract addresses of all private function\n /// calls will remain private, so an observer of the public mempool will\n /// not be able to look at a tx and deduce which private functions have\n /// been executed.\n /// - The arguments and return values of all private function calls will\n /// remain private.\n /// - The person who initiated the tx will remain private.\n /// - The notes and nullifiers and private logs that are emitted by all\n /// private function calls will (if designed well) not leak any user\n /// secrets, nor leak which functions have been executed.\n ///\n /// [1] Caveats: Some of these privacy guarantees depend on how app\n /// developers design their smart contracts. Some actions _can_ leak\n /// information, such as:\n /// - Calling an internal public function.\n /// - Calling a public function and not setting msg_sender to Option::none\n /// (see https://github.com/AztecProtocol/aztec-packages/pull/16433)\n /// - Calling any public function will always leak details about the nature\n /// of the transaction, so devs should be careful in their contract\n /// designs. If it can be done in a private function, then that will give\n /// the best privacy.\n /// - Not padding the side-effects of a tx to some standardized, uniform\n /// size. The kernel circuits can take hints to pad side-effects, so a\n /// wallet should be able to request for a particular amount of padding.\n /// Wallets should ideally agree on some standard.\n /// - Padding should include:\n /// - Padding the lengths of note & nullifier arrays\n /// - Padding private logs with random fields, up to some standardized\n /// size.\n /// See also: https://docs.aztec.network/developers/resources/considerations/privacy_considerations\n ///\n /// # Advanced\n /// * The call is added to the private call stack and executed by kernel\n /// circuits after this function completes\n /// * The called function can modify its own contract's private state\n /// * Side effects from the called function are included in this transaction\n /// * The call inherits the current transaction's context and gas limits\n ///\n pub fn call(&mut self, call: PrivateCall) -> T\n where\n T: Deserialize,\n {\n call.call(self.context)\n }\n\n /// Makes a read-only call to the private function defined by the `call` parameter.\n ///\n /// This is similar to Solidity's `staticcall`. The called function\n /// cannot modify state, emit L2->L1 messages, nor emit events. Any nested\n /// calls are constrained to also be static calls.\n ///\n /// # Arguments\n /// * `call` - The object representing the read-only private function to invoke.\n ///\n /// # Returns\n /// * `T` - Whatever data the called function has returned.\n ///\n /// # Example\n /// ```noir\n /// self.view(Token::at(address).balance_of_private(recipient));\n /// ```\n pub fn view(&mut self, call: PrivateStaticCall) -> T\n where\n T: Deserialize,\n {\n call.view(self.context)\n }\n\n /// Enqueues a call to the public function defined by the `call` parameter,\n /// to be executed later.\n ///\n /// Unlike private functions which execute immediately on the user's device,\n /// public function calls are \"enqueued\" and executed some time later by a\n /// block proposer.\n ///\n /// This means a public function cannot return any values back to a private\n /// function, because by the time the public function is being executed,\n /// the private function which called it has already completed execution.\n /// (In fact, the private function has been executed and proven, along with\n /// all other private function calls of the user's tx. A single proof of the\n /// tx has been submitted to the Aztec network, and some time later a\n /// proposer has picked the tx up from the mempool and begun executing all\n /// of the enqueued public functions).\n ///\n /// # Privacy warning\n /// Enqueueing a public function call is an inherently leaky action.\n /// Many interesting applications will require some interaction with public\n /// state, but smart contract developers should try to use public function\n /// calls sparingly, and carefully.\n /// _Internal_ public function calls are especially leaky, because they\n /// completely leak which private contract made the call.\n /// See also: https://docs.aztec.network/developers/resources/considerations/privacy_considerations\n ///\n /// # Arguments\n /// * `call` - The interface representing the public function to enqueue.\n ///\n /// TODO(F-131): We should drop T from here because it is strange as there\n /// is no return value. The PublicCall type seems to be defined\n /// incorrectly.\n pub fn enqueue(&mut self, call: PublicCall)\n where\n T: Deserialize,\n {\n call.enqueue(self.context)\n }\n\n /// Enqueues a read-only call to the public function defined by the `call` parameter.\n ///\n /// This is similar to Solidity's `staticcall`. The called function\n /// cannot modify state, emit L2->L1 messages, nor emit events. Any nested\n /// calls are constrained to also be static calls.\n ///\n /// # Arguments\n /// * `call` - The object representing the read-only public function to enqueue.\n ///\n /// # Example\n /// ```noir\n /// self.enqueue_view(MyContract::at(address).assert_timestamp_less_than(timestamp));\n /// ```\n ///\n /// TODO(F-131): We should drop T from here because it is strange as there\n /// is no return value. The PublicCall type seems to be defined\n /// incorrectly.\n pub fn enqueue_view(&mut self, call: PublicStaticCall)\n where\n T: Deserialize,\n {\n call.enqueue_view(self.context)\n }\n\n /// Enqueues a call to the public function defined by the `call` parameter,\n /// to be executed later.\n ///\n /// As per `enqueue`, but hides this calling contract's address from the\n /// target public function.\n /// This means the origin of the call (msg_sender) will not be publicly\n /// visible to any blockchain observers, nor to the target public function.\n /// When the target public function reads `context.msg_sender()` it will\n /// receive an `Option::none`.\n ///\n /// NOTES:\n /// - Not all public functions will accept a msg_sender of \"none\". Many\n /// public functions will require that msg_sender is \"some\" and will\n /// revert otherwise. Therefore, if using `enqueue_incognito`, you must\n /// understand whether the function you're calling will accept a\n /// msg_sender of \"none\".\n /// Lots of public bookkeeping patterns rely on knowing which address made\n /// the call, so as to ascribe state against the caller's address.\n /// (There are patterns whereby bookkeeping could instead be done in\n /// private-land).\n /// - If you are enqueueing a call to an _internal_ public function (i.e.\n /// a public function that will only accept calls from other functions\n /// of its own contract), then by definition a call to it cannot possibly\n /// be \"incognito\": the msg_sender must be its own address, and indeed the\n /// called public function will assert this. Tl;dr this is not usable for\n /// enqueued internal public calls.\n ///\n /// # Arguments\n /// * `call` - The object representing the public function to enqueue.\n ///\n /// # Example\n /// ```noir\n /// self.enqueue_incognito(Token::at(address).increase_total_supply_by(amount));\n /// ```\n ///\n /// Advanced:\n /// - The kernel circuits will permit _any_ private function to set the\n /// msg_sender field of any enqueued public function call to\n /// NULL_MSG_SENDER_CONTRACT_ADDRESS.\n /// - When the called public function calls `PublicContext::msg_sender()`,\n /// aztec-nr will translate NULL_MSG_SENDER_CONTRACT_ADDRESS into\n /// `Option::none` for familiarity to devs.\n ///\n /// TODO(F-131): We should drop T from here because it is strange as there\n /// is no return value. The PublicCall type seems to be defined\n /// incorrectly.\n pub fn enqueue_incognito(&mut self, call: PublicCall)\n where\n T: Deserialize,\n {\n call.enqueue_incognito(self.context)\n }\n\n /// Enqueues a read-only call to the public function defined by the `call` parameter.\n ///\n /// As per `enqueue_view`, but hides this calling contract's address from\n /// the target public function.\n ///\n /// See `enqueue_incognito` for more details relating to hiding msg_sender.\n ///\n /// # Arguments\n /// * `call` - The object representing the read-only public function to enqueue.\n ///\n /// # Example\n /// ```noir\n /// self.enqueue_view_incognito(MyContract::at(address).assert_timestamp_less_than(timestamp));\n /// ```\n ///\n /// TODO(F-131): We should drop T from here because it is strange as there\n /// is no return value. The PublicCall type seems to be defined\n /// incorrectly.\n pub fn enqueue_view_incognito(\n &mut self,\n call: PublicStaticCall,\n )\n where\n T: Deserialize,\n {\n call.enqueue_view_incognito(self.context)\n }\n\n /// Enqueues a call to the public function defined by the `call` parameter,\n /// and designates it to be the teardown function for this tx. Only one teardown\n /// function call can be made by a tx.\n ///\n /// Niche function: Only wallet developers and paymaster contract developers\n /// (aka Fee-payment contracts) will need to make use of this function.\n ///\n /// Aztec supports a three-phase execution model: setup, app logic, teardown.\n /// The phases exist to enable a fee payer to take on the risk of paying\n /// a transaction fee, safe in the knowledge that their payment (in whatever\n /// token or method the user chooses) will succeed, regardless of whether\n /// the app logic will succeed. The \"setup\" phase ensures the fee payer\n /// has sufficient balance to pay the proposer their fees.\n /// The teardown phase is primarily intended to: calculate exactly\n /// how much the user owes, based on gas consumption, and refund the user\n /// any change.\n ///\n /// Note: in some cases, the cost of refunding the user (i.e. DA costs of\n /// tx side-effects) might exceed the refund amount. For app logic with\n /// fairly stable and predictable gas consumption, a material refund amount\n /// is unlikely. For app logic with unpredictable gas consumption, a\n /// refund might be important to the user (e.g. if a hefty function reverts\n /// very early). Wallet/FPC/Paymaster developers should be mindful of this.\n ///\n /// See `enqueue` for more information about enqueuing public function calls.\n ///\n /// # Arguments\n /// * `call` - The object representing the public function to designate as teardown.\n ///\n /// TODO(F-131): We should drop T from here because it is strange as there\n /// is no return value. The PublicCall type seems to be defined\n /// incorrectly.\n pub fn set_as_teardown(&mut self, call: PublicCall)\n where\n T: Deserialize,\n {\n call.set_as_teardown(self.context)\n }\n\n /// Enqueues a call to the public function defined by the `call` parameter,\n /// and designates it to be the teardown function for this tx. Only one teardown\n /// function call can be made by a tx.\n ///\n /// As per `set_as_teardown`, but hides this calling contract's address from\n /// the target public function.\n ///\n /// See `enqueue_incognito` for more details relating to hiding msg_sender.\n ///\n /// TODO(F-131): We should drop T from here because it is strange as there\n /// is no return value. The PublicCall type seems to be defined\n /// incorrectly.\n pub fn set_as_teardown_incognito(\n &mut self,\n call: PublicCall,\n )\n where\n T: Deserialize,\n {\n call.set_as_teardown_incognito(self.context)\n }\n}\n\n/// Implementation for `ContractSelf` in public execution contexts.\n///\n/// This implementation is used when a contract function is marked with `#[external(\"public\")]`.\n/// Public functions are executed by the sequencer in the Aztec Virtual Machine (AVM) and can work only with public\n/// state.\nimpl ContractSelf {\n /// Creates a new `ContractSelf` instance for a public function.\n ///\n /// This constructor is called automatically by the macro system and should not be called directly.\n pub fn new_public(\n context: PublicContext,\n storage: Storage,\n call_self: CallSelf,\n call_self_static: CallSelfStatic,\n internal: CallInternal,\n ) -> Self {\n Self {\n context,\n storage,\n address: context.this_address(),\n call_self,\n enqueue_self: (),\n call_self_static,\n enqueue_self_static: (),\n internal,\n }\n }\n\n /// Returns the contract address that initiated this function call.\n ///\n /// This is similar to `msg.sender` in Solidity (hence the name).\n ///\n /// Important Note: If the calling function is a _private_ function, then it had the option of hiding its address\n /// when enqueuing this public function call. In such cases, this `context.msg_sender()` method will return\n /// `Option::none`. If the calling function is a _public_ function, it will always return an\n /// `Option::some` (i.e. a non-null value).\n ///\n /// # Returns\n /// * `Option` - The address of the smart contract that called this function (be it an app contract or\n /// a user's account contract).\n ///\n /// # Advanced\n /// * Value is provided by the AVM sender opcode\n /// * In nested calls, this is the immediate caller, not the original transaction sender\n ///\n pub fn msg_sender(self: Self) -> Option {\n // Safety: AVM opcodes are constrained by the AVM itself\n let maybe_msg_sender = self.context.msg_sender_unsafe();\n if maybe_msg_sender == NULL_MSG_SENDER_CONTRACT_ADDRESS {\n Option::none()\n } else {\n Option::some(maybe_msg_sender)\n }\n }\n\n /// Emits an event publicly.\n ///\n /// Public events are emitted as plaintext and are therefore visible to everyone. This is is the same as Solidity\n /// events on EVM chains.\n ///\n /// Unlike private events, they don't require delivery of an event message.\n ///\n /// # Example\n /// ```noir\n /// #[event]\n /// struct Update { value: Field }\n ///\n /// #[external(\"public\")]\n /// fn publish_update(value: Field) {\n /// self.emit(Update { value });\n /// }\n /// ```\n ///\n /// # Cost\n ///\n /// Public event emission is achieved by emitting public transaction logs. A total of `N+1` fields are emitted,\n /// where `N` is the serialization length of the event.\n pub fn emit(&mut self, event: Event)\n where\n Event: EventInterface + Serialize,\n {\n emit_event_in_public(self.context, event);\n }\n\n /// Makes the call to the public function defined by the `call` parameter.\n ///\n /// Will revert if the called function reverts or runs out of gas.\n ///\n /// # Arguments\n /// * `call` - The object representing the public function to invoke.\n ///\n /// # Returns\n /// * `T` - Whatever data the called function has returned.\n ///\n /// # Example\n /// ```noir\n /// self.call(Token::at(address).transfer_in_public(recipient, amount));\n /// ```\n ///\n pub unconstrained fn call(self, call: PublicCall) -> T\n where\n T: Deserialize,\n {\n call.call(self.context)\n }\n\n /// Makes the read-only call to the public function defined by the `call` parameter.\n ///\n /// This is similar to Solidity's `staticcall`. The called function\n /// cannot modify state or emit events. Any nested calls are constrained to\n /// also be static calls.\n ///\n /// Will revert if the called function reverts or runs out of gas.\n ///\n /// # Arguments\n /// * `call` - The object representing the read-only public function to invoke.\n ///\n /// # Returns\n /// * `T` - Whatever data the called function has returned.\n ///\n /// # Example\n /// ```noir\n /// self.view(Token::at(address).balance_of_public(recipient));\n /// ```\n ///\n pub unconstrained fn view(self, call: PublicStaticCall) -> T\n where\n T: Deserialize,\n {\n call.view(self.context)\n }\n}\n\n/// Implementation for `ContractSelf` in utility execution contexts.\n///\n/// This implementation is used when a contract function is marked with `#[external(\"utility\")]`.\n/// Utility functions are unconstrained functions that can read private state for offchain queries.\n/// They are typically used for view functions that need to access private notes (e.g. a Token's balance_of function).\nimpl ContractSelf {\n /// Creates a new `ContractSelf` instance for a utility function.\n ///\n /// This constructor is called automatically by the macro system and should not be called directly.\n pub fn new_utility(context: UtilityContext, storage: Storage) -> Self {\n Self {\n context,\n storage,\n address: context.this_address(),\n call_self: (),\n enqueue_self: (),\n call_self_static: (),\n enqueue_self_static: (),\n internal: (),\n }\n }\n}\n" + }, + "75": { + "path": "/home/ubuntu/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.20251212/noir-projects/aztec-nr/aztec/src/event/event_emission.nr", + "source": "use crate::{\n context::{PrivateContext, PublicContext},\n event::{\n event_interface::{compute_private_event_commitment, EventInterface},\n event_message::EventMessage,\n },\n oracle::random::random,\n};\nuse protocol_types::traits::{Serialize, ToField};\n\n/// An event that was emitted in the current contract call.\npub struct NewEvent {\n pub(crate) event: Event,\n pub(crate) randomness: Field,\n pub(crate) commitment: Field,\n}\n\n/// Equivalent to `self.emit(event)`: see [crate::contract_self::ContractSelf::emit].\npub fn emit_event_in_private(\n context: &mut PrivateContext,\n event: Event,\n) -> EventMessage\nwhere\n Event: EventInterface + Serialize,\n{\n // In private events, we automatically inject randomness to prevent event commitment preimage attacks and event\n // commitment collisions (the commitments are included in the nullifier tree and duplicate nullifiers are by\n // definition not allowed).\n\n // Safety: We use the randomness to preserve the privacy of the event recipient by preventing brute-forcing,\n // so a malicious sender could use non-random values to make the event less private. But they already know\n // the full event pre-image anyway, and so the recipient already trusts them to not disclose this information.\n // We can therefore assume that the sender will cooperate in the random value generation.\n let randomness = unsafe { random() };\n\n // The event commitment is emitted as a nullifier instead of as a note because these are simpler: nullifiers cannot\n // be squashed, making kernel processing simpler, and they have no nonce that recipients need to discover.\n let commitment = compute_private_event_commitment(event, randomness);\n context.push_nullifier(commitment);\n\n EventMessage::new(NewEvent { event, randomness, commitment }, context)\n}\n\n/// Equivalent to `self.emit(event)`: see [crate::contract_self::ContractSelf::emit].\npub fn emit_event_in_public(context: PublicContext, event: Event)\nwhere\n Event: EventInterface + Serialize,\n{\n let mut log_content = [0; ::N + 1];\n\n let serialized_event = event.serialize();\n for i in 0..serialized_event.len() {\n log_content[i] = serialized_event[i];\n }\n\n // We put the selector in the \"last\" place, to avoid reading or assigning to an expression in an index\n // TODO(F-224): change this order.\n log_content[serialized_event.len()] = Event::get_event_type_id().to_field();\n\n context.emit_public_log(log_content);\n}\n" + }, + "78": { + "path": "/home/ubuntu/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.20251212/noir-projects/aztec-nr/aztec/src/event/event_selector.nr", + "source": "use dep::protocol_types::{\n hash::poseidon2_hash_bytes,\n traits::{Deserialize, Empty, FromField, Serialize, ToField},\n};\n\n#[derive(Deserialize, Eq, Serialize)]\npub struct EventSelector {\n // 1st 4-bytes (big-endian leftmost) of abi-encoding of an event.\n inner: u32,\n}\n\nimpl FromField for EventSelector {\n fn from_field(field: Field) -> Self {\n Self { inner: field as u32 }\n }\n}\n\nimpl ToField for EventSelector {\n fn to_field(self) -> Field {\n self.inner as Field\n }\n}\n\nimpl Empty for EventSelector {\n fn empty() -> Self {\n Self { inner: 0 as u32 }\n }\n}\n\nimpl EventSelector {\n pub fn from_u32(value: u32) -> Self {\n Self { inner: value }\n }\n\n pub fn from_signature(signature: str) -> Self {\n let bytes = signature.as_bytes();\n let hash = poseidon2_hash_bytes(bytes);\n\n // `hash` is automatically truncated to fit within 32 bits.\n EventSelector::from_field(hash)\n }\n\n pub fn zero() -> Self {\n Self { inner: 0 }\n }\n}\n" + }, + "97": { + "path": "/home/ubuntu/nargo/github.com/AztecProtocol/aztec-packages/v3.0.0-devnet.20251212/noir-projects/aztec-nr/aztec/src/keys/getters/mod.nr", + "source": "use crate::{\n keys::constants::{NULLIFIER_INDEX, OUTGOING_INDEX},\n oracle::{\n key_validation_request::get_key_validation_request,\n keys::get_public_keys_and_partial_address,\n },\n};\nuse dep::protocol_types::{address::AztecAddress, public_keys::PublicKeys};\n\npub unconstrained fn get_nsk_app(npk_m_hash: Field) -> Field {\n get_key_validation_request(npk_m_hash, NULLIFIER_INDEX).sk_app\n}\n\n// A helper function that gets app-siloed outgoing viewing key for a given `ovpk_m_hash`. This function is used\n// in unconstrained contexts only - when computing unconstrained note logs. The safe alternative is `request_ovsk_app`\n// function defined on `PrivateContext`.\npub unconstrained fn get_ovsk_app(ovpk_m_hash: Field) -> Field {\n get_key_validation_request(ovpk_m_hash, OUTGOING_INDEX).sk_app\n}\n\n// Returns all public keys for a given account, applying proper constraints to the context. We read all\n// keys at once since the constraints for reading them all are actually fewer than if we read them one at a time - any\n// read keys that are not required by the caller can simply be discarded.\npub fn get_public_keys(account: AztecAddress) -> PublicKeys {\n // Safety: Public keys are constrained by showing their inclusion in the address's preimage.\n let (public_keys, partial_address) = unsafe { get_public_keys_and_partial_address(account) };\n assert_eq(\n account,\n AztecAddress::compute(public_keys, partial_address),\n \"Invalid public keys hint for address\",\n );\n\n public_keys\n}\n\nmod test {\n use super::get_public_keys;\n\n use crate::test::helpers::test_environment::TestEnvironment;\n use protocol_types::traits::Serialize;\n use std::test::OracleMock;\n\n global KEY_ORACLE_RESPONSE_LENGTH: u32 = 13; // 12 fields for the keys, one field for the partial address\n\n #[test(should_fail_with = \"Invalid public keys hint for address\")]\n unconstrained fn get_public_keys_fails_with_bad_hint() {\n let mut env = TestEnvironment::new();\n let account = env.create_light_account();\n\n // Instead of querying for some unknown account, which would result in the oracle erroring out, we mock a bad oracle\n // response to check that the circuit properly checks the address derivation.\n let mut random_keys_and_partial_address = [0; KEY_ORACLE_RESPONSE_LENGTH];\n // We use randomly generated points on the curve, and a random partial address to ensure that\n // this combination does not derive the address and we should see the assertion fail.\n // npk_m\n random_keys_and_partial_address[0] =\n 0x292364b852c6c6f01472951e76a39cbcf074591fd0e063a81965e7b51ad868a5;\n random_keys_and_partial_address[1] =\n 0x0a687b46cdc9238f1c311f126aaaa4acbd7a737bff2efd7aeabdb8d805843a27;\n random_keys_and_partial_address[2] =\n 0x0000000000000000000000000000000000000000000000000000000000000000;\n // ivpk_m\n random_keys_and_partial_address[3] =\n 0x173c5229a00c5425255680dd6edc27e278c48883991f348fe6985de43b4ec25f;\n random_keys_and_partial_address[4] =\n 0x1698608e23b5f6c2f43c49a559108bb64e2247b8fc2da842296a416817f40b7f;\n random_keys_and_partial_address[5] =\n 0x0000000000000000000000000000000000000000000000000000000000000000;\n // ovpk_m\n random_keys_and_partial_address[6] =\n 0x1bad2f7d1ad960a1bd0fe4d2c8d17f5ab4a86ef8b103e0a9e7f67ec0d3b4795e;\n random_keys_and_partial_address[7] =\n 0x206db87110abbecc9fbaef2c865189d94ef2c106202f734ee4eba9257fd28bf1;\n random_keys_and_partial_address[8] =\n 0x0000000000000000000000000000000000000000000000000000000000000000;\n // tpk_m\n random_keys_and_partial_address[9] =\n 0x05e3bd9cfe6b47daa139613619cf7d7fd8bb0112b6f2908caa6d9b536ed948ed;\n random_keys_and_partial_address[10] =\n 0x051066f877c9df47552d02e7dc32127ff4edefc8498e813bca1cbd3f5d1be429;\n random_keys_and_partial_address[11] =\n 0x0000000000000000000000000000000000000000000000000000000000000000;\n // partial address\n random_keys_and_partial_address[12] =\n 0x236703e2cb00a182e024e98e9f759231b556d25ff19f98896cebb69e9e678cc9;\n\n let _ = OracleMock::mock(\"utilityGetPublicKeysAndPartialAddress\").returns(\n random_keys_and_partial_address.serialize(),\n );\n let _ = get_public_keys(account);\n }\n}\n" + } + } +} diff --git a/chains/aztec/scripts/Train.ts b/chains/aztec/scripts/Train.ts index dbfae17..6f49f11 100644 --- a/chains/aztec/scripts/Train.ts +++ b/chains/aztec/scripts/Train.ts @@ -4,7 +4,7 @@ /* eslint-disable */ import { AztecAddress, CompleteAddress } from '@aztec/aztec.js/addresses'; import { type AbiType, type AztecAddressLike, type ContractArtifact, EventSelector, decodeFromAbi, type EthAddressLike, type FieldLike, type FunctionSelectorLike, loadContractArtifact, loadContractArtifactForPublic, type NoirCompiledContract, type U128Like, type WrappedFieldLike } from '@aztec/aztec.js/abi'; -import { Contract, ContractBase, ContractFunctionInteraction, type ContractInstanceWithAddress, type ContractMethod, type ContractStorageLayout, DeployMethod } from '@aztec/aztec.js/contracts'; +import { Contract, ContractBase, ContractFunctionInteraction, type ContractMethod, type ContractStorageLayout, DeployMethod } from '@aztec/aztec.js/contracts'; import { EthAddress } from '@aztec/aztec.js/addresses'; import { Fr, Point } from '@aztec/aztec.js/fields'; import { type PublicKey, PublicKeys } from '@aztec/aztec.js/keys'; @@ -13,6 +13,52 @@ import TrainContractArtifactJson from '../contracts/train/target/train-Train.jso export const TrainContractArtifact = loadContractArtifact(TrainContractArtifactJson as NoirCompiledContract); + export type TokenRefunded = { + swap_id: FieldLike +htlc_id: FieldLike + } + + + export type TokenRedeemed = { + swap_id: FieldLike +htlc_id: FieldLike +redeem_address: AztecAddressLike +secret_high: (bigint | number) +secret_low: (bigint | number) +hashlock: (bigint | number)[] + } + + + export type SrcLocked = { + swap_id: FieldLike +hashlock: (bigint | number)[] +dst_chain: string +dst_address: string +dst_asset: string +sender: AztecAddressLike +src_receiver: AztecAddressLike +src_asset: string +amount: (bigint | number) +timelock: (bigint | number) + } + + + export type DstLocked = { + swap_id: FieldLike +htlc_id: FieldLike +hashlock: (bigint | number)[] +dst_chain: string +dst_address: string +dst_asset: string +sender: AztecAddressLike +src_receiver: AztecAddressLike +src_asset: string +amount: (bigint | number) +reward: (bigint | number) +reward_timelock: (bigint | number) +timelock: (bigint | number) + } + /** * Type-safe interface for contract Train; @@ -20,10 +66,10 @@ export const TrainContractArtifact = loadContractArtifact(TrainContractArtifactJ export class TrainContract extends ContractBase { private constructor( - instance: ContractInstanceWithAddress, + address: AztecAddress, wallet: Wallet, ) { - super(instance, TrainContractArtifact, wallet); + super(address, TrainContractArtifact, wallet); } @@ -32,13 +78,13 @@ export class TrainContract extends ContractBase { * Creates a contract instance. * @param address - The deployed contract's address. * @param wallet - The wallet to use when interacting with the contract. - * @returns A promise that resolves to a new Contract instance. + * @returns A new Contract instance. */ - public static async at( + public static at( address: AztecAddress, wallet: Wallet, - ) { - return Contract.at(address, TrainContract.artifact, wallet) as Promise; + ): TrainContract { + return Contract.at(address, TrainContract.artifact, wallet) as TrainContract; } @@ -46,14 +92,14 @@ export class TrainContract extends ContractBase { * Creates a tx to deploy a new instance of this contract. */ public static deploy(wallet: Wallet, ) { - return new DeployMethod(PublicKeys.default(), wallet, TrainContractArtifact, TrainContract.at, Array.from(arguments).slice(1)); + return new DeployMethod(PublicKeys.default(), wallet, TrainContractArtifact, (instance, wallet) => TrainContract.at(instance.address, wallet), Array.from(arguments).slice(1)); } /** * Creates a tx to deploy a new instance of this contract using the specified public keys hash to derive the address. */ public static deployWithPublicKeys(publicKeys: PublicKeys, wallet: Wallet, ) { - return new DeployMethod(publicKeys, wallet, TrainContractArtifact, TrainContract.at, Array.from(arguments).slice(2)); + return new DeployMethod(publicKeys, wallet, TrainContractArtifact, (instance, wallet) => TrainContract.at(instance.address, wallet), Array.from(arguments).slice(2)); } /** @@ -67,7 +113,7 @@ export class TrainContract extends ContractBase { opts.publicKeys ?? PublicKeys.default(), opts.wallet, TrainContractArtifact, - TrainContract.at, + (instance, wallet) => TrainContract.at(instance.address, wallet), Array.from(arguments).slice(1), opts.method ?? 'constructor', ); @@ -90,38 +136,41 @@ export class TrainContract extends ContractBase { } - public static get storage(): ContractStorageLayout<'contracts_private' | 'contracts_public'> { + public static get storage(): ContractStorageLayout<'contracts' | 'user_swaps_count' | 'user_swaps'> { return { - contracts_private: { + contracts: { slot: new Fr(1n), }, -contracts_public: { +user_swaps_count: { slot: new Fr(2n), + }, +user_swaps: { + slot: new Fr(3n), } - } as ContractStorageLayout<'contracts_private' | 'contracts_public'>; + } as ContractStorageLayout<'contracts' | 'user_swaps_count' | 'user_swaps'>; } /** Type-safe wrappers for the public methods exposed by the contract. */ public declare methods: { - /** add_lock_private_user(Id: field, hashlock_high: integer, hashlock_low: integer, timelock: integer) */ - add_lock_private_user: ((Id: FieldLike, hashlock_high: (bigint | number), hashlock_low: (bigint | number), timelock: (bigint | number)) => ContractFunctionInteraction) & Pick; - - /** commit_private_user(Id: field, src_receiver: struct, timelock: integer, token: struct, amount: integer, src_asset: string, dst_chain: string, dst_asset: string, dst_address: string, randomness: field) */ - commit_private_user: ((Id: FieldLike, src_receiver: AztecAddressLike, timelock: (bigint | number), token: AztecAddressLike, amount: (bigint | number), src_asset: string, dst_chain: string, dst_asset: string, dst_address: string, randomness: FieldLike) => ContractFunctionInteraction) & Pick; - /** constructor() */ constructor: (() => ContractFunctionInteraction) & Pick; - /** get_htlc_public(key: field) */ - get_htlc_public: ((key: FieldLike) => ContractFunctionInteraction) & Pick; + /** get_htlc(swap_id: field, htlc_id: field) */ + get_htlc: ((swap_id: FieldLike, htlc_id: FieldLike) => ContractFunctionInteraction) & Pick; - /** is_contract_initialized(id: field) */ - is_contract_initialized: ((id: FieldLike) => ContractFunctionInteraction) & Pick; + /** get_user_swaps_count(user: struct) */ + get_user_swaps_count: ((user: AztecAddressLike) => ContractFunctionInteraction) & Pick; - /** lock_private_solver(Id: field, hashlock_high: integer, hashlock_low: integer, amount: integer, ownership_hash_high: integer, ownership_hash_low: integer, timelock: integer, token: struct, randomness: field, src_asset: string, dst_chain: string, dst_asset: string, dst_address: string) */ - lock_private_solver: ((Id: FieldLike, hashlock_high: (bigint | number), hashlock_low: (bigint | number), amount: (bigint | number), ownership_hash_high: (bigint | number), ownership_hash_low: (bigint | number), timelock: (bigint | number), token: AztecAddressLike, randomness: FieldLike, src_asset: string, dst_chain: string, dst_asset: string, dst_address: string) => ContractFunctionInteraction) & Pick; + /** has_htlc(swap_id: field, htlc_id: field) */ + has_htlc: ((swap_id: FieldLike, htlc_id: FieldLike) => ContractFunctionInteraction) & Pick; + + /** lock_dst(swap_id: field, htlc_id: field, hashlock_high: integer, hashlock_low: integer, reward: integer, reward_timelock: integer, timelock: integer, src_receiver: struct, token: struct, total_amount: integer, src_asset: string, dst_chain: string, dst_asset: string, dst_address: string) */ + lock_dst: ((swap_id: FieldLike, htlc_id: FieldLike, hashlock_high: (bigint | number), hashlock_low: (bigint | number), reward: (bigint | number), reward_timelock: (bigint | number), timelock: (bigint | number), src_receiver: AztecAddressLike, token: AztecAddressLike, total_amount: (bigint | number), src_asset: string, dst_chain: string, dst_asset: string, dst_address: string) => ContractFunctionInteraction) & Pick; + + /** lock_src(swap_id: field, hashlock_high: integer, hashlock_low: integer, timelock: integer, src_receiver: struct, token: struct, amount: integer, src_asset: string, dst_chain: string, dst_asset: string, dst_address: string) */ + lock_src: ((swap_id: FieldLike, hashlock_high: (bigint | number), hashlock_low: (bigint | number), timelock: (bigint | number), src_receiver: AztecAddressLike, token: AztecAddressLike, amount: (bigint | number), src_asset: string, dst_chain: string, dst_asset: string, dst_address: string) => ContractFunctionInteraction) & Pick; /** process_message(message_ciphertext: struct, message_context: struct) */ process_message: ((message_ciphertext: FieldLike[], message_context: { tx_hash: FieldLike, unique_note_hashes_in_tx: FieldLike[], first_nullifier_in_tx: FieldLike, recipient: AztecAddressLike }) => ContractFunctionInteraction) & Pick; @@ -129,15 +178,333 @@ contracts_public: { /** public_dispatch(selector: field) */ public_dispatch: ((selector: FieldLike) => ContractFunctionInteraction) & Pick; - /** redeem_private(Id: field, secret_high: integer, secret_low: integer, ownership_key_high: integer, ownership_key_low: integer) */ - redeem_private: ((Id: FieldLike, secret_high: (bigint | number), secret_low: (bigint | number), ownership_key_high: (bigint | number), ownership_key_low: (bigint | number)) => ContractFunctionInteraction) & Pick; + /** redeem(swap_id: field, htlc_id: field, secret_high: integer, secret_low: integer) */ + redeem: ((swap_id: FieldLike, htlc_id: FieldLike, secret_high: (bigint | number), secret_low: (bigint | number)) => ContractFunctionInteraction) & Pick; - /** refund_private(Id: field) */ - refund_private: ((Id: FieldLike) => ContractFunctionInteraction) & Pick; + /** refund(swap_id: field, htlc_id: field) */ + refund: ((swap_id: FieldLike, htlc_id: FieldLike) => ContractFunctionInteraction) & Pick; /** sync_private_state() */ sync_private_state: (() => ContractFunctionInteraction) & Pick; }; + public static get events(): { TokenRefunded: {abiType: AbiType, eventSelector: EventSelector, fieldNames: string[] }, TokenRedeemed: {abiType: AbiType, eventSelector: EventSelector, fieldNames: string[] }, SrcLocked: {abiType: AbiType, eventSelector: EventSelector, fieldNames: string[] }, DstLocked: {abiType: AbiType, eventSelector: EventSelector, fieldNames: string[] } } { + return { + TokenRefunded: { + abiType: { + "kind": "struct", + "fields": [ + { + "name": "swap_id", + "type": { + "kind": "field" + } + }, + { + "name": "htlc_id", + "type": { + "kind": "field" + } + } + ], + "path": "Train::TokenRefunded" +}, + eventSelector: EventSelector.fromString("0x04359982"), + fieldNames: ["swap_id","htlc_id"], + }, +TokenRedeemed: { + abiType: { + "kind": "struct", + "fields": [ + { + "name": "swap_id", + "type": { + "kind": "field" + } + }, + { + "name": "htlc_id", + "type": { + "kind": "field" + } + }, + { + "name": "redeem_address", + "type": { + "kind": "struct", + "fields": [ + { + "name": "inner", + "type": { + "kind": "field" + } + } + ], + "path": "aztec::protocol_types::address::aztec_address::AztecAddress" + } + }, + { + "name": "secret_high", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 128 + } + }, + { + "name": "secret_low", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 128 + } + }, + { + "name": "hashlock", + "type": { + "kind": "array", + "length": 32, + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 8 + } + } + } + ], + "path": "Train::TokenRedeemed" +}, + eventSelector: EventSelector.fromString("0x82e3418e"), + fieldNames: ["swap_id","htlc_id","redeem_address","secret_high","secret_low","hashlock"], + }, +SrcLocked: { + abiType: { + "kind": "struct", + "fields": [ + { + "name": "swap_id", + "type": { + "kind": "field" + } + }, + { + "name": "hashlock", + "type": { + "kind": "array", + "length": 32, + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 8 + } + } + }, + { + "name": "dst_chain", + "type": { + "kind": "string", + "length": 30 + } + }, + { + "name": "dst_address", + "type": { + "kind": "string", + "length": 90 + } + }, + { + "name": "dst_asset", + "type": { + "kind": "string", + "length": 30 + } + }, + { + "name": "sender", + "type": { + "kind": "struct", + "fields": [ + { + "name": "inner", + "type": { + "kind": "field" + } + } + ], + "path": "aztec::protocol_types::address::aztec_address::AztecAddress" + } + }, + { + "name": "src_receiver", + "type": { + "kind": "struct", + "fields": [ + { + "name": "inner", + "type": { + "kind": "field" + } + } + ], + "path": "aztec::protocol_types::address::aztec_address::AztecAddress" + } + }, + { + "name": "src_asset", + "type": { + "kind": "string", + "length": 30 + } + }, + { + "name": "amount", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 128 + } + }, + { + "name": "timelock", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 64 + } + } + ], + "path": "Train::SrcLocked" +}, + eventSelector: EventSelector.fromString("0x2c334ea7"), + fieldNames: ["swap_id","hashlock","dst_chain","dst_address","dst_asset","sender","src_receiver","src_asset","amount","timelock"], + }, +DstLocked: { + abiType: { + "kind": "struct", + "fields": [ + { + "name": "swap_id", + "type": { + "kind": "field" + } + }, + { + "name": "htlc_id", + "type": { + "kind": "field" + } + }, + { + "name": "hashlock", + "type": { + "kind": "array", + "length": 32, + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 8 + } + } + }, + { + "name": "dst_chain", + "type": { + "kind": "string", + "length": 30 + } + }, + { + "name": "dst_address", + "type": { + "kind": "string", + "length": 90 + } + }, + { + "name": "dst_asset", + "type": { + "kind": "string", + "length": 30 + } + }, + { + "name": "sender", + "type": { + "kind": "struct", + "fields": [ + { + "name": "inner", + "type": { + "kind": "field" + } + } + ], + "path": "aztec::protocol_types::address::aztec_address::AztecAddress" + } + }, + { + "name": "src_receiver", + "type": { + "kind": "struct", + "fields": [ + { + "name": "inner", + "type": { + "kind": "field" + } + } + ], + "path": "aztec::protocol_types::address::aztec_address::AztecAddress" + } + }, + { + "name": "src_asset", + "type": { + "kind": "string", + "length": 30 + } + }, + { + "name": "amount", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 128 + } + }, + { + "name": "reward", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 128 + } + }, + { + "name": "reward_timelock", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 64 + } + }, + { + "name": "timelock", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 64 + } + } + ], + "path": "Train::DstLocked" +}, + eventSelector: EventSelector.fromString("0x8818cb5e"), + fieldNames: ["swap_id","htlc_id","hashlock","dst_chain","dst_address","dst_asset","sender","src_receiver","src_asset","amount","reward","reward_timelock","timelock"], + } + }; + } + } diff --git a/chains/aztec/scripts/package.json b/chains/aztec/scripts/package.json index 95564c4..3f9d450 100644 --- a/chains/aztec/scripts/package.json +++ b/chains/aztec/scripts/package.json @@ -11,12 +11,12 @@ "license": "ISC", "description": "", "dependencies": { - "@aztec/accounts": "3.0.0-devnet.2", - "@aztec/aztec.js": "3.0.0-devnet.2", - "@aztec/bb-prover": "3.0.0-devnet.2", - "@aztec/noir-contracts.js": "3.0.0-devnet.2", - "@aztec/pxe": "3.0.0-devnet.2", - "@aztec/test-wallet": "3.0.0-devnet.2", + "@aztec/accounts": "3.0.0-devnet.20251212", + "@aztec/aztec.js": "3.0.0-devnet.20251212", + "@aztec/bb-prover": "3.0.0-devnet.20251212", + "@aztec/noir-contracts.js": "3.0.0-devnet.20251212", + "@aztec/pxe": "3.0.0-devnet.20251212", + "@aztec/test-wallet": "3.0.0-devnet.20251212", "dotenv": "^16.5.0" }, "devDependencies": {