From fa6a841f8a4192f96520fd9ff96c77b13ba45c58 Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Mon, 26 Feb 2024 20:55:51 +0000 Subject: [PATCH 01/36] feat(honk): verifier start --- .../cpp/src/barretenberg/flavor/ultra.hpp | 1 + .../src/barretenberg/sumcheck/sumcheck.hpp | 5 + .../barretenberg/transcript/transcript.hpp | 16 +- .../ultra_honk/ultra_composer.test.cpp | 7 +- .../barretenberg/ultra_honk/ultra_prover.cpp | 3 + barretenberg/sol/src/honk/HonkVerifier.sol | 287 ++++++++++++++++++ .../src/contracts/target/blank-Blank.json | 1 + 7 files changed, 315 insertions(+), 5 deletions(-) create mode 100644 barretenberg/sol/src/honk/HonkVerifier.sol create mode 100644 boxes/blank-react/src/contracts/target/blank-Blank.json diff --git a/barretenberg/cpp/src/barretenberg/flavor/ultra.hpp b/barretenberg/cpp/src/barretenberg/flavor/ultra.hpp index b4f5b055a92..5d481723b94 100644 --- a/barretenberg/cpp/src/barretenberg/flavor/ultra.hpp +++ b/barretenberg/cpp/src/barretenberg/flavor/ultra.hpp @@ -534,6 +534,7 @@ class UltraFlavor { zm_cq_comm = deserialize_from_buffer(proof_data, num_frs_read); zm_pi_comm = deserialize_from_buffer(proof_data, num_frs_read); } + /** * @brief Serializes the structure variables into a FULL Ultra proof. Should be called only if * deserialize_full_transcript() was called and some transcript variable was modified. diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp index d8cb79f6bcc..7ce470440de 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp @@ -97,7 +97,9 @@ template class SumcheckProver { // First round // This populates partially_evaluated_polynomials. auto round_univariate = round.compute_univariate(full_polynomials, relation_parameters, pow_univariate, alpha); + transcript->send_to_verifier("Sumcheck:univariate_0", round_univariate); + FF round_challenge = transcript->template get_challenge("Sumcheck:u_0"); multivariate_challenge.emplace_back(round_challenge); partially_evaluate(full_polynomials, multivariate_n, round_challenge); @@ -109,7 +111,9 @@ template class SumcheckProver { // Write the round univariate to the transcript round_univariate = round.compute_univariate(partially_evaluated_polynomials, relation_parameters, pow_univariate, alpha); + transcript->send_to_verifier("Sumcheck:univariate_" + std::to_string(round_idx), round_univariate); + FF round_challenge = transcript->template get_challenge("Sumcheck:u_" + std::to_string(round_idx)); multivariate_challenge.emplace_back(round_challenge); partially_evaluate(partially_evaluated_polynomials, round.round_size, round_challenge); @@ -123,6 +127,7 @@ template class SumcheckProver { zip_view(multivariate_evaluations.get_all(), partially_evaluated_polynomials.get_all())) { eval = poly[0]; } + transcript->send_to_verifier("Sumcheck:evaluations", multivariate_evaluations.get_all()); return { multivariate_challenge, multivariate_evaluations }; diff --git a/barretenberg/cpp/src/barretenberg/transcript/transcript.hpp b/barretenberg/cpp/src/barretenberg/transcript/transcript.hpp index 655641144b3..59d76a96169 100644 --- a/barretenberg/cpp/src/barretenberg/transcript/transcript.hpp +++ b/barretenberg/cpp/src/barretenberg/transcript/transcript.hpp @@ -160,9 +160,12 @@ template class BaseTranscript { // Hash the full buffer with poseidon2, which is believed to be a collision resistant hash function and a random // oracle, removing the need to pre-hash to compress and then hash with a random oracle, as we previously did // with Pedersen and Blake3s. - Fr base_hash = TranscriptParams::hash(full_buffer); + info("full_buffer size: ", full_buffer.size()); + for (size_t i = 0; i < full_buffer.size(); i++) { + info("full_buffer[", i, "]: ", full_buffer[i]); + } + Fr new_challenge = TranscriptParams::hash(full_buffer); - Fr new_challenge = base_hash; // update previous challenge buffer for next time we call this function previous_challenge = new_challenge; return new_challenge; @@ -279,7 +282,13 @@ template class BaseTranscript { // HASH_OUTPUT_SIZE / 2, // field_element_buffer.begin() + HASH_OUTPUT_SIZE / 2); */ - challenges[i] = TranscriptParams::template convert_challenge(get_next_challenge_buffer()); + auto challenge_buffer = get_next_challenge_buffer(); + challenges[i] = TranscriptParams::template convert_challenge(challenge_buffer); + } + + info("round ", round_number); + for (size_t i = 0; i < num_challenges; i++) { + info(" challenge ", i, ": ", challenges[i]); } // Prepare for next round. @@ -374,6 +383,7 @@ template class BaseTranscript { template ChallengeType get_challenge(const std::string& label) { + info("getting challenge: ", label); ChallengeType result = get_challenges(label)[0]; #if defined LOG_CHALLENGES || defined LOG_INTERACTIONS info("challenge: ", label, ": ", result); diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_composer.test.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_composer.test.cpp index 205a67aad24..fc4ffb67f7e 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_composer.test.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_composer.test.cpp @@ -37,8 +37,11 @@ void prove_and_verify(auto& circuit_builder, auto& composer, bool expected_resul auto prover = composer.create_prover(instance); auto verifier = composer.create_verifier(instance); auto proof = prover.construct_proof(); - bool verified = verifier.verify_proof(proof); - EXPECT_EQ(verified, expected_result); + + info(expected_result); + // + // bool verified = verifier.verify_proof(proof); + // EXPECT_EQ(verified, expected_result); }; void ensure_non_zero(auto& polynomial) diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_prover.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_prover.cpp index e4630c377ea..35fd7313eee 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_prover.cpp @@ -187,12 +187,15 @@ template HonkProof& UltraProver_::export_proof() template HonkProof& UltraProver_::construct_proof() { // Add circuit size public input size and public inputs to transcript-> + info("Running the preamble round"); execute_preamble_round(); // Compute first three wire commitments + info("Running the wire commitments round"); execute_wire_commitments_round(); // Compute sorted list accumulator and commitment + info("Running the wire commitments round"); execute_sorted_list_accumulator_round(); // Fiat-Shamir: beta & gamma diff --git a/barretenberg/sol/src/honk/HonkVerifier.sol b/barretenberg/sol/src/honk/HonkVerifier.sol new file mode 100644 index 00000000000..3d7c10d296b --- /dev/null +++ b/barretenberg/sol/src/honk/HonkVerifier.sol @@ -0,0 +1,287 @@ + + + +/// Smart contract verifier of honk proofs +contract HonkVerifier { + + /// Plan of action + /// We want to implement the non goblinised version of the protocol + + /// 0. Implement loading the verification key + + /// 1. Generate challenges + /// 2. Perform the public inputs delta calculations + + /// 3. Implement the sumcheck verifier + /// 4. Implement the zero morph verifier + + // TODO: increase this number accordingly + uint256 constant NUMBER_OF_SUBRELATIONS = 4; + uint256 constant BATCHED_RELATION_PARTIAL_LENGTH = 7; + uint256 constant NUMBER_OF_ENTITIES = 43; + + /// Log of the circuit size - precomputed + uint256 constant LOG_N = 4; + + struct Proof { + // Free wires + uint256 w1; + uint256 w2; + uint256 w3; + uint256 w4; + + // Lookup helpers - classic plookup + uint256 sortedAccum; + uint256 zPerm; + uint256 zLookup; + + // Sumcheck + // TODO: [uinvariate[batched_relation_partial_length]] - not sure how to represent a univariate + uint256[LOG_N][BATCHED_RELATION_PARTIAL_LENGTH] sumcheckUnivariates; + uint256[NUMBER_OF_ENTITIES] sumcheckEvaluations; + + // Zero morph + uint256[LOG_N] zmCqs; + uint256 zmCq; + uint256 zmPi; + } + + struct VerificationKey { + // Misc Params + uint256 circuitSize; + uint256 publicInputsSize; + uint256 publicInputsOffset; + + // Selectors + uint256 qm; + uint256 qc; + uint256 ql; + uint256 qr; + uint256 qo; + uint256 q4; + uint256 qArith; // Arithmetic widget + uint256 qSort; // Gen perm sort + uint256 qAux; // Auxillary + uint256 qLookup; // Lookup + // Copy constraints + uint256 s1; + uint256 s2; + uint256 s3; + uint256 s4; + // Copy identity + uint256 id1; + uint256 id2; + uint256 id3; + uint256 id4; + // Precomputed lookup table + uint256 t1; + uint256 t2; + uint256 t3; + uint256 t4; + // Fixed first and last + uint256 lagrangeFirst; + uint256 lagrangeLast; + } + + struct ProofParameters { + uint256 logCircuitSize; + + } + + + struct TranscriptParameters { + // Relation Challenges + uint256[] alphas; + uint256[] gateChallenges; + + // perm challenges + uint256 beta; + uint256 gamma; + uint256 eta; // Challenge for sorted list batching and w4 memory records + uint256 publicInputsDelta; + uint256 lookupGrandProductDelta; + } + + /// Check how the challenges are calculated on the otherside + + function loadVerificationKey() internal returns (VerificationKey memory) { + // Load the verification key -> this can be hardcoded + + } + + + function loadProof() internal returns (Proof memory) { + // Load the proof -> this will be dymanic + } + + + + error PublicInputsLengthWrong(); + + function verify(bytes calldata proof, uint256[] calldata publicInputs) public returns (bool) { + VerificationKey memory vk = loadVerificationKey(); + Proof memory p = loadProof(); + + if (vk.publicInputsSize != publicInputs.length) { + revert PublicInputsLengthWrong(); + } + + // Perform each of the rounds + TranscriptParameters memory tp = computeChallenges(p, publicInputs); + + // Compute the public input delta + uint256 publicInputDelta = computePublicInputDelta( + publicInputs, + tp.beta, + tp.gamma, + vk.circuitSize, + vk.publicInputsOffset + ); + + uint256 grandProductPlookupDelta = computeLookupGrandProductDelta( + tp.beta, + tp.gamma, + vk.circuitSize + ); + + + } + + function computeChallenges(Proof memory proof, VerificationKey memory vk, uint256[] calldata publicInputs) { + TranscriptParameters memory tp; + + // We generate the first challenge by hashing the public inputs + // TODO: check the length here + bytes32[3 + publicInputs.length] memory round0; + round0[0] = bytes32(vk.circuitSize); + round0[1] = bytes32(vk.publicInputsSize); + round0[2] = bytes32(vk.publicInputsOffset); + for (uint256 i = 0; i < publicInputs.length; i++) { + round0[3 + i] = bytes32(publicInputs[i]); + } + + // Create the first challenge + // Note: w4 is added to the challenge later on + round0[3 + publicInputs.length] = bytes32(proof.w1); + round0[3 + publicInputs.length + 1] = bytes32(proof.w2); + round0[3 + publicInputs.length + 2] = bytes32(proof.w3); + + uint256 eta = uint256(keccak256(abi.encodePacked(round0))); + + // We generate the beta and gamma challenges by appending eta with the sorted_accumulator and w4 + bytes32[3] memory round1; + round1[0] = bytes32(eta); + round1[1] = bytes32(proof.sortedAccum); + round1[1] = bytes32(proof.w4); + + uint256 beta = uint256(keccak256(abi.encodePacked(round1))); + + // We generate the gamma challenge by hashing beta + // TODO: Check this is how we create spare challenges + uint256 gamma = uint256(keccak256(abi.encodePacked(beta))); + + // WORKTODO: there are more items pushed to the sumcheck challenges 1 + uint256[NUMBER_OF_SUBRELATIONS] memory alphas = generateAlphaChallenges(gamma); + tp.alphas = alphas; + + uint256[LOG_N] memory gate_challenges = generateGateChallenges(alphas[NUMBER_OF_SUBRELATIONS - 1]); + tp.gate_challenges = gate_challenges; + + uint256[LOG_N] sumCheckUChallenges = generateSumcheckChallenges(proof, gate_challenges[LOG_N - 1]); + uint256 rhoChallenge = generateRhoChallenge(proof, sumCheckUChallenges[LOG_N - 1]); + + uint256 zmY = generateZmYChallenge(proof, rhoChallenge); + + + + } + + // Alpha challenges non-linearise the gate contributions + function generateAlphaChallenges(uint256 previousChallenge) internal returns (uint256[] memory) { + uint256[NUMBER_OF_SUBRELATIONS] memory alphas; + uint256 prevChallenge = previousChallenge; + for (uint256 i = 0; i < NUMBER_OF_SUBRELATIONS; i++) { + prevChallenge = uint256(keccak256(bytes32(prevChallenge))); + alphas[i] = prevChallenge; + } + return alphas; + } + + function generateGateChallenges(uint256 previousChalenge) internal returns (uint256[] memory) { + uint256[LOG_N] memory gate_challanges; + uint256 prevChallenge = previousChalenge; + for (uint256 i = 0; i < LOG_N; i++) { + prevChallenge = uint256(keccak256(bytes32(prevChallenge))); + gate_challanges[i] = prevChallenge; + } + return gate_challanges; + } + + function generateSumcheckChallenges(Proof memory proof, uint256 prevChallenge) internal return (uint256[] memory) { + uint256[LOG_N] memory sumcheckChallenges; + uint256 prevChallenge = prevChallenge; + for (uint256 i = 0; i < LOG_N; i++) { + uint256[BATCHED_RELATION_PARTIAL_LENGTH + 1] memory multivariateChal; + multivariateChal[0] = prevChallenge; + + // TODO(opt): memcpy + for (uint256 j = 0; j < BATCHED_RELATION_PARTIAL_LENGTH; j++) { + multivariateChal[j + 1] = proof.sumcheckUnivariates[i][j]; + } + + sumcheckChallenges = uint256(keccak256(multivariate)); + } + + return sumcheckChallenges; + } + + function generateRhoChallenge(Proof memory proof, prevChallenge) internal return (uint256) { + uint256[NUMBER_OF_ENTITIES + 1] rhoChallengeElements; + rhoChallengeElements[0] = prevChallenge; + + // TODO: memcpy + for (uint256 i = 0; i < NUMBER_OF_ENTITIES; i++) { + rhoChallengeElements[i + 1] = proof.sumcheckEvaluations[i]; + } + return uint256(keccak256(rhoChallengeElements)); + } + + // We add an offset to the public inputs, this adds the values of our public inputs + // to the copy constraints + function computePublicInputDelta(uint256[] memory publicInputs, uint256 beta, uint256 gamma, + // TODO: check how to deal with this Domain size and offset are somewhat new + uint256 domainSize, uint256 offset + ) internal returns (uint256) { + uint256 numerator = 1; + uint256 denominator = 1; + + // TODO: all of this needs to be mod p + uint256 numeratorAcc = gamma + beta * (domainSize + offset); + uint256 denominatorAcc = gamma - beta * (offset + 1); + + for (uint256 i = 0; i < publicInputs.length; i++) { + numerator = numerator * (numeratorAcc + publicInputs[i]); + denominator = denominator * (denominatorAcc + publicInputs[i]); + + // TODO: mod p + numeratorAcc += beta; + denominatorAcc -= beta; + } + // mod p this shit + return numerator / denominator; + } + + // Incorportate the original plookup construction into honk + function computeLookupGrandProductDelta(uint256 beta, uint256 gamma, + // Again double check - i think it comes from the proving key + uint256 domainSize + ) internal returns (uint256) { + uint256 gammaByOnePlusBeta = gamma * (beta + 1); + return gammaByOnePlusBeta ** domainSize; + } + + function verifySumcheck() {} + + function verifyZeroMorph() {} + +} \ No newline at end of file diff --git a/boxes/blank-react/src/contracts/target/blank-Blank.json b/boxes/blank-react/src/contracts/target/blank-Blank.json new file mode 100644 index 00000000000..ed079d9e4ce --- /dev/null +++ b/boxes/blank-react/src/contracts/target/blank-Blank.json @@ -0,0 +1 @@ +{"noir_version":"0.23.0+6ff518af281afe601edb8574d425b07d9d2f9c5d","name":"Blank","functions":[{"name":"setNumber","function_type":"Secret","is_internal":false,"abi":{"parameters":[{"name":"inputs","type":{"kind":"struct","path":"aztec::context::inputs::private_context_inputs::PrivateContextInputs","fields":[{"name":"call_context","type":{"kind":"struct","path":"aztec::protocol_types::abis::call_context::CallContext","fields":[{"name":"msg_sender","type":{"kind":"struct","path":"aztec::protocol_types::address::AztecAddress","fields":[{"name":"inner","type":{"kind":"field"}}]}},{"name":"storage_contract_address","type":{"kind":"struct","path":"aztec::protocol_types::address::AztecAddress","fields":[{"name":"inner","type":{"kind":"field"}}]}},{"name":"portal_contract_address","type":{"kind":"struct","path":"aztec::protocol_types::address::EthAddress","fields":[{"name":"inner","type":{"kind":"field"}}]}},{"name":"function_selector","type":{"kind":"struct","path":"aztec::protocol_types::abis::function_selector::FunctionSelector","fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}]}},{"name":"is_delegate_call","type":{"kind":"boolean"}},{"name":"is_static_call","type":{"kind":"boolean"}},{"name":"is_contract_deployment","type":{"kind":"boolean"}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}]}},{"name":"historical_header","type":{"kind":"struct","path":"aztec::protocol_types::header::Header","fields":[{"name":"last_archive","type":{"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot","fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}]}},{"name":"body_hash","type":{"kind":"array","length":2,"type":{"kind":"field"}}},{"name":"state","type":{"kind":"struct","path":"aztec::protocol_types::state_reference::StateReference","fields":[{"name":"l1_to_l2_message_tree","type":{"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot","fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}]}},{"name":"partial","type":{"kind":"struct","path":"aztec::protocol_types::partial_state_reference::PartialStateReference","fields":[{"name":"note_hash_tree","type":{"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot","fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}]}},{"name":"nullifier_tree","type":{"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot","fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}]}},{"name":"contract_tree","type":{"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot","fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}]}},{"name":"public_data_tree","type":{"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot","fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}]}}]}}]}},{"name":"global_variables","type":{"kind":"struct","path":"aztec::protocol_types::abis::global_variables::GlobalVariables","fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"block_number","type":{"kind":"field"}},{"name":"timestamp","type":{"kind":"field"}},{"name":"coinbase","type":{"kind":"struct","path":"aztec::protocol_types::address::EthAddress","fields":[{"name":"inner","type":{"kind":"field"}}]}},{"name":"fee_recipient","type":{"kind":"struct","path":"aztec::protocol_types::address::AztecAddress","fields":[{"name":"inner","type":{"kind":"field"}}]}}]}}]}},{"name":"contract_deployment_data","type":{"kind":"struct","path":"aztec::protocol_types::contrakt::deployment_data::ContractDeploymentData","fields":[{"name":"public_key","type":{"kind":"struct","path":"aztec::protocol_types::grumpkin_point::GrumpkinPoint","fields":[{"name":"x","type":{"kind":"field"}},{"name":"y","type":{"kind":"field"}}]}},{"name":"initialization_hash","type":{"kind":"field"}},{"name":"contract_class_id","type":{"kind":"struct","path":"aztec::protocol_types::contract_class::ContractClassId","fields":[{"name":"inner","type":{"kind":"field"}}]}},{"name":"contract_address_salt","type":{"kind":"field"}},{"name":"portal_contract_address","type":{"kind":"struct","path":"aztec::protocol_types::address::EthAddress","fields":[{"name":"inner","type":{"kind":"field"}}]}}]}},{"name":"private_global_variables","type":{"kind":"struct","path":"aztec::context::globals::private_global_variables::PrivateGlobalVariables","fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}}]}}]},"visibility":"private"},{"name":"number","type":{"kind":"field"},"visibility":"private"}],"param_witnesses":{"inputs":[{"start":0,"end":36}],"number":[{"start":36,"end":37}]},"return_type":{"abi_type":{"kind":"struct","path":"aztec::protocol_types::abis::private_circuit_public_inputs::PrivateCircuitPublicInputs","fields":[{"name":"call_context","type":{"kind":"struct","path":"aztec::protocol_types::abis::call_context::CallContext","fields":[{"name":"msg_sender","type":{"kind":"struct","path":"aztec::protocol_types::address::AztecAddress","fields":[{"name":"inner","type":{"kind":"field"}}]}},{"name":"storage_contract_address","type":{"kind":"struct","path":"aztec::protocol_types::address::AztecAddress","fields":[{"name":"inner","type":{"kind":"field"}}]}},{"name":"portal_contract_address","type":{"kind":"struct","path":"aztec::protocol_types::address::EthAddress","fields":[{"name":"inner","type":{"kind":"field"}}]}},{"name":"function_selector","type":{"kind":"struct","path":"aztec::protocol_types::abis::function_selector::FunctionSelector","fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}]}},{"name":"is_delegate_call","type":{"kind":"boolean"}},{"name":"is_static_call","type":{"kind":"boolean"}},{"name":"is_contract_deployment","type":{"kind":"boolean"}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}]}},{"name":"args_hash","type":{"kind":"field"}},{"name":"return_values","type":{"kind":"array","length":4,"type":{"kind":"field"}}},{"name":"max_non_revertible_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"read_requests","type":{"kind":"array","length":32,"type":{"kind":"struct","path":"aztec::protocol_types::abis::side_effect::SideEffect","fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}]}}},{"name":"nullifier_key_validation_requests","type":{"kind":"array","length":1,"type":{"kind":"struct","path":"aztec::protocol_types::abis::nullifier_key_validation_request::NullifierKeyValidationRequest","fields":[{"name":"public_key","type":{"kind":"struct","path":"aztec::protocol_types::grumpkin_point::GrumpkinPoint","fields":[{"name":"x","type":{"kind":"field"}},{"name":"y","type":{"kind":"field"}}]}},{"name":"secret_key","type":{"kind":"struct","path":"aztec::protocol_types::grumpkin_private_key::GrumpkinPrivateKey","fields":[{"name":"high","type":{"kind":"field"}},{"name":"low","type":{"kind":"field"}}]}}]}}},{"name":"new_commitments","type":{"kind":"array","length":16,"type":{"kind":"struct","path":"aztec::protocol_types::abis::side_effect::SideEffect","fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}]}}},{"name":"new_nullifiers","type":{"kind":"array","length":16,"type":{"kind":"struct","path":"aztec::protocol_types::abis::side_effect::SideEffectLinkedToNoteHash","fields":[{"name":"value","type":{"kind":"field"}},{"name":"note_hash","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}]}}},{"name":"private_call_stack_hashes","type":{"kind":"array","length":4,"type":{"kind":"field"}}},{"name":"public_call_stack_hashes","type":{"kind":"array","length":4,"type":{"kind":"field"}}},{"name":"new_l2_to_l1_msgs","type":{"kind":"array","length":2,"type":{"kind":"field"}}},{"name":"end_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"encrypted_logs_hash","type":{"kind":"array","length":2,"type":{"kind":"field"}}},{"name":"unencrypted_logs_hash","type":{"kind":"array","length":2,"type":{"kind":"field"}}},{"name":"encrypted_log_preimages_length","type":{"kind":"field"}},{"name":"unencrypted_log_preimages_length","type":{"kind":"field"}},{"name":"historical_header","type":{"kind":"struct","path":"aztec::protocol_types::header::Header","fields":[{"name":"last_archive","type":{"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot","fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}]}},{"name":"body_hash","type":{"kind":"array","length":2,"type":{"kind":"field"}}},{"name":"state","type":{"kind":"struct","path":"aztec::protocol_types::state_reference::StateReference","fields":[{"name":"l1_to_l2_message_tree","type":{"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot","fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}]}},{"name":"partial","type":{"kind":"struct","path":"aztec::protocol_types::partial_state_reference::PartialStateReference","fields":[{"name":"note_hash_tree","type":{"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot","fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}]}},{"name":"nullifier_tree","type":{"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot","fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}]}},{"name":"contract_tree","type":{"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot","fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}]}},{"name":"public_data_tree","type":{"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot","fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}]}}]}}]}},{"name":"global_variables","type":{"kind":"struct","path":"aztec::protocol_types::abis::global_variables::GlobalVariables","fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"block_number","type":{"kind":"field"}},{"name":"timestamp","type":{"kind":"field"}},{"name":"coinbase","type":{"kind":"struct","path":"aztec::protocol_types::address::EthAddress","fields":[{"name":"inner","type":{"kind":"field"}}]}},{"name":"fee_recipient","type":{"kind":"struct","path":"aztec::protocol_types::address::AztecAddress","fields":[{"name":"inner","type":{"kind":"field"}}]}}]}}]}},{"name":"contract_deployment_data","type":{"kind":"struct","path":"aztec::protocol_types::contrakt::deployment_data::ContractDeploymentData","fields":[{"name":"public_key","type":{"kind":"struct","path":"aztec::protocol_types::grumpkin_point::GrumpkinPoint","fields":[{"name":"x","type":{"kind":"field"}},{"name":"y","type":{"kind":"field"}}]}},{"name":"initialization_hash","type":{"kind":"field"}},{"name":"contract_class_id","type":{"kind":"struct","path":"aztec::protocol_types::contract_class::ContractClassId","fields":[{"name":"inner","type":{"kind":"field"}}]}},{"name":"contract_address_salt","type":{"kind":"field"}},{"name":"portal_contract_address","type":{"kind":"struct","path":"aztec::protocol_types::address::EthAddress","fields":[{"name":"inner","type":{"kind":"field"}}]}}]}},{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}}]},"visibility":"public"},"return_witnesses":[98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304]},"bytecode":"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","debug_symbols":"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"},{"name":"getNumber","function_type":"Unconstrained","is_internal":false,"abi":{"parameters":[],"param_witnesses":{},"return_type":{"abi_type":{"kind":"struct","path":"easy_private_state::value_note::value_note::ValueNote","fields":[{"name":"value","type":{"kind":"field"}},{"name":"owner","type":{"kind":"struct","path":"aztec::protocol_types::address::AztecAddress","fields":[{"name":"inner","type":{"kind":"field"}}]}},{"name":"randomness","type":{"kind":"field"}},{"name":"header","type":{"kind":"struct","path":"aztec::note::note_header::NoteHeader","fields":[{"name":"contract_address","type":{"kind":"struct","path":"aztec::protocol_types::address::AztecAddress","fields":[{"name":"inner","type":{"kind":"field"}}]}},{"name":"nonce","type":{"kind":"field"}},{"name":"storage_slot","type":{"kind":"field"}},{"name":"is_transient","type":{"kind":"boolean"}}]}}]},"visibility":"public"},"return_witnesses":[0,1,2,3,4,5,6]},"bytecode":"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","debug_symbols":"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azB7DWavwew1mL0Gs9dg9hrMXoPZazB7DWavwew1mL0Gs9dg9hrMXoPZazB7DWavwew1mL0Gs9dg9hrMXoPZazB7DWavwew1mL0Gs9dg9hrMXoPZazB7DWavwew1mL0Gs9dg9hrMXoPZazB7DWavwew1mL0Gs9dg9hrMXoPZazB7DWavwew1mL0Gs9dg9hrMXoPZazB7DWavwew1mL0Gs9dg9hrMXoPZazB7DWavwew1mL0Gs9dg9hrMXoPZazB7DWavwew1mL0Gs9dg9hrMXoPZazB7DWavwew1mL0Gs9dg9hrMXoPZazB7TWavyew1mb0ms9dk9prMXpPZazJ7TWavyew1mb0ms9dk9prMXpPZazJ7TWavyew1mb0ms9dk9prMXpPZazJ7TWavyew1mb0ms9dk9prMXpPZazJ7TWavyew1mb0ms9dk9prMXpPZazJ7TWavyew1mb0ms9dk9prMXpPZazJ7TWavyew1mb0ms9dk9prMXpPZazJ7TWavyew1mb0ms9dk9prMXpPZazJ7TWavyew1mb0ms9dk9prMXpPZazJ7TWavyew1mb0ms9dk9prMXpPZazJ7TWavyew1mb0ms9dk9prMXpPZazJ7TWavyew1mb0ms9dk9prMXpPZazJ7TWavyew1mb0ms9di9lrMXovZazF7LWavxey1mL0Ws9di9lrMXovZazF7LWavxey1mL0Ws9di9lrMXovZazF7LWavxey1mL0Ws9di9lrMXovZazF7LWavxey1mL0Ws9di9lrMXovZazF7LWavxey1mL0Ws9di9lrMXovZazF7LWavxey1mL0Ws9di9lrMXovZazF7LWavxey1mL0Ws9di9lrMXovZazF7LWavxey1mL0Ws9di9lrMXovZazF7LWavxey1mL0Ws9di9lrMXovZazF7LWavxey1mL0Ws9di9lrMXovZazF7LWavxey1mL0Ws9di9lrMXovZazF7LWavxey1mL0Ws9di9lrMXovZazF7bWavzey1mb02s9dm9trMXpvZazN7bWavzey1mb02s9dm9trMXpvZazN7bWavzey1mb02s9dm9trMXpvZazN7bWavzey1mb02s9dm9trMXpvZazN7bWavzey1mb02s9dm9trMXpvZazN7bWavzey1mb02s9dm9trMXpvZazN7bWavzey1mb02s9dm9trM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HNSQgxpyUEMOashBDTmoIQc15KCGHNSQgxpyUEMOashBDTmoIQc15KCGHNSQgxpyUEMOashBDTmoIQc15KCGHNSQgxpyUEMOashBDTmoIQc15KCGHNSQgxpyUEMOashBDTmoIQc15KCGHNSQkxpyUkNOashJDTmpISc15KSGnNSQkxpyUkNOashJDTmpISc15KSGnNSQkxpyUkNOashJDTmpISc15KSGnNSQkxpyUkNOashJDTmpISc15KSGnNSQkxpyUkNOashJDTmpISc15KSGnNSQkxpyUkNOashJDTmpISc15KSGnNSQkxpyUkNOashJDTmpISc15KSGnNSQkxpyUkNOashJDTmpISc15KSGnNSQkxpyUkNOashJDTmpISc15KSGnNSQkxpyUkNOashJDTmpISc15KSGnNSQkxpyUkNOashJDTmpISc15KSGnNSQkxpyUkNOashJDTmpISc15KSGnNSQkxpyUkNOashJDbmoIRc15KKGXNSQixpyUUMuashFDbmoIRc15KKGXNSQixpyUUMuashFDbmoIRc15KKGXNSQixpyUUMuashFDbmoIRc15KKGXNSQixpyUUMuashFDbmoIRc15KKGXNSQixpyUUMuashFDbmoIRc15KKGXNSQixpyUUMuashFDbmoIRc15KKGXNSQixpyUUMuashFDbmoIRc15KKGXNSQixpyUUMuashFDbmoIRc15KKGXNSQixpyUUMuashFDbmoIRc15KKGXNSQixpyUUMuashFDbmoIRc15KKGXNSQixpyUUMuashFDbmoIRc15KKGXNSQixpyUUMuashFDbmoIRc15KKGXNSQmxpyU0NuashNDbmpITc15KaG3NSQmxpyU0NuashNDbmpITc15KaG3NSQmxpyU0NuashNDbmpITc15KaG3NSQmxpyU0NuashNDbmpITc15KaG3NSQmxpyU0NuashNDbmpITc15KaG3NSQmxpyU0NuashNDbmpITc15KaG3NSQmxpyU0NuashNDbmpITc15KaG3NSQmxpyU0NuashNDbmpITc15KaG3NSQ+/cYcrwMFg02DQ4NLg0eDP4eQ34dNBp0GgwapM0Z2pyhzRnanKHNGdqcpc1Z2pylzVnanKXNWdqcpc1Z2pylzVnanKPNOdqco8052pyjzTnanKPNOdqco8052Jx5PGjQaNBp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303ouwl9N6HvJvTdhL6b0HcT+m5C303ouwl9N6HvJvTdhL6b0HcT+m5C303ouwl9N6HvJvTdhL6b0HcT+m5C303ouwl9N6HvJvTdhL6b0HcT+m5C303ouwl9N6HvJvTdhL6b0HcT+m5C303ouwl9N6HvJvTdhL6b0HcT+m5C303ouwl9N6HvJvTdhL6b0HcT+m5C303ouwl9N6HvJvTdhL6b0HcT+m5C303ouwl9N6HvJvTdhL6b0HcT+m5C303ouwl9N6HvJvTdhL6b0HcT+m5C303ouwl9N6HvJvTdhL6b0HcT+m5C303ouwl9N6HvJvTdhL6b0HcT+m5C303ouwl9t6DvFvTdgr5b0HcL+m5B3y3ouwV9t6DvFvTdgr5b0HcL+m5B3y3ouwV9t6DvFvTdgr5b0HcL+m5B3y3ouwV9t6DvFvTdgr5b0HcL+m5B3y3ouwV9t6DvFvTdgr5b0HcL+m5B3y3ouwV9t6DvFvTdgr5b0HcL+m5B3y3ouwV9t6DvFvTdgr5b0HcL+m5B3y3ouwV9t6DvFvTdgr5b0HcL+m5B3y3ouwV9t6DvFvTdgr5b0HcL+m5B3y3ouwV9t6DvFvTdgr5b0HcL+m5B3y3ouwV9t6DvFvTdgr5b0HcL+m5B3y3ouwV9t6DvFvTdgr5b0HcL+m5B3y3ouwV9t6DvFvTdgr5b0Hcb+m5D323ouw19t6HvNvTdhr7b0Hcb+m5D323ouw19t6HvNvTdhr7b0Hcb+m5D323ouw19t6HvNvTdhr7b0Hcb+m5D323ouw19t6HvNvTdhr7b0Hcb+m5D323ouw19t6HvNvTdhr7b0Hcb+m5D323ouw19t6HvNvTdhr7b0Hcb+m5D323ouw19t6HvNvTdhr7b0Hcb+m5D323ouw19t6HvNvTdhr7b0Hcb+m5D323ouw19t6HvNvTdhr7b0Hcb+m5D323ouw19t6HvNvTdhr7b0Hcb+m5D323ouw19t6HvNvTdhr7b0Hcb+m5D323ouw19t6HvNvTdhr7b0Hcb+m5D323ouw19d6DvDvTdgb470HcH+u5A3x3ouwN9d6DvDvTdgb470HcH+u5A3x3ouwN9d6DvDvTdgb470HcH+u5A3x3ouwN9d6DvDvTdgb470HcH+u5A3x3ouwN9d6DvDvTdgb470HcH+u5A3x3ouwN9d6DvDvTdgb470HcH+u5A3x3ouwN9d6DvDvTdgb470HcH+u5A3x3ouwN9d6DvDvTdgb470HcH+u5A3x3ouwN9d6DvDvTdgb470HcH+u5A3x3ouwN9d6DvDvTdgb470HcH+u5A3x3ouwN9d6DvDvTdgb470HcH+u5A3x3ouwN9d6DvDvTdgb470HcH+u5A3x3ouwN9d6DvDvTdgb470HcX+u5C313ouwt9d6HvLvTdhb670HcX+u5C313ouwt9d6HvLvTdhb670HcX+u5C313ouwt9d6HvLvTdhb670HcX+u5C313ouwt9d6HvLvTdhb670HcX+u5C313ouwt9d6HvLvTdhb670HcX+u5C313ouwt9d6HvLvTdhb670HcX+u5C313ouwt9d6HvLvTdhb670HcX+u5C313ouwt9d6HvLvTdhb670HcX+u5C313ouwt9d6HvLvTdhb670HcX+u5C313ouwt9d6HvLvTdhb670HcX+u5C313ouwt9d6HvLvTdhb670HcX+u5C313ouwt9d6HvLvTdhb670HcX+u5C313ouwt996DvHvTdg7570HcP+u5B3z3ouwd996DvHvTdg7570HcP+u5B3z3ouwd996DvHvTdg7570HcP+u5B3z3ouwd996DvHvTdg7570HcP+u5B3z3ouwd996DvHvTdg7570HcP+u5B3z3ouwd996DvHvTdg7570HcP+u5B3z3ouwd996DvHvTdg7570HcP+u5B3z3ouwd996DvHvTdg7570HcP+u5B3z3ouwd996DvHvTdg7570HcP+u5B3z3ouwd996DvHvTdg7570HcP+u5B3z3ouwd996DvHvTdg7570HcP+u5B3z3ouwd996DvHvTdg7570HcP+u5B3z3ouwd996DvHvTdg757zHfzwXz3mTOYc5gLmEuYK5hrmBuYW5iDfTHYF4N9MdgXg30x2BeDfTHYF4N9MdgXg31x2BeHfXHYF4d9cdgXh31x2BeHfXHYF4d9CdiXgH0J2JeAfQnYl4B9CdiXgH0J2JeAfUnYl4R9SdiXhH1J2JeEfUnYl4R9SdiXhH0p2JeCfSnYl4J9KdiXgn0p2JeCfSnYl4J9adiXhn1p2JeGfWnYl4Z9adiXhn1p2JeGfRnYl4F9GdiXgX0Z2JeBfRnYl4F9GdiXgX1Z2JeFfVnYl4V9WdiXhX1Z2JeFfVnYl4V9OdiXg305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"},{"name":"constructor","function_type":"Secret","is_internal":false,"abi":{"parameters":[{"name":"inputs","type":{"kind":"struct","path":"aztec::context::inputs::private_context_inputs::PrivateContextInputs","fields":[{"name":"call_context","type":{"kind":"struct","path":"aztec::protocol_types::abis::call_context::CallContext","fields":[{"name":"msg_sender","type":{"kind":"struct","path":"aztec::protocol_types::address::AztecAddress","fields":[{"name":"inner","type":{"kind":"field"}}]}},{"name":"storage_contract_address","type":{"kind":"struct","path":"aztec::protocol_types::address::AztecAddress","fields":[{"name":"inner","type":{"kind":"field"}}]}},{"name":"portal_contract_address","type":{"kind":"struct","path":"aztec::protocol_types::address::EthAddress","fields":[{"name":"inner","type":{"kind":"field"}}]}},{"name":"function_selector","type":{"kind":"struct","path":"aztec::protocol_types::abis::function_selector::FunctionSelector","fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}]}},{"name":"is_delegate_call","type":{"kind":"boolean"}},{"name":"is_static_call","type":{"kind":"boolean"}},{"name":"is_contract_deployment","type":{"kind":"boolean"}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}]}},{"name":"historical_header","type":{"kind":"struct","path":"aztec::protocol_types::header::Header","fields":[{"name":"last_archive","type":{"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot","fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}]}},{"name":"body_hash","type":{"kind":"array","length":2,"type":{"kind":"field"}}},{"name":"state","type":{"kind":"struct","path":"aztec::protocol_types::state_reference::StateReference","fields":[{"name":"l1_to_l2_message_tree","type":{"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot","fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}]}},{"name":"partial","type":{"kind":"struct","path":"aztec::protocol_types::partial_state_reference::PartialStateReference","fields":[{"name":"note_hash_tree","type":{"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot","fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}]}},{"name":"nullifier_tree","type":{"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot","fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}]}},{"name":"contract_tree","type":{"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot","fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}]}},{"name":"public_data_tree","type":{"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot","fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}]}}]}}]}},{"name":"global_variables","type":{"kind":"struct","path":"aztec::protocol_types::abis::global_variables::GlobalVariables","fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"block_number","type":{"kind":"field"}},{"name":"timestamp","type":{"kind":"field"}},{"name":"coinbase","type":{"kind":"struct","path":"aztec::protocol_types::address::EthAddress","fields":[{"name":"inner","type":{"kind":"field"}}]}},{"name":"fee_recipient","type":{"kind":"struct","path":"aztec::protocol_types::address::AztecAddress","fields":[{"name":"inner","type":{"kind":"field"}}]}}]}}]}},{"name":"contract_deployment_data","type":{"kind":"struct","path":"aztec::protocol_types::contrakt::deployment_data::ContractDeploymentData","fields":[{"name":"public_key","type":{"kind":"struct","path":"aztec::protocol_types::grumpkin_point::GrumpkinPoint","fields":[{"name":"x","type":{"kind":"field"}},{"name":"y","type":{"kind":"field"}}]}},{"name":"initialization_hash","type":{"kind":"field"}},{"name":"contract_class_id","type":{"kind":"struct","path":"aztec::protocol_types::contract_class::ContractClassId","fields":[{"name":"inner","type":{"kind":"field"}}]}},{"name":"contract_address_salt","type":{"kind":"field"}},{"name":"portal_contract_address","type":{"kind":"struct","path":"aztec::protocol_types::address::EthAddress","fields":[{"name":"inner","type":{"kind":"field"}}]}}]}},{"name":"private_global_variables","type":{"kind":"struct","path":"aztec::context::globals::private_global_variables::PrivateGlobalVariables","fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}}]}}]},"visibility":"private"},{"name":"number","type":{"kind":"field"},"visibility":"private"},{"name":"owner","type":{"kind":"struct","path":"aztec::protocol_types::address::AztecAddress","fields":[{"name":"inner","type":{"kind":"field"}}]},"visibility":"private"}],"param_witnesses":{"inputs":[{"start":0,"end":36}],"number":[{"start":36,"end":37}],"owner":[{"start":37,"end":38}]},"return_type":{"abi_type":{"kind":"struct","path":"aztec::protocol_types::abis::private_circuit_public_inputs::PrivateCircuitPublicInputs","fields":[{"name":"call_context","type":{"kind":"struct","path":"aztec::protocol_types::abis::call_context::CallContext","fields":[{"name":"msg_sender","type":{"kind":"struct","path":"aztec::protocol_types::address::AztecAddress","fields":[{"name":"inner","type":{"kind":"field"}}]}},{"name":"storage_contract_address","type":{"kind":"struct","path":"aztec::protocol_types::address::AztecAddress","fields":[{"name":"inner","type":{"kind":"field"}}]}},{"name":"portal_contract_address","type":{"kind":"struct","path":"aztec::protocol_types::address::EthAddress","fields":[{"name":"inner","type":{"kind":"field"}}]}},{"name":"function_selector","type":{"kind":"struct","path":"aztec::protocol_types::abis::function_selector::FunctionSelector","fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}]}},{"name":"is_delegate_call","type":{"kind":"boolean"}},{"name":"is_static_call","type":{"kind":"boolean"}},{"name":"is_contract_deployment","type":{"kind":"boolean"}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}]}},{"name":"args_hash","type":{"kind":"field"}},{"name":"return_values","type":{"kind":"array","length":4,"type":{"kind":"field"}}},{"name":"max_non_revertible_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"read_requests","type":{"kind":"array","length":32,"type":{"kind":"struct","path":"aztec::protocol_types::abis::side_effect::SideEffect","fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}]}}},{"name":"nullifier_key_validation_requests","type":{"kind":"array","length":1,"type":{"kind":"struct","path":"aztec::protocol_types::abis::nullifier_key_validation_request::NullifierKeyValidationRequest","fields":[{"name":"public_key","type":{"kind":"struct","path":"aztec::protocol_types::grumpkin_point::GrumpkinPoint","fields":[{"name":"x","type":{"kind":"field"}},{"name":"y","type":{"kind":"field"}}]}},{"name":"secret_key","type":{"kind":"struct","path":"aztec::protocol_types::grumpkin_private_key::GrumpkinPrivateKey","fields":[{"name":"high","type":{"kind":"field"}},{"name":"low","type":{"kind":"field"}}]}}]}}},{"name":"new_commitments","type":{"kind":"array","length":16,"type":{"kind":"struct","path":"aztec::protocol_types::abis::side_effect::SideEffect","fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}]}}},{"name":"new_nullifiers","type":{"kind":"array","length":16,"type":{"kind":"struct","path":"aztec::protocol_types::abis::side_effect::SideEffectLinkedToNoteHash","fields":[{"name":"value","type":{"kind":"field"}},{"name":"note_hash","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}]}}},{"name":"private_call_stack_hashes","type":{"kind":"array","length":4,"type":{"kind":"field"}}},{"name":"public_call_stack_hashes","type":{"kind":"array","length":4,"type":{"kind":"field"}}},{"name":"new_l2_to_l1_msgs","type":{"kind":"array","length":2,"type":{"kind":"field"}}},{"name":"end_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"encrypted_logs_hash","type":{"kind":"array","length":2,"type":{"kind":"field"}}},{"name":"unencrypted_logs_hash","type":{"kind":"array","length":2,"type":{"kind":"field"}}},{"name":"encrypted_log_preimages_length","type":{"kind":"field"}},{"name":"unencrypted_log_preimages_length","type":{"kind":"field"}},{"name":"historical_header","type":{"kind":"struct","path":"aztec::protocol_types::header::Header","fields":[{"name":"last_archive","type":{"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot","fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}]}},{"name":"body_hash","type":{"kind":"array","length":2,"type":{"kind":"field"}}},{"name":"state","type":{"kind":"struct","path":"aztec::protocol_types::state_reference::StateReference","fields":[{"name":"l1_to_l2_message_tree","type":{"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot","fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}]}},{"name":"partial","type":{"kind":"struct","path":"aztec::protocol_types::partial_state_reference::PartialStateReference","fields":[{"name":"note_hash_tree","type":{"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot","fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}]}},{"name":"nullifier_tree","type":{"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot","fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}]}},{"name":"contract_tree","type":{"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot","fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}]}},{"name":"public_data_tree","type":{"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot","fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}]}}]}}]}},{"name":"global_variables","type":{"kind":"struct","path":"aztec::protocol_types::abis::global_variables::GlobalVariables","fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"block_number","type":{"kind":"field"}},{"name":"timestamp","type":{"kind":"field"}},{"name":"coinbase","type":{"kind":"struct","path":"aztec::protocol_types::address::EthAddress","fields":[{"name":"inner","type":{"kind":"field"}}]}},{"name":"fee_recipient","type":{"kind":"struct","path":"aztec::protocol_types::address::AztecAddress","fields":[{"name":"inner","type":{"kind":"field"}}]}}]}}]}},{"name":"contract_deployment_data","type":{"kind":"struct","path":"aztec::protocol_types::contrakt::deployment_data::ContractDeploymentData","fields":[{"name":"public_key","type":{"kind":"struct","path":"aztec::protocol_types::grumpkin_point::GrumpkinPoint","fields":[{"name":"x","type":{"kind":"field"}},{"name":"y","type":{"kind":"field"}}]}},{"name":"initialization_hash","type":{"kind":"field"}},{"name":"contract_class_id","type":{"kind":"struct","path":"aztec::protocol_types::contract_class::ContractClassId","fields":[{"name":"inner","type":{"kind":"field"}}]}},{"name":"contract_address_salt","type":{"kind":"field"}},{"name":"portal_contract_address","type":{"kind":"struct","path":"aztec::protocol_types::address::EthAddress","fields":[{"name":"inner","type":{"kind":"field"}}]}}]}},{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}}]},"visibility":"public"},"return_witnesses":[56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262]},"bytecode":"H4sIAAAAAAAA/+2dB5AcxRWGe6Mu6A4kGRsM2GtbEsiA2KjbI0oIiSAhhMiZPe2edHB3K04riSMHG2cb52xjbONs45xtjHME52xjnAPOiSR4PzejfYxWBVX3Buj66aq/JuxMz/t6ezq8menOJpy73U0FWXVJUUqUU9vpYD3czkS2s5HtGZHzuyPbfZHtnSLbsyLbcyLbuwTbOiSC5eJgWcovKpcbA8VGoVSo5YuDQ9VKvlwZWlQtVAuVaqVerJZKjWq5OjA4NDiQHyyUS43CcGWwNJyfCvNVXPlpBtjWpWyeK9oqmhcs55Mt9xXtFfxnOl32Ik0PnS57u6n7LwwJtb7ATd1LLki3MOScUV4t5wtZRJJ2HQPu60yw3quOSwb7dlb7Qrt7RP3B+rpGa01tvN4cWz7SGK1rsmQH2mjAFVOR43vVevhbd6d4FgfL/PRCQcdpXeQ83dDO8NYKbUTcyGL4e/eJpE3SOI1mGKbJvsZpAlbEmXPt4ifMONFieUGwRNhPHZ+MpOl+6riFQXw7uINM09kq7qFqcajQKAxW6vlaURK/XipXEu6BxZBz2+f3/PRCYa5dXPm4bJzngY0LYrAxDjsXOtsmVRj2d0HV42KrFgd0tZh1Dwy6EgqP0ZVVIt22LW1vWxHxZqzjlf+rV7FmAsNRtvco7myHJkA20gToCs6zti+huMO4w+3werB1VrA+3myNDE8unWjUWo36qmaroTNReILepwvxpFpPqWPTkX0I2Q7nh8cnOsSDgMTsitiiM1b42yPWuslPLxT2d/GUUtatF93imG7rJe/sWy+IMxdknk7N5UdzDZhQNoaZH5muiLQW7Rnsi6kUL+tSPJp2nUpx3IhzlE0xlN6FmErvUkyl7jZnBkI2iDu8TkalVdhRTTjbe6BLxZtw23eI02p9tmuHbrUe/s+h3TNdu9Du3sE56cg5fer3bAfunDH3DGVLTm2H18uofaiFw1ZHStkWRz7TLZ0wRO+tnFrXecT8fpK0Qo0fliPicFi9aWh0ZO2KxuSS8frq2kRrpDa6pF6faGzc2KkwSkUAdlRjP5jvoleBptS+aMtAFzrasxKeozNlbLV+tF+LEhn92WKw3F1Udtv3f8vB76VgCTduJWJjtHaebo1qWBsVKnZx5VNu+36Bc/a1sWFpmu9grhe+iTjTt+DiSV9rO4vOtkZ/zNfD5+vRlVxYTi8SDbgpnwpCTC3xmm6J62sgPFR/Sm/7Z5dU+7ZVvGrftopXXdO8dVzOV7pcm8cs3sCnvptr2x5DT6QaUwux+FhPxLldXTsw9ET6gnX0RLoiPsI4bYuWV10R23pc21fcGBtpLRtfOzG5QfyBK5vrdANb5xkXSVvNgqDrTu3yy3Q4V6dftJHfKeyoAwKumcF6ztndqygrezrYoENOrc9U9vTa21OIifP++rlPcfREePrU7/q+7ouBMaGuG8at7Yhee6uzTYf+B0mH/g629D/M6RBer1ft088h9O/hMhlh0W2I8PiHzZ1u7abWcU23U1119g3fOJgThsyDnjAnDZkP8IQ5Zch8oCfMaUPmgzxhzhgyH+wJc9aQ+RBPmC1fCDvUE+a9DZkXe8I835B5CSHzYYTMSwmZDydkXkbIvJyQ+QhC5iMJmY8iZD6akHkFIfNKQuZjCJlXETIfS8i8mpD5OELmNYTMxxMyn0DIfCIh80mEzCcTMp9CyHwqIfNphMynEzKfQch8JiHzWYTMZxMyn0PIXCNkHiJkXkvIXCdkbhAyDxMyryNkXk/IPELIfC4h83mEzKOEzGOEzOOEzE1C5g2EzOcTMk8QMm8kZG4RMm8iZN5MyLyFkPkCQuZJQuYLCZkvImS+mJD5EkLmSwmZLyNkvpyQ+QpC5isJma8iZH4GIfMzCZmvJmR+FiHzswmZn+MJ80JD5ud6wmw5hcvzPGG2zNvPJ2R+ASHzCwmZX0TIfA0h84sJmV9CyPxSQuaXETK/nJD5FYTMryRkfhUh86sJmV9DyPxaQubXETK/npD5DYTMbyRkvpaQ+U2EzNcRMr+ZkPkthMxvJWS+npD5bYTMbydkfocnzPsYMr+T8H9+lyfMlnP8vJvwf34PIfN7CZnfR8h8AyHz+wmZP0DI/EFC5g8RMn+YkPkjhMwfJWT+GCHzxwmZP0HI/ElC5k8RMn+akPkzhMyfJWS+kZD5c4TMNxEyf56Q+QuEzF8kZP4SIfOXCZm/Qsj8VULmrxEyf52Q+RuEzN8kZP4WIfPNhMy3EDJ/m5D5O4TM3yVk/h4h8/cJmX9AyPxDQuYfETL/mJD5J4TMPyVk/hkh888JmX9ByPxLQuZbCZl/Rch8GyHzrz1hzhsy/4bwf/4tIfPvCJl/T8j8B0LmPxIy/8kT5i5D5j97wtxtyPwXT5h7DJlv94S515D5r54wzzRk/psnzH2GzH/3hLnfkPkfnjDvZMj8T0+YdzZk/pcnzLMMmf/tCfNsQ+b/eMI8x5D5v54wP86Q+X+eMO9iyPx/T5gfb8h8hyfMTzBkvtMT5l0Nme/yhHk3Q+a7PWF+oiHzPZ4w727IvNUT5j0Mme/1hHlPQ2aX8IP5SYbMCU+Yn2zInPSEOWfInPKE+SmGzGlPmJ9qyJzxhPlphsxZQ2aJyqWCuOYr/kSQBvgtLcqIsiKMR4vnUHgug+cU8NvDjw2/Lvyc8PvBDwa/EPwk8BugH41+JfpZ6HegHY52KdppaLegHke9hnIe5V5OhPsC+QTpNlc0T9l2c7CsigZFB4gOFB0kOlh0iOjQIL2XiA4TLRUdLlomWi46QnSk6CjR0aIVopWiY0SrRMeKVouOE60RHS86QXSi6CTRyaJTRKeKThOdLjpDdKboLNHZonNENdGQaK2oLmqIhkXrROtFI6JzReeJRkVjonFRU7RBdL5oQrRR1BJtEm0WbRFdIJoUXSi6SHSx6BLRpaLLRJeLrhBdKbpKhPnhMV/61SLMp435pTHfMuYfxny8mJ8W87Vi/lLM53mNCPM9Yv5DzAeI+fEwXxzmT8N8YphfC/NNYf4lzEeE+XkwXw3mb8F8JteKMN/FdSLMh4D5ATBe/vUijKeO8cUx3jbGn8Z4zBifGOP1YvxajOd6gwjjfWL8S4wHifERMV4gxs/DeHIYXw3jjWH8LYxHhfGZMF4Rxu/BeDY3ijDeyU0ijIeB8SEwXgLGD8D39Pi+HN9b4/tjfI+L71PxvSa+X0Qeu0WE773w/RO+B8L3MfheBN9P4HsCvF+P983x/jXeR8b7uXhfFe9v4n3GW0V43+02Ed6HwvtBeF8G74/gfQq8X4Dn7Xj+jOexeD6J53V4foXnOXi+AX8//N/wB8M/Cn8h/GfwJ8G/An8D+t/oj6J/hv4K2u9oz+ImRnsH9T/qQ9QPKC9RfoTlG8LsYLlHsKy1Wo2xDa1cq5mr1eu5LSOt9bnm5sbE8GgT2e7++/chH38fqRiuiQnvAAA=","debug_symbols":"3VjbbuIwEP2XPCPkuXhmzK+s9iG7y0pIiFYFrbRC/HudFDtpamE1SLTwBEFnJsdnbh6Ozfbpd3vYPO32zerYADSrH8dm/9zuusf9oX05NCu3aNa7P/HztGj+brbrZsV0WnyAgQ9nIBhkqNcCFNHojEXiwS+wLzkGEp9cA2N4h/+5aADvkzbdiDaDJtqsejVtLtEWTu8QlcvUMWh6AYYReTDq/fuif5OzjRLX/FvyTw4HMDgpquOS5OgBKui6OnLX7PVK9uSIM3utsTfIWWOgfkhj7snYdyITriYzxBW4FinjxNwMM1aLCROjmlIgxjSDzZX8WjpjgHAZCtFxyhX0+K5MZ6QWuocQMFiqN3DkKgpWNYGbahJ/tUwnhLEqHRn8MjIIOCVDtyWDmAOFYpfzRTUksBrSpFEg3y1zf2PmIScAMVVqlDHPOWapNCPO9zRPQyMP2J9SHuWUCqnF6QgbT/kRKh4TCxEbJIkNalbf0kfRUAImzsKXNYSh9SOMWv9cDe1h8lDzvcnptNrCdz6lTzRQFCqnJE0LV6yljI0dt1+JlsXeGfKONhpwcfD2o38JxRtR3DGTFZrQdDvq7GCmXXHAe0kiiB9VgLxNhGX53kucZKZg05D7ZfmuVzOCOUY4x4g+bRSW5eno84bhFSdZ0RnJHKNydyWXq2zI1RB7SXz4175s2l/bdfcvTnw8/H9++3p6BQ=="},{"name":"compute_note_hash_and_nullifier","function_type":"Unconstrained","is_internal":false,"abi":{"parameters":[{"name":"contract_address","type":{"kind":"struct","path":"aztec::protocol_types::address::AztecAddress","fields":[{"name":"inner","type":{"kind":"field"}}]},"visibility":"private"},{"name":"nonce","type":{"kind":"field"},"visibility":"private"},{"name":"storage_slot","type":{"kind":"field"},"visibility":"private"},{"name":"serialized_note","type":{"kind":"array","length":3,"type":{"kind":"field"}},"visibility":"private"}],"param_witnesses":{"contract_address":[{"start":0,"end":1}],"nonce":[{"start":1,"end":2}],"serialized_note":[{"start":3,"end":6}],"storage_slot":[{"start":2,"end":3}]},"return_type":{"abi_type":{"kind":"array","length":4,"type":{"kind":"field"}},"visibility":"public"},"return_witnesses":[6,7,8,9]},"bytecode":"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","debug_symbols":"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DLu0DLu0DLu0DLu0DLu0DLu0DLu0DLu0DLu0DLu0DLu0DLu0DLu0DLu0DLu0DLu0DLu0DLu0DLu0Dbu0Dbu0Dbu0Dbu0b0SLbsMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMubcMutZuBl44cRI8eOYgiPXIQTXrkIKr0yEF06ZGDKNMjB9GmRw6iTo8cSJ8ajOnIgfSpAZmOHEifGpTpyIH0qYGZjhxInxqc6ciB9KkBmo4cSJ8apOnIgfSpgZqOHEifGqzpyIH0qQGbjhxInxq06ciB9KmBm44cSJ8avOnIgfSpAZyOHEifGsTpyIH0qYGcjhxInxrM6ciB9KkBnY4cSJ8a1OnIgfSpgZ2OHEifGtzpyIH0qQGejhxInxrk6ciB9KmBno4cSJ8a7OnIgfSpAZ+OHEifGvTpyIH0qYGfjhxInxr86ciB9KkBoI4cSJ8aBOrIgfSpgaCOHEifGgzqyIH0qQGhjhxInxoU6siB9KmBoY4cSJ8aHOrIgfSpAaKOHEifGiTqyIH0qYGijhxInxos6siB9KkBo44cSJ8aNOrIgfTpP4ajarzlmLd/MMdEciwkxyZytH/MR90xR0NyBJKjIzkSyVFIDqNP283o03Yz+rTdkD5tSJ82pE8b0qcN6dOG9GlD+rQhfdqQPm1InzakTwPp00D6NJA+DaRPA+nTQPo0kD4NpE8D6dNA+rQjfdqRPu1In3akTzvSpx3p0470aUf6tCN92pE+TaRPE+nTRPo0kT5NpE8T6dNE+jSRPk2kTxPp00L6tJA+LaRPC+nTQvq0kD4tpE8L6dNC+rSQPh1Inw6kTwfSpwPp04H06UD6dCB9OpA+HUifDqRPJ9KnE+nTifTpRPp0In06kT6dSJ9OpE8n0qcT6dOF9OlC+nQhfbqQPl1Iny6kTxfSpwvp04X06UL6dCN9upE+3UifbqRPN9KnG+lTxEc1xEc1xEc1xEcF4qMC8VGB+KhAfFTcjD4NxEcF4qMC8VGB+KhAfFQgPioQHxWIjwrERwXiowLxUYH4qEB8VCA+KhAfFYiPCsRHBeKjAvFRgfioQHxUID4qEB8ViI8KxEcF4qMC8VGB+KhAfFQgPioQHxWIjwrERwXiowLxUYH4qEB8VCA+KhAfFYiPCsRHBeKjAvFRgfioQHxUID4qEB8ViI8KxEcF4qMC8VGB+KhAfFQgPioQHxWIjwrERwXiowLxUYH4qEB8VCA+KhAfFYiPCsRHBeKjAvFRgfioQHxUID4qEB8ViI8KxEcF4qMC8VGB+KhAfFQgPioQHxWIjwrERwXiowLxUYH4qEB8VCA+KhAfFYiPCsRHBeKjAvFRgfioQHxUID4qEB/VER/VER/VER/VER/Vb0afdsRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHdcRHJeKjEvFRifioRHxU3ow+TcRHJeKjEvFRifioRHxUIj4qER+ViI9KxEcl4qMS8VGJ+KhEfFQiPioRH5WIj0rERyXioxLxUYn4qER8VCI+KhEflYiPSsRHJeKjEvFRifioRHxUIj4qER+ViI9KxEcl4qMS8VGJ+KhEfFQiPioRH5WIj0rERyXioxLxUYn4qER8VCI+KhEflYiPSsRHJeKjEvFRifioRHxUIj4qER+ViI9KxEcl4qMS8VGJ+KhEfFQiPioRH5WIj0rERyXioxLxUYn4qER8VCI+KhEflYiPSsRHJeKjEvFRifioRHxUIj4qER+ViI9KxEcl4qMS8VGJ+KhEfFQiPioRH5WIj0rERyXioxLxUYn4qER8VCI+KhEfVYiPKsRHFeKjCvFRdTP6tBAfVYiPKsRHFeKjCvFRhfioQnxUIT6qEB9ViI8qxEcV4qMK8VGF+KhCfFQhPqoQH1WIjyrERxXiowrxUYX4qEJ8VCE+qhAfVYiPKsRHFeKjCvFRhfioQnxUIT6qEB9ViI8qxEcV4qMK8VGF+KhCfFQhPqoQH1WIjyrERxXiowrxUYX4qEJ8VCE+qhAfVYiPKsRHFeKjCvFRhfioQnxUIT6qEB9ViI8qxEcV4qMK8VGF+KhCfFQhPqoQH1WIjyrERxXiowrxUYX4qEJ8VCE+qhAfVYiPKsRHFeKjCvFRhfioQnxUIT6qEB9ViI8qxEcV4qMK8VGF+KhCfFQhPqoQH1WIjyrERxXiowrxUYX4qEJ81EB81EB81EB81EB81LgZfToQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzUQHzURHzURHzURHzURHzVvRp9OxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEdNxEctxEctxEctxEctxEetm9GnC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRC/FRG/FRG/FRG/FRG/FR+2b06UZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81EZ81DZ81PE1ok+PrxF9enyN6NPja0SfHl8j+vT4GtGnx9eIPj2+RvTp8TWiT4+vIX1q+KgjB9Knho86ciB9avioIwfSp4aPOnIgfWr4qCMH0qeGjzpyIH1q+KgjB9Knho86ciB9avioIwfSp4aPOnIgfWr4qCMH0qeGjzpyIH1q+KgjB9Knho86ciB9avioIwfSp4aPOnIgfWr4qCMH0qeGjzpyIH1q+KgjB9Knho86ciB9avioIwfSp4aPOnIgfWr4qCMH0qeGjzpyIH1q+KgjB9Knho86ciB9avioIwfSp4aPOnIgfWr4qCMH0qeGjzpyIH1q+KgjB9Knho86ciB9avioIwfSp4aPOnIgfWr4qCMH0qeGjzpyIH1q+KgjB9Knho86ciB9avioIwfSp4aPOnIgfWr4qCMH0qeGjzpyIH1q+KgjB9Knho86ciB9avioI4fRpw3xUQ3xUQ3xUQ3xUe1m9GlDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFRDfFQgPioQHxWIjwrER8XN6NNAfFQgPioQHxWIjwrERwXiowLxUYH4qEB8VCA+KhAfFYiPCsRHBeKjAvFRgfioQHxUID4qEB8ViI8KxEfFxz6qxXw7Q+v979K8HTc/edyHfdV6vl16y6xfvvo+Vvz4zcf/9vdvXrf3k+wHnORjOfQ/PEn+7CT585N8cCdbH/X2o1vGfv/2dpznLVQTQ4UYqouhUgxVYqghhppiqCWG2mCoFBs9xUZPsdFTbPQUGz3FRk+x0VNs9BQbPcVGL7HRS2z0Ehu9xEYvsdHrwT1Vrf34vRU/bfPbjPdACws0HvyvrvrbTas+PgwUWqCuBUotUGmBftXHTG8nmY84yT36In52kvrl0e5b/vi9O+Kn0a73JyrHxgLNmxaoaYFCC9S1QKkFqgcHGust0BofBhpaoKkFWlqgjQVaNy1Q0wI9uKnbrfW3n3w7fvn5UaTuRUovUnmRhhdpepGWF+lX7e0fT7JvjzhJe8RJ4hEn6Y84ST7iJPWIk4xHnGQ+4iTrESd5wL/4frs94iTtESeJR5ykP+Ik+YiT1CNOMh5xkvmIk6xHnOQR/+LbHf7Fr9v7SVa27zy2+W/8Rqa3JoYKMVQXQ6UYqsRQQww1xVB3aNw1b++h9v7lUGu9vfZ7t+98a4v335+2qL9/qvazV7tf6Wrj9lJX217qauOlrra/1NXmS11tvdTVjpe62vlSV/tSj6XipR5L9Zd6LNVf6rFUf6nHUv2lHkvdQy+e6Gpf6rFUf6nHUv2lHkv1Bz+W2uv9B99+9iYBn39ire+TX0Dezn4B7ewXEGe/gH72C8izX0Cd/QLG2S9gnv0Czr4S59lX4jr7SlxnX4nr7CvxPdTyjv12AXt/56W2dXv7wVXzHvnz5Pnr5PnHyfPPk+dfJ8+/z51/3E6ev508f5w8/8nX33u87cFT8598/R0nX3/HydffcfL19w7vHJG3/vba07yt9cuhfnqn2tn3HfLf4Y0mnpu/nTx/nDx/P3n+PHn+Onn+cfL88+T518nzn3z9XSdff9fJ19918vV3nXz9vcPbnjw3/x3W39beXhCU7bubkhXvP3nVzyJ9+IqgmPvt9UOxbn83mrf84+T5t5y/9/cPb+l99+/86Lq95WiV339l2HuOqO+Axee+4uwO78py3aJf+Ra16xbptyiuW6Tfon7dIv0W5XWL9FtEP6K+btHfbhG9abhu0d9u0bxukX6L1nWL9Ft0PbuA36K8Xc8u8LfoenaBv0XXswv8LbqeXeBvUV63SL9F17ML/C26nl3gb9H17AJ/i65nF/hbdD278P1bdG+xm+16wuAZU7+eA3jG1K9t/TOmfu3UnzH1vKb+hKlf++lnTP3aIj9j6teu9xlTvzayz5j6tTd9wtTj2ps+Y+rX3vQZU7/2ps+Y+rU3fcbU81WnXuvtm/v3nmG/81uzZLzs1vSZQ3/Znekzh/6yG9NnDv1l96XPHPrLbkufOPT+srvSZw79ZTelzxz6y+5Jnzn0l92SPnPoeQ398UO/dqRPGPq1I33C0K8d6ROGfu1InzD0a0f6+KHnV9qRvn9zG7fv5LjzuxdmfqVN5jPn+JX2jc+c41faCj5zjnnN8S5z/EobtmfO8SvtwZ45x6+0rXrmHL/STumZc/xKm58nzrGu/cx95njtZ+4zx2s/c585XvuZ+8wxrzneZY7XfuY+c6QfP8a+vT01G7t/5wNRTvR+GUU/2vyqUx/0Y9MvO3X6keyXnTr9uPfLTp1+lPxlp57X1J8wdfvz4r7q1O1PufuqU6d/W/Flp37tTZ8x9Wtv+oSpz2tv+oypX3vTZ0z92ps+Y+rX3vQZU89r6k+Y+rU3fcbUr73pM6Z+7U2fMfUX3Zve/Q2l5otuN+8+yPWiO8j7D/JFN4X3H+SL7vPuP8gX3brdf5B5DfI+g3zRDdb9B/mie6b7D/JFt0H3H+S1s7nTIK+dzX0Gua+dzZ0Gee1s7jTIa2dzp0F+pZ3NE99GZuc1x7vM8Svta545x6+0rXnmHL/SruaZc/xKm5pnzvEr7WmeN8fjx11zvMscv9KO5plz/EobmmfO8drP3GeOec3xLnO89jP3meO1n7nPHK/9zH3meO1n7jLH9vD1+v39W9pu6ztz3O9Xu/OnZ1v3fE+fp05fp04/Tp1+njr9OnX6feb0j/9g77umb6dOH6dOf+q19vEffHzX9Kdea+PUa22ceq2NU6+1ceq1tp96re2nXmv7qdfafuq19vEf6XjX9Kdea/up19p+6rW2n3qt7adea/PUa22eeq3NU6+1eeq19vEfsHXX9Kdea/PUa22eeq3NU6+1eeq1tk691tap19o69Vpbp15rH//hL3dNf+q1tk691tap19o69Vpbp15rx6nX2nHqtXaceq0dp15rH/+hEHdNf+q1dpx6rR2nXmvHqdfaceq1dp56rZ2nXmvnqdfaeeq19vFvcn3X9Kdea+ep19p56rV2nnqtnadea9ep19p16rV2nXqtXadeax//FqZ3TX/qtXadeq1dp15r16nX2nXqtXafeq3dp15r96nX2n3qtfbx76p31/SnXmv3qdfafeq1dp96rd1nXmvH7cxr7bidea0dtzOvteN25rV23M681o7bmdfa8fB3N9r77SdHu93j89jGw99Y6Fe4hHX+S9inv4R2O/8ltPNfQpz/Evr5LyHPfwl1/ks4/+rczr86t/Ovzu38q3Ocf3WO86/Ocf7VOc6/Oj/8Hal+hUs4/+p8B0/XR75t5vtY+cuXUO8fZV7x016+zXgP1LVAqQUqLdDQAs0HB8p8C1T5YaD16EC390D1YaCNBbqD87pzoKYFCi1Q1wI9uqn72/JafXwYqLRAQws0tUBLC7SxQPOmBWpaoNACdS2Q1tRTa+qpNfXUmnpqTT21pl5aUy+tqZfW1Etr6qU19dKaemlNvbSmXlpTL62pt9bUW2vqrTX11pp6a029tabeWlNvram31tQba+r58Wusc7z/AuBnv5Z7f4Xq/Pi1zd89Kj91VH3qqPGpo+anjlqfOurDvwq1+ttR+6OjPn495HePap86Kj51VP/UUfmpo+pTR334d6P22y+ux218dNT81FHrU0ftzxz18atxvntU+9RR8amjPvy7cfx+8+2o8eFR+amj6lNHjU8dNT911PrUUfszR3382UXHM6lvR62P/qV8/JlB3z0qPnVU/9RR+amj6lNHjf/ZUccf/u2Hf/39D//3D7/703HA8cc///u//Of//vU/AA=="}],"events":[],"file_map":{"3":{"source":"struct BoundedVec {\n storage: [T; MaxLen],\n // TODO: change this to return a u64 as Noir now\n // uses u64 for indexing\n len: Field,\n empty_value: T,\n}\n\nimpl BoundedVec {\n pub fn new(initial_value: T) -> Self {\n BoundedVec { storage: [initial_value; MaxLen], len: 0, empty_value: initial_value }\n }\n\n pub fn get(mut self: Self, index: Field) -> T {\n assert(index as u64 < self.len as u64);\n self.storage[index]\n }\n\n pub fn get_unchecked(mut self: Self, index: Field) -> T {\n self.storage[index]\n }\n\n pub fn push(&mut self, elem: T) {\n assert(self.len as u64 < MaxLen as u64, \"push out of bounds\");\n\n self.storage[self.len] = elem;\n self.len += 1;\n }\n\n pub fn len(self) -> Field {\n self.len\n }\n\n pub fn max_len(_self: BoundedVec) -> Field {\n MaxLen\n }\n\n // This is a intermediate method, while we don't have an\n // .extend method\n pub fn storage(self) -> [T; MaxLen] {\n self.storage\n }\n\n pub fn extend_from_array(&mut self, array: [T; Len]) {\n let new_len = self.len + array.len();\n assert(new_len as u64 <= MaxLen as u64, \"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 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 as u64 <= MaxLen as u64, \"extend_from_bounded_vec out of bounds\");\n\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 as Field)] = vec.get_unchecked(i as Field);\n }\n }\n self.len = new_len;\n }\n\n pub fn pop(&mut self) -> T {\n assert(self.len as u64 > 0);\n self.len -= 1;\n\n let elem = self.storage[self.len];\n self.storage[self.len] = self.empty_value;\n elem\n }\n\n pub fn any(self, predicate: fn[Env](T) -> bool) -> bool {\n let mut ret = false;\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 ret\n }\n}","path":"std/collections/bounded_vec.nr"},"31":{"source":"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::unsafe::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 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","path":"std/option.nr"},"43":{"source":"contract Blank {\n use dep::aztec::{\n protocol_types::address::AztecAddress,\n state_vars::singleton::Singleton,\n context::{PrivateContext, PublicContext, Context},\n note::{\n utils as note_utils,\n note_interface::NoteInterface,\n note_header::NoteHeader,\n },\n };\n\n use dep::value_note::value_note::{ValueNote, VALUE_NOTE_LEN};\n\n use dep::easy_private_state::easy_private_state::EasyPrivateUint;\n\n struct Storage {\n number: Singleton,\n }\n\n #[aztec(private)]\n fn constructor(number: Field, owner: AztecAddress) {\n let mut new_number = ValueNote::new(number, owner);\n storage.number.initialize(&mut new_number, true);\n }\n\n #[aztec(private)]\n fn setNumber(number: Field) {\n let mut new_number = ValueNote::new(number, context.msg_sender());\n storage.number.replace(&mut new_number, true);\n }\n\n unconstrained fn getNumber() -> pub ValueNote {\n storage.number.view_note()\n }\n\n unconstrained fn compute_note_hash_and_nullifier(\n contract_address: AztecAddress,\n nonce: Field,\n storage_slot: Field,\n serialized_note: [Field; VALUE_NOTE_LEN]\n ) -> pub [Field; 4] {\n let note_header = NoteHeader::new(contract_address, nonce, storage_slot);\n note_utils::compute_note_hash_and_nullifier(ValueNote::deserialize_content, note_header, serialized_note)\n }\n}\n","path":"/mnt/user-data/sean/docs/aztec3-packages/boxes/blank-react/src/contracts/src/main.nr"},"46":{"source":"mod globals;\nmod inputs;\n\nmod private_context;\nmod public_context;\nmod avm;\n\nuse private_context::PrivateContext;\nuse public_context::PublicContext;\nuse avm::AVMContext;\n\nstruct Context {\n private: Option<&mut PrivateContext>,\n public: Option<&mut PublicContext>,\n}\n\nimpl Context {\n pub fn private(context: &mut PrivateContext) -> Context {\n Context { private: Option::some(context), public: Option::none() }\n }\n\n pub fn public(context: &mut PublicContext) -> Context {\n Context { public: Option::some(context), private: Option::none() }\n }\n\n pub fn none() -> Context {\n Context { public: Option::none(), private: Option::none() }\n }\n}\n","path":"/mnt/user-data/sean/nargo/github.com/AztecProtocol/aztec-packages/master/yarn-project/aztec-nr/aztec/src/context.nr"},"54":{"source":"use crate::{\n context::inputs::PrivateContextInputs, key::nullifier_key::validate_nullifier_key_against_address,\n messaging::process_l1_to_l2_message,\n oracle::{\n arguments, call_private_function::call_private_function_internal,\n enqueue_public_function_call::enqueue_public_function_call_internal, context::get_portal_address,\n header::get_header_at, nullifier_key::{get_nullifier_key_pair, NullifierKeyPair}\n}\n};\nuse dep::protocol_types::{\n abis::{\n call_context::CallContext, function_data::FunctionData, function_selector::FunctionSelector,\n nullifier_key_validation_request::NullifierKeyValidationRequest,\n private_call_stack_item::PrivateCallStackItem,\n private_circuit_public_inputs::PrivateCircuitPublicInputs,\n public_call_stack_item::PublicCallStackItem,\n public_circuit_public_inputs::PublicCircuitPublicInputs,\n side_effect::{SideEffect, SideEffectLinkedToNoteHash}\n},\n address::{AztecAddress, EthAddress},\n constants::{\n MAX_NEW_COMMITMENTS_PER_CALL, MAX_NEW_L2_TO_L1_MSGS_PER_CALL, MAX_NEW_NULLIFIERS_PER_CALL,\n MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL,\n MAX_PUBLIC_DATA_READS_PER_CALL, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL,\n MAX_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL, NUM_FIELDS_PER_SHA256,\n RETURN_VALUES_LENGTH\n},\n contrakt::{storage_read::StorageRead, storage_update_request::StorageUpdateRequest},\n grumpkin_private_key::GrumpkinPrivateKey, hash::hash_args, header::Header, utils::reader::Reader\n};\nuse dep::std::option::Option;\n\n// TODO(https://github.com/AztecProtocol/aztec-packages/issues/1165)\n// use dep::std::collections::vec::Vec;\n\n// When finished, one can call .finish() to convert back to the abi\nstruct PrivateContext {\n // docs:start:private-context\n inputs: PrivateContextInputs,\n side_effect_counter: u32,\n\n max_non_revertible_side_effect_counter: u32,\n\n args_hash : Field,\n return_values : BoundedVec,\n\n read_requests: BoundedVec,\n nullifier_key_validation_requests: BoundedVec,\n\n new_commitments: BoundedVec,\n new_nullifiers: BoundedVec,\n\n private_call_stack_hashes : BoundedVec,\n public_call_stack_hashes : BoundedVec,\n new_l2_to_l1_msgs : BoundedVec,\n // docs:end:private-context\n\n // Header of a block whose state is used during private execution (not the block the transaction is included in).\n historical_header: Header,\n\n // TODO(https://github.com/AztecProtocol/aztec-packages/issues/1165)\n // encrypted_logs_preimages: Vec,\n // unencrypted_logs_preimages: Vec,\n\n nullifier_key: Option,\n}\n\nimpl PrivateContext {\n pub fn new(inputs: PrivateContextInputs, args_hash: Field) -> PrivateContext {\n PrivateContext {\n inputs,\n side_effect_counter: inputs.call_context.start_side_effect_counter,\n max_non_revertible_side_effect_counter: 0,\n args_hash,\n return_values: BoundedVec::new(0),\n read_requests: BoundedVec::new(SideEffect::empty()),\n nullifier_key_validation_requests: BoundedVec::new(NullifierKeyValidationRequest::empty()),\n new_commitments: BoundedVec::new(SideEffect::empty()),\n new_nullifiers: BoundedVec::new(SideEffectLinkedToNoteHash::empty()),\n historical_header: inputs.historical_header,\n private_call_stack_hashes: BoundedVec::new(0),\n public_call_stack_hashes: BoundedVec::new(0),\n new_l2_to_l1_msgs: BoundedVec::new(0),\n // TODO(https://github.com/AztecProtocol/aztec-packages/issues/1165)\n // encrypted_logs_preimages: Vec::new(),\n // unencrypted_logs_preimages: Vec::new(),\n nullifier_key: Option::none()\n }\n }\n\n pub fn msg_sender(self) -> AztecAddress {\n self.inputs.call_context.msg_sender\n }\n\n pub fn this_address(self) -> AztecAddress {\n self.inputs.call_context.storage_contract_address\n }\n\n pub fn this_portal_address(self) -> EthAddress {\n self.inputs.call_context.portal_contract_address\n }\n\n pub fn chain_id(self) -> Field {\n self.inputs.private_global_variables.chain_id\n }\n\n pub fn version(self) -> Field {\n self.inputs.private_global_variables.version\n }\n\n pub fn selector(self) -> FunctionSelector {\n self.inputs.call_context.function_selector\n }\n\n // Returns the header of a block whose state is used during private execution (not the block the transaction is\n // included in).\n pub fn get_header(self) -> Header {\n self.historical_header\n }\n\n // Returns the header of an arbitrary block whose block number is less than or equal to the block number\n // of historical header.\n pub fn get_header_at(self, block_number: u32) -> Header {\n get_header_at(block_number, self)\n }\n\n pub fn finish(self) -> PrivateCircuitPublicInputs {\n // TODO(https://github.com/AztecProtocol/aztec-packages/issues/1165)\n let encrypted_logs_hash = [0; NUM_FIELDS_PER_SHA256];\n let unencrypted_logs_hash = [0; NUM_FIELDS_PER_SHA256];\n let encrypted_log_preimages_length = 0;\n let unencrypted_log_preimages_length = 0;\n\n let priv_circuit_pub_inputs = PrivateCircuitPublicInputs {\n call_context: self.inputs.call_context,\n args_hash: self.args_hash,\n return_values: self.return_values.storage,\n max_non_revertible_side_effect_counter: self.max_non_revertible_side_effect_counter,\n read_requests: self.read_requests.storage,\n nullifier_key_validation_requests: self.nullifier_key_validation_requests.storage,\n new_commitments: self.new_commitments.storage,\n new_nullifiers: self.new_nullifiers.storage,\n private_call_stack_hashes: self.private_call_stack_hashes.storage,\n public_call_stack_hashes: self.public_call_stack_hashes.storage,\n new_l2_to_l1_msgs: self.new_l2_to_l1_msgs.storage,\n end_side_effect_counter: self.side_effect_counter,\n encrypted_logs_hash,\n unencrypted_logs_hash,\n encrypted_log_preimages_length,\n unencrypted_log_preimages_length,\n historical_header: self.historical_header,\n contract_deployment_data: self.inputs.contract_deployment_data,\n chain_id: self.inputs.private_global_variables.chain_id,\n version: self.inputs.private_global_variables.version\n };\n priv_circuit_pub_inputs\n }\n\n pub fn capture_max_non_revertible_side_effect_counter(&mut self) {\n assert(\n self.max_non_revertible_side_effect_counter == 0, \"Already captured the non-revertible side effect counter\"\n );\n self.max_non_revertible_side_effect_counter = self.side_effect_counter;\n }\n\n pub fn push_read_request(&mut self, read_request: Field) {\n let side_effect = SideEffect { value: read_request, counter: self.side_effect_counter };\n self.read_requests.push(side_effect);\n self.side_effect_counter = self.side_effect_counter + 1;\n }\n\n pub fn push_new_note_hash(&mut self, note_hash: Field) {\n let side_effect = SideEffect { value: note_hash, counter: self.side_effect_counter };\n self.new_commitments.push(side_effect);\n self.side_effect_counter = self.side_effect_counter + 1;\n }\n\n pub fn push_new_nullifier(&mut self, nullifier: Field, nullified_commitment: Field) {\n let side_effect = SideEffectLinkedToNoteHash { value: nullifier, note_hash: nullified_commitment, counter: self.side_effect_counter };\n self.new_nullifiers.push(side_effect);\n self.side_effect_counter = self.side_effect_counter + 1;\n }\n\n pub fn request_nullifier_secret_key(&mut self, account: AztecAddress) -> GrumpkinPrivateKey {\n let key_pair = if self.nullifier_key.is_none() {\n let key_pair = get_nullifier_key_pair(account);\n validate_nullifier_key_against_address(account, key_pair.public_key);\n let request = NullifierKeyValidationRequest { public_key: key_pair.public_key, secret_key: key_pair.secret_key };\n self.nullifier_key_validation_requests.push(request);\n self.nullifier_key = Option::some(key_pair);\n key_pair\n } else {\n let key_pair = self.nullifier_key.unwrap_unchecked();\n // If MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL is larger than 1, need to update the way the key pair is cached.\n assert(MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL == 1);\n assert(\n key_pair.account == account, \"Cannot query nullifier key for more than one account per call\"\n );\n key_pair\n };\n key_pair.secret_key\n }\n\n // docs:start:context_message_portal\n pub fn message_portal(&mut self, content: Field) {\n // docs:end:context_message_portal\n self.new_l2_to_l1_msgs.push(content);\n }\n\n // PrivateContextInputs must be temporarily passed in to prevent too many unknowns\n // Note this returns self to get around an issue where mutable structs do not maintain mutations unless reassigned\n // docs:start:context_consume_l1_to_l2_message\n // docs:start:consume_l1_to_l2_message\n pub fn consume_l1_to_l2_message(&mut self, msg_key: Field, content: Field, secret: Field) {\n // docs:end:context_consume_l1_to_l2_message\n let nullifier = process_l1_to_l2_message(\n self.historical_header.state.l1_to_l2_message_tree.root,\n self.this_address(),\n self.this_portal_address(),\n self.chain_id(),\n self.version(),\n msg_key,\n content,\n secret\n );\n\n // Push nullifier (and the \"commitment\" corresponding to this can be \"empty\")\n self.push_new_nullifier(nullifier, 0)\n }\n // docs:end:consume_l1_to_l2_message\n\n pub fn accumulate_encrypted_logs(&mut self, log: [Field; N]) {\n let _void1 = self.inputs;\n let _void2 = log;\n // TODO(https://github.com/AztecProtocol/aztec-packages/issues/1165)\n }\n\n pub fn accumulate_unencrypted_logs(&mut self, log: T) {\n let _void1 = self.inputs;\n let _void2 = log;\n // TODO(https://github.com/AztecProtocol/aztec-packages/issues/1165)\n }\n\n pub fn call_private_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) -> [Field; RETURN_VALUES_LENGTH] {\n let args_hash = hash_args(args);\n assert(args_hash == arguments::pack_arguments(args));\n self.call_private_function_with_packed_args(contract_address, function_selector, args_hash)\n }\n\n pub fn call_private_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) -> [Field; RETURN_VALUES_LENGTH] {\n self.call_private_function_with_packed_args(contract_address, function_selector, 0)\n }\n\n pub fn call_private_function_with_packed_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field\n ) -> [Field; RETURN_VALUES_LENGTH] {\n let item = call_private_function_internal(\n contract_address,\n function_selector,\n args_hash,\n self.side_effect_counter\n );\n\n assert_eq(item.public_inputs.call_context.start_side_effect_counter, self.side_effect_counter);\n self.side_effect_counter = item.public_inputs.end_side_effect_counter + 1;\n\n assert(contract_address.eq(item.contract_address));\n assert(function_selector.eq(item.function_data.selector));\n\n assert(args_hash == item.public_inputs.args_hash);\n\n // Assert that the call context of the enqueued call generated by the oracle matches our request.\n // We are issuing a regular call which is not delegate, static, or deployment. We also constrain\n // the msg_sender in the nested call to be equal to our address, and the execution context address\n // for the nested call to be equal to the address we actually called.\n assert(item.public_inputs.call_context.is_delegate_call == false);\n assert(item.public_inputs.call_context.is_static_call == false);\n assert(item.public_inputs.call_context.is_contract_deployment == false);\n assert(\n item.public_inputs.call_context.msg_sender.eq(self.inputs.call_context.storage_contract_address)\n );\n assert(item.public_inputs.call_context.storage_contract_address.eq(contract_address));\n\n self.private_call_stack_hashes.push(item.hash());\n\n item.public_inputs.return_values\n }\n\n pub fn call_public_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) {\n let args_hash = hash_args(args);\n assert(args_hash == arguments::pack_arguments(args));\n self.call_public_function_with_packed_args(contract_address, function_selector, args_hash)\n }\n\n pub fn call_public_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) {\n self.call_public_function_with_packed_args(contract_address, function_selector, 0)\n }\n\n pub fn call_public_function_with_packed_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field\n ) {\n let fields = enqueue_public_function_call_internal(\n contract_address,\n function_selector,\n args_hash,\n self.side_effect_counter\n );\n\n let mut reader = Reader::new(fields);\n\n // Note: Not using PublicCirclePublicInputs::deserialize here, because everything below args_hash is 0 and\n // there is no more data in fields because there is only ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_SIZE fields!\n let item = PublicCallStackItem {\n contract_address: AztecAddress::from_field(reader.read()),\n function_data: reader.read_struct(FunctionData::deserialize),\n public_inputs: PublicCircuitPublicInputs {\n call_context: reader.read_struct(CallContext::deserialize),\n args_hash: reader.read(),\n return_values: [0; RETURN_VALUES_LENGTH],\n contract_storage_update_requests: [StorageUpdateRequest::empty(); MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL],\n contract_storage_reads: [StorageRead::empty(); MAX_PUBLIC_DATA_READS_PER_CALL],\n public_call_stack_hashes: [0; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL],\n new_commitments: [SideEffect::empty(); MAX_NEW_COMMITMENTS_PER_CALL],\n new_nullifiers: [SideEffectLinkedToNoteHash::empty(); MAX_NEW_NULLIFIERS_PER_CALL],\n new_l2_to_l1_msgs: [0; MAX_NEW_L2_TO_L1_MSGS_PER_CALL],\n unencrypted_logs_hash: [0; NUM_FIELDS_PER_SHA256],\n unencrypted_log_preimages_length: 0,\n historical_header: Header::empty(),\n prover_address: AztecAddress::zero()\n },\n is_execution_request: true\n };\n reader.finish();\n\n assert(contract_address.eq(item.contract_address));\n assert(function_selector.eq(item.function_data.selector));\n\n assert_eq(item.public_inputs.call_context.start_side_effect_counter, self.side_effect_counter);\n // We increment the sideffect counter by one, to account for the call itself being a side effect.\n self.side_effect_counter = self.side_effect_counter + 1;\n\n assert(args_hash == item.public_inputs.args_hash);\n\n // Assert that the call context of the enqueued call generated by the oracle matches our request.\n // We are issuing a regular call which is not delegate, static, or deployment. We also constrain\n // the msg_sender in the nested call to be equal to our address, and the execution context address\n // for the nested call to be equal to the address we actually called.\n assert(item.public_inputs.call_context.is_delegate_call == false);\n assert(item.public_inputs.call_context.is_static_call == false);\n assert(item.public_inputs.call_context.is_contract_deployment == false);\n assert(\n item.public_inputs.call_context.msg_sender.eq(self.inputs.call_context.storage_contract_address)\n );\n assert(item.public_inputs.call_context.storage_contract_address.eq(contract_address));\n\n self.public_call_stack_hashes.push(item.hash());\n }\n}\n","path":"/mnt/user-data/sean/nargo/github.com/AztecProtocol/aztec-packages/master/yarn-project/aztec-nr/aztec/src/context/private_context.nr"},"57":{"source":"use dep::protocol_types::{hash::hash_args, traits::Hash};\n\nstruct Hasher {\n fields: [Field],\n}\n\nimpl Hash for Hasher {\n fn hash(self) -> Field {\n hash_args(self.fields)\n }\n}\n\nimpl Hasher {\n pub fn new() -> Self {\n Self { fields: [] }\n }\n\n pub fn add(&mut self, field: Field) {\n self.fields = self.fields.push_back(field);\n }\n\n pub fn add_multiple(&mut self, fields: [Field; N]) {\n for i in 0..N {\n self.fields = self.fields.push_back(fields[i]);\n }\n }\n}\n","path":"/mnt/user-data/sean/nargo/github.com/AztecProtocol/aztec-packages/master/yarn-project/aztec-nr/aztec/src/hasher.nr"},"68":{"source":"use crate::context::{PrivateContext, PublicContext};\nuse crate::oracle;\nuse dep::protocol_types::{address::AztecAddress, grumpkin_point::GrumpkinPoint};\n\npub fn emit_encrypted_log(\n context: &mut PrivateContext,\n contract_address: AztecAddress,\n storage_slot: Field,\n note_type_id: Field,\n encryption_pub_key: GrumpkinPoint,\n log: [Field; N]\n) {\n let _ = oracle::logs::emit_encrypted_log(\n contract_address,\n storage_slot,\n note_type_id,\n encryption_pub_key,\n log\n );\n context.accumulate_encrypted_logs(log);\n}\n\npub fn emit_unencrypted_log(context: &mut PublicContext, log: T) {\n let contract_address = context.this_address();\n let event_selector = 5; // TODO: compute actual event selector.\n let _ = oracle::logs::emit_unencrypted_log(contract_address, event_selector, log);\n // context.accumulate_unencrypted_logs(log);\n}\n\n// TODO: We might want to remove this since emitting unencrypted logs from private functions is violating privacy.\n// --> might be a better approach to force devs to make a public function call that emits the log if needed then\n// it would be less easy to accidentally leak information.\n// If we decide to keep this function around would make sense to wait for traits and then merge it with emit_unencrypted_log.\npub fn emit_unencrypted_log_from_private(context: &mut PrivateContext, log: T) {\n let contract_address = context.this_address();\n let event_selector = 5; // TODO: compute actual event selector.\n let _ = oracle::logs::emit_unencrypted_log(contract_address, event_selector, log);\n // context.accumulate_unencrypted_logs(log);\n}\n","path":"/mnt/user-data/sean/nargo/github.com/AztecProtocol/aztec-packages/master/yarn-project/aztec-nr/aztec/src/log.nr"},"73":{"source":"use crate::context::{PrivateContext, PublicContext};\nuse crate::note::{\n note_header::NoteHeader, note_interface::NoteInterface,\n utils::{compute_note_hash_for_insertion, compute_note_hash_for_consumption}\n};\nuse crate::oracle::notes::{notify_created_note, notify_nullified_note};\n\npub fn create_note(\n context: &mut PrivateContext,\n storage_slot: Field,\n note: &mut Note,\n broadcast: bool\n) where Note: NoteInterface {\n let contract_address = (*context).this_address();\n\n let header = NoteHeader { contract_address, storage_slot, nonce: 0, is_transient: true };\n // TODO: change this to note.setHeader(header) once https://github.com/noir-lang/noir/issues/4095 is fixed\n Note::set_header(note, header);\n // As `is_transient` is true, this will compute the inner note hsah\n let inner_note_hash = compute_note_hash_for_insertion(*note);\n\n // TODO: Strong typing required because of https://github.com/noir-lang/noir/issues/4088\n let serialized_note: [Field; N] = Note::serialize_content(*note);\n assert(\n notify_created_note(\n storage_slot,\n Note::get_note_type_id(),\n serialized_note,\n inner_note_hash\n )\n == 0\n );\n\n context.push_new_note_hash(inner_note_hash);\n\n if broadcast {\n Note::broadcast(*note, context, storage_slot);\n }\n}\n\npub fn create_note_hash_from_public(\n context: &mut PublicContext,\n storage_slot: Field,\n note: &mut Note\n) where Note: NoteInterface {\n let contract_address = (*context).this_address();\n\n let header = NoteHeader { contract_address, storage_slot, nonce: 0, is_transient: true };\n // TODO: change this to note.setHeader(header) once https://github.com/noir-lang/noir/issues/4095 is fixed\n Note::set_header(note, header);\n let inner_note_hash = compute_note_hash_for_insertion(*note);\n\n context.push_new_note_hash(inner_note_hash);\n}\n\npub fn destroy_note(context: &mut PrivateContext, note: Note) where Note: NoteInterface {\n let mut nullifier = 0;\n let mut consumed_note_hash: Field = 0;\n nullifier = note.compute_nullifier(context);\n\n // We also need the note hash corresponding to the \"nullifier\"\n let header = note.get_header();\n // `consumed_note_hash` is used to inform the kernel which pending note hash\n // the nullifier corresponds to so they can be matched and both squashed/deleted.\n // nonzero nonce implies \"persistable\" nullifier (nullifies a persistent/in-tree\n // note hash) in which case `consumed_note_hash` is not used since the kernel\n // just siloes and forwards the nullifier to its output.\n if (header.is_transient) {\n // TODO(1718): Can we reuse the note hash computed in `compute_nullifier`?\n consumed_note_hash = compute_note_hash_for_consumption(note);\n }\n assert(notify_nullified_note(nullifier, consumed_note_hash) == 0);\n\n context.push_new_nullifier(nullifier, consumed_note_hash)\n}\n","path":"/mnt/user-data/sean/nargo/github.com/AztecProtocol/aztec-packages/master/yarn-project/aztec-nr/aztec/src/note/lifecycle.nr"},"74":{"source":"use dep::std::option::Option;\nuse dep::protocol_types::{\n constants::{\n MAX_READ_REQUESTS_PER_CALL,\n GET_NOTE_ORACLE_RETURN_LENGTH,\n GET_NOTES_ORACLE_RETURN_LENGTH,\n MAX_NOTES_PER_PAGE,\n VIEW_NOTE_ORACLE_RETURN_LENGTH,\n },\n};\nuse crate::context::PrivateContext;\nuse crate::note::{\n note_getter_options::{NoteGetterOptions, Select, Sort, SortOrder, Comparator, NoteStatus},\n note_interface::NoteInterface,\n note_viewer_options::NoteViewerOptions,\n utils::compute_note_hash_for_consumption,\n};\nuse crate::oracle;\n\nfn check_note_header(\n context: PrivateContext,\n storage_slot: Field,\n note: Note\n) where Note: NoteInterface {\n let header = note.get_header();\n let contract_address = context.this_address();\n assert(header.contract_address.eq(contract_address));\n assert(header.storage_slot == storage_slot);\n}\n\nfn check_note_fields(fields: [Field; N], selects: BoundedVec, N>) {\n for i in 0..selects.len {\n let select = selects.get_unchecked(i).unwrap_unchecked();\n\n // Values are computed ahead of time because circuits evaluate all branches\n let isEqual = fields[select.field_index] == select.value;\n let isLt = fields[select.field_index].lt(select.value);\n\n if (select.comparator == Comparator.EQ) {\n assert(isEqual, \"Mismatch return note field.\");\n } else if (select.comparator == Comparator.NEQ) {\n assert(!isEqual, \"Mismatch return note field.\");\n } else if (select.comparator == Comparator.LT) {\n assert(isLt, \"Mismatch return note field.\");\n } else if (select.comparator == Comparator.LTE) {\n assert(isLt | isEqual, \"Mismatch return note field.\");\n } else if (select.comparator == Comparator.GT) {\n assert(!isLt & !isEqual, \"Mismatch return note field.\");\n } else if (select.comparator == Comparator.GTE) {\n assert(!isLt, \"Mismatch return note field.\");\n }\n }\n}\n\nfn check_notes_order(\n fields_0: [Field; N],\n fields_1: [Field; N],\n sorts: BoundedVec, N>\n) {\n for i in 0..sorts.len {\n let sort = sorts.get_unchecked(i).unwrap_unchecked();\n let eq = fields_0[sort.field_index] == fields_1[sort.field_index];\n let lt = fields_0[sort.field_index] as u120 < fields_1[sort.field_index] as u120;\n if sort.order == SortOrder.ASC {\n assert(eq | lt, \"Return notes not sorted in ascending order.\");\n } else if !eq {\n assert(!lt, \"Return notes not sorted in descending order.\");\n }\n }\n}\n\npub fn get_note(\n context: &mut PrivateContext,\n storage_slot: Field\n) -> Note where Note: NoteInterface {\n let note = get_note_internal(storage_slot);\n\n check_note_header(*context, storage_slot, note);\n\n let note_hash_for_read_request = compute_note_hash_for_consumption(note);\n\n context.push_read_request(note_hash_for_read_request);\n note\n}\n\npub fn get_notes(\n context: &mut PrivateContext,\n storage_slot: Field,\n options: NoteGetterOptions\n) -> [Option; MAX_READ_REQUESTS_PER_CALL] where Note: NoteInterface {\n let opt_notes = get_notes_internal(storage_slot, options);\n let mut num_notes = 0;\n let mut prev_fields = [0; N];\n for i in 0..opt_notes.len() {\n let opt_note = opt_notes[i];\n if opt_note.is_some() {\n let note = opt_note.unwrap_unchecked();\n let fields = note.serialize_content();\n check_note_header(*context, storage_slot, note);\n check_note_fields(fields, options.selects);\n if i != 0 {\n check_notes_order(prev_fields, fields, options.sorts);\n }\n prev_fields = fields;\n\n let note_hash_for_read_request = compute_note_hash_for_consumption(note);\n // TODO(https://github.com/AztecProtocol/aztec-packages/issues/1410): test to ensure\n // failure if malicious oracle injects 0 nonce here for a \"pre-existing\" note.\n context.push_read_request(note_hash_for_read_request);\n\n num_notes += 1;\n };\n }\n if options.limit != 0 {\n assert(num_notes <= options.limit, \"Invalid number of return notes.\");\n }\n opt_notes\n}\n\nunconstrained fn get_note_internal(storage_slot: Field) -> Note where Note: NoteInterface {\n let placeholder_note = [Option::none()];\n let placeholder_fields = [0; GET_NOTE_ORACLE_RETURN_LENGTH];\n let placeholder_note_length = [0; N];\n oracle::notes::get_notes(\n storage_slot,\n 0,\n [],\n [],\n [],\n [],\n [],\n 1, // limit\n 0, // offset\n NoteStatus.ACTIVE,\n placeholder_note,\n placeholder_fields,\n placeholder_note_length\n )[0].unwrap() // Notice: we don't allow dummies to be returned from get_note (singular).\n}\n\nunconstrained fn get_notes_internal(\n storage_slot: Field,\n options: NoteGetterOptions\n) -> [Option; MAX_READ_REQUESTS_PER_CALL] where Note: NoteInterface {\n let (num_selects, select_by, select_values, select_comparators, sort_by, sort_order) = flatten_options(options.selects, options.sorts);\n let placeholder_opt_notes = [Option::none(); MAX_READ_REQUESTS_PER_CALL];\n let placeholder_fields = [0; GET_NOTES_ORACLE_RETURN_LENGTH];\n let placeholder_note_length = [0; N];\n let opt_notes = oracle::notes::get_notes(\n storage_slot,\n num_selects,\n select_by,\n select_values,\n select_comparators,\n sort_by,\n sort_order,\n options.limit,\n options.offset,\n options.status,\n placeholder_opt_notes,\n placeholder_fields,\n placeholder_note_length\n );\n\n let filter = options.filter;\n let filter_args = options.filter_args;\n filter(opt_notes, filter_args)\n}\n\nunconstrained pub fn view_notes(\n storage_slot: Field,\n options: NoteViewerOptions\n) -> [Option; MAX_NOTES_PER_PAGE] where Note: NoteInterface {\n let (num_selects, select_by, select_values, select_comparators, sort_by, sort_order) = flatten_options(options.selects, options.sorts);\n let placeholder_opt_notes = [Option::none(); MAX_NOTES_PER_PAGE];\n let placeholder_fields = [0; VIEW_NOTE_ORACLE_RETURN_LENGTH];\n let placeholder_note_length = [0; N];\n oracle::notes::get_notes(\n storage_slot,\n num_selects,\n select_by,\n select_values,\n select_comparators,\n sort_by,\n sort_order,\n options.limit,\n options.offset,\n options.status,\n placeholder_opt_notes,\n placeholder_fields,\n placeholder_note_length\n )\n}\n\nunconstrained fn flatten_options(\n selects: BoundedVec, N>,\n sorts: BoundedVec, N>\n) -> (u8, [u8; N], [Field; N], [u3; N], [u8; N], [u2; N]) {\n let mut num_selects = 0;\n let mut select_by = [0; N];\n let mut select_values = [0; N];\n let mut select_comparators = [0; N];\n\n for i in 0..selects.len {\n let select = selects.get(i);\n if select.is_some() {\n select_by[num_selects] = select.unwrap_unchecked().field_index;\n select_values[num_selects] = select.unwrap_unchecked().value;\n select_comparators[num_selects] = select.unwrap_unchecked().comparator;\n num_selects += 1;\n };\n }\n\n let mut sort_by = [0; N];\n let mut sort_order = [0; N];\n for i in 0..sorts.len {\n let sort = sorts.get(i);\n if sort.is_some() {\n sort_by[i] = sort.unwrap_unchecked().field_index;\n sort_order[i] = sort.unwrap_unchecked().order;\n };\n }\n\n (num_selects, select_by, select_values, select_comparators, sort_by, sort_order)\n}\n","path":"/mnt/user-data/sean/nargo/github.com/AztecProtocol/aztec-packages/master/yarn-project/aztec-nr/aztec/src/note/note_getter.nr"},"80":{"source":"use crate::{context::PrivateContext, note::{note_header::NoteHeader, note_interface::NoteInterface}};\n\nuse dep::protocol_types::{\n address::AztecAddress,\n constants::{\n GENERATOR_INDEX__OUTER_NULLIFIER, GENERATOR_INDEX__UNIQUE_COMMITMENT,\n GENERATOR_INDEX__SILOED_COMMITMENT\n},\n hash::pedersen_hash, utils::arr_copy_slice\n};\n\nfn compute_siloed_hash(contract_address: AztecAddress, inner_note_hash: Field) -> Field {\n let inputs = [contract_address.to_field(), inner_note_hash];\n pedersen_hash(inputs, GENERATOR_INDEX__SILOED_COMMITMENT)\n}\n\nfn compute_unique_hash(nonce: Field, siloed_note_hash: Field) -> Field {\n let inputs = [nonce, siloed_note_hash];\n pedersen_hash(inputs, GENERATOR_INDEX__UNIQUE_COMMITMENT)\n}\n\nfn compute_inner_note_hash(note: Note) -> Field where Note: NoteInterface {\n let header = note.get_header();\n let note_hash = note.compute_note_content_hash();\n\n // TODO(#1205) Do we need a generator index here?\n pedersen_hash([header.storage_slot, note_hash], 0)\n}\n\nfn compute_siloed_note_hash(note_with_header: Note) -> Field where Note: NoteInterface {\n let header = note_with_header.get_header();\n\n let inner_note_hash = compute_inner_note_hash(note_with_header);\n\n compute_siloed_hash(header.contract_address, inner_note_hash)\n}\n\nfn compute_unique_siloed_note_hash(note_with_header: Note) -> Field where Note: NoteInterface {\n let header = note_with_header.get_header();\n\n let siloed_note_hash = compute_siloed_note_hash(note_with_header);\n\n compute_unique_hash(header.nonce, siloed_note_hash)\n}\n\npub fn compute_siloed_nullifier(\n note_with_header: Note,\n context: &mut PrivateContext\n) -> Field where Note: NoteInterface {\n let header = note_with_header.get_header();\n let inner_nullifier = note_with_header.compute_nullifier(context);\n\n let input = [header.contract_address.to_field(), inner_nullifier];\n pedersen_hash(input, GENERATOR_INDEX__OUTER_NULLIFIER)\n}\n\npub fn compute_note_hash_for_insertion(note: Note) -> Field where Note: NoteInterface {\n compute_inner_note_hash(note)\n}\n\npub fn compute_note_hash_for_consumption(note: Note) -> Field where Note: NoteInterface {\n let header = note.get_header();\n // There are 3 cases for reading a note intended for consumption:\n // 1. The note was inserted in this transaction, and is transient.\n // 2. The note was inserted in a previous transaction, and was inserted in public\n // 3. The note was inserted in a previous transaction, and was inserted in private\n\n if (header.is_transient) {\n // If a note is transient, we just read the inner_note_hash (kernel will silo by contract address).\n compute_inner_note_hash(note)\n } else if (header.nonce == 0) {\n // If not transient and nonce is zero, that means we are reading a public note.\n compute_siloed_note_hash(note)\n } else {\n // When nonce is nonzero, that means we are reading a settled note (from tree) created in a\n // previous TX. So we need the unique_siloed_note_hash which has already been hashed with\n // contract address and then nonce. This hash will match the existing leaf in the private\n // data tree, so the kernel can just perform a membership check directly on this hash/leaf.\n compute_unique_siloed_note_hash(note)\n }\n}\n\npub fn compute_note_hash_and_nullifier(\n deserialize_content: fn([Field; N]) -> T,\n note_header: NoteHeader,\n serialized_note: [Field; S]\n) -> [Field; 4] where T: NoteInterface {\n let mut note = deserialize_content(arr_copy_slice(serialized_note, [0; N], 0));\n // TODO: change this to note.setHeader(header) once https://github.com/noir-lang/noir/issues/4095 is fixed\n T::set_header((&mut note), note_header);\n\n let inner_note_hash = compute_inner_note_hash(note);\n\n let siloed_note_hash = compute_siloed_hash(note_header.contract_address, inner_note_hash);\n\n let unique_siloed_note_hash = compute_unique_hash(note_header.nonce, siloed_note_hash);\n\n let inner_nullifier = note.compute_nullifier_without_context();\n\n [inner_note_hash, siloed_note_hash, unique_siloed_note_hash, inner_nullifier]\n}\n","path":"/mnt/user-data/sean/nargo/github.com/AztecProtocol/aztec-packages/master/yarn-project/aztec-nr/aztec/src/note/utils.nr"},"92":{"source":"use dep::protocol_types::{address::{AztecAddress, PartialAddress, PublicKeysHash}, grumpkin_point::GrumpkinPoint};\n\n#[oracle(getPublicKeyAndPartialAddress)]\nfn get_public_key_and_partial_address_oracle(_address: AztecAddress) -> [Field; 3] {}\n\nunconstrained fn get_public_key_and_partial_address_internal(address: AztecAddress) -> [Field; 3] {\n get_public_key_and_partial_address_oracle(address)\n}\n\npub fn get_public_key(address: AztecAddress) -> GrumpkinPoint {\n let result = get_public_key_and_partial_address_internal(address);\n let pub_key = GrumpkinPoint::new(result[0], result[1]);\n let partial_address = PartialAddress::from_field(result[2]);\n\n let calculated_address = AztecAddress::compute(PublicKeysHash::compute(pub_key), partial_address);\n assert(calculated_address.eq(address));\n\n pub_key\n}\n","path":"/mnt/user-data/sean/nargo/github.com/AztecProtocol/aztec-packages/master/yarn-project/aztec-nr/aztec/src/oracle/get_public_key.nr"},"95":{"source":"use dep::protocol_types::{address::AztecAddress, constants::NUM_FIELDS_PER_SHA256, grumpkin_point::GrumpkinPoint};\n\n// TODO: Should take encrypted data.\n#[oracle(emitEncryptedLog)]\nfn emit_encrypted_log_oracle(\n _contract_address: AztecAddress,\n _storage_slot: Field,\n _note_type_id: Field,\n _encryption_pub_key: GrumpkinPoint,\n _preimage: [Field; N]\n) -> Field {}\n\nunconstrained pub fn emit_encrypted_log(\n contract_address: AztecAddress,\n storage_slot: Field,\n note_type_id: Field,\n encryption_pub_key: GrumpkinPoint,\n preimage: [Field; N]\n) -> [Field; NUM_FIELDS_PER_SHA256] {\n [\n emit_encrypted_log_oracle(\n contract_address,\n storage_slot,\n note_type_id,\n encryption_pub_key,\n preimage\n ), 0\n ]\n}\n\n#[oracle(emitUnencryptedLog)]\nfn emit_unencrypted_log_oracle(\n _contract_address: AztecAddress,\n _event_selector: Field,\n _message: T\n) -> Field {}\n\nunconstrained pub fn emit_unencrypted_log(\n contract_address: AztecAddress,\n event_selector: Field,\n message: T\n) -> [Field; NUM_FIELDS_PER_SHA256] {\n // https://github.com/AztecProtocol/aztec-packages/issues/885\n [emit_unencrypted_log_oracle(contract_address, event_selector, message), 0]\n}\n","path":"/mnt/user-data/sean/nargo/github.com/AztecProtocol/aztec-packages/master/yarn-project/aztec-nr/aztec/src/oracle/logs.nr"},"96":{"source":"use dep::std::option::Option;\nuse crate::note::{\n note_header::NoteHeader,\n note_interface::NoteInterface,\n};\n\nuse dep::protocol_types::{\n address::AztecAddress,\n utils::arr_copy_slice,\n};\n\n#[oracle(notifyCreatedNote)]\nfn notify_created_note_oracle(\n _storage_slot: Field,\n _note_type_id: Field,\n _serialized_note: [Field; N],\n _inner_note_hash: Field\n) -> Field {}\n\nunconstrained pub fn notify_created_note(\n storage_slot: Field,\n note_type_id: Field,\n serialized_note: [Field; N],\n inner_note_hash: Field\n) -> Field {\n notify_created_note_oracle(storage_slot, note_type_id, serialized_note, inner_note_hash)\n}\n\n#[oracle(notifyNullifiedNote)]\nfn notify_nullified_note_oracle(_nullifier: Field, _inner_note_hash: Field) -> Field {}\n\nunconstrained pub fn notify_nullified_note(nullifier: Field, inner_note_hash: Field) -> Field {\n notify_nullified_note_oracle(nullifier, inner_note_hash)\n}\n\n#[oracle(getNotes)]\nfn get_notes_oracle(\n _storage_slot: Field,\n _num_selects: u8,\n _select_by: [u8; N],\n _select_values: [Field; N],\n _select_comparators: [u3; N],\n _sort_by: [u8; N],\n _sort_order: [u2; N],\n _limit: u32,\n _offset: u32,\n _status: u2,\n _return_size: u32,\n _placeholder_fields: [Field; S]\n) -> [Field; S] {}\n\nunconstrained fn get_notes_oracle_wrapper(\n storage_slot: Field,\n num_selects: u8,\n select_by: [u8; N],\n select_values: [Field; N],\n select_comparators: [u3; N],\n sort_by: [u8; N],\n sort_order: [u2; N],\n limit: u32,\n offset: u32,\n status: u2,\n mut placeholder_fields: [Field; S]\n) -> [Field; S] {\n let return_size = placeholder_fields.len() as u32;\n get_notes_oracle(\n storage_slot,\n num_selects,\n select_by,\n select_values,\n select_comparators,\n sort_by,\n sort_order,\n limit,\n offset,\n status,\n return_size,\n placeholder_fields\n )\n}\n\nunconstrained pub fn get_notes(\n storage_slot: Field,\n num_selects: u8,\n select_by: [u8; M],\n select_values: [Field; M],\n select_comparators: [u3; M],\n sort_by: [u8; M],\n sort_order: [u2; M],\n limit: u32,\n offset: u32,\n status: u2,\n mut placeholder_opt_notes: [Option; S], // TODO: Remove it and use `limit` to initialize the note array.\n placeholder_fields: [Field; NS], // TODO: Remove it and use `limit` to initialize the note array.\n _placeholder_note_length: [Field; N] // Turbofish hack? Compiler breaks calculating read_offset unless we add this parameter\n) -> [Option; S] where Note: NoteInterface {\n let fields = get_notes_oracle_wrapper(\n storage_slot,\n num_selects,\n select_by,\n select_values,\n select_comparators,\n sort_by,\n sort_order,\n limit,\n offset,\n status,\n placeholder_fields\n );\n let num_notes = fields[0] as u32;\n let contract_address = AztecAddress::from_field(fields[1]);\n for i in 0..placeholder_opt_notes.len() {\n if i as u32 < num_notes {\n // lengths named as per typescript.\n let return_header_length: Field = 2; // num_notes & contract_address.\n let extra_preimage_length: Field = 2; // nonce & is_transient.\n let read_offset: Field = return_header_length + i * (N + extra_preimage_length);\n let nonce = fields[read_offset];\n let is_transient = fields[read_offset + 1] as bool;\n let header = NoteHeader { contract_address, nonce, storage_slot, is_transient };\n let serialized_note = arr_copy_slice(fields, [0; N], read_offset + 2);\n let mut note = Note::deserialize_content(serialized_note);\n // TODO: change this to note.setHeader(header) once https://github.com/noir-lang/noir/issues/4095 is fixed\n Note::set_header(&mut note, header);\n placeholder_opt_notes[i] = Option::some(note);\n };\n }\n placeholder_opt_notes\n}\n\n#[oracle(checkNullifierExists)]\nfn check_nullifier_exists_oracle(_inner_nullifier: Field) -> Field {}\n\nunconstrained pub fn check_nullifier_exists(inner_nullifier: Field) -> bool {\n check_nullifier_exists_oracle(inner_nullifier) == 1\n}\n","path":"/mnt/user-data/sean/nargo/github.com/AztecProtocol/aztec-packages/master/yarn-project/aztec-nr/aztec/src/oracle/notes.nr"},"97":{"source":"use dep::protocol_types::{address::AztecAddress, grumpkin_point::GrumpkinPoint, grumpkin_private_key::GrumpkinPrivateKey};\n\nstruct NullifierKeyPair {\n account: AztecAddress,\n public_key: GrumpkinPoint,\n secret_key: GrumpkinPrivateKey,\n}\n\n#[oracle(getNullifierKeyPair)]\nfn get_nullifier_key_pair_oracle(_account: AztecAddress) -> [Field; 4] {}\n\nunconstrained fn get_nullifier_key_pair_internal(account: AztecAddress) -> NullifierKeyPair {\n let result = get_nullifier_key_pair_oracle(account);\n NullifierKeyPair {\n account,\n public_key: GrumpkinPoint { x: result[0], y: result[1] },\n secret_key: GrumpkinPrivateKey { high: result[2], low: result[3] }\n }\n}\n\npub fn get_nullifier_key_pair(account: AztecAddress) -> NullifierKeyPair {\n get_nullifier_key_pair_internal(account)\n}\n\npub fn get_nullifier_secret_key(account: AztecAddress) -> GrumpkinPrivateKey {\n get_nullifier_key_pair_internal(account).secret_key\n}\n","path":"/mnt/user-data/sean/nargo/github.com/AztecProtocol/aztec-packages/master/yarn-project/aztec-nr/aztec/src/oracle/nullifier_key.nr"},"99":{"source":"#[oracle(getRandomField)]\nfn rand_oracle() -> Field {}\n\nunconstrained pub fn rand() -> Field {\n rand_oracle()\n}\n","path":"/mnt/user-data/sean/nargo/github.com/AztecProtocol/aztec-packages/master/yarn-project/aztec-nr/aztec/src/oracle/rand.nr"},"106":{"source":"use dep::std::option::Option;\n\nuse dep::protocol_types::{address::AztecAddress, constants::{GENERATOR_INDEX__INITIALIZATION_NULLIFIER}, hash::pedersen_hash};\n\nuse crate::context::{PrivateContext, PublicContext, Context};\nuse crate::note::{\n lifecycle::{create_note, destroy_note}, note_getter::{get_note, view_notes},\n note_interface::NoteInterface, note_viewer_options::NoteViewerOptions\n};\nuse crate::oracle::{nullifier_key::get_nullifier_secret_key, notes::check_nullifier_exists};\nuse crate::state_vars::storage::Storage;\n\n// docs:start:struct\nstruct Singleton {\n context: Option<&mut PrivateContext>,\n storage_slot: Field\n}\n// docs:end:struct\n\nimpl Storage for Singleton {}\n\nimpl Singleton {\n // docs:start:new\n pub fn new(context: Context, storage_slot: Field) -> Self {\n assert(storage_slot != 0, \"Storage slot 0 not allowed. Storage slots must start from 1.\");\n Self { context: context.private, storage_slot }\n }\n // docs:end:new\n\n // The following computation is leaky, in that it doesn't hide the storage slot that has been initialized, nor does it hide the contract address of this contract.\n // When this initialization nullifier is emitted, an observer could do a dictionary or rainbow attack to learn the preimage of this nullifier to deduce the storage slot and contract address.\n // For some applications, leaking the details that a particular state variable of a particular contract has been initialized will be unacceptable.\n // Under such circumstances, such application developers might wish to _not_ use this state variable type.\n // This is especially dangerous for initial assignment to elements of a `Map` type (for example), because the storage slot often also identifies an actor. e.g. \n // the initial assignment to `my_map.at(msg.sender)` will leak: `msg.sender`, the fact that an element of `my_map` was assigned-to for the first time, and the contract_address.\n // Note: subsequent nullification of this state variable, via the `replace` method will not be leaky, if the `compute_nullifier()` method of the underlying note is designed to ensure privacy. \n // For example, if the `compute_nullifier()` method injects the secret key of a note owner into the computed nullifier's preimage.\n pub fn compute_initialization_nullifier(self) -> Field {\n pedersen_hash(\n [self.storage_slot],\n GENERATOR_INDEX__INITIALIZATION_NULLIFIER\n )\n }\n\n // docs:start:is_initialized\n unconstrained pub fn is_initialized(self) -> bool {\n let nullifier = self.compute_initialization_nullifier();\n check_nullifier_exists(nullifier)\n }\n // docs:end:is_initialized\n\n // docs:start:initialize\n pub fn initialize(self, note: &mut Note, broadcast: bool) where Note: NoteInterface {\n let context = self.context.unwrap();\n\n // Nullify the storage slot.\n let nullifier = self.compute_initialization_nullifier();\n context.push_new_nullifier(nullifier, 0);\n\n create_note(context, self.storage_slot, note, broadcast);\n }\n // docs:end:initialize\n\n // docs:start:replace\n pub fn replace(self, new_note: &mut Note, broadcast: bool) where Note: NoteInterface {\n let context = self.context.unwrap();\n let prev_note = get_note(context, self.storage_slot);\n\n // Nullify previous note.\n destroy_note(context, prev_note);\n\n // Add replacement note.\n create_note(context, self.storage_slot, new_note, broadcast);\n }\n // docs:end:replace\n\n // docs:start:get_note\n pub fn get_note(self, broadcast: bool) -> Note where Note: NoteInterface {\n let context = self.context.unwrap();\n let mut note = get_note(context, self.storage_slot);\n\n // Nullify current note to make sure it's reading the latest note.\n destroy_note(context, note);\n\n // Add the same note again.\n // Because a nonce is added to every note in the kernel, its nullifier will be different.\n create_note(context, self.storage_slot, &mut note, broadcast);\n\n note\n }\n // docs:end:get_note\n\n // docs:start:view_note\n unconstrained pub fn view_note(self) -> Note where Note: NoteInterface {\n let options = NoteViewerOptions::new().set_limit(1);\n view_notes(self.storage_slot, options)[0].unwrap()\n }\n // docs:end:view_note\n}\n","path":"/mnt/user-data/sean/nargo/github.com/AztecProtocol/aztec-packages/master/yarn-project/aztec-nr/aztec/src/state_vars/singleton.nr"},"136":{"source":"use crate::{\n constants::{GENERATOR_INDEX__CONTRACT_ADDRESS, GENERATOR_INDEX__PARTIAL_ADDRESS, GENERATOR_INDEX__CONSTRUCTOR},\n hash::pedersen_hash, contract_class::ContractClassId, utils, grumpkin_point::GrumpkinPoint\n};\nuse dep::std::cmp::Eq;\nuse crate::traits::{Empty, ToField, Serialize, Deserialize};\nuse crate::type_serialization::{ETH_ADDRESS_SERIALIZED_LEN, AZTEC_ADDRESS_SERIALIZED_LEN};\n\n// Aztec address\nstruct AztecAddress {\n inner : Field\n}\n\nimpl Eq for AztecAddress {\n fn eq(self, other : Self) -> bool {\n self.to_field() == other.to_field()\n }\n}\n\nimpl Empty for AztecAddress {\n fn empty() -> Self {\n Self {\n inner : 0\n }\n }\n}\n\nimpl ToField for AztecAddress {\n fn to_field(self) -> Field {\n self.inner\n }\n}\n\nimpl Serialize for AztecAddress {\n fn serialize(self: Self) -> [Field; AZTEC_ADDRESS_SERIALIZED_LEN] {\n [self.to_field()]\n }\n}\n\nimpl Deserialize for AztecAddress {\n fn deserialize(fields: [Field; AZTEC_ADDRESS_SERIALIZED_LEN]) -> Self {\n AztecAddress::from_field(fields[0])\n }\n}\n\nimpl AztecAddress {\n pub fn zero() -> Self {\n Self { inner: 0 }\n }\n\n pub fn from_field(field: Field) -> Self {\n Self { inner: field }\n }\n\n pub fn compute_from_public_key(\n pub_key: GrumpkinPoint,\n contract_class_id: ContractClassId,\n salt: Field,\n initialization_hash: Field,\n portal_contract_address: EthAddress\n ) -> AztecAddress {\n AztecAddress::compute(\n PublicKeysHash::compute(pub_key),\n PartialAddress::compute(\n contract_class_id,\n salt,\n initialization_hash,\n portal_contract_address\n )\n )\n }\n\n pub fn compute(pub_keys_hash: PublicKeysHash, partial_address: PartialAddress) -> AztecAddress {\n AztecAddress::from_field(\n pedersen_hash(\n [pub_keys_hash.to_field(), partial_address.to_field()],\n GENERATOR_INDEX__CONTRACT_ADDRESS\n )\n )\n }\n\n pub fn is_zero(self) -> bool {\n self.inner == 0\n }\n\n pub fn assert_is_zero(self) {\n assert(self.to_field() == 0);\n }\n\n pub fn conditional_assign(predicate: bool, lhs: Self, rhs: Self) -> Self {\n let result = utils::conditional_assign(predicate, rhs.to_field(), lhs.to_field());\n Self { inner: result }\n }\n}\n\nstruct EthAddress{\n inner : Field\n}\n\nimpl Eq for EthAddress {\n fn eq(self, other : Self) -> bool {\n self.to_field() == other.to_field()\n }\n}\n\nimpl Empty for EthAddress {\n fn empty() -> Self {\n Self {\n inner : 0\n }\n }\n}\n\nimpl ToField for EthAddress {\n fn to_field(self) -> Field {\n self.inner\n }\n}\n\nimpl Serialize for EthAddress {\n fn serialize(self: Self) -> [Field; ETH_ADDRESS_SERIALIZED_LEN] {\n [self.inner]\n }\n}\n\nimpl Deserialize for EthAddress {\n fn deserialize(fields: [Field; ETH_ADDRESS_SERIALIZED_LEN]) -> Self {\n Self {\n inner: fields[0]\n }\n }\n}\n\nimpl EthAddress {\n pub fn zero() -> Self {\n Self { inner: 0 }\n }\n\n pub fn from_field(field: Field) -> Self {\n Self { inner: 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 pub fn conditional_assign(predicate: bool, lhs: Self, rhs: Self) -> Self {\n let result = utils::conditional_assign(predicate, rhs.to_field(), lhs.to_field());\n Self { inner: result }\n }\n}\n\n// Partial address\nstruct PartialAddress {\n inner : Field\n}\n\nimpl ToField for PartialAddress {\n fn to_field(self) -> Field {\n self.inner\n }\n}\n\nimpl PartialAddress {\n pub fn from_field(field: Field) -> Self {\n Self { inner: field }\n }\n\n pub fn compute(\n contract_class_id: ContractClassId,\n salt: Field,\n initialization_hash: Field,\n portal_contract_address: EthAddress\n ) -> Self {\n PartialAddress::compute_from_salted_initialization_hash(\n contract_class_id,\n SaltedInitializationHash::compute(salt, initialization_hash, portal_contract_address)\n )\n }\n\n pub fn compute_from_salted_initialization_hash(\n contract_class_id: ContractClassId,\n salted_initialization_hash: SaltedInitializationHash\n ) -> Self {\n PartialAddress::from_field(\n pedersen_hash(\n [\n contract_class_id.to_field(),\n salted_initialization_hash.to_field()\n ],\n GENERATOR_INDEX__PARTIAL_ADDRESS\n )\n )\n }\n\n pub fn to_field(self) -> Field {\n self.inner\n }\n\n pub fn assert_is_zero(self) {\n assert(self.to_field() == 0);\n }\n}\n\n// Salted initialization hash. Used in the computation of a partial address.\nstruct SaltedInitializationHash {\n inner: Field\n}\n\nimpl ToField for SaltedInitializationHash {\n fn to_field(self) -> Field {\n self.inner\n }\n}\n\nimpl SaltedInitializationHash {\n pub fn from_field(field: Field) -> Self {\n Self { inner: field }\n }\n\n pub fn compute(salt: Field, initialization_hash: Field, portal_contract_address: EthAddress) -> Self {\n SaltedInitializationHash::from_field(\n pedersen_hash(\n [\n salt,\n initialization_hash,\n portal_contract_address.to_field()\n ],\n GENERATOR_INDEX__PARTIAL_ADDRESS\n )\n )\n }\n\n pub fn to_field(self) -> Field {\n self.inner\n }\n\n pub fn assert_is_zero(self) {\n assert(self.to_field() == 0);\n }\n}\n\n// Public keys hash. Used in the computation of an address.\nstruct PublicKeysHash {\n inner: Field\n}\n\nimpl ToField for PublicKeysHash {\n fn to_field(self) -> Field {\n self.inner\n }\n}\n\nimpl Serialize<1> for PublicKeysHash {\n fn serialize(self: Self) -> [Field; 1] {\n [self.to_field()]\n }\n}\n\nimpl Deserialize<1> for PublicKeysHash {\n fn deserialize(fields: [Field; 1]) -> Self {\n PublicKeysHash::from_field(fields[0])\n }\n}\n\nimpl PublicKeysHash {\n pub fn from_field(field: Field) -> Self {\n Self { inner: field }\n }\n\n pub fn compute(public_key: GrumpkinPoint) -> Self {\n PublicKeysHash::from_field(\n pedersen_hash(\n [\n public_key.x,\n public_key.y\n ],\n GENERATOR_INDEX__PARTIAL_ADDRESS\n )\n )\n }\n\n pub fn to_field(self) -> Field {\n self.inner\n }\n\n pub fn assert_is_zero(self) {\n assert(self.to_field() == 0);\n }\n}\n\npub fn compute_initialization_hash(selector: Field, args_hash: Field) -> Field {\n pedersen_hash(\n [\n selector,\n args_hash\n ],\n GENERATOR_INDEX__CONSTRUCTOR\n )\n}\n","path":"/mnt/user-data/sean/nargo/github.com/AztecProtocol/aztec-packages/master/yarn-project/noir-protocol-circuits/src/crates/types/src/address.nr"},"145":{"source":"use crate::address::{AztecAddress, EthAddress};\nuse crate::mocked::VerificationKey;\nuse crate::abis::function_selector::FunctionSelector;\nuse crate::abis::function_leaf_preimage::{ContractClassFunctionLeafPreimage, FunctionLeafPreimage};\nuse crate::contract_class::ContractClassId;\nuse crate::abis::new_contract_data::NewContractData as ContractLeafPreimage;\nuse crate::abis::function_data::FunctionData;\nuse crate::abis::side_effect::{SideEffect};\nuse crate::utils::uint256::U256;\nuse crate::constants::{\n ARGS_HASH_CHUNK_COUNT, ARGS_HASH_CHUNK_LENGTH, CONTRACT_TREE_HEIGHT, FUNCTION_TREE_HEIGHT,\n NOTE_HASH_TREE_HEIGHT, NUM_FIELDS_PER_SHA256, GENERATOR_INDEX__SILOED_COMMITMENT,\n GENERATOR_INDEX__OUTER_NULLIFIER, GENERATOR_INDEX__VK, GENERATOR_INDEX__CONSTRUCTOR,\n GENERATOR_INDEX__PARTIAL_ADDRESS, GENERATOR_INDEX__CONTRACT_ADDRESS,\n GENERATOR_INDEX__COMMITMENT_NONCE, GENERATOR_INDEX__UNIQUE_COMMITMENT,\n GENERATOR_INDEX__FUNCTION_ARGS\n};\n\nuse dep::std::hash::{pedersen_hash_with_separator, sha256};\n\npub fn sha256_to_field(bytes_to_hash: [u8; N]) -> Field {\n let sha256_hashed = sha256(bytes_to_hash);\n\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 + (sha256_hashed[15 - i] as Field) * v;\n low = low + (sha256_hashed[16 + 15 - i] as Field) * v;\n v = v * 256;\n }\n\n // Abuse that a % p + b % p = (a + b) % p and that low < p\n let hash_in_a_field = low + high * v;\n\n hash_in_a_field\n}\n\npub fn hash_args(args: [Field; N]) -> Field {\n if args.len() == 0 {\n 0\n } else {\n let mut chunks_hashes = [0; ARGS_HASH_CHUNK_COUNT];\n for i in 0..ARGS_HASH_CHUNK_COUNT {\n let mut chunk_hash = 0;\n let start_chunk_index = i * ARGS_HASH_CHUNK_LENGTH;\n if start_chunk_index < (args.len() as u32) {\n let mut chunk_args = [0; ARGS_HASH_CHUNK_LENGTH];\n for j in 0..ARGS_HASH_CHUNK_LENGTH {\n let item_index = i * ARGS_HASH_CHUNK_LENGTH + j;\n if item_index < (args.len() as u32) {\n chunk_args[j] = args[item_index];\n }\n }\n chunk_hash = pedersen_hash(chunk_args, GENERATOR_INDEX__FUNCTION_ARGS);\n }\n chunks_hashes[i] = chunk_hash;\n }\n pedersen_hash(chunks_hashes, GENERATOR_INDEX__FUNCTION_ARGS)\n }\n}\n\n// Checks that `value` is a member of a merkle tree with root `root` at position `index`\n// The witness being the `sibling_path`\npub fn assert_check_membership(value: Field, index: Field, sibling_path: [Field; N], root: Field) {\n let calculated_root = root_from_sibling_path(value, index, sibling_path);\n assert(calculated_root == root, \"membership check failed\");\n}\n\n// Calculate the Merkle tree root from the sibling path and leaf.\n//\n// The leaf is hashed with its sibling, and then the result is hashed\n// with the next sibling etc in the path. The last hash is the root.\n//\n// TODO(David/Someone): The cpp code is using a uint256, whereas its\n// TODO a bit simpler in Noir to just have a bit array.\n// TODO: I'd generally like to avoid u256 for algorithms like \n// this because it means we never even need to consider cases where \n// the index is greater than p.\npub fn root_from_sibling_path(leaf: Field, leaf_index: Field, sibling_path: [Field; N]) -> Field {\n let mut node = leaf;\n let indices = leaf_index.to_le_bits(N);\n\n for i in 0..N {\n let (hash_left, hash_right) = if indices[i] == 1 {\n (sibling_path[i], node)\n } else {\n (node, sibling_path[i])\n };\n node = merkle_hash(hash_left, hash_right);\n }\n node\n}\n\n// Calculate the function tree root from the sibling path and leaf preimage.\n//\n// TODO: The cpp code passes in components of the FunctionLeafPreimage and then \n// builds it up. We should build it up and then pass the leaf preimage as a parameter.\n// We can then choose to have a general method that takes in anything hashable\n// and deduplicate the logic in `contract_tree_root_from_siblings`\npub fn function_tree_root_from_siblings(\n selector: FunctionSelector,\n is_internal: bool,\n is_private: bool,\n vk_hash: Field,\n acir_hash: Field,\n function_leaf_index: Field,\n function_leaf_sibling_path: [Field; FUNCTION_TREE_HEIGHT]\n) -> Field {\n let function_leaf_preimage = FunctionLeafPreimage { selector, is_internal, is_private, vk_hash, acir_hash };\n\n let function_leaf = function_leaf_preimage.hash();\n\n let function_tree_root = root_from_sibling_path(function_leaf, function_leaf_index, function_leaf_sibling_path);\n\n function_tree_root\n}\n\n// Calculate the contract tree root from the sibling path and leaf preimage.\npub fn contract_tree_root_from_siblings(\n contract_class_id: ContractClassId,\n storage_contract_address: AztecAddress,\n portal_contract_address: EthAddress,\n contract_leaf_index: Field,\n contract_leaf_sibling_path: [Field; CONTRACT_TREE_HEIGHT]\n) -> Field {\n //TODO(Kev): if we use shorthand syntax here, we get an error as expected,\n // since variable name is `storage_contract_address` but the span is incorrect.\n let contract_leaf_preimage = ContractLeafPreimage { contract_address: storage_contract_address, portal_contract_address, contract_class_id };\n\n let contract_leaf = contract_leaf_preimage.hash();\n\n let computed_contract_tree_root = root_from_sibling_path(contract_leaf, contract_leaf_index, contract_leaf_sibling_path);\n\n computed_contract_tree_root\n}\n\npub fn private_functions_root_from_siblings(\n selector: FunctionSelector,\n vk_hash: Field,\n function_leaf_index: Field,\n function_leaf_sibling_path: [Field; FUNCTION_TREE_HEIGHT]\n) -> Field {\n let function_leaf_preimage = ContractClassFunctionLeafPreimage { selector, vk_hash };\n let function_leaf = function_leaf_preimage.hash();\n root_from_sibling_path(function_leaf, function_leaf_index, function_leaf_sibling_path)\n}\n\npub fn read_request_root_from_siblings(\n read_request: Field,\n leaf_index: Field,\n sibling_path: [Field; NOTE_HASH_TREE_HEIGHT]\n) -> Field {\n root_from_sibling_path(read_request, leaf_index, sibling_path)\n}\n\npub fn silo_commitment(address: AztecAddress, inner_commitment: Field) -> Field {\n pedersen_hash(\n [\n address.to_field(),\n inner_commitment\n ],\n GENERATOR_INDEX__SILOED_COMMITMENT\n )\n}\n\npub fn silo_nullifier(address: AztecAddress, nullifier: Field) -> Field {\n pedersen_hash(\n [\n address.to_field(),\n nullifier\n ],\n GENERATOR_INDEX__OUTER_NULLIFIER\n )\n}\n\nfn merkle_hash(left: Field, right: Field) -> Field {\n pedersen_hash([left, right], 0)\n}\n\npub fn stdlib_recursion_verification_key_compress_native_vk(_vk: VerificationKey) -> Field {\n // Original cpp code\n // stdlib::recursion::verification_key::compress_native(private_call.vk, GeneratorIndex::VK);\n // The above cpp method is only ever called on verification key, so it has been special cased here\n let _hash_index = GENERATOR_INDEX__VK;\n 0\n}\n\n// TODO CPP uses blake2s for this\npub fn compute_new_contract_address_hash(new_contract_address: AztecAddress) -> Field {\n dep::std::hash::pedersen_hash([new_contract_address.to_field()])\n}\n\npub fn compute_l2_to_l1_hash(\n contract_address: AztecAddress,\n rollup_version_id: Field,\n portal_contract_address: EthAddress,\n chain_id: Field,\n content: Field\n) -> Field {\n let mut bytes: BoundedVec = BoundedVec::new(0);\n\n let inputs = [\n contract_address.to_field(), rollup_version_id, portal_contract_address.to_field(), chain_id, content\n ];\n for i in 0..inputs.len() {\n // TODO are bytes be in fr.to_buffer() ?\n let item_bytes = inputs[i].to_be_bytes(32);\n for j in 0..32 {\n bytes.push(item_bytes[j]);\n }\n }\n\n sha256_to_field(bytes.storage)\n}\n\npub fn compute_constructor_hash(\n function_data: FunctionData,\n args_hash: Field,\n constructor_vk_hash: Field\n) -> Field {\n let function_data_hash = function_data.hash();\n\n pedersen_hash(\n [\n function_data_hash,\n args_hash,\n constructor_vk_hash\n ],\n GENERATOR_INDEX__CONSTRUCTOR\n )\n}\n\n// Computes sha256 hash of 2 input hashes stored in 4 fields.\n// \n// This method is bn254 specific. Two fields is needed in order to \n// encode the sha256 output. It can be abstracted away with any 4-2 hash function.\n//\n// TODO(Jan and David): This is used for the encrypted_log hashes.\n// Can we check to see if we can just use hash_to_field or pedersen_compress here?\n//\n// Returning a Field would be desirable because then this can be replaced with \n// poseidon without changing the rest of the code\n//\npub fn accumulate_sha256(input: [U128; 4]) -> [Field; NUM_FIELDS_PER_SHA256] {\n // This is a note about the cpp code, since it takes an array of Fields\n // instead of a U128.\n // 4 Field elements when converted to bytes will usually \n // occupy 4 * 32 = 128 bytes.\n // However, this function is making the assumption that each Field \n // only occupies 128 bits.\n //\n // TODO(David): This does not seem to be getting guaranteed anywhere in the code?\n //\n // Concatenate 4 u128 bit integers into a byte array.\n let mut hash_input_flattened = [0; 64];\n for offset in 0..4 {\n let input_as_bytes = input[offset].to_be_bytes();\n for byte_index in 0..16 {\n hash_input_flattened[offset * 16 + byte_index] = input_as_bytes[byte_index];\n }\n }\n\n let sha_digest = dep::std::hash::sha256(hash_input_flattened);\n\n U256::from_bytes32(sha_digest).to_u128_limbs()\n}\n\npub fn compute_logs_hash(\n previous_log_hash: [Field; 2],\n current_log_hash: [Field; 2]\n) -> [Field; NUM_FIELDS_PER_SHA256] {\n accumulate_sha256(\n [\n U128::from_integer(previous_log_hash[0]),\n U128::from_integer(previous_log_hash[1]),\n U128::from_integer(current_log_hash[0]),\n U128::from_integer(current_log_hash[1])\n ]\n )\n}\n\npub fn compute_commitment_nonce(first_nullifier: Field, commitment_index: Field) -> Field {\n pedersen_hash(\n [\n first_nullifier,\n commitment_index\n ],\n GENERATOR_INDEX__COMMITMENT_NONCE\n )\n}\n\npub fn compute_unique_siloed_commitment(nonce: Field, siloed_commitment: Field) -> Field {\n pedersen_hash(\n [\n nonce,\n siloed_commitment\n ],\n GENERATOR_INDEX__UNIQUE_COMMITMENT\n )\n}\n\npub fn compute_unique_siloed_commitments(\n first_nullifier: Field,\n siloed_commitments: [SideEffect; N]\n) -> [SideEffect; N] {\n let mut unique_siloed_commitments = [SideEffect::empty(); N];\n for i in 0..N {\n let siloed_commitment = siloed_commitments[i];\n if siloed_commitment.value != 0 {\n let nonce = compute_commitment_nonce(first_nullifier, i);\n unique_siloed_commitments[i] = SideEffect {\n value: compute_unique_siloed_commitment(nonce, siloed_commitment.value),\n counter: siloed_commitment.counter\n };\n }\n }\n unique_siloed_commitments\n}\n\npub fn pedersen_hash(inputs: [Field; N], hash_index: u32) -> Field {\n dep::std::hash::pedersen_hash_with_separator(inputs, hash_index)\n}\n","path":"/mnt/user-data/sean/nargo/github.com/AztecProtocol/aztec-packages/master/yarn-project/noir-protocol-circuits/src/crates/types/src/hash.nr"},"172":{"source":"// general util packages/modules are usually bad practice\n// because there is no criteria for what we should not put in here.\n// Reducing the size of this package would be welcome.\n\nmod arrays;\nmod field;\nmod reader;\nmod uint256;\n\n// if predicate == true then return lhs, else return rhs\npub fn conditional_assign(predicate: bool, lhs: Field, rhs: Field) -> Field {\n if predicate { lhs } else { rhs }\n}\n\npub fn arr_copy_slice(src: [T; N], mut dst: [T; M], offset: Field) -> [T; M] {\n for i in 0..dst.len() {\n dst[i] = src[i + offset];\n }\n dst\n}\n","path":"/mnt/user-data/sean/nargo/github.com/AztecProtocol/aztec-packages/master/yarn-project/noir-protocol-circuits/src/crates/types/src/utils.nr"},"183":{"source":"use dep::aztec::{\n protocol_types::{address::AztecAddress, traits::{Deserialize, Serialize}},\n note::{note_header::NoteHeader, note_interface::NoteInterface, utils::compute_note_hash_for_consumption},\n oracle::{rand::rand, nullifier_key::get_nullifier_secret_key, get_public_key::get_public_key},\n log::emit_encrypted_log, hash::pedersen_hash, context::PrivateContext\n};\n\nglobal VALUE_NOTE_LEN: Field = 3; // 3 plus a header.\n\n// docs:start:value-note-def\nstruct ValueNote {\n value: Field,\n owner: AztecAddress,\n randomness: Field,\n header: NoteHeader,\n}\n// docs:end:value-note-def\n\nimpl NoteInterface for ValueNote {\n fn serialize_content(self) -> [Field; VALUE_NOTE_LEN] {\n [self.value, self.owner.to_field(), self.randomness]\n }\n\n fn deserialize_content(serialized_note: [Field; VALUE_NOTE_LEN]) -> Self {\n ValueNote {\n value: serialized_note[0],\n owner: AztecAddress::from_field(serialized_note[1]),\n randomness: serialized_note[2],\n header: NoteHeader::empty(),\n }\n }\n\n fn compute_note_content_hash(self) -> Field {\n // TODO(#1205) Should use a non-zero generator index.\n pedersen_hash(self.serialize_content(),0)\n }\n\n // docs:start:nullifier\n\n fn compute_nullifier(self, context: &mut PrivateContext) -> Field {\n let note_hash_for_nullify = compute_note_hash_for_consumption(self);\n let secret = context.request_nullifier_secret_key(self.owner);\n // TODO(#1205) Should use a non-zero generator index.\n pedersen_hash([\n note_hash_for_nullify,\n secret.low,\n secret.high,\n ],0)\n }\n\n // docs:end:nullifier\n\n fn compute_nullifier_without_context(self) -> Field {\n let note_hash_for_nullify = compute_note_hash_for_consumption(self);\n let secret = get_nullifier_secret_key(self.owner);\n // TODO(#1205) Should use a non-zero generator index.\n pedersen_hash([\n note_hash_for_nullify,\n secret.low,\n secret.high,\n ],0)\n }\n\n fn set_header(&mut self, header: NoteHeader) {\n self.header = header;\n }\n\n fn get_header(self) -> NoteHeader {\n self.header\n }\n\n // Broadcasts the note as an encrypted log on L1.\n fn broadcast(self, context: &mut PrivateContext, slot: Field) {\n let encryption_pub_key = get_public_key(self.owner);\n emit_encrypted_log(\n context,\n (*context).this_address(),\n slot,\n Self::get_note_type_id(),\n encryption_pub_key,\n self.serialize_content(),\n );\n }\n\n fn get_note_type_id() -> Field {\n // TODO(#4519): autogenerate\n // python -c \"print(int(''.join(str(ord(c)) for c in 'ValueNote')))\"\n 869710811710178111116101\n }\n}\n\nimpl ValueNote {\n pub fn new(value: Field, owner: AztecAddress) -> Self {\n let randomness = rand();\n let header = NoteHeader::empty();\n ValueNote { value, owner, randomness, header }\n }\n}\n","path":"/mnt/user-data/sean/nargo/github.com/AztecProtocol/aztec-packages/master/yarn-project/aztec-nr/value-note/src/value_note.nr"}}} \ No newline at end of file From fabd16966783af2226d5cfab0cdadd8cb3314db0 Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Mon, 4 Mar 2024 11:52:05 +0000 Subject: [PATCH 02/36] temp --- .../cpp/src/barretenberg/flavor/flavor.hpp | 11 +- .../src/barretenberg/flavor/ultra_keccak.hpp | 577 ++++++++++++++++++ .../solidity_helpers/CMakeLists.txt | 18 +- .../solidity_helpers/honk_key_gen.cpp | 97 +++ .../solidity_helpers/honk_proof_gen.cpp | 108 ++++ .../solidity_helpers/honk_sol_gen.hpp | 98 +++ .../barretenberg/solidity_helpers/key_gen.cpp | 14 +- .../circuit_builders/circuit_builders_fwd.hpp | 3 + .../barretenberg/transcript/transcript.hpp | 61 ++ .../ultra_honk/ultra_composer.cpp | 2 + .../ultra_honk/ultra_composer.hpp | 1 + barretenberg/sol/scripts/init_honk.sh | 11 + barretenberg/sol/scripts/run_fuzzer.sh | 10 +- barretenberg/sol/src/honk/HonkVerifier.sol | 227 ++++--- .../sol/src/honk/HonkVerifierTypes.sol | 81 +++ .../src/honk/keys/Add2HonkVerificationKey.sol | 115 ++++ .../honk/keys/BlakeHonkVerificationKey.sol | 115 ++++ .../honk/keys/EcdsaHonkVerificationKey.sol | 115 ++++ .../src/ultra/instance/Add2UltraVerifier.sol | 2 +- .../src/ultra/instance/BlakeUltraVerifier.sol | 2 +- .../src/ultra/instance/EcdsaUltraVerifier.sol | 2 +- .../ultra/instance/RecursiveUltraVerifier.sol | 2 +- .../ultra/keys/Add2UltraVerificationKey.sol | 30 +- .../ultra/keys/BlakeUltraVerificationKey.sol | 30 +- .../ultra/keys/EcdsaUltraVerificationKey.sol | 38 +- .../keys/RecursiveUltraVerificationKey.sol | 38 +- .../sol/test/base/DifferentialFuzzer.sol | 5 +- barretenberg/sol/test/honk/Add2.t.sol | 42 ++ barretenberg/sol/test/honk/TestBaseHonk.sol | 23 + barretenberg/sol/test/ultra/TestBaseUltra.sol | 1 - 30 files changed, 1696 insertions(+), 183 deletions(-) create mode 100644 barretenberg/cpp/src/barretenberg/flavor/ultra_keccak.hpp create mode 100644 barretenberg/cpp/src/barretenberg/solidity_helpers/honk_key_gen.cpp create mode 100644 barretenberg/cpp/src/barretenberg/solidity_helpers/honk_proof_gen.cpp create mode 100644 barretenberg/cpp/src/barretenberg/solidity_helpers/honk_sol_gen.hpp create mode 100755 barretenberg/sol/scripts/init_honk.sh create mode 100644 barretenberg/sol/src/honk/HonkVerifierTypes.sol create mode 100644 barretenberg/sol/src/honk/keys/Add2HonkVerificationKey.sol create mode 100644 barretenberg/sol/src/honk/keys/BlakeHonkVerificationKey.sol create mode 100644 barretenberg/sol/src/honk/keys/EcdsaHonkVerificationKey.sol create mode 100644 barretenberg/sol/test/honk/Add2.t.sol create mode 100644 barretenberg/sol/test/honk/TestBaseHonk.sol diff --git a/barretenberg/cpp/src/barretenberg/flavor/flavor.hpp b/barretenberg/cpp/src/barretenberg/flavor/flavor.hpp index 20008d3f67c..c7f74c3f79e 100644 --- a/barretenberg/cpp/src/barretenberg/flavor/flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/flavor/flavor.hpp @@ -263,6 +263,11 @@ namespace bb { class UltraFlavor; class ECCVMFlavor; class GoblinUltraFlavor; + +// TODO(md): research this forward declaration pattern +// - howing of file existence is enough +class UltraKeccakFlavor; + template class UltraRecursiveFlavor_; template class GoblinUltraRecursiveFlavor_; } // namespace bb @@ -289,14 +294,16 @@ concept IsPlonkFlavor = IsAnyOf concept IsUltraPlonkFlavor = IsAnyOf; +// TODO: dirty adding this to is goblin flavor template -concept IsHonkFlavor = IsAnyOf; +concept IsHonkFlavor = IsAnyOf; template -concept IsUltraFlavor = IsAnyOf; +concept IsUltraFlavor = IsAnyOf; template concept IsGoblinFlavor = IsAnyOf, GoblinUltraRecursiveFlavor_>; diff --git a/barretenberg/cpp/src/barretenberg/flavor/ultra_keccak.hpp b/barretenberg/cpp/src/barretenberg/flavor/ultra_keccak.hpp new file mode 100644 index 00000000000..e8bb7511860 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/flavor/ultra_keccak.hpp @@ -0,0 +1,577 @@ +#pragma once +#include "barretenberg/commitment_schemes/kzg/kzg.hpp" +#include "barretenberg/ecc/curves/bn254/g1.hpp" +#include "barretenberg/flavor/flavor.hpp" +#include "barretenberg/flavor/flavor_macros.hpp" +#include "barretenberg/polynomials/barycentric.hpp" +#include "barretenberg/polynomials/evaluation_domain.hpp" +#include "barretenberg/polynomials/polynomial.hpp" +#include "barretenberg/polynomials/univariate.hpp" +#include "barretenberg/proof_system/circuit_builder/ultra_circuit_builder.hpp" +#include "barretenberg/relations/auxiliary_relation.hpp" +#include "barretenberg/relations/elliptic_relation.hpp" +#include "barretenberg/relations/gen_perm_sort_relation.hpp" +#include "barretenberg/relations/lookup_relation.hpp" +#include "barretenberg/relations/permutation_relation.hpp" +#include "barretenberg/relations/ultra_arithmetic_relation.hpp" +#include "barretenberg/transcript/transcript.hpp" + +namespace bb { + +class UltraKeccakFlavor { + public: + using CircuitBuilder = UltraCircuitBuilder; + using Curve = curve::BN254; + using FF = Curve::ScalarField; + using GroupElement = Curve::Element; + using Commitment = Curve::AffineElement; + using PCS = KZG; + using Polynomial = bb::Polynomial; + using CommitmentKey = bb::CommitmentKey; + using VerifierCommitmentKey = bb::VerifierCommitmentKey; + + static constexpr size_t NUM_WIRES = CircuitBuilder::NUM_WIRES; + // The number of multivariate polynomials on which a sumcheck prover sumcheck operates (including shifts). We often + // need containers of this size to hold related data, so we choose a name more agnostic than `NUM_POLYNOMIALS`. + // Note: this number does not include the individual sorted list polynomials. + static constexpr size_t NUM_ALL_ENTITIES = 43; + // The number of polynomials precomputed to describe a circuit and to aid a prover in constructing a satisfying + // assignment of witnesses. We again choose a neutral name. + static constexpr size_t NUM_PRECOMPUTED_ENTITIES = 25; + // The total number of witness entities not including shifts. + static constexpr size_t NUM_WITNESS_ENTITIES = 7; + + using GrandProductRelations = std::tuple, bb::LookupRelation>; + // define the tuple of Relations that comprise the Sumcheck relation + using Relations = std::tuple, + bb::UltraPermutationRelation, + bb::LookupRelation, + bb::GenPermSortRelation, + bb::EllipticRelation, + bb::AuxiliaryRelation>; + + static constexpr size_t MAX_PARTIAL_RELATION_LENGTH = compute_max_partial_relation_length(); + static_assert(MAX_PARTIAL_RELATION_LENGTH == 6); + static constexpr size_t MAX_TOTAL_RELATION_LENGTH = compute_max_total_relation_length(); + static_assert(MAX_TOTAL_RELATION_LENGTH == 12); + static constexpr size_t NUM_SUBRELATIONS = compute_number_of_subrelations(); + // For instances of this flavour, used in folding, we need a unique sumcheck batching challenge for each + // subrelation. This is because using powers of alpha would increase the degree of Protogalaxy polynomial $G$ (the + // combiner) too much. + using RelationSeparator = std::array; + + // BATCHED_RELATION_PARTIAL_LENGTH = algebraic degree of sumcheck relation *after* multiplying by the `pow_zeta` + // random polynomial e.g. For \sum(x) [A(x) * B(x) + C(x)] * PowZeta(X), relation length = 2 and random relation + // length = 3 + static constexpr size_t BATCHED_RELATION_PARTIAL_LENGTH = MAX_PARTIAL_RELATION_LENGTH + 1; + static constexpr size_t BATCHED_RELATION_TOTAL_LENGTH = MAX_TOTAL_RELATION_LENGTH + 1; + static constexpr size_t NUM_RELATIONS = std::tuple_size_v; + + template + using ProtogalaxyTupleOfTuplesOfUnivariates = + decltype(create_protogalaxy_tuple_of_tuples_of_univariates()); + using SumcheckTupleOfTuplesOfUnivariates = decltype(create_sumcheck_tuple_of_tuples_of_univariates()); + using TupleOfArraysOfValues = decltype(create_tuple_of_arrays_of_values()); + + // Whether or not the first row of the execution trace is reserved for 0s to enable shifts + static constexpr bool has_zero_row = true; + + static constexpr bool is_decider = true; + + private: + /** + * @brief A base class labelling precomputed entities and (ordered) subsets of interest. + * @details Used to build the proving key and verification key. + */ + template class PrecomputedEntities : public PrecomputedEntitiesBase { + public: + using DataType = DataType_; + DEFINE_FLAVOR_MEMBERS(DataType, + q_m, // column 0 + q_c, // column 1 + q_l, // column 2 + q_r, // column 3 + q_o, // column 4 + q_4, // column 5 + q_arith, // column 6 + q_sort, // column 7 + q_elliptic, // column 8 + q_aux, // column 9 + q_lookup, // column 10 + sigma_1, // column 11 + sigma_2, // column 12 + sigma_3, // column 13 + sigma_4, // column 14 + id_1, // column 15 + id_2, // column 16 + id_3, // column 17 + id_4, // column 18 + table_1, // column 19 + table_2, // column 20 + table_3, // column 21 + table_4, // column 22 + lagrange_first, // column 23 + lagrange_last) // column 24 + + static constexpr CircuitType CIRCUIT_TYPE = CircuitBuilder::CIRCUIT_TYPE; + + auto get_selectors() + { + return RefArray{ q_m, q_c, q_l, q_r, q_o, q_4, q_arith, q_sort, q_elliptic, q_aux, q_lookup }; + }; + auto get_sigma_polynomials() { return RefArray{ sigma_1, sigma_2, sigma_3, sigma_4 }; }; + auto get_id_polynomials() { return RefArray{ id_1, id_2, id_3, id_4 }; }; + + auto get_table_polynomials() { return RefArray{ table_1, table_2, table_3, table_4 }; }; + }; + + /** + * @brief Container for all witness polynomials used/constructed by the prover. + * @details Shifts are not included here since they do not occupy their own memory. + */ + template class WitnessEntities { + public: + DEFINE_FLAVOR_MEMBERS(DataType, + w_l, // column 0 + w_r, // column 1 + w_o, // column 2 + w_4, // column 3 + sorted_accum, // column 4 + z_perm, // column 5 + z_lookup) // column 6 + + auto get_wires() { return RefArray{ w_l, w_r, w_o, w_4 }; }; + }; + + /** + * @brief Class for ShiftedEntities, containing shifted witness and table polynomials. + */ + template class ShiftedEntities { + public: + DEFINE_FLAVOR_MEMBERS(DataType, + table_1_shift, // column 0 + table_2_shift, // column 1 + table_3_shift, // column 2 + table_4_shift, // column 3 + w_l_shift, // column 4 + w_r_shift, // column 5 + w_o_shift, // column 6 + w_4_shift, // column 7 + sorted_accum_shift, // column 8 + z_perm_shift, // column 9 + z_lookup_shift) // column 10 + + auto get_shifted() + { + return RefArray{ table_1_shift, table_2_shift, table_3_shift, table_4_shift, w_l_shift, w_r_shift, + w_o_shift, w_4_shift, sorted_accum_shift, z_perm_shift, z_lookup_shift }; + }; + }; + + /** + * @brief A base class labelling all entities (for instance, all of the polynomials used by the prover during + * sumcheck) in this Honk variant along with particular subsets of interest + * @details Used to build containers for: the prover's polynomial during sumcheck; the sumcheck's folded + * polynomials; the univariates consturcted during during sumcheck; the evaluations produced by sumcheck. + * + * Symbolically we have: AllEntities = PrecomputedEntities + WitnessEntities + "ShiftedEntities". It could be + * implemented as such, but we have this now. + */ + template class AllEntities { + public: + DEFINE_FLAVOR_MEMBERS(DataType, + q_c, // column 0 + q_l, // column 1 + q_r, // column 2 + q_o, // column 3 + q_4, // column 4 + q_m, // column 5 + q_arith, // column 6 + q_sort, // column 7 + q_elliptic, // column 8 + q_aux, // column 9 + q_lookup, // column 10 + sigma_1, // column 11 + sigma_2, // column 12 + sigma_3, // column 13 + sigma_4, // column 14 + id_1, // column 15 + id_2, // column 16 + id_3, // column 17 + id_4, // column 18 + table_1, // column 19 + table_2, // column 20 + table_3, // column 21 + table_4, // column 22 + lagrange_first, // column 23 + lagrange_last, // column 24 + w_l, // column 25 + w_r, // column 26 + w_o, // column 27 + w_4, // column 28 + sorted_accum, // column 29 + z_perm, // column 30 + z_lookup, // column 31 + table_1_shift, // column 32 + table_2_shift, // column 33 + table_3_shift, // column 34 + table_4_shift, // column 35 + w_l_shift, // column 36 + w_r_shift, // column 37 + w_o_shift, // column 38 + w_4_shift, // column 39 + sorted_accum_shift, // column 40 + z_perm_shift, // column 41 + z_lookup_shift) // column 42 + + auto get_wires() { return RefArray{ w_l, w_r, w_o, w_4 }; }; + // Gemini-specific getters. + auto get_unshifted() + { + return RefArray{ q_m, q_c, q_l, q_r, q_o, q_4, q_arith, q_sort, + q_elliptic, q_aux, q_lookup, sigma_1, sigma_2, sigma_3, sigma_4, id_1, + id_2, id_3, id_4, table_1, table_2, table_3, table_4, lagrange_first, + lagrange_last, w_l, w_r, w_o, w_4, sorted_accum, z_perm, z_lookup + + }; + }; + + auto get_precomputed() + { + return RefArray{ q_m, q_c, q_l, q_r, q_o, q_4, q_arith, q_sort, + q_elliptic, q_aux, q_lookup, sigma_1, sigma_2, sigma_3, sigma_4, id_1, + id_2, id_3, id_4, table_1, table_2, table_3, table_4, lagrange_first, + lagrange_last + + }; + } + + auto get_witness() { return RefArray{ w_l, w_r, w_o, w_4, sorted_accum, z_perm, z_lookup }; }; + auto get_to_be_shifted() + { + return RefArray{ table_1, table_2, table_3, table_4, w_l, w_r, w_o, w_4, sorted_accum, z_perm, z_lookup }; + }; + auto get_shifted() + { + return RefArray{ table_1_shift, table_2_shift, table_3_shift, table_4_shift, w_l_shift, w_r_shift, + w_o_shift, w_4_shift, sorted_accum_shift, z_perm_shift, z_lookup_shift }; + }; + }; + + public: + /** + * @brief The proving key is responsible for storing the polynomials used by the prover. + * @note TODO(Cody): Maybe multiple inheritance is the right thing here. In that case, nothing should eve inherit + * from ProvingKey. + */ + class ProvingKey : public ProvingKey_, WitnessEntities> { + public: + // Expose constructors on the base class + using Base = ProvingKey_, WitnessEntities>; + using Base::Base; + + std::vector memory_read_records; + std::vector memory_write_records; + + auto get_to_be_shifted() + { + return RefArray{ this->table_1, this->table_2, this->table_3, this->table_4, this->w_l, this->w_r, + this->w_o, this->w_4, this->sorted_accum, this->z_perm, this->z_lookup }; + }; + // The plookup wires that store plookup read data. + auto get_table_column_wires() { return RefArray{ w_l, w_r, w_o }; }; + }; + + /** + * @brief The verification key is responsible for storing the the commitments to the precomputed (non-witnessk) + * polynomials used by the verifier. + * + * @note Note the discrepancy with what sort of data is stored here vs in the proving key. We may want to resolve + * that, and split out separate PrecomputedPolynomials/Commitments data for clarity but also for portability of our + * circuits. + */ + using VerificationKey = VerificationKey_>; + + /** + * @brief A field element for each entity of the flavor. These entities represent the prover polynomials + * evaluated at one point. + */ + class AllValues : public AllEntities { + public: + using Base = AllEntities; + using Base::Base; + }; + + /** + * @brief A container for polynomials handles. + */ + class ProverPolynomials : public AllEntities { + public: + // Define all operations as default, except move construction/assignment + ProverPolynomials() = default; + ProverPolynomials& operator=(const ProverPolynomials&) = delete; + ProverPolynomials(const ProverPolynomials& o) = delete; + ProverPolynomials(ProverPolynomials&& o) noexcept = default; + ProverPolynomials& operator=(ProverPolynomials&& o) noexcept = default; + ~ProverPolynomials() = default; + [[nodiscard]] size_t get_polynomial_size() const { return q_c.size(); } + [[nodiscard]] AllValues get_row(const size_t row_idx) const + { + AllValues result; + for (auto [result_field, polynomial] : zip_view(result.get_all(), get_all())) { + result_field = polynomial[row_idx]; + } + return result; + } + }; + + /** + * @brief A container for storing the partially evaluated multivariates produced by sumcheck. + */ + class PartiallyEvaluatedMultivariates : public AllEntities { + + public: + PartiallyEvaluatedMultivariates() = default; + PartiallyEvaluatedMultivariates(const size_t circuit_size) + { + // Storage is only needed after the first partial evaluation, hence polynomials of size (n / 2) + for (auto& poly : this->get_all()) { + poly = Polynomial(circuit_size / 2); + } + } + }; + + /** + * @brief A container for univariates used during Protogalaxy folding and sumcheck. + * @details During folding and sumcheck, the prover evaluates the relations on these univariates. + */ + template using ProverUnivariates = AllEntities>; + + /** + * @brief A container for univariates produced during the hot loop in sumcheck. + */ + using ExtendedEdges = ProverUnivariates; + + /** + * @brief A container for the witness commitments. + */ + using WitnessCommitments = WitnessEntities; + + /** + * @brief A container for commitment labels. + * @note It's debatable whether this should inherit from AllEntities. since most entries are not strictly needed. It + * has, however, been useful during debugging to have these labels available. + * + */ + class CommitmentLabels : public AllEntities { + public: + CommitmentLabels() + { + w_l = "W_L"; + w_r = "W_R"; + w_o = "W_O"; + w_4 = "W_4"; + z_perm = "Z_PERM"; + z_lookup = "Z_LOOKUP"; + sorted_accum = "SORTED_ACCUM"; + + q_c = "Q_C"; + q_l = "Q_L"; + q_r = "Q_R"; + q_o = "Q_O"; + q_4 = "Q_4"; + q_m = "Q_M"; + q_arith = "Q_ARITH"; + q_sort = "Q_SORT"; + q_elliptic = "Q_ELLIPTIC"; + q_aux = "Q_AUX"; + q_lookup = "Q_LOOKUP"; + sigma_1 = "SIGMA_1"; + sigma_2 = "SIGMA_2"; + sigma_3 = "SIGMA_3"; + sigma_4 = "SIGMA_4"; + id_1 = "ID_1"; + id_2 = "ID_2"; + id_3 = "ID_3"; + id_4 = "ID_4"; + table_1 = "TABLE_1"; + table_2 = "TABLE_2"; + table_3 = "TABLE_3"; + table_4 = "TABLE_4"; + lagrange_first = "LAGRANGE_FIRST"; + lagrange_last = "LAGRANGE_LAST"; + }; + }; + + /** + * @brief A container encapsulating all the commitments that the verifier receives (to precomputed polynomials and + * witness polynomials). + * + */ + class VerifierCommitments : public AllEntities { + public: + VerifierCommitments(const std::shared_ptr& verification_key, + const std::optional& witness_commitments = std::nullopt) + { + q_m = verification_key->q_m; + q_c = verification_key->q_c; + q_l = verification_key->q_l; + q_r = verification_key->q_r; + q_o = verification_key->q_o; + q_4 = verification_key->q_4; + q_arith = verification_key->q_arith; + q_sort = verification_key->q_sort; + q_elliptic = verification_key->q_elliptic; + q_aux = verification_key->q_aux; + q_lookup = verification_key->q_lookup; + sigma_1 = verification_key->sigma_1; + sigma_2 = verification_key->sigma_2; + sigma_3 = verification_key->sigma_3; + sigma_4 = verification_key->sigma_4; + id_1 = verification_key->id_1; + id_2 = verification_key->id_2; + id_3 = verification_key->id_3; + id_4 = verification_key->id_4; + table_1 = verification_key->table_1; + table_2 = verification_key->table_2; + table_3 = verification_key->table_3; + table_4 = verification_key->table_4; + lagrange_first = verification_key->lagrange_first; + lagrange_last = verification_key->lagrange_last; + + if (witness_commitments.has_value()) { + auto commitments = witness_commitments.value(); + this->w_l = commitments.w_l; + this->w_r = commitments.w_r; + this->w_o = commitments.w_o; + this->sorted_accum = commitments.sorted_accum; + this->w_4 = commitments.w_4; + this->z_perm = commitments.z_perm; + this->z_lookup = commitments.z_lookup; + } + } + }; + + /** + * @brief Derived class that defines proof structure for Ultra proofs, as well as supporting functions. + * + */ + class Transcript : public SolidityTranscript { + public: + // Transcript objects defined as public member variables for easy access and modification + uint32_t circuit_size; + uint32_t public_input_size; + uint32_t pub_inputs_offset; + std::vector public_inputs; + Commitment w_l_comm; + Commitment w_r_comm; + Commitment w_o_comm; + Commitment sorted_accum_comm; + Commitment w_4_comm; + Commitment z_perm_comm; + Commitment z_lookup_comm; + std::vector> sumcheck_univariates; + std::array sumcheck_evaluations; + std::vector zm_cq_comms; + Commitment zm_cq_comm; + Commitment zm_pi_comm; + + Transcript() = default; + + // Used by verifier to initialize the transcript + Transcript(const std::vector& proof) + : SolidityTranscript(proof) + {} + + static std::shared_ptr prover_init_empty() + { + auto transcript = std::make_shared(); + constexpr uint32_t init{ 42 }; // arbitrary + transcript->send_to_verifier("Init", init); + return transcript; + }; + + static std::shared_ptr verifier_init_empty(const std::shared_ptr& transcript) + { + auto verifier_transcript = std::make_shared(transcript->proof_data); + [[maybe_unused]] auto _ = verifier_transcript->template receive_from_prover("Init"); + return verifier_transcript; + }; + + /** + * @brief Takes a FULL Ultra proof and deserializes it into the public member variables that compose the + * structure. Must be called in order to access the structure of the proof. + * + */ + void deserialize_full_transcript() + { + // take current proof and put them into the struct + size_t num_frs_read = 0; + circuit_size = deserialize_from_buffer(proof_data, num_frs_read); + size_t log_n = numeric::get_msb(circuit_size); + + public_input_size = deserialize_from_buffer(proof_data, num_frs_read); + pub_inputs_offset = deserialize_from_buffer(proof_data, num_frs_read); + for (size_t i = 0; i < public_input_size; ++i) { + public_inputs.push_back(deserialize_from_buffer(proof_data, num_frs_read)); + } + w_l_comm = deserialize_from_buffer(proof_data, num_frs_read); + w_r_comm = deserialize_from_buffer(proof_data, num_frs_read); + w_o_comm = deserialize_from_buffer(proof_data, num_frs_read); + sorted_accum_comm = deserialize_from_buffer(proof_data, num_frs_read); + w_4_comm = deserialize_from_buffer(proof_data, num_frs_read); + z_perm_comm = deserialize_from_buffer(proof_data, num_frs_read); + z_lookup_comm = deserialize_from_buffer(proof_data, num_frs_read); + for (size_t i = 0; i < log_n; ++i) { + sumcheck_univariates.push_back( + deserialize_from_buffer>(proof_data, + num_frs_read)); + } + sumcheck_evaluations = deserialize_from_buffer>(proof_data, num_frs_read); + for (size_t i = 0; i < log_n; ++i) { + zm_cq_comms.push_back(deserialize_from_buffer(proof_data, num_frs_read)); + } + zm_cq_comm = deserialize_from_buffer(proof_data, num_frs_read); + zm_pi_comm = deserialize_from_buffer(proof_data, num_frs_read); + } + + /** + * @brief Serializes the structure variables into a FULL Ultra proof. Should be called only if + * deserialize_full_transcript() was called and some transcript variable was modified. + * + */ + void serialize_full_transcript() + { + size_t old_proof_length = proof_data.size(); + proof_data.clear(); // clear proof_data so the rest of the function can replace it + size_t log_n = numeric::get_msb(circuit_size); + serialize_to_buffer(circuit_size, proof_data); + serialize_to_buffer(public_input_size, proof_data); + serialize_to_buffer(pub_inputs_offset, proof_data); + for (size_t i = 0; i < public_input_size; ++i) { + serialize_to_buffer(public_inputs[i], proof_data); + } + serialize_to_buffer(w_l_comm, proof_data); + serialize_to_buffer(w_r_comm, proof_data); + serialize_to_buffer(w_o_comm, proof_data); + serialize_to_buffer(sorted_accum_comm, proof_data); + serialize_to_buffer(w_4_comm, proof_data); + serialize_to_buffer(z_perm_comm, proof_data); + serialize_to_buffer(z_lookup_comm, proof_data); + for (size_t i = 0; i < log_n; ++i) { + serialize_to_buffer(sumcheck_univariates[i], proof_data); + } + serialize_to_buffer(sumcheck_evaluations, proof_data); + for (size_t i = 0; i < log_n; ++i) { + serialize_to_buffer(zm_cq_comms[i], proof_data); + } + serialize_to_buffer(zm_cq_comm, proof_data); + serialize_to_buffer(zm_pi_comm, proof_data); + + // sanity check to make sure we generate the same length of proof as before. + ASSERT(proof_data.size() == old_proof_length); + } + }; +}; + +} // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/solidity_helpers/CMakeLists.txt b/barretenberg/cpp/src/barretenberg/solidity_helpers/CMakeLists.txt index 76bbe00dc57..e48cb052ab9 100644 --- a/barretenberg/cpp/src/barretenberg/solidity_helpers/CMakeLists.txt +++ b/barretenberg/cpp/src/barretenberg/solidity_helpers/CMakeLists.txt @@ -1,6 +1,22 @@ -barretenberg_module(stdlib_solidity_helpers plonk proof_system transcript crypto_pedersen_commitment polynomials crypto_sha256 ecc crypto_blake3s stdlib_primitives stdlib_pedersen_commitment stdlib_blake3s stdlib_blake2s stdlib_sha256 srs) +barretenberg_module(stdlib_solidity_helpers ultra_honk plonk proof_system transcript crypto_pedersen_commitment polynomials crypto_sha256 ecc crypto_blake3s stdlib_primitives stdlib_pedersen_commitment stdlib_blake3s stdlib_blake2s stdlib_sha256 srs) if (NOT(FUZZING)) + # Honk + add_executable(honk_solidity_key_gen honk_key_gen.cpp) + + target_link_libraries( + honk_solidity_key_gen + stdlib_solidity_helpers + ) + + add_executable(honk_solidity_proof_gen honk_proof_gen.cpp) + + target_link_libraries( + honk_solidity_proof_gen + stdlib_solidity_helpers + ) + + # Plonk add_executable(solidity_key_gen key_gen.cpp) add_executable(solidity_proof_gen proof_gen.cpp) diff --git a/barretenberg/cpp/src/barretenberg/solidity_helpers/honk_key_gen.cpp b/barretenberg/cpp/src/barretenberg/solidity_helpers/honk_key_gen.cpp new file mode 100644 index 00000000000..12bd3855cef --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/solidity_helpers/honk_key_gen.cpp @@ -0,0 +1,97 @@ + +#include + +#include "barretenberg/ultra_honk/ultra_composer.hpp" + +#include "./honk_sol_gen.hpp" + +#include "circuits/add_2_circuit.hpp" +#include "circuits/blake_circuit.hpp" +#include "circuits/ecdsa_circuit.hpp" + +// #include "utils/instance_sol_gen.hpp" +// #include "utils/utils.hpp" + +template