diff --git a/.github/ci-setup-action/action.yml b/.github/ci-setup-action/action.yml index 14708938330..93ad03f5941 100644 --- a/.github/ci-setup-action/action.yml +++ b/.github/ci-setup-action/action.yml @@ -35,6 +35,10 @@ runs: # TODO reconsider how jq gets into image - name: Setup jq uses: dcarbone/install-jq-action@v2.1.0 + - name: Setup yq + uses: dcarbone/install-yq-action@v1.1.1 + with: + version: v4.44.3 - name: Setup Earthly uses: earthly/actions-setup@v1 diff --git a/.github/ensure-tester/action.yml b/.github/ensure-tester/action.yml index 4525f2df30a..ec6b1c27542 100644 --- a/.github/ensure-tester/action.yml +++ b/.github/ensure-tester/action.yml @@ -95,6 +95,16 @@ runs: " || true fi + - name: Setup yq + shell: bash + run: | + set -x + scripts/run_on_tester " + wget https://github.com/mikefarah/yq/releases/download/v4.44.3/yq_linux_amd64 -O ./yq + chmod +x ./yq + sudo mv ./yq /usr/bin/yq + " + - name: Ensure Tester Cleanup uses: gacts/run-and-post-run@v1 with: diff --git a/.github/workflows/ci-arm.yml b/.github/workflows/ci-arm.yml index 104914717e6..1ba74da9a63 100644 --- a/.github/workflows/ci-arm.yml +++ b/.github/workflows/ci-arm.yml @@ -3,7 +3,7 @@ on: push: branches: - master - - '*/*arm-build' + - "*/*arm-build" workflow_dispatch: inputs: {} concurrency: @@ -101,8 +101,9 @@ jobs: # prepare images locally, tagged by commit hash - name: "Build E2E Image" timeout-minutes: 40 + working-directory: ./yarn-project/end-to-end run: | - earthly-ci ./yarn-project/end-to-end+uniswap-trade-on-l1-from-l2 + ./scripts/e2e_compose_test.sh uniswap_trade_on_l1_from_l2.test.ts rerun-check: runs-on: ubuntu-20.04 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 84b63b632d1..13c81faeb90 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -4,7 +4,7 @@ on: branches: - master - provernet - - '*/ci-push*' + - "*/ci-push*" pull_request: types: - opened @@ -172,6 +172,7 @@ jobs: LABELS="" fi echo Labels: $LABELS + echo "list=$(./scripts/ci/get_e2e_jobs.sh ${{github.ref_name}} "$LABELS")" echo "list=$(./scripts/ci/get_e2e_jobs.sh ${{github.ref_name}} "$LABELS")" >> $GITHUB_OUTPUT - name: Create list of bench end-to-end jobs id: bench_list @@ -197,24 +198,26 @@ jobs: - uses: actions/checkout@v4 with: { ref: "${{ env.GIT_COMMIT }}" } - uses: ./.github/ci-setup-action + - name: Determine runner type + id: runner_type + run: | + runner=$(./scripts/ci/select_runner.sh ${{ matrix.test }}) + echo "type=$runner" >> $GITHUB_OUTPUT - name: Setup and Test timeout-minutes: 40 uses: ./.github/ensure-tester-with-images env: USERNAME: ${{ needs.configure.outputs.username }} with: - runner_type: ${{ contains(matrix.test, 'prover') && '64core-tester-x86' || '8core-tester-x86' }} + runner_type: ${{ steps.runner_type.outputs.type }} builder_type: builder-x86 - # these are copied to the tester and expected by the earthly command below - # if they fail to copy, it will try to build them on the tester and fail builder_images_to_copy: aztecprotocol/aztec:${{ env.GIT_COMMIT }} aztecprotocol/end-to-end:${{ env.GIT_COMMIT }} - # command to produce the images in case they don't exist builder_command: scripts/earthly-ci ./yarn-project+export-e2e-test-images run: | set -eux cd ./yarn-project/end-to-end/ export FORCE_COLOR=1 - ../../scripts/earthly-ci -P --no-output +${{ matrix.test }} + ./scripts/e2e_test.sh ${{ matrix.test }} # all the benchmarking end-to-end integration tests for aztec (not required to merge) bench-e2e: @@ -229,13 +232,18 @@ jobs: - uses: actions/checkout@v4 with: { ref: "${{ env.GIT_COMMIT }}" } - uses: ./.github/ci-setup-action + - name: Determine runner type + id: runner_type + run: | + runner=$(./scripts/ci/select_runner.sh ${{ matrix.test }}) + echo "type=$runner" >> $GITHUB_OUTPUT - name: Setup and Test uses: ./.github/ensure-tester-with-images env: USERNAME: ${{ needs.configure.outputs.username }} timeout-minutes: 45 with: - runner_type: ${{ contains(matrix.test, 'prover') && '64core-tester-x86' || '16core-tester-x86' }} + runner_type: ${{ steps.runner_type.outputs.type }} builder_type: builder-x86 # these are copied to the tester and expected by the earthly command below # if they fail to copy, it will try to build them on the tester and fail @@ -248,7 +256,9 @@ jobs: cd ./yarn-project/end-to-end/ export FORCE_COLOR=1 export EARTHLY_BUILD_ARGS="${{ env.EARTHLY_BUILD_ARGS }}" - ../../scripts/earthly-ci --exec-stats -P --no-output +${{ matrix.test }} + ./scripts/e2e_test.sh ${{ matrix.test }} + + earthly-ci +UPLOAD_LOGS --PULL_REQUEST=${{ github.event.pull_request.number }} --BRANCH=${{ github.ref_name }} --COMMIT_HASH=${{ env.GIT_COMMIT }} acir-bench: runs-on: ubuntu-20.04 @@ -584,7 +594,7 @@ jobs: yarn-project-formatting: needs: [build, configure] - if: needs.configure.outputs.yarn-project == 'true' || github.ref_name == 'master' + if: needs.configure.outputs.yarn-project == 'true' || github.ref_name == 'master' runs-on: ${{ needs.configure.outputs.username }}-x86 steps: - uses: actions/checkout@v4 @@ -598,7 +608,7 @@ jobs: yarn-project-test: needs: [build, configure] - if: needs.configure.outputs.yarn-project == 'true' || github.ref_name == 'master' + if: needs.configure.outputs.yarn-project == 'true' || github.ref_name == 'master' runs-on: ${{ needs.configure.outputs.username }}-x86 steps: - uses: actions/checkout@v4 @@ -613,7 +623,7 @@ jobs: prover-client-test: needs: [build, configure] runs-on: ${{ needs.configure.outputs.username }}-x86 - if: needs.configure.outputs.yarn-project == 'true' || github.ref_name == 'master' + if: needs.configure.outputs.yarn-project == 'true' || github.ref_name == 'master' steps: - uses: actions/checkout@v4 with: { ref: "${{ env.GIT_COMMIT }}" } @@ -627,7 +637,7 @@ jobs: # proving disabled network-test: needs: [build, configure] - if: needs.configure.outputs.yarn-project == 'true' + if: needs.configure.outputs.yarn-project == 'true' || github.ref_name == 'master' runs-on: ${{ needs.configure.outputs.username }}-x86 strategy: max-parallel: 1 @@ -649,7 +659,7 @@ jobs: # note: proving disabled kind-network-test: needs: [build, configure] - if: needs.configure.output.yarn-project == 'true' + if: needs.configure.outputs.yarn-project == 'true' || github.ref_name == 'master' runs-on: ${{ needs.configure.outputs.username }}-x86 strategy: fail-fast: false diff --git a/.github/workflows/nightly-kind-test.yml b/.github/workflows/nightly-kind-test.yml index 255835daa76..668dc341ca6 100644 --- a/.github/workflows/nightly-kind-test.yml +++ b/.github/workflows/nightly-kind-test.yml @@ -74,8 +74,7 @@ jobs: set -eux ./spartan/scripts/setup_local_k8s.sh export FORCE_COLOR=1 - export EARTHLY_BUILD_ARGS="${{ env.EARTHLY_BUILD_ARGS }}" - ./scripts/earthly-ci --exec-stats -P --no-output ./yarn-project/end-to-end/+kind-network-transfer --values-file=${{ matrix.values_file }} + NAMESPACE=transfer FRESH_INSTALL=true VALUES_FILE=${{ matrix.values_file }} ./scripts/network_test.sh ./src/spartan/transfer.test.ts || true success-check: runs-on: ubuntu-20.04 diff --git a/.github/workflows/sepolia-test.yml b/.github/workflows/sepolia-test.yml index e2e6210f28a..b389302f2a5 100644 --- a/.github/workflows/sepolia-test.yml +++ b/.github/workflows/sepolia-test.yml @@ -54,11 +54,11 @@ jobs: set -eux cd ./yarn-project/end-to-end/ export FORCE_COLOR=1 - ../../scripts/earthly-ci -P --no-output +e2e-public-testnet \ - --SEQ_PUBLISHER_PRIVATE_KEY=${{ secrets.SEPOLIA_SEQ_PRIVATE_KEY }} \ - --PROVER_PUBLISHER_PRIVATE_KEY=${{ secrets.SEPOLIA_PROVER_PRIVATE_KEY }} \ - --ETHEREUM_HOST="https://sepolia.infura.io/v3/${{ secrets.SEPOLIA_API_KEY }}" \ - --L1_CHAIN_ID=${{ env.L1_CHAIN_ID }} + SEQ_PUBLISHER_PRIVATE_KEY=${{ secrets.SEPOLIA_SEQ_PRIVATE_KEY }} \ + PROVER_PUBLISHER_PRIVATE_KEY=${{ secrets.SEPOLIA_PROVER_PRIVATE_KEY }} \ + ETHEREUM_HOST="https://sepolia.infura.io/v3/${{ secrets.SEPOLIA_API_KEY }}" \ + L1_CHAIN_ID=${{ env.L1_CHAIN_ID }} \ + ./scripts/e2e_test_public_testnet.sh ./src/public-testnet success-check: runs-on: ubuntu-20.04 diff --git a/Earthfile b/Earthfile index f8eea6475ba..ed020738d41 100644 --- a/Earthfile +++ b/Earthfile @@ -20,9 +20,6 @@ build: # yarn-project has the entry point to Aztec BUILD ./yarn-project/+build -test-end-to-end: - BUILD ./yarn-project/end-to-end+e2e-tests - release-meta: COPY .release-please-manifest.json /usr/src/.release-please-manifest.json SAVE ARTIFACT /usr/src /usr/src @@ -46,7 +43,7 @@ UPLOAD_LOGS: ENV BRANCH=$BRANCH ENV COMMIT_HASH=$COMMIT_HASH RUN --secret AWS_ACCESS_KEY_ID --secret AWS_SECRET_ACCESS_KEY /usr/src/scripts/logs/upload_logs_to_s3.sh /usr/var/log - + base-log-uploader: # Install awscli on a fresh ubuntu, and copy the repo "scripts" folder, which we'll use to upload logs # Note that we cannot do this LOCALLY because Earthly does not support using secrets locally diff --git a/barretenberg/cpp/src/barretenberg/bb/main.cpp b/barretenberg/cpp/src/barretenberg/bb/main.cpp index 58bbb33f8bd..07fabf7029d 100644 --- a/barretenberg/cpp/src/barretenberg/bb/main.cpp +++ b/barretenberg/cpp/src/barretenberg/bb/main.cpp @@ -598,8 +598,8 @@ void prove_tube(const std::string& output_path) // these public inputs by turning proof into witnesses and call // set_public on each witness auto num_public_inputs = static_cast(static_cast(proof.folding_proof[1])); - num_public_inputs -= bb::AGGREGATION_OBJECT_SIZE; // don't add the agg object - num_public_inputs -= 1 * 8; // TODO(https://github.com/AztecProtocol/barretenberg/issues/1125) Make this dynamic + num_public_inputs -= bb::AGGREGATION_OBJECT_SIZE; // don't add the agg object + num_public_inputs -= bb::PROPAGATED_DATABUS_COMMITMENTS_SIZE; // exclude propagated databus commitments for (size_t i = 0; i < num_public_inputs; i++) { auto offset = acir_format::HONK_RECURSION_PUBLIC_INPUT_OFFSET; builder->add_public_variable(proof.folding_proof[i + offset]); diff --git a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp index 66926c1a07d..9dc931e0c1d 100644 --- a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp +++ b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp @@ -54,6 +54,9 @@ void ClientIVC::perform_recursive_verification_and_databus_consistency_checks( const std::shared_ptr& vkey, const QUEUE_TYPE type) { + // Store the decider vk for the incoming circuit; its data is used in the databus consistency checks below + std::shared_ptr decider_vk; + switch (type) { case QUEUE_TYPE::PG: { // Construct stdlib verifier accumulator from the native counterpart computed on a previous round @@ -66,10 +69,8 @@ void ClientIVC::perform_recursive_verification_and_databus_consistency_checks( // Extract native verifier accumulator from the stdlib accum for use on the next round verifier_accumulator = std::make_shared(verifier_accum->get_value()); - // Perform databus commitment consistency checks and propagate return data commitments via public inputs - bus_depot.execute(verifier.keys_to_fold[1]->witness_commitments, - verifier.keys_to_fold[1]->public_inputs, - verifier.keys_to_fold[1]->verification_key->databus_propagation_data); + decider_vk = verifier.keys_to_fold[1]; // decider vk for the incoming circuit + break; } case QUEUE_TYPE::OINK: { @@ -86,14 +87,20 @@ void ClientIVC::perform_recursive_verification_and_databus_consistency_checks( // Initialize the gate challenges to zero for use in first round of folding verifier_accumulator->gate_challenges = std::vector(CONST_PG_LOG_N, 0); - // Perform databus commitment consistency checks and propagate return data commitments via public inputs - bus_depot.execute(verifier_accum->witness_commitments, - verifier_accum->public_inputs, - verifier_accum->verification_key->databus_propagation_data); + decider_vk = verifier_accum; // decider vk for the incoming circuit break; } } + + // Set the return data commitment to be propagated on the public inputs of the present kernel and peform consistency + // checks between the calldata commitments and the return data commitments contained within the public inputs + bus_depot.set_return_data_to_be_propagated_and_perform_consistency_checks( + decider_vk->witness_commitments.return_data, + decider_vk->witness_commitments.calldata, + decider_vk->witness_commitments.secondary_calldata, + decider_vk->public_inputs, + decider_vk->verification_key->databus_propagation_data); } /** @@ -133,6 +140,9 @@ void ClientIVC::complete_kernel_circuit_logic(ClientCircuit& circuit) } stdlib_verification_queue.clear(); + // Propagate return data commitments via the public inputs for use in databus consistency checks + bus_depot.propagate_return_data_commitments(circuit); + // Perform recursive merge verification for every merge proof in the queue process_recursive_merge_verification_queue(circuit); } diff --git a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc_integration.test.cpp b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc_integration.test.cpp index fe62b038db2..5b08a08c810 100644 --- a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc_integration.test.cpp +++ b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc_integration.test.cpp @@ -93,10 +93,14 @@ TEST_F(ClientIVCIntegrationTests, BenchmarkCasePrecomputedVKs) size_t NUM_CIRCUITS = 6; - MockCircuitProducer circuit_producer; - - auto precomputed_vks = circuit_producer.precompute_verification_keys(NUM_CIRCUITS, ivc.trace_structure); + // Precompute the verification keys for each circuit in the IVC + std::vector> precomputed_vks; + { + MockCircuitProducer circuit_producer; + precomputed_vks = circuit_producer.precompute_verification_keys(NUM_CIRCUITS, ivc.trace_structure); + } + MockCircuitProducer circuit_producer; // Construct and accumulate a series of mocked private function execution circuits for (size_t idx = 0; idx < NUM_CIRCUITS; ++idx) { Builder circuit = circuit_producer.create_next_circuit(ivc); diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/bigfield/goblin_field.hpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/bigfield/goblin_field.hpp index 8e3885e46a6..8e18a679ce4 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/bigfield/goblin_field.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/bigfield/goblin_field.hpp @@ -74,6 +74,16 @@ template class goblin_field { return goblin_field(lo, hi); } + /** + * Create a witness from a constant. This way the value of the witness is fixed and public. + **/ + void convert_constant_to_fixed_witness(Builder* builder) + { + for (auto& limb : limbs) { + limb.convert_constant_to_fixed_witness(builder); + } + } + static goblin_field conditional_assign(const bool_ct& predicate, const goblin_field& lhs, goblin_field& rhs) { goblin_field result; diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/biggroup/biggroup.hpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/biggroup/biggroup.hpp index 110df1f0cbe..e033d481f35 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/biggroup/biggroup.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/biggroup/biggroup.hpp @@ -75,6 +75,15 @@ template class element { } } + /** + * @brief Creates fixed witnesses from a constant element. + **/ + void convert_constant_to_fixed_witness(Builder* builder) + { + this->x.convert_constant_to_fixed_witness(builder); + this->y.convert_constant_to_fixed_witness(builder); + } + static element one(Builder* ctx) { uint256_t x = uint256_t(NativeGroup::one.x); diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/biggroup/biggroup_goblin.hpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/biggroup/biggroup_goblin.hpp index 96fa5b85997..dcb321b3e5c 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/biggroup/biggroup_goblin.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/biggroup/biggroup_goblin.hpp @@ -69,6 +69,15 @@ template class goblin_ele return out; } + /** + * @brief Creates fixed witnesses from a constant element. + **/ + void convert_constant_to_fixed_witness(Builder* builder) + { + this->x.convert_constant_to_fixed_witness(builder); + this->y.convert_constant_to_fixed_witness(builder); + } + void validate_on_curve() const { // happens in goblin eccvm diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/databus/databus.hpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/databus/databus.hpp index 3bdd40c02cd..6639158e411 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/databus/databus.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/databus/databus.hpp @@ -68,6 +68,8 @@ template class DataBusDepot { using Commitment = typename Curve::Group; using Fr = typename Curve::ScalarField; using Fq = typename Curve::BaseField; + using CommitmentNative = typename Curve::AffineElementNative; + using FrNative = typename Curve::ScalarFieldNative; using RecursiveFlavor = MegaRecursiveFlavor_; using RecursiveDeciderVerificationKeys = @@ -77,54 +79,98 @@ template class DataBusDepot { static constexpr size_t NUM_FR_LIMBS_PER_FQ = Fq::NUM_LIMBS; static constexpr size_t NUM_FR_LIMBS_PER_COMMITMENT = NUM_FR_LIMBS_PER_FQ * 2; + Commitment app_return_data_commitment; + Commitment kernel_return_data_commitment; + bool app_return_data_commitment_exists = false; + bool kernel_return_data_commitment_exists = false; + /** * @brief Execute circuit logic to establish proper transfer of databus data between circuits * @details The databus mechanism establishes the transfer of data between two circuits (i-1 and i) in a third * circuit (i+1) via commitment equality checks of the form [R_{i-1}] = [C_i], where R and C represent return data * and calldata, respectively. In practice, circuit (i+1) is given access to [R_{i-1}] via the public inputs of * \pi_i, and it has access to [C_i] directly from \pi_i. The consistency checks in circuit (i+1) are thus of the - * form \pi_i.public_inputs.[R_{i-1}] = \pi_i.[C_i]. This method peforms the two primary operations required for - * these checks: (1) extract commitments [R] from proofs received as private witnesses and propagate them to the - * next circuit via adding them to the public inputs. (2) Assert equality of commitments. + * form \pi_i.public_inputs.[R_{i-1}] = \pi_i.[C_i]. This method performs these consistency checks. It also prepares + * return data commitments [R] to be propagated via the public inputs of the present circuit. * - * In Aztec private function execution, this mechanism is used as follows. Kernel circuit K_{i+1} must in general - * perform two databus consistency checks: (1) that the return_data of app circuit A_{i} was secondary calldata to - * K_{i}, and (2) that the return_data of K_{i-1} was calldata to K_{i}. + * @note In Aztec private function execution, this mechanism is used as follows. Kernel circuit K_{i+1} must in + * general perform two databus consistency checks: (1) that the return_data of app circuit A_{i} was secondary + * calldata to K_{i}, and (2) that the return_data of K_{i-1} was calldata to K_{i}. * - * @param commitments Witness polynomial commitments for an key that has been accumulated - * @param public_inputs The public inputs of that key - * @param propagation_data Data about the presence of databus commitments on the public inputs of the key. + * @param return_data Return data from either an app or a kernel + * @param calldata Calldata corresponding to return data from a previous kernel + * @param secondary_calldata Calldata corresponding to some app return data + * @param public_inputs Public inputs of a kernel proof which contain propagated return data commitments + * @param propagation_data Info about the return data commitments stored in the provided public inputs */ - void execute(const WitnessCommitments& commitments, - const std::vector& public_inputs, - const DatabusPropagationData& propagation_data) + void set_return_data_to_be_propagated_and_perform_consistency_checks(const Commitment& return_data, + const Commitment& calldata, + const Commitment& secondary_calldata, + const std::vector& public_inputs, + const DatabusPropagationData& propagation_data) { - // Flag indicating whether the input data corresponds to a kernel decider proving key (else, an app decider - // proving key). This is used to indicate whether the return data commitment being propagated belongs to a - // kernel or an app so that it can be checked against the appropriate calldata commitment in a subsequent round. - bool is_kernel_data = propagation_data.is_kernel; - - // Assert equality between return data commitments propagated via the public inputs and the corresponding - // calldata commitment - if (propagation_data.contains_app_return_data_commitment) { // public inputs contain [R]_app - ASSERT(is_kernel_data); // Only kernels should contain databus commitments in their public inputs - size_t start_idx = propagation_data.app_return_data_public_input_idx; - Commitment app_return_data = reconstruct_commitment_from_public_inputs(public_inputs, start_idx); - // App return data should correspond to the secondary calldata of the subsequent kernel - assert_equality_of_commitments(app_return_data, commitments.secondary_calldata); + // Set the kernel/app return data commitment to be propagated via the public inputs + if (propagation_data.is_kernel) { + kernel_return_data_commitment = return_data; + kernel_return_data_commitment_exists = true; + } else { + app_return_data_commitment = return_data; + app_return_data_commitment_exists = true; } - if (propagation_data.contains_kernel_return_data_commitment) { // pub inputs contain [R]_kernel - ASSERT(is_kernel_data); // Only kernels should contain databus commitments in their public inputs + // If the input data corresponds to a kernel, perform consistency checks between the provided calldata + // commitments and the return data commitments stored in the provided kernel proof public inputs + if (propagation_data.is_kernel) { + // Reconstruct the kernel and app return data commitments stored in the public inputs of the kernel proof size_t start_idx = propagation_data.kernel_return_data_public_input_idx; Commitment kernel_return_data = reconstruct_commitment_from_public_inputs(public_inputs, start_idx); - // Previous kernel return data should correspond to the calldata of the subsequent kernel - assert_equality_of_commitments(kernel_return_data, commitments.calldata); + start_idx = propagation_data.app_return_data_public_input_idx; + Commitment app_return_data = reconstruct_commitment_from_public_inputs(public_inputs, start_idx); + + // Assert equality between the corresponding calldata and return data commitments + assert_equality_of_commitments(kernel_return_data, calldata); + assert_equality_of_commitments(app_return_data, secondary_calldata); } + } - // Propagate the return data commitment via the public inputs mechanism - propagate_commitment_via_public_inputs(commitments.return_data, is_kernel_data); - }; + /** + * @brief Propagate the existing return data commitments via the public inputs of the provided circuit + * @details For consistent behavior across kernels, every kernel propagates two return data commitments via its + * public inputs. If one of either the app or kernel return data does not exist, it is populated with a default + * value that will satisfy the consistency check on the next cycle. For example, the first kernel has no previous + * kernel to verify and thus neither receives a previous kernel return data commitment nor a calldata input + * corresponding to a previous kernel. The commitment to the "empty" calldata will take a default value and thus we + * set the same value for the missing return data so that the consistency check will be satisfied. + * TODO(https://github.com/AztecProtocol/barretenberg/issues/1138): Resolve issues around default commitment value + * and bool_t "existence" type flags. + * @note The ordering of the kernel/app return data commitments within the public inputs is arbitrary but must be + * consistent across all kernels in order for the corresponding conistency check constraints to be consistent. + * + * @param builder + */ + void propagate_return_data_commitments(Builder& builder) + { + // Set default commitment value to be used in the absence of one or the other return_data commitment + CommitmentNative default_commitment_val = CommitmentNative::one() * FrNative(BusVector::DEFAULT_VALUE); + if (kernel_return_data_commitment_exists) { + propagate_commitment_via_public_inputs(kernel_return_data_commitment, /*is_kernel=*/true); + } else { + Commitment default_commitment(default_commitment_val); + default_commitment.convert_constant_to_fixed_witness(&builder); + propagate_commitment_via_public_inputs(default_commitment, /*is_kernel=*/true); + } + + if (app_return_data_commitment_exists) { + propagate_commitment_via_public_inputs(app_return_data_commitment, /*is_kernel=*/false); + } else { + Commitment default_commitment(default_commitment_val); + default_commitment.convert_constant_to_fixed_witness(&builder); + propagate_commitment_via_public_inputs(default_commitment, /*is_kernel=*/false); + } + // Reset flags indicating existence of return data commitments + kernel_return_data_commitment_exists = false; + app_return_data_commitment_exists = false; + } /** * @brief Set the witness indices for a commitment to public @@ -142,10 +188,8 @@ template class DataBusDepot { // Set flag indicating propagation of return data; save the index at which it will be stored in public inputs auto start_idx = static_cast(context->public_inputs.size()); if (is_kernel) { - context->databus_propagation_data.contains_kernel_return_data_commitment = true; context->databus_propagation_data.kernel_return_data_public_input_idx = start_idx; } else { - context->databus_propagation_data.contains_app_return_data_commitment = true; context->databus_propagation_data.app_return_data_public_input_idx = start_idx; } diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/databus.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/databus.hpp index f40f44eb50a..92fda074a99 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/databus.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/databus.hpp @@ -1,14 +1,22 @@ #pragma once +#include "barretenberg/ecc/curves/bn254/fr.hpp" #include namespace bb { +// We assume all kernels have space for two return data commitments on their public inputs +constexpr uint32_t PROPAGATED_DATABUS_COMMITMENTS_SIZE = 16; + /** * @brief A DataBus column * */ struct BusVector { + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1138): A default value added to every databus column to + // avoid the point at infinity commitment and to ensure the validity of the databus commitment consistency checks. + static constexpr bb::fr DEFAULT_VALUE = 25; + /** * @brief Add an element to the data defining this bus column * @@ -70,10 +78,6 @@ enum class BusId { CALLDATA, SECONDARY_CALLDATA, RETURNDATA }; struct DatabusPropagationData { bool operator==(const DatabusPropagationData&) const = default; - // Flags indicating whether the public inputs contain commitment(s) to app/kernel return data - bool contains_app_return_data_commitment = false; - bool contains_kernel_return_data_commitment = false; - // The start index of the return data commitments (if present) in the public inputs. Note: a start index is all // that's needed here since the commitents are represented by a fixed number of witnesses and are contiguous in the // public inputs by construction. @@ -85,19 +89,13 @@ struct DatabusPropagationData { friend std::ostream& operator<<(std::ostream& os, DatabusPropagationData const& data) { - os << data.contains_app_return_data_commitment << ",\n" - << data.contains_kernel_return_data_commitment << ",\n" - << data.app_return_data_public_input_idx << ",\n" + os << data.app_return_data_public_input_idx << ",\n" << data.kernel_return_data_public_input_idx << ",\n" << data.is_kernel << "\n"; return os; }; - MSGPACK_FIELDS(contains_app_return_data_commitment, - contains_kernel_return_data_commitment, - app_return_data_public_input_idx, - kernel_return_data_public_input_idx, - is_kernel); + MSGPACK_FIELDS(app_return_data_public_input_idx, kernel_return_data_public_input_idx, is_kernel); }; } // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/flavor_serialization.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/flavor_serialization.test.cpp index 46b73cbbfe4..162385bdcba 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/flavor_serialization.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/flavor_serialization.test.cpp @@ -49,8 +49,6 @@ TYPED_TEST(FlavorSerializationTests, VerificationKeySerialization) // Populate some non-zero values in the databus_propagation_data to ensure its being handled if constexpr (IsMegaBuilder) { - original_vkey.databus_propagation_data.contains_app_return_data_commitment = 1; - original_vkey.databus_propagation_data.contains_kernel_return_data_commitment = 1; original_vkey.databus_propagation_data.app_return_data_public_input_idx = 2; original_vkey.databus_propagation_data.kernel_return_data_public_input_idx = 4; original_vkey.databus_propagation_data.is_kernel = 1; diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_circuit_builder.cpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_circuit_builder.cpp index 3accdd2b758..e05d1f10f90 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_circuit_builder.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_circuit_builder.cpp @@ -29,33 +29,30 @@ template void MegaCircuitBuilder_::finalize_circuit(const bool * @param in Structure containing variables and witness selectors */ // TODO(https://github.com/AztecProtocol/barretenberg/issues/1066): This function adds valid (but arbitrary) gates to -// ensure that the circuit which includes them will not result in any zero-polynomials. It also ensures that the first -// coefficient of the wire polynomials is zero, which is required for them to be shiftable. +// ensure that the circuit which includes them will not result in any zero-polynomials. This method is designed to be +// used in conjunction with the corresponding method on the Ultra builder. It handles databus and ecc-op related +// polynomials. template void MegaCircuitBuilder_::add_mega_gates_to_ensure_all_polys_are_non_zero() { - // All that remains is to handle databus related and poseidon2 related polynomials. In what follows we populate the - // calldata with some mock data then constuct a single calldata read gate - - // Define a single dummy value to add to all databus columns. Note: This value must be equal across all columns in - // order for inter-circuit databus commitment checks to pass in IVC settings. These dummy gates can be deleted with - // all of the others when (https://github.com/AztecProtocol/barretenberg/issues/1066) is resolved. - FF databus_dummy_value = 25; + // Add a single default value to all databus columns. Note: This value must be equal across all columns in order for + // inter-circuit databus commitment checks to pass in IVC settings. + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1138): Consider default value. // Create an arbitrary calldata read gate - add_public_calldata(this->add_variable(databus_dummy_value)); // add one entry in calldata + add_public_calldata(this->add_variable(BusVector::DEFAULT_VALUE)); // add one entry in calldata auto raw_read_idx = static_cast(get_calldata().size()) - 1; // read data that was just added auto read_idx = this->add_variable(raw_read_idx); read_calldata(read_idx); // Create an arbitrary secondary_calldata read gate - add_public_secondary_calldata(this->add_variable(databus_dummy_value)); // add one entry in secondary_calldata - raw_read_idx = static_cast(get_secondary_calldata().size()) - 1; // read data that was just added + add_public_secondary_calldata(this->add_variable(BusVector::DEFAULT_VALUE)); // add one entry in secondary_calldata + raw_read_idx = static_cast(get_secondary_calldata().size()) - 1; // read data that was just added read_idx = this->add_variable(raw_read_idx); read_secondary_calldata(read_idx); // Create an arbitrary return data read gate - add_public_return_data(this->add_variable(databus_dummy_value)); // add one entry in return data - raw_read_idx = static_cast(get_return_data().size()) - 1; // read data that was just added + add_public_return_data(this->add_variable(BusVector::DEFAULT_VALUE)); // add one entry in return data + raw_read_idx = static_cast(get_return_data().size()) - 1; // read data that was just added read_idx = this->add_variable(raw_read_idx); read_return_data(read_idx); diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_flavor.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_flavor.hpp index e8560197a6d..787c4e782b7 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_flavor.hpp @@ -578,8 +578,6 @@ class MegaFlavor { serialize_to_field_buffer(this->contains_recursive_proof, elements); serialize_to_field_buffer(this->recursive_proof_public_input_indices, elements); - serialize_to_field_buffer(this->databus_propagation_data.contains_app_return_data_commitment, elements); - serialize_to_field_buffer(this->databus_propagation_data.contains_kernel_return_data_commitment, elements); serialize_to_field_buffer(this->databus_propagation_data.app_return_data_public_input_idx, elements); serialize_to_field_buffer(this->databus_propagation_data.kernel_return_data_public_input_idx, elements); serialize_to_field_buffer(this->databus_propagation_data.is_kernel, elements); diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_recursive_flavor.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_recursive_flavor.hpp index f650f4b2761..fc310b80e54 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_recursive_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_recursive_flavor.hpp @@ -155,10 +155,6 @@ template class MegaRecursiveFlavor_ { idx = uint32_t(deserialize_from_frs(builder, elements, num_frs_read).get_value()); } - this->databus_propagation_data.contains_app_return_data_commitment = - bool(deserialize_from_frs(builder, elements, num_frs_read).get_value()); - this->databus_propagation_data.contains_kernel_return_data_commitment = - bool(deserialize_from_frs(builder, elements, num_frs_read).get_value()); this->databus_propagation_data.app_return_data_public_input_idx = uint32_t(deserialize_from_frs(builder, elements, num_frs_read).get_value()); this->databus_propagation_data.kernel_return_data_public_input_idx = diff --git a/boxes/boxes/react/src/contracts/src/main.nr b/boxes/boxes/react/src/contracts/src/main.nr index 0e66096d868..bccebdcf0e5 100644 --- a/boxes/boxes/react/src/contracts/src/main.nr +++ b/boxes/boxes/react/src/contracts/src/main.nr @@ -20,11 +20,10 @@ contract BoxReact { fn constructor( number: Field, owner: AztecAddress, - owner_npk_m_hash: Field, owner_ovpk_m: OvpkM ) { let numbers = storage.numbers; - let mut new_number = ValueNote::new(number, owner_npk_m_hash); + let mut new_number = ValueNote::new(number, owner); numbers.at(owner).initialize(&mut new_number).emit(encode_and_encrypt_note(&mut context, owner_ovpk_m, owner)); } @@ -32,11 +31,10 @@ contract BoxReact { fn setNumber( number: Field, owner: AztecAddress, - owner_npk_m_hash: Field, owner_ovpk_m: OvpkM ) { let numbers = storage.numbers; - let mut new_number = ValueNote::new(number, owner_npk_m_hash); + let mut new_number = ValueNote::new(number, owner); numbers.at(owner).replace(&mut new_number).emit(encode_and_encrypt_note(&mut context, owner_ovpk_m, owner)); } diff --git a/boxes/boxes/react/src/hooks/useContract.tsx b/boxes/boxes/react/src/hooks/useContract.tsx index 8efedd8e656..e4bc764404d 100644 --- a/boxes/boxes/react/src/hooks/useContract.tsx +++ b/boxes/boxes/react/src/hooks/useContract.tsx @@ -15,13 +15,12 @@ export function useContract() { setWait(true); const wallet = await deployerEnv.getWallet(); const salt = Fr.random(); - const { masterNullifierPublicKey, masterOutgoingViewingPublicKey } = + const { masterOutgoingViewingPublicKey } = wallet.getCompleteAddress().publicKeys; const tx = await BoxReactContract.deploy( wallet, Fr.random(), wallet.getCompleteAddress().address, - masterNullifierPublicKey.hash(), masterOutgoingViewingPublicKey.toWrappedNoirStruct(), ).send({ contractAddressSalt: salt, diff --git a/boxes/boxes/react/src/hooks/useNumber.tsx b/boxes/boxes/react/src/hooks/useNumber.tsx index 1c8bcd5b466..d22c0c0bdda 100644 --- a/boxes/boxes/react/src/hooks/useNumber.tsx +++ b/boxes/boxes/react/src/hooks/useNumber.tsx @@ -32,7 +32,6 @@ export function useNumber({ contract }: { contract: Contract }) { .setNumber( value, deployerWallet.getCompleteAddress().address, - masterNullifierPublicKey.hash(), masterOutgoingViewingPublicKey.toWrappedNoirStruct(), ) .send() diff --git a/boxes/boxes/react/tests/node.test.ts b/boxes/boxes/react/tests/node.test.ts index 1e42955421b..78ed1731006 100644 --- a/boxes/boxes/react/tests/node.test.ts +++ b/boxes/boxes/react/tests/node.test.ts @@ -20,7 +20,6 @@ describe('BoxReact Contract Tests', () => { wallet, Fr.random(), accountCompleteAddress.address, - masterNullifierPublicKey.hash(), masterOutgoingViewingPublicKey.toWrappedNoirStruct() ) .send({ contractAddressSalt: salt }) @@ -37,7 +36,6 @@ describe('BoxReact Contract Tests', () => { .setNumber( numberToSet, accountCompleteAddress.address, - masterNullifierPublicKey.hash(), masterOutgoingViewingPublicKey.toWrappedNoirStruct(), ) .send() diff --git a/boxes/boxes/vanilla/src/contracts/src/main.nr b/boxes/boxes/vanilla/src/contracts/src/main.nr index 9ee28895fe4..fc5bdadfb12 100644 --- a/boxes/boxes/vanilla/src/contracts/src/main.nr +++ b/boxes/boxes/vanilla/src/contracts/src/main.nr @@ -20,11 +20,10 @@ contract Vanilla { fn constructor( number: Field, owner: AztecAddress, - owner_npk_m_hash: Field, owner_ovpk_m: OvpkM ) { let numbers = storage.numbers; - let mut new_number = ValueNote::new(number, owner_npk_m_hash); + let mut new_number = ValueNote::new(number, owner); numbers.at(owner).initialize(&mut new_number).emit(encode_and_encrypt_note(&mut context, owner_ovpk_m, owner)); } @@ -32,11 +31,10 @@ contract Vanilla { fn setNumber( number: Field, owner: AztecAddress, - owner_npk_m_hash: Field, owner_ovpk_m: OvpkM ) { let numbers = storage.numbers; - let mut new_number = ValueNote::new(number, owner_npk_m_hash); + let mut new_number = ValueNote::new(number, owner); numbers.at(owner).replace(&mut new_number).emit(encode_and_encrypt_note(&mut context, owner_ovpk_m, owner)); } diff --git a/boxes/boxes/vanilla/src/index.ts b/boxes/boxes/vanilla/src/index.ts index c6b5d4ecd14..050001ab729 100644 --- a/boxes/boxes/vanilla/src/index.ts +++ b/boxes/boxes/vanilla/src/index.ts @@ -26,7 +26,6 @@ document.querySelector('#deploy').addEventListener('click', async ({ target }: a wallet, Fr.random(), wallet.getCompleteAddress().address, - masterNullifierPublicKey.hash(), masterOutgoingViewingPublicKey.toWrappedNoirStruct(), ) .send({ contractAddressSalt: Fr.random() }) @@ -49,7 +48,6 @@ document.querySelector('#set').addEventListener('submit', async (e: Event) => { .setNumber( parseInt(value), owner, - masterNullifierPublicKey.hash(), masterOutgoingViewingPublicKey.toWrappedNoirStruct(), ) .send() diff --git a/docker_fast.sh b/docker_fast.sh index 4a78b4f8b2b..2c24eceac12 100755 --- a/docker_fast.sh +++ b/docker_fast.sh @@ -30,8 +30,14 @@ elif [ ! -z "${AWS_ACCESS_KEY_ID:-}" ] ; then S3_BUILD_CACHE_DOWNLOAD=true elif [ -f ~/.aws/credentials ]; then # Retrieve credentials if available in AWS config + + # Do not trace this information + set +x AWS_ACCESS_KEY_ID=$(aws configure get default.aws_access_key_id) AWS_SECRET_ACCESS_KEY=$(aws configure get default.aws_secret_access_key) + + # Resume tracing + set -x S3_BUILD_CACHE_DOWNLOAD=true else S3_BUILD_CACHE_UPLOAD=false @@ -46,8 +52,11 @@ function on_exit() { trap on_exit EXIT # Save each secret environment variable into a separate file in $TMP directory +set +x echo "${AWS_ACCESS_KEY_ID:-}" > "$TMP/aws_access_key_id.txt" echo "${AWS_SECRET_ACCESS_KEY:-}" > "$TMP/aws_secret_access_key.txt" +set -x + echo "${S3_BUILD_CACHE_MINIO_URL:-}" > "$TMP/s3_build_cache_minio_url.txt" echo "${S3_BUILD_CACHE_UPLOAD:-}" > "$TMP/s3_build_cache_upload.txt" echo "${S3_BUILD_CACHE_DOWNLOAD:-}" > "$TMP/s3_build_cache_download.txt" diff --git a/l1-contracts/src/core/libraries/ConstantsGen.sol b/l1-contracts/src/core/libraries/ConstantsGen.sol index 1483b140a3b..8c42fe769d9 100644 --- a/l1-contracts/src/core/libraries/ConstantsGen.sol +++ b/l1-contracts/src/core/libraries/ConstantsGen.sol @@ -243,7 +243,7 @@ library Constants { uint256 internal constant NESTED_RECURSIVE_PROOF_LENGTH = 463; uint256 internal constant TUBE_PROOF_LENGTH = 463; uint256 internal constant HONK_VERIFICATION_KEY_LENGTH_IN_FIELDS = 128; - uint256 internal constant CLIENT_IVC_VERIFICATION_KEY_LENGTH_IN_FIELDS = 145; + uint256 internal constant CLIENT_IVC_VERIFICATION_KEY_LENGTH_IN_FIELDS = 143; uint256 internal constant MEM_TAG_FF = 0; uint256 internal constant MEM_TAG_U1 = 1; uint256 internal constant MEM_TAG_U8 = 2; diff --git a/noir-projects/aztec-nr/address-note/src/address_note.nr b/noir-projects/aztec-nr/address-note/src/address_note.nr index a1207e21603..7251d5b731b 100644 --- a/noir-projects/aztec-nr/address-note/src/address_note.nr +++ b/noir-projects/aztec-nr/address-note/src/address_note.nr @@ -1,6 +1,6 @@ use dep::aztec::{ context::PrivateContext, - keys::getters::get_nsk_app, + keys::getters::{get_nsk_app, get_public_keys}, macros::notes::note, note::{ note_header::NoteHeader, note_interface::NullifiableNote, @@ -20,7 +20,7 @@ use dep::aztec::{ pub struct AddressNote { address: AztecAddress, // The nullifying public key hash is used with the nsk_app to ensure that the note can be privately spent. - npk_m_hash: Field, + owner: AztecAddress, randomness: Field, } // docs:end:address_note_struct @@ -32,7 +32,8 @@ impl NullifiableNote for AddressNote { context: &mut PrivateContext, note_hash_for_nullify: Field, ) -> Field { - let secret = context.request_nsk_app(self.npk_m_hash); + let owner_npk_m_hash = get_public_keys(self.owner).npk_m.hash(); + let secret = context.request_nsk_app(owner_npk_m_hash); poseidon2_hash_with_separator( [note_hash_for_nullify, secret], GENERATOR_INDEX__NOTE_NULLIFIER as Field, @@ -41,7 +42,8 @@ impl NullifiableNote for AddressNote { unconstrained fn compute_nullifier_without_context(self) -> Field { let note_hash_for_nullify = compute_note_hash_for_nullify(self); - let secret = get_nsk_app(self.npk_m_hash); + let owner_npk_m_hash = get_public_keys(self.owner).npk_m.hash(); + let secret = get_nsk_app(owner_npk_m_hash); poseidon2_hash_with_separator( [note_hash_for_nullify, secret], GENERATOR_INDEX__NOTE_NULLIFIER as Field, @@ -50,13 +52,13 @@ impl NullifiableNote for AddressNote { } impl AddressNote { - pub fn new(address: AztecAddress, npk_m_hash: Field) -> Self { + pub fn new(address: AztecAddress, owner: AztecAddress) -> Self { // We use the randomness to preserve the privacy of the note recipient by preventing brute-forcing, so a // malicious sender could use non-random values to make the note less private. But they already know the full // note pre-image anyway, and so the recipient already trusts them to not disclose this information. We can // therefore assume that the sender will cooperate in the random value generation. let randomness = unsafe { random() }; - AddressNote { address, npk_m_hash, randomness, header: NoteHeader::empty() } + AddressNote { address, owner, randomness, header: NoteHeader::empty() } } // docs:end:address_note_def } diff --git a/noir-projects/aztec-nr/easy-private-state/src/easy_private_uint.nr b/noir-projects/aztec-nr/easy-private-state/src/easy_private_uint.nr index 25652be227e..dbbaebb2859 100644 --- a/noir-projects/aztec-nr/easy-private-state/src/easy_private_uint.nr +++ b/noir-projects/aztec-nr/easy-private-state/src/easy_private_uint.nr @@ -23,10 +23,9 @@ impl EasyPrivateUint { impl EasyPrivateUint<&mut PrivateContext> { // Very similar to `value_note::utils::increment`. pub fn add(self, addend: u64, owner: AztecAddress, outgoing_viewer: AztecAddress) { - let owner_keys = get_public_keys(owner); let outgoing_viewer_keys = get_public_keys(outgoing_viewer); // Creates new note for the owner. - let mut addend_note = ValueNote::new(addend as Field, owner_keys.npk_m.hash()); + let mut addend_note = ValueNote::new(addend as Field, owner); // Insert the new note to the owner's set of notes. // docs:start:insert @@ -40,7 +39,6 @@ impl EasyPrivateUint<&mut PrivateContext> { // Very similar to `value_note::utils::decrement`. pub fn sub(self, subtrahend: u64, owner: AztecAddress, outgoing_viewer: AztecAddress) { - let owner_keys = get_public_keys(owner); let outgoing_viewer_keys = get_public_keys(outgoing_viewer); // docs:start:pop_notes @@ -60,7 +58,7 @@ impl EasyPrivateUint<&mut PrivateContext> { // Creates change note for the owner. let result_value = minuend - subtrahend; - let mut result_note = ValueNote::new(result_value as Field, owner_keys.npk_m.hash()); + let mut result_note = ValueNote::new(result_value as Field, owner); self.set.insert(&mut result_note).emit(encode_and_encrypt_note( self.context, outgoing_viewer_keys.ovpk_m, diff --git a/noir-projects/aztec-nr/uint-note/src/uint_note.nr b/noir-projects/aztec-nr/uint-note/src/uint_note.nr index 3bc3840d30e..45b1001932f 100644 --- a/noir-projects/aztec-nr/uint-note/src/uint_note.nr +++ b/noir-projects/aztec-nr/uint-note/src/uint_note.nr @@ -1,11 +1,12 @@ use dep::aztec::{ - keys::getters::get_nsk_app, + keys::getters::{get_nsk_app, get_public_keys}, macros::notes::partial_note, note::utils::compute_note_hash_for_nullify, oracle::random::random, prelude::{NoteHeader, NullifiableNote, PrivateContext}, protocol_types::{ - constants::GENERATOR_INDEX__NOTE_NULLIFIER, hash::poseidon2_hash_with_separator, + address::AztecAddress, constants::GENERATOR_INDEX__NOTE_NULLIFIER, + hash::poseidon2_hash_with_separator, }, }; @@ -14,8 +15,7 @@ use dep::aztec::{ pub struct UintNote { // The amount of tokens in the note value: U128, - // The nullifying public key hash is used with the nsk_app to ensure that the note can be privately spent. - npk_m_hash: Field, + owner: AztecAddress, // Randomness of the note to hide its contents randomness: Field, } @@ -28,7 +28,8 @@ impl NullifiableNote for UintNote { context: &mut PrivateContext, note_hash_for_nullify: Field, ) -> Field { - let secret = context.request_nsk_app(self.npk_m_hash); + let owner_npk_m_hash = get_public_keys(self.owner).npk_m.hash(); + let secret = context.request_nsk_app(owner_npk_m_hash); poseidon2_hash_with_separator( [note_hash_for_nullify, secret], GENERATOR_INDEX__NOTE_NULLIFIER as Field, @@ -38,7 +39,8 @@ impl NullifiableNote for UintNote { unconstrained fn compute_nullifier_without_context(self) -> Field { let note_hash_for_nullify = compute_note_hash_for_nullify(self); - let secret = get_nsk_app(self.npk_m_hash); + let owner_npk_m_hash = get_public_keys(self.owner).npk_m.hash(); + let secret = get_nsk_app(owner_npk_m_hash); poseidon2_hash_with_separator( [note_hash_for_nullify, secret], GENERATOR_INDEX__NOTE_NULLIFIER, @@ -49,19 +51,19 @@ impl NullifiableNote for UintNote { impl Eq for UintNote { fn eq(self, other: Self) -> bool { (self.value == other.value) - & (self.npk_m_hash == other.npk_m_hash) + & (self.owner == other.owner) & (self.randomness == other.randomness) } } impl UintNote { - pub fn new(value: U128, owner_npk_m_hash: Field) -> Self { + pub fn new(value: U128, owner: AztecAddress) -> Self { // We use the randomness to preserve the privacy of the note recipient by preventing brute-forcing, so a // malicious sender could use non-random values to make the note less private. But they already know the full // note pre-image anyway, and so the recipient already trusts them to not disclose this information. We can // therefore assume that the sender will cooperate in the random value generation. let randomness = unsafe { random() }; - Self { value, npk_m_hash: owner_npk_m_hash, randomness, header: NoteHeader::empty() } + Self { value, owner, randomness, header: NoteHeader::empty() } } pub fn get_value(self) -> U128 { diff --git a/noir-projects/aztec-nr/value-note/src/utils.nr b/noir-projects/aztec-nr/value-note/src/utils.nr index 333ab4b83b8..fd7bb7c41c8 100644 --- a/noir-projects/aztec-nr/value-note/src/utils.nr +++ b/noir-projects/aztec-nr/value-note/src/utils.nr @@ -24,10 +24,9 @@ pub fn increment( recipient: AztecAddress, outgoing_viewer: AztecAddress, // docs:end:increment_args ) { - let recipient_keys = get_public_keys(recipient); let outgoing_viewer_ovpk_m = get_public_keys(outgoing_viewer).ovpk_m; - let mut note = ValueNote::new(amount, recipient_keys.npk_m.hash()); + let mut note = ValueNote::new(amount, recipient); // Insert the new note to the owner's set of notes and emit the log if value is non-zero. balance.insert(&mut note).emit(encode_and_encrypt_note( balance.context, diff --git a/noir-projects/aztec-nr/value-note/src/value_note.nr b/noir-projects/aztec-nr/value-note/src/value_note.nr index c243dbea25c..250a299f233 100644 --- a/noir-projects/aztec-nr/value-note/src/value_note.nr +++ b/noir-projects/aztec-nr/value-note/src/value_note.nr @@ -1,6 +1,6 @@ use dep::aztec::{ context::PrivateContext, - keys::getters::get_nsk_app, + keys::getters::{get_nsk_app, get_public_keys}, macros::notes::note, note::{ note_header::NoteHeader, note_interface::NullifiableNote, @@ -8,8 +8,8 @@ use dep::aztec::{ }, oracle::random::random, protocol_types::{ - constants::GENERATOR_INDEX__NOTE_NULLIFIER, hash::poseidon2_hash_with_separator, - traits::Serialize, + address::AztecAddress, constants::GENERATOR_INDEX__NOTE_NULLIFIER, + hash::poseidon2_hash_with_separator, traits::Serialize, }, }; @@ -22,8 +22,7 @@ global VALUE_NOTE_LEN: u32 = 3; // 3 plus a header. #[derive(Serialize)] pub struct ValueNote { value: Field, - // The nullifying public key hash is used with the nsk_app to ensure that the note can be privately spent. - npk_m_hash: Field, + owner: AztecAddress, randomness: Field, } // docs:end:value-note-def @@ -36,7 +35,8 @@ impl NullifiableNote for ValueNote { context: &mut PrivateContext, note_hash_for_nullify: Field, ) -> Field { - let secret = context.request_nsk_app(self.npk_m_hash); + let owner_npk_m_hash: Field = get_public_keys(self.owner).npk_m.hash(); + let secret = context.request_nsk_app(owner_npk_m_hash); poseidon2_hash_with_separator( [note_hash_for_nullify, secret], GENERATOR_INDEX__NOTE_NULLIFIER as Field, @@ -47,7 +47,8 @@ impl NullifiableNote for ValueNote { unconstrained fn compute_nullifier_without_context(self) -> Field { let note_hash_for_nullify = compute_note_hash_for_nullify(self); - let secret = get_nsk_app(self.npk_m_hash); + let owner_npk_m_hash: Field = get_public_keys(self.owner).npk_m.hash(); + let secret = get_nsk_app(owner_npk_m_hash); poseidon2_hash_with_separator( [note_hash_for_nullify, secret], GENERATOR_INDEX__NOTE_NULLIFIER as Field, @@ -56,21 +57,21 @@ impl NullifiableNote for ValueNote { } impl ValueNote { - pub fn new(value: Field, npk_m_hash: Field) -> Self { + pub fn new(value: Field, owner: AztecAddress) -> Self { // We use the randomness to preserve the privacy of the note recipient by preventing brute-forcing, so a // malicious sender could use non-random values to make the note less private. But they already know the full // note pre-image anyway, and so the recipient already trusts them to not disclose this information. We can // therefore assume that the sender will cooperate in the random value generation. let randomness = unsafe { random() }; let header = NoteHeader::empty(); - ValueNote { value, npk_m_hash, randomness, header } + ValueNote { value, owner, randomness, header } } } impl Eq for ValueNote { fn eq(self, other: Self) -> bool { (self.value == other.value) - & (self.npk_m_hash == other.npk_m_hash) + & (self.owner == other.owner) & (self.randomness == other.randomness) } } diff --git a/noir-projects/noir-contracts/contracts/app_subscription_contract/src/main.nr b/noir-projects/noir-contracts/contracts/app_subscription_contract/src/main.nr index 1aea6fa65f8..2e9f3e9299d 100644 --- a/noir-projects/noir-contracts/contracts/app_subscription_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/app_subscription_contract/src/main.nr @@ -111,11 +111,10 @@ contract AppSubscription { &mut context, ); - let subscriber_keys = get_public_keys(subscriber); let msg_sender_ovpk_m = get_public_keys(context.msg_sender()).ovpk_m; let mut subscription_note = - SubscriptionNote::new(subscriber_keys.npk_m.hash(), expiry_block_number, tx_count); + SubscriptionNote::new(subscriber, expiry_block_number, tx_count); storage.subscriptions.at(subscriber).initialize_or_replace(&mut subscription_note).emit( encode_and_encrypt_note(&mut context, msg_sender_ovpk_m, subscriber), ); diff --git a/noir-projects/noir-contracts/contracts/app_subscription_contract/src/subscription_note.nr b/noir-projects/noir-contracts/contracts/app_subscription_contract/src/subscription_note.nr index c8ce2bc8184..b3525e74152 100644 --- a/noir-projects/noir-contracts/contracts/app_subscription_contract/src/subscription_note.nr +++ b/noir-projects/noir-contracts/contracts/app_subscription_contract/src/subscription_note.nr @@ -1,17 +1,17 @@ use dep::aztec::{ hash::poseidon2_hash_with_separator, - keys::getters::get_nsk_app, + keys::getters::{get_nsk_app, get_public_keys}, macros::notes::note, note::utils::compute_note_hash_for_nullify, oracle::random::random, prelude::{NoteHeader, NullifiableNote, PrivateContext}, - protocol_types::constants::GENERATOR_INDEX__NOTE_NULLIFIER, + protocol_types::{address::AztecAddress, constants::GENERATOR_INDEX__NOTE_NULLIFIER}, }; #[note] pub struct SubscriptionNote { // The nullifying public key hash is used with the nsk_app to ensure that the note can be privately spent. - npk_m_hash: Field, + owner: AztecAddress, expiry_block_number: Field, remaining_txs: Field, // Randomness of the note to hide its contents @@ -24,7 +24,8 @@ impl NullifiableNote for SubscriptionNote { context: &mut PrivateContext, note_hash_for_nullify: Field, ) -> Field { - let secret = context.request_nsk_app(self.npk_m_hash); + let owner_npk_m_hash: Field = get_public_keys(self.owner).npk_m.hash(); + let secret = context.request_nsk_app(owner_npk_m_hash); poseidon2_hash_with_separator( [note_hash_for_nullify, secret], GENERATOR_INDEX__NOTE_NULLIFIER as Field, @@ -33,7 +34,8 @@ impl NullifiableNote for SubscriptionNote { unconstrained fn compute_nullifier_without_context(self) -> Field { let note_hash_for_nullify = compute_note_hash_for_nullify(self); - let secret = get_nsk_app(self.npk_m_hash); + let owner_npk_m_hash: Field = get_public_keys(self.owner).npk_m.hash(); + let secret = get_nsk_app(owner_npk_m_hash); poseidon2_hash_with_separator( [note_hash_for_nullify, secret], GENERATOR_INDEX__NOTE_NULLIFIER as Field, @@ -42,18 +44,12 @@ impl NullifiableNote for SubscriptionNote { } impl SubscriptionNote { - pub fn new(npk_m_hash: Field, expiry_block_number: Field, remaining_txs: Field) -> Self { + pub fn new(owner: AztecAddress, expiry_block_number: Field, remaining_txs: Field) -> Self { // We use the randomness to preserve the privacy of the note recipient by preventing brute-forcing, so a // malicious sender could use non-random values to make the note less private. But they already know the full // note pre-image anyway, and so the recipient already trusts them to not disclose this information. We can // therefore assume that the sender will cooperate in the random value generation. let randomness = unsafe { random() }; - Self { - npk_m_hash, - expiry_block_number, - remaining_txs, - randomness, - header: NoteHeader::empty(), - } + Self { owner, expiry_block_number, remaining_txs, randomness, header: NoteHeader::empty() } } } diff --git a/noir-projects/noir-contracts/contracts/avm_test_contract/src/main.nr b/noir-projects/noir-contracts/contracts/avm_test_contract/src/main.nr index 5d39516e793..bc3d85ae168 100644 --- a/noir-projects/noir-contracts/contracts/avm_test_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/avm_test_contract/src/main.nr @@ -569,8 +569,8 @@ contract AvmTest { let _ = read_storage_map(context.this_address()); dep::aztec::oracle::debug_log::debug_log("keccak_hash"); let _ = keccak_hash(args_u8); - dep::aztec::oracle::debug_log::debug_log("sha256_hash"); - let _ = sha256_hash(args_u8); + // dep::aztec::oracle::debug_log::debug_log("sha256_hash"); + // let _ = sha256_hash(args_u8); dep::aztec::oracle::debug_log::debug_log("poseidon2_hash"); let _ = poseidon2_hash(args_field); dep::aztec::oracle::debug_log::debug_log("pedersen_hash"); @@ -617,9 +617,9 @@ contract AvmTest { let _ = l1_to_l2_msg_exists(1, 2); dep::aztec::oracle::debug_log::debug_log("send_l2_to_l1_msg"); let _ = send_l2_to_l1_msg(EthAddress::from_field(0x2020), 1); - //dep::aztec::oracle::debug_log::debug_log("nested_call_to_add"); - //let _ = nested_call_to_add(1, 2); - //dep::aztec::oracle::debug_log::debug_log("nested_static_call_to_add"); - //let _ = nested_static_call_to_add(1, 2); + dep::aztec::oracle::debug_log::debug_log("nested_call_to_add"); + let _ = nested_call_to_add(1, 2); + dep::aztec::oracle::debug_log::debug_log("nested_static_call_to_add"); + let _ = nested_static_call_to_add(1, 2); } } diff --git a/noir-projects/noir-contracts/contracts/card_game_contract/src/cards.nr b/noir-projects/noir-contracts/contracts/card_game_contract/src/cards.nr index 3116bcb211d..2cc91c195db 100644 --- a/noir-projects/noir-contracts/contracts/card_game_contract/src/cards.nr +++ b/noir-projects/noir-contracts/contracts/card_game_contract/src/cards.nr @@ -1,4 +1,4 @@ -use dep::aztec::prelude::{AztecAddress, NoteGetterOptions, NoteViewerOptions, PrivateContext}; +use dep::aztec::prelude::{NoteGetterOptions, NoteViewerOptions, PrivateContext}; use dep::aztec::{ context::UnconstrainedContext, @@ -6,6 +6,7 @@ use dep::aztec::{ keys::getters::get_public_keys, note::constants::MAX_NOTES_PER_PAGE, protocol_types::{ + address::AztecAddress, constants::MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, traits::{FromField, Serialize, ToField}, }, @@ -55,13 +56,13 @@ pub struct CardNote { } impl CardNote { - fn new(strength: u32, points: u32, npk_m_hash: Field) -> Self { + fn new(strength: u32, points: u32, owner: AztecAddress) -> Self { let card = Card { strength, points }; - CardNote::from_card(card, npk_m_hash) + CardNote::from_card(card, owner) } - pub fn from_card(card: Card, npk_m_hash: Field) -> CardNote { - CardNote { card, note: ValueNote::new(card.to_field(), npk_m_hash) } + pub fn from_card(card: Card, owner: AztecAddress) -> CardNote { + CardNote { card, note: ValueNote::new(card.to_field(), owner) } } pub fn from_note(note: ValueNote) -> CardNote { @@ -108,14 +109,11 @@ impl Deck { impl Deck<&mut PrivateContext> { pub fn add_cards(&mut self, cards: [Card; N], owner: AztecAddress) -> [CardNote] { - let owner_keys = get_public_keys(owner); - - let owner_npk_m_hash = owner_keys.npk_m.hash(); let msg_sender_ovpk_m = get_public_keys(self.set.context.msg_sender()).ovpk_m; let mut inserted_cards = &[]; for card in cards { - let mut card_note = CardNote::from_card(card, owner_npk_m_hash); + let mut card_note = CardNote::from_card(card, owner); self.set.insert(&mut card_note.note).emit(encode_and_encrypt_note( self.set.context, msg_sender_ovpk_m, diff --git a/noir-projects/noir-contracts/contracts/child_contract/src/main.nr b/noir-projects/noir-contracts/contracts/child_contract/src/main.nr index 231c9721f1c..a07237b535a 100644 --- a/noir-projects/noir-contracts/contracts/child_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/child_contract/src/main.nr @@ -56,12 +56,12 @@ contract Child { #[private] fn private_set_value(new_value: Field, owner: AztecAddress) -> Field { - let owner_keys = get_public_keys(owner); + let owner_ovpk_m = get_public_keys(owner).ovpk_m; - let mut note = ValueNote::new(new_value, owner_keys.npk_m.hash()); + let mut note = ValueNote::new(new_value, owner); storage.a_map_with_private_values.at(owner).insert(&mut note).emit(encode_and_encrypt_note( &mut context, - owner_keys.ovpk_m, + owner_ovpk_m, owner, )); new_value diff --git a/noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr b/noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr index 28ed8f4d764..d59d4c89e0c 100644 --- a/noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr @@ -82,13 +82,14 @@ contract Crowdfunding { // docs:end:do-transfer // 3) Create a value note for the donor so that he can later on claim a rewards token in the Claim // contract by proving that the hash of this note exists in the note hash tree. - let donor_keys = get_public_keys(donor); // docs:start:valuenote_new - let mut note = ValueNote::new(amount as Field, donor_keys.npk_m.hash()); + let mut note = ValueNote::new(amount as Field, donor); + + let donor_ovpk_m = get_public_keys(donor).ovpk_m; // docs:end:valuenote_new storage.donation_receipts.insert(&mut note).emit(encode_and_encrypt_note( &mut context, - donor_keys.ovpk_m, + donor_ovpk_m, donor, )); } diff --git a/noir-projects/noir-contracts/contracts/docs_example_contract/src/main.nr b/noir-projects/noir-contracts/contracts/docs_example_contract/src/main.nr index d9e401e4841..9422490654b 100644 --- a/noir-projects/noir-contracts/contracts/docs_example_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/docs_example_contract/src/main.nr @@ -174,12 +174,12 @@ contract DocsExample { // docs:start:initialize-private-mutable #[private] fn initialize_private_immutable(randomness: Field, points: u8) { - let msg_sender_keys = get_public_keys(context.msg_sender()); + let mut new_card = CardNote::new(points, randomness, context.msg_sender()); - let mut new_card = CardNote::new(points, randomness, msg_sender_keys.npk_m.hash()); + let msg_sender_ovpk_m = get_public_keys(context.msg_sender()).ovpk_m; storage.private_immutable.initialize(&mut new_card).emit(encode_and_encrypt_note( &mut context, - msg_sender_keys.ovpk_m, + msg_sender_ovpk_m, context.msg_sender(), )); } @@ -188,38 +188,38 @@ contract DocsExample { #[private] // msg_sender() is 0 at deploy time. So created another function fn initialize_private(randomness: Field, points: u8) { - let msg_sender_keys = get_public_keys(context.msg_sender()); + let mut legendary_card = CardNote::new(points, randomness, context.msg_sender()); - let mut legendary_card = CardNote::new(points, randomness, msg_sender_keys.npk_m.hash()); + let msg_sender_ovpk_m = get_public_keys(context.msg_sender()).ovpk_m; // create and broadcast note storage.legendary_card.initialize(&mut legendary_card).emit(encode_and_encrypt_note( &mut context, - msg_sender_keys.ovpk_m, + msg_sender_ovpk_m, context.msg_sender(), )); } #[private] fn insert_notes(amounts: [u8; 3]) { - let msg_sender_keys = get_public_keys(context.msg_sender()); + let msg_sender_ovpk_m = get_public_keys(context.msg_sender()).ovpk_m; for i in 0..amounts.len() { - let mut note = CardNote::new(amounts[i], 1, msg_sender_keys.npk_m.hash()); + let mut note = CardNote::new(amounts[i], 1, context.msg_sender()); storage.set.insert(&mut note).emit(encode_and_encrypt_note( &mut context, - msg_sender_keys.ovpk_m, + msg_sender_ovpk_m, context.msg_sender(), )); } } #[private] fn insert_note(amount: u8, randomness: Field) { - let msg_sender_keys = get_public_keys(context.msg_sender()); + let mut note = CardNote::new(amount, randomness, context.msg_sender()); - let mut note = CardNote::new(amount, randomness, msg_sender_keys.npk_m.hash()); + let msg_sender_ovpk_m = get_public_keys(context.msg_sender()).ovpk_m; storage.set.insert(&mut note).emit(encode_and_encrypt_note( &mut context, - msg_sender_keys.ovpk_m, + msg_sender_ovpk_m, context.msg_sender(), )); } @@ -231,12 +231,12 @@ contract DocsExample { // docs:end:state_vars-NoteGetterOptionsComparatorExampleNoir #[private] fn update_legendary_card(randomness: Field, points: u8) { - let msg_sender_keys = get_public_keys(context.msg_sender()); + let mut new_card = CardNote::new(points, randomness, context.msg_sender()); - let mut new_card = CardNote::new(points, randomness, msg_sender_keys.npk_m.hash()); + let msg_sender_ovpk_m = get_public_keys(context.msg_sender()).ovpk_m; storage.legendary_card.replace(&mut new_card).emit(encode_and_encrypt_note( &mut context, - msg_sender_keys.ovpk_m, + msg_sender_ovpk_m, context.msg_sender(), )); DocsExample::at(context.this_address()).update_leader(context.msg_sender(), points).enqueue( @@ -247,17 +247,17 @@ contract DocsExample { fn increase_legendary_points() { // Ensure `points` > current value // Also serves as a e2e test that you can `get_note()` and then `replace()` - let msg_sender_keys = get_public_keys(context.msg_sender()); - // docs:start:state_vars-PrivateMutableGet let card = storage.legendary_card.get_note().note; // docs:end:state_vars-PrivateMutableGet let points = card.points + 1; - let mut new_card = CardNote::new(points, card.randomness, msg_sender_keys.npk_m.hash()); + let mut new_card = CardNote::new(points, card.randomness, context.msg_sender()); + + let msg_sender_ovpk_m = get_public_keys(context.msg_sender()).ovpk_m; // docs:start:state_vars-PrivateMutableReplace storage.legendary_card.replace(&mut new_card).emit(encode_and_encrypt_note( &mut context, - msg_sender_keys.ovpk_m, + msg_sender_ovpk_m, context.msg_sender(), )); // docs:end:state_vars-PrivateMutableReplace diff --git a/noir-projects/noir-contracts/contracts/docs_example_contract/src/options.nr b/noir-projects/noir-contracts/contracts/docs_example_contract/src/options.nr index cdeea999865..e6df49a8401 100644 --- a/noir-projects/noir-contracts/contracts/docs_example_contract/src/options.nr +++ b/noir-projects/noir-contracts/contracts/docs_example_contract/src/options.nr @@ -2,18 +2,20 @@ use crate::types::card_note::{CARD_NOTE_LEN, CardNote}; use dep::aztec::prelude::NoteGetterOptions; use dep::aztec::{note::note_getter_options::SortOrder, utils::comparison::Comparator}; -use dep::aztec::protocol_types::constants::MAX_NOTE_HASH_READ_REQUESTS_PER_CALL; +use dep::aztec::protocol_types::{ + address::AztecAddress, constants::MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, +}; // Shows how to use NoteGetterOptions and query for notes. // docs:start:state_vars-NoteGetterOptionsSelectSortOffset pub fn create_npk_card_getter_options( - account_npk_m_hash: Field, + account: AztecAddress, offset: u32, ) -> NoteGetterOptions { let mut options = NoteGetterOptions::new(); options - .select(CardNote::properties().npk_m_hash, Comparator.EQ, account_npk_m_hash) + .select(CardNote::properties().owner, Comparator.EQ, account) .sort(CardNote::properties().points, SortOrder.DESC) .set_offset(offset) } @@ -23,13 +25,13 @@ pub fn create_npk_card_getter_options( pub fn create_exact_card_getter_options( points: u8, secret: Field, - account_npk_m_hash: Field, + account: AztecAddress, ) -> NoteGetterOptions { let mut options = NoteGetterOptions::new(); options .select(CardNote::properties().points, Comparator.EQ, points as Field) .select(CardNote::properties().randomness, Comparator.EQ, secret) - .select(CardNote::properties().npk_m_hash, Comparator.EQ, account_npk_m_hash) + .select(CardNote::properties().owner, Comparator.EQ, account) } // docs:end:state_vars-NoteGetterOptionsMultiSelects diff --git a/noir-projects/noir-contracts/contracts/docs_example_contract/src/types/card_note.nr b/noir-projects/noir-contracts/contracts/docs_example_contract/src/types/card_note.nr index 219a098ac06..17ed22a689a 100644 --- a/noir-projects/noir-contracts/contracts/docs_example_contract/src/types/card_note.nr +++ b/noir-projects/noir-contracts/contracts/docs_example_contract/src/types/card_note.nr @@ -1,10 +1,10 @@ use dep::aztec::{ - keys::getters::get_nsk_app, + keys::getters::{get_nsk_app, get_public_keys}, macros::notes::note, note::utils::compute_note_hash_for_nullify, protocol_types::{ - constants::GENERATOR_INDEX__NOTE_NULLIFIER, hash::poseidon2_hash_with_separator, - traits::Serialize, + address::AztecAddress, constants::GENERATOR_INDEX__NOTE_NULLIFIER, + hash::poseidon2_hash_with_separator, traits::Serialize, }, }; use dep::aztec::prelude::{NoteHeader, NullifiableNote, PrivateContext}; @@ -16,15 +16,14 @@ global CARD_NOTE_LEN: u32 = 3; // 3 plus a header. pub struct CardNote { points: u8, randomness: Field, - // The nullifying public key hash is used with the nsk_app to ensure that the note can be privately spent. - npk_m_hash: Field, + owner: AztecAddress, } // docs:end:state_vars-CardNote // docs:start:cardnote_impl impl CardNote { - pub fn new(points: u8, randomness: Field, npk_m_hash: Field) -> Self { - CardNote { points, randomness, npk_m_hash, header: NoteHeader::empty() } + pub fn new(points: u8, randomness: Field, owner: AztecAddress) -> Self { + CardNote { points, randomness, owner, header: NoteHeader::empty() } } } // docs:end:cardnote_impl @@ -36,7 +35,8 @@ impl NullifiableNote for CardNote { context: &mut PrivateContext, note_hash_for_nullify: Field, ) -> Field { - let secret = context.request_nsk_app(self.npk_m_hash); + let owner_npk_m_hash: Field = get_public_keys(self.owner).npk_m.hash(); + let secret = context.request_nsk_app(owner_npk_m_hash); poseidon2_hash_with_separator( [note_hash_for_nullify, secret], GENERATOR_INDEX__NOTE_NULLIFIER as Field, @@ -45,7 +45,8 @@ impl NullifiableNote for CardNote { unconstrained fn compute_nullifier_without_context(self) -> Field { let note_hash_for_nullify = compute_note_hash_for_nullify(self); - let secret = get_nsk_app(self.npk_m_hash); + let owner_npk_m_hash: Field = get_public_keys(self.owner).npk_m.hash(); + let secret = get_nsk_app(owner_npk_m_hash); poseidon2_hash_with_separator( [note_hash_for_nullify, secret], GENERATOR_INDEX__NOTE_NULLIFIER as Field, @@ -57,7 +58,7 @@ impl NullifiableNote for CardNote { // docs:start:serialize impl Serialize<3> for CardNote { fn serialize(self) -> [Field; 3] { - [self.points.to_field(), self.randomness, self.npk_m_hash.to_field()] + [self.points.to_field(), self.randomness, self.owner.to_field()] } } // docs:end:serialize @@ -65,7 +66,7 @@ impl Serialize<3> for CardNote { impl Eq for CardNote { fn eq(self, other: Self) -> bool { (self.points == other.points) - & (self.npk_m_hash == other.npk_m_hash) + & (self.owner == other.owner) & (self.randomness == other.randomness) } } diff --git a/noir-projects/noir-contracts/contracts/ecdsa_k_account_contract/src/main.nr b/noir-projects/noir-contracts/contracts/ecdsa_k_account_contract/src/main.nr index 061c6229a4e..8f2dc055f33 100644 --- a/noir-projects/noir-contracts/contracts/ecdsa_k_account_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/ecdsa_k_account_contract/src/main.nr @@ -29,15 +29,15 @@ contract EcdsaKAccount { #[initializer] fn constructor(signing_pub_key_x: [u8; 32], signing_pub_key_y: [u8; 32]) { let this = context.this_address(); - let this_keys = get_public_keys(this); // Not emitting outgoing for msg_sender here to not have to register keys for the contract through which we // deploy this (typically MultiCallEntrypoint). I think it's ok here as I feel the outgoing here is not that // important. - let mut pub_key_note = - EcdsaPublicKeyNote::new(signing_pub_key_x, signing_pub_key_y, this_keys.npk_m.hash()); + let mut pub_key_note = EcdsaPublicKeyNote::new(signing_pub_key_x, signing_pub_key_y, this); + + let this_ovpk_m = get_public_keys(this).ovpk_m; storage.public_key.initialize(&mut pub_key_note).emit(encode_and_encrypt_note( &mut context, - this_keys.ovpk_m, + this_ovpk_m, this, )); } diff --git a/noir-projects/noir-contracts/contracts/ecdsa_public_key_note/src/lib.nr b/noir-projects/noir-contracts/contracts/ecdsa_public_key_note/src/lib.nr index 1f88a0851a3..d571cc6328b 100644 --- a/noir-projects/noir-contracts/contracts/ecdsa_public_key_note/src/lib.nr +++ b/noir-projects/noir-contracts/contracts/ecdsa_public_key_note/src/lib.nr @@ -1,10 +1,10 @@ use dep::aztec::prelude::{NoteHeader, NoteInterface, NullifiableNote, PrivateContext}; use dep::aztec::{ - note::utils::compute_note_hash_for_nullify, keys::getters::get_nsk_app, - protocol_types::{constants::GENERATOR_INDEX__NOTE_NULLIFIER, hash::poseidon2_hash_with_separator}, + note::utils::compute_note_hash_for_nullify, keys::getters::{get_nsk_app, get_public_keys}, + protocol_types::{address::AztecAddress, constants::GENERATOR_INDEX__NOTE_NULLIFIER, hash::poseidon2_hash_with_separator}, macros::notes::note_custom_interface, generators::Ga1 as Gx_1, generators::Ga2 as Gx_2, - generators::Ga3 as Gy_1, generators::Ga4 as Gy_2, generators::Ga5 as Gnpk_m_hash, generators::G_slot + generators::Ga3 as Gy_1, generators::Ga4 as Gy_2, generators::Ga5 as G_owner, generators::G_slot }; use std::hash::from_field_unsafe; @@ -17,8 +17,7 @@ global ECDSA_PUBLIC_KEY_NOTE_LEN: u32 = 5; pub struct EcdsaPublicKeyNote { x: [u8; 32], y: [u8; 32], - // We store the npk_m_hash only to get the secret key to compute the nullifier - npk_m_hash: Field, + owner: AztecAddress, } impl NoteInterface for EcdsaPublicKeyNote { @@ -27,7 +26,7 @@ impl NoteInterface for EcdsaPublicKeyNote { // [1] = x[31] // [2] = y[0..31] // [3] = y[31] - // [4] = npk_m_hash + // [4] = owner fn serialize_content(self) -> [Field; ECDSA_PUBLIC_KEY_NOTE_LEN] { let mut x: Field = 0; let mut y: Field = 0; @@ -44,7 +43,7 @@ impl NoteInterface for EcdsaPublicKeyNote { let last_x = self.x[31] as Field; let last_y = self.y[31] as Field; - [x, last_x, y, last_y, self.npk_m_hash] + [x, last_x, y, last_y, self.owner.to_field()] } // Cannot use the automatic deserialization for the aforementioned reasons @@ -64,7 +63,7 @@ impl NoteInterface for EcdsaPublicKeyNote { } y[31] = serialized_note[3].to_be_bytes::<32>()[31]; - EcdsaPublicKeyNote { x, y, npk_m_hash: serialized_note[4], header: NoteHeader::empty() } + EcdsaPublicKeyNote { x, y, owner: AztecAddress::from_field(serialized_note[4]), header: NoteHeader::empty() } } fn to_be_bytes(self, storage_slot: Field) -> [u8; ECDSA_PUBLIC_KEY_NOTE_LEN * 32 + 64] { @@ -110,7 +109,7 @@ impl NoteInterface for EcdsaPublicKeyNote { fn compute_note_hash(self) -> Field { let serialized = self.serialize_content(); std::embedded_curve_ops::multi_scalar_mul( - [Gx_1, Gx_2, Gy_1, Gy_2, Gnpk_m_hash, G_slot], + [Gx_1, Gx_2, Gy_1, Gy_2, G_owner, G_slot], [ from_field_unsafe(serialized[0]), from_field_unsafe(serialized[1]), @@ -126,7 +125,8 @@ impl NoteInterface for EcdsaPublicKeyNote { impl NullifiableNote for EcdsaPublicKeyNote { fn compute_nullifier(self, context: &mut PrivateContext, note_hash_for_nullify: Field) -> Field { - let secret = context.request_nsk_app(self.npk_m_hash); + let owner_npk_m_hash = get_public_keys(self.owner).npk_m.hash(); + let secret = context.request_nsk_app(owner_npk_m_hash); poseidon2_hash_with_separator( [ note_hash_for_nullify, @@ -138,7 +138,8 @@ impl NullifiableNote for EcdsaPublicKeyNote { unconstrained fn compute_nullifier_without_context(self) -> Field { let note_hash_for_nullify = compute_note_hash_for_nullify(self); - let secret = get_nsk_app(self.npk_m_hash); + let owner_npk_m_hash = get_public_keys(self.owner).npk_m.hash(); + let secret = get_nsk_app(owner_npk_m_hash); poseidon2_hash_with_separator( [ note_hash_for_nullify, @@ -150,7 +151,7 @@ impl NullifiableNote for EcdsaPublicKeyNote { } impl EcdsaPublicKeyNote { - pub fn new(x: [u8; 32], y: [u8; 32], npk_m_hash: Field) -> Self { - EcdsaPublicKeyNote { x, y, npk_m_hash, header: NoteHeader::empty() } + pub fn new(x: [u8; 32], y: [u8; 32], owner: AztecAddress) -> Self { + EcdsaPublicKeyNote { x, y, owner, header: NoteHeader::empty() } } } diff --git a/noir-projects/noir-contracts/contracts/ecdsa_r_account_contract/src/main.nr b/noir-projects/noir-contracts/contracts/ecdsa_r_account_contract/src/main.nr index 9c90302f1f4..b8e2e18b08a 100644 --- a/noir-projects/noir-contracts/contracts/ecdsa_r_account_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/ecdsa_r_account_contract/src/main.nr @@ -28,15 +28,14 @@ contract EcdsaRAccount { #[initializer] fn constructor(signing_pub_key_x: [u8; 32], signing_pub_key_y: [u8; 32]) { let this = context.this_address(); - let this_keys = get_public_keys(this); // Not emitting outgoing for msg_sender here to not have to register keys for the contract through which we // deploy this (typically MultiCallEntrypoint). I think it's ok here as I feel the outgoing here is not that // important. - let mut pub_key_note = - EcdsaPublicKeyNote::new(signing_pub_key_x, signing_pub_key_y, this_keys.npk_m.hash()); + let mut pub_key_note = EcdsaPublicKeyNote::new(signing_pub_key_x, signing_pub_key_y, this); + let this_ovpk_m = get_public_keys(this).ovpk_m; storage.public_key.initialize(&mut pub_key_note).emit(encode_and_encrypt_note( &mut context, - this_keys.ovpk_m, + this_ovpk_m, this, )); } diff --git a/noir-projects/noir-contracts/contracts/escrow_contract/src/main.nr b/noir-projects/noir-contracts/contracts/escrow_contract/src/main.nr index d990e05fad9..b5438144c2a 100644 --- a/noir-projects/noir-contracts/contracts/escrow_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/escrow_contract/src/main.nr @@ -24,14 +24,13 @@ contract Escrow { #[private] #[initializer] fn constructor(owner: AztecAddress) { - let owner_keys = get_public_keys(owner); - let msg_sender_keys = get_public_keys(context.msg_sender()); // docs:start:addressnote_new - let mut note = AddressNote::new(owner, owner_keys.npk_m.hash()); + let mut note = AddressNote::new(owner, owner); // docs:end:addressnote_new + let msg_sender_ovpk_m = get_public_keys(context.msg_sender()).ovpk_m; storage.owner.initialize(&mut note).emit(encode_and_encrypt_note( &mut context, - msg_sender_keys.ovpk_m, + msg_sender_ovpk_m, owner, )); } diff --git a/noir-projects/noir-contracts/contracts/inclusion_proofs_contract/src/main.nr b/noir-projects/noir-contracts/contracts/inclusion_proofs_contract/src/main.nr index 8059b989688..cdb13bbe4a6 100644 --- a/noir-projects/noir-contracts/contracts/inclusion_proofs_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/inclusion_proofs_contract/src/main.nr @@ -33,13 +33,12 @@ contract InclusionProofs { // Creates a value note owned by `owner`. #[private] fn create_note(owner: AztecAddress, value: Field) { - let msg_sender_keys = get_public_keys(context.msg_sender()); - let owner_keys = get_public_keys(owner); + let mut note = ValueNote::new(value, owner); - let mut note = ValueNote::new(value, owner_keys.npk_m.hash()); + let msg_sender_ovpk_m = get_public_keys(context.msg_sender()).ovpk_m; storage.private_values.at(owner).insert(&mut note).emit(encode_and_encrypt_note( &mut context, - msg_sender_keys.ovpk_m, + msg_sender_ovpk_m, owner, )); } @@ -81,8 +80,7 @@ contract InclusionProofs { block_number: u32, // The block at which we'll prove that the note exists ) { let header = context.get_header(); - let owner_npk_m_hash = get_public_keys(owner).npk_m.hash(); - let mut note = ValueNote::new(1, owner_npk_m_hash); + let mut note = ValueNote::new(1, owner); let header = if (use_block_number) { context.get_header_at(block_number) diff --git a/noir-projects/noir-contracts/contracts/nft_contract/src/main.nr b/noir-projects/noir-contracts/contracts/nft_contract/src/main.nr index e7a043140fa..3115bf04346 100644 --- a/noir-projects/noir-contracts/contracts/nft_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/nft_contract/src/main.nr @@ -179,15 +179,13 @@ contract NFT { storage: Storage<&mut PrivateContext>, ) -> Field { let to_keys = get_public_keys(to); - let to_npk_m_hash = to_keys.npk_m.hash(); let to_note_slot = storage.private_nfts.at(to).storage_slot; // We create a setup payload with unpopulated/zero token id for 'to' // TODO(#7775): Manually fetching the randomness here is not great. If we decide to include randomness in all // notes we could just inject it in macros. let note_randomness = unsafe { random() }; - let note_setup_payload = - NFTNote::setup_payload().new(to_npk_m_hash, note_randomness, to_note_slot); + let note_setup_payload = NFTNote::setup_payload().new(to, note_randomness, to_note_slot); // We encrypt the note log let setup_log = note_setup_payload.encrypt_log(context, to_keys, to); @@ -303,9 +301,8 @@ contract NFT { assert(notes.len() == 1, "NFT not found when transferring"); let from_ovpk_m = get_public_keys(from).ovpk_m; - let to_keys = get_public_keys(to); - let mut new_note = NFTNote::new(token_id, to_keys.npk_m.hash()); + let mut new_note = NFTNote::new(token_id, to); nfts.at(to).insert(&mut new_note).emit(encode_and_encrypt_note( &mut context, from_ovpk_m, diff --git a/noir-projects/noir-contracts/contracts/nft_contract/src/test/transfer_to_private.nr b/noir-projects/noir-contracts/contracts/nft_contract/src/test/transfer_to_private.nr index 21e109704a7..742109682dc 100644 --- a/noir-projects/noir-contracts/contracts/nft_contract/src/test/transfer_to_private.nr +++ b/noir-projects/noir-contracts/contracts/nft_contract/src/test/transfer_to_private.nr @@ -1,6 +1,5 @@ use crate::{NFT, test::utils, types::nft_note::NFTNote}; use dep::aztec::{ - keys::getters::get_public_keys, oracle::random::random, prelude::{AztecAddress, NoteHeader}, protocol_types::storage::map::derive_storage_slot_in_map, @@ -51,14 +50,13 @@ unconstrained fn transfer_to_private_external_orchestration() { // TODO(#8771): We need to manually add the note because in the partial notes flow `notify_created_note_oracle` // is not called and we don't have a `NoteProcessor` in TXE. - let recipient_npk_m_hash = get_public_keys(recipient).npk_m.hash(); let private_nfts_recipient_slot = derive_storage_slot_in_map(NFT::storage_layout().private_nfts.slot, recipient); env.add_note( &mut NFTNote { token_id, - npk_m_hash: recipient_npk_m_hash, + owner: recipient, randomness: note_randomness, header: NoteHeader::empty(), }, diff --git a/noir-projects/noir-contracts/contracts/nft_contract/src/test/utils.nr b/noir-projects/noir-contracts/contracts/nft_contract/src/test/utils.nr index 429844e7f59..7610cdf073a 100644 --- a/noir-projects/noir-contracts/contracts/nft_contract/src/test/utils.nr +++ b/noir-projects/noir-contracts/contracts/nft_contract/src/test/utils.nr @@ -1,7 +1,6 @@ use crate::{NFT, types::nft_note::NFTNote}; use dep::aztec::{ hash::pedersen_hash, - keys::getters::get_public_keys, oracle::{ execution::{get_block_number, get_contract_address}, random::random, @@ -74,14 +73,13 @@ pub unconstrained fn setup_mint_and_transfer_to_private( // TODO(#8771): We need to manually add the note because in the partial notes flow `notify_created_note_oracle` // is not called and we don't have a `NoteProcessor` in TXE. - let owner_npk_m_hash = get_public_keys(owner).npk_m.hash(); let private_nfts_owner_slot = derive_storage_slot_in_map(NFT::storage_layout().private_nfts.slot, owner); env.add_note( &mut NFTNote { token_id: minted_token_id, - npk_m_hash: owner_npk_m_hash, + owner, randomness: note_randomness, header: NoteHeader::empty(), }, diff --git a/noir-projects/noir-contracts/contracts/nft_contract/src/types/nft_note.nr b/noir-projects/noir-contracts/contracts/nft_contract/src/types/nft_note.nr index e055e32c983..025127127a6 100644 --- a/noir-projects/noir-contracts/contracts/nft_contract/src/types/nft_note.nr +++ b/noir-projects/noir-contracts/contracts/nft_contract/src/types/nft_note.nr @@ -1,10 +1,11 @@ use dep::aztec::{ - keys::getters::get_nsk_app, + keys::getters::{get_nsk_app, get_public_keys}, macros::notes::partial_note, note::utils::compute_note_hash_for_nullify, oracle::random::random, prelude::{NoteHeader, NullifiableNote, PrivateContext}, protocol_types::{ + address::AztecAddress, constants::GENERATOR_INDEX__NOTE_NULLIFIER, hash::poseidon2_hash_with_separator, traits::{Empty, Eq}, @@ -16,7 +17,7 @@ pub struct NFTNote { // ID of the token token_id: Field, // The nullifying public key hash is used with the nsk_app to ensure that the note can be privately spent. - npk_m_hash: Field, + owner: AztecAddress, // Randomness of the note to hide its contents randomness: Field, } @@ -27,7 +28,8 @@ impl NullifiableNote for NFTNote { context: &mut PrivateContext, note_hash_for_nullify: Field, ) -> Field { - let secret = context.request_nsk_app(self.npk_m_hash); + let owner_npk_m_hash: Field = get_public_keys(self.owner).npk_m.hash(); + let secret = context.request_nsk_app(owner_npk_m_hash); poseidon2_hash_with_separator( [note_hash_for_nullify, secret], GENERATOR_INDEX__NOTE_NULLIFIER as Field, @@ -36,7 +38,8 @@ impl NullifiableNote for NFTNote { unconstrained fn compute_nullifier_without_context(self) -> Field { let note_hash_for_nullify = compute_note_hash_for_nullify(self); - let secret = get_nsk_app(self.npk_m_hash); + let owner_npk_m_hash: Field = get_public_keys(self.owner).npk_m.hash(); + let secret = get_nsk_app(owner_npk_m_hash); poseidon2_hash_with_separator( [note_hash_for_nullify, secret], GENERATOR_INDEX__NOTE_NULLIFIER as Field, @@ -45,20 +48,20 @@ impl NullifiableNote for NFTNote { } impl NFTNote { - pub fn new(token_id: Field, npk_m_hash: Field) -> Self { + pub fn new(token_id: Field, owner: AztecAddress) -> Self { // We use the randomness to preserve the privacy of the note recipient by preventing brute-forcing, so a // malicious sender could use non-random values to make the note less private. But they already know the full // note pre-image anyway, and so the recipient already trusts them to not disclose this information. We can // therefore assume that the sender will cooperate in the random value generation. let randomness = unsafe { random() }; - NFTNote { token_id, npk_m_hash, randomness, header: NoteHeader::empty() } + NFTNote { token_id, owner, randomness, header: NoteHeader::empty() } } } impl Eq for NFTNote { fn eq(self, other: Self) -> bool { (self.token_id == other.token_id) - & (self.npk_m_hash == other.npk_m_hash) + & (self.owner == other.owner) & (self.randomness == other.randomness) } } diff --git a/noir-projects/noir-contracts/contracts/pending_note_hashes_contract/src/main.nr b/noir-projects/noir-contracts/contracts/pending_note_hashes_contract/src/main.nr index 4124b9992bb..5858192c8d8 100644 --- a/noir-projects/noir-contracts/contracts/pending_note_hashes_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/pending_note_hashes_contract/src/main.nr @@ -38,15 +38,14 @@ contract PendingNoteHashes { ) -> Field { let owner_balance = storage.balances.at(owner); - let owner_keys = get_public_keys(owner); - let outgoing_viewer_keys = get_public_keys(outgoing_viewer); + let outgoing_viewer_ovpk_m = get_public_keys(outgoing_viewer).ovpk_m; - let mut note = ValueNote::new(amount, owner_keys.npk_m.hash()); + let mut note = ValueNote::new(amount, owner); // Insert note owner_balance.insert(&mut note).emit(encode_and_encrypt_note( &mut context, - outgoing_viewer_keys.ovpk_m, + outgoing_viewer_ovpk_m, owner, )); @@ -72,10 +71,8 @@ contract PendingNoteHashes { assert(notes.len() == 0); - let owner_npk_m_hash = get_public_keys(owner).npk_m.hash(); - // Insert note - let mut note = ValueNote::new(amount, owner_npk_m_hash); + let mut note = ValueNote::new(amount, owner); owner_balance.insert(&mut note).discard(); 0 @@ -90,15 +87,14 @@ contract PendingNoteHashes { fn insert_note(amount: Field, owner: AztecAddress, outgoing_viewer: AztecAddress) { let owner_balance = storage.balances.at(owner); - let owner_keys = get_public_keys(owner); - let outgoing_viewer_keys = get_public_keys(outgoing_viewer); + let outgoing_viewer_ovpk_m = get_public_keys(outgoing_viewer).ovpk_m; - let mut note = ValueNote::new(amount, owner_keys.npk_m.hash()); + let mut note = ValueNote::new(amount, owner); // Insert note owner_balance.insert(&mut note).emit(encode_and_encrypt_note( &mut context, - outgoing_viewer_keys.ovpk_m, + outgoing_viewer_ovpk_m, owner, )); } @@ -114,16 +110,15 @@ contract PendingNoteHashes { ) { let mut owner_balance = storage.balances.at(owner); - let owner_keys = get_public_keys(owner); - let outgoing_viewer_keys = get_public_keys(outgoing_viewer); + let outgoing_viewer_ovpk_m = get_public_keys(outgoing_viewer).ovpk_m; - let mut note = ValueNote::new(amount, owner_keys.npk_m.hash()); + let mut note = ValueNote::new(amount, owner); note.randomness = 2; // Insert note owner_balance.insert(&mut note).emit(encode_and_encrypt_note( &mut context, - outgoing_viewer_keys.ovpk_m, + outgoing_viewer_ovpk_m, owner, )); } @@ -134,18 +129,17 @@ contract PendingNoteHashes { fn insert_note_extra_emit(amount: Field, owner: AztecAddress, outgoing_viewer: AztecAddress) { let mut owner_balance = storage.balances.at(owner); - let owner_keys = get_public_keys(owner); - let outgoing_viewer_keys = get_public_keys(outgoing_viewer); + let outgoing_viewer_ovpk_m = get_public_keys(outgoing_viewer).ovpk_m; - let mut note = ValueNote::new(amount, owner_keys.npk_m.hash()); + let mut note = ValueNote::new(amount, owner); // Insert note let emission = owner_balance.insert(&mut note); - emission.emit(encode_and_encrypt_note(&mut context, outgoing_viewer_keys.ovpk_m, owner)); + emission.emit(encode_and_encrypt_note(&mut context, outgoing_viewer_ovpk_m, owner)); // Emit note again - emission.emit(encode_and_encrypt_note(&mut context, outgoing_viewer_keys.ovpk_m, owner)); + emission.emit(encode_and_encrypt_note(&mut context, outgoing_viewer_ovpk_m, owner)); } // Nested/inner function to get a note and confirm it matches the expected value @@ -357,28 +351,26 @@ contract PendingNoteHashes { fn test_emit_bad_note_log(owner: AztecAddress, outgoing_viewer: AztecAddress) { let owner_balance = storage.balances.at(owner); - let owner_keys = get_public_keys(owner); - let owner_npk_m_hash = owner_keys.npk_m.hash(); - let outgoing_viewer_keys = get_public_keys(outgoing_viewer); + let outgoing_viewer_ovpk_m = get_public_keys(outgoing_viewer).ovpk_m; - let mut good_note = ValueNote::new(10, owner_npk_m_hash); + let mut good_note = ValueNote::new(10, owner); // Insert good note with real log owner_balance.insert(&mut good_note).emit(encode_and_encrypt_note( &mut context, - outgoing_viewer_keys.ovpk_m, + outgoing_viewer_ovpk_m, owner, )); // We will emit a note log with an incorrect preimage to ensure the pxe throws // This note has not been inserted... - let mut bad_note = ValueNote::new(5, owner_npk_m_hash); + let mut bad_note = ValueNote::new(5, owner); // ...but we need a 'good' note header to get the context to add the note log let existing_note_header = good_note.get_header(); bad_note.set_header(existing_note_header); NoteEmission::new(bad_note).emit(encode_and_encrypt_note( &mut context, - outgoing_viewer_keys.ovpk_m, + outgoing_viewer_ovpk_m, owner, )); } @@ -392,12 +384,10 @@ contract PendingNoteHashes { ) { let owner_balance = storage.balances.at(owner); - let owner_keys = get_public_keys(owner); - let owner_npk_m_hash = owner_keys.npk_m.hash(); let outgoing_viewer_ovpk_m = get_public_keys(outgoing_viewer).ovpk_m; for i in 0..max_notes_per_call() { - let mut note = ValueNote::new(i as Field, owner_npk_m_hash); + let mut note = ValueNote::new(i as Field, owner); owner_balance.insert(&mut note).emit(encode_and_encrypt_note( context, outgoing_viewer_ovpk_m, diff --git a/noir-projects/noir-contracts/contracts/schnorr_account_contract/src/main.nr b/noir-projects/noir-contracts/contracts/schnorr_account_contract/src/main.nr index 60e5c676db2..325932f6206 100644 --- a/noir-projects/noir-contracts/contracts/schnorr_account_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/schnorr_account_contract/src/main.nr @@ -35,15 +35,14 @@ contract SchnorrAccount { #[initializer] fn constructor(signing_pub_key_x: Field, signing_pub_key_y: Field) { let this = context.this_address(); - let this_keys = get_public_keys(this); // Not emitting outgoing for msg_sender here to not have to register keys for the contract through which we // deploy this (typically MultiCallEntrypoint). I think it's ok here as I feel the outgoing here is not that // important. - let mut pub_key_note = - PublicKeyNote::new(signing_pub_key_x, signing_pub_key_y, this_keys.npk_m.hash()); + let mut pub_key_note = PublicKeyNote::new(signing_pub_key_x, signing_pub_key_y, this); + let this_ovpk_m = get_public_keys(this).ovpk_m; storage.signing_public_key.initialize(&mut pub_key_note).emit(encode_and_encrypt_note( &mut context, - this_keys.ovpk_m, + this_ovpk_m, this, )); } diff --git a/noir-projects/noir-contracts/contracts/schnorr_account_contract/src/public_key_note.nr b/noir-projects/noir-contracts/contracts/schnorr_account_contract/src/public_key_note.nr index 2e48a31ac8d..27cfb18abf3 100644 --- a/noir-projects/noir-contracts/contracts/schnorr_account_contract/src/public_key_note.nr +++ b/noir-projects/noir-contracts/contracts/schnorr_account_contract/src/public_key_note.nr @@ -1,9 +1,10 @@ use dep::aztec::{ - keys::getters::get_nsk_app, + keys::getters::{get_nsk_app, get_public_keys}, macros::notes::note, note::utils::compute_note_hash_for_nullify, protocol_types::{ - constants::GENERATOR_INDEX__NOTE_NULLIFIER, hash::poseidon2_hash_with_separator, + address::AztecAddress, constants::GENERATOR_INDEX__NOTE_NULLIFIER, + hash::poseidon2_hash_with_separator, }, }; use dep::aztec::prelude::{NoteHeader, NullifiableNote, PrivateContext}; @@ -14,8 +15,7 @@ use dep::aztec::prelude::{NoteHeader, NullifiableNote, PrivateContext}; pub struct PublicKeyNote { x: Field, y: Field, - // We store the npk_m_hash only to get the secret key to compute the nullifier - npk_m_hash: Field, + owner: AztecAddress, } impl NullifiableNote for PublicKeyNote { @@ -24,7 +24,8 @@ impl NullifiableNote for PublicKeyNote { context: &mut PrivateContext, note_hash_for_nullify: Field, ) -> Field { - let secret = context.request_nsk_app(self.npk_m_hash); + let owner_npk_m_hash: Field = get_public_keys(self.owner).npk_m.hash(); + let secret = context.request_nsk_app(owner_npk_m_hash); poseidon2_hash_with_separator( [note_hash_for_nullify, secret], GENERATOR_INDEX__NOTE_NULLIFIER as Field, @@ -33,7 +34,8 @@ impl NullifiableNote for PublicKeyNote { unconstrained fn compute_nullifier_without_context(self) -> Field { let note_hash_for_nullify = compute_note_hash_for_nullify(self); - let secret = get_nsk_app(self.npk_m_hash); + let owner_npk_m_hash: Field = get_public_keys(self.owner).npk_m.hash(); + let secret = get_nsk_app(owner_npk_m_hash); poseidon2_hash_with_separator( [note_hash_for_nullify, secret], GENERATOR_INDEX__NOTE_NULLIFIER as Field, @@ -42,7 +44,7 @@ impl NullifiableNote for PublicKeyNote { } impl PublicKeyNote { - pub fn new(x: Field, y: Field, npk_m_hash: Field) -> Self { - PublicKeyNote { x, y, npk_m_hash, header: NoteHeader::empty() } + pub fn new(x: Field, y: Field, owner: AztecAddress) -> Self { + PublicKeyNote { x, y, owner, header: NoteHeader::empty() } } } diff --git a/noir-projects/noir-contracts/contracts/spam_contract/src/main.nr b/noir-projects/noir-contracts/contracts/spam_contract/src/main.nr index 63d3faaac39..b1bfe78f565 100644 --- a/noir-projects/noir-contracts/contracts/spam_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/spam_contract/src/main.nr @@ -31,12 +31,12 @@ contract Spam { #[private] fn spam(nullifier_seed: Field, nullifier_count: u32, call_public: bool) { let caller = context.msg_sender(); - let caller_keys = get_public_keys(caller); + let caller_ovpk_m = get_public_keys(caller).ovpk_m; let amount = U128::from_integer(1); for _ in 0..MAX_NOTE_HASHES_PER_CALL { - storage.balances.at(caller).add(caller_keys.npk_m, U128::from_integer(amount)).emit( - encode_and_encrypt_note_unconstrained(&mut context, caller_keys.ovpk_m, caller), + storage.balances.at(caller).add(caller, U128::from_integer(amount)).emit( + encode_and_encrypt_note_unconstrained(&mut context, caller_ovpk_m, caller), ); } diff --git a/noir-projects/noir-contracts/contracts/spam_contract/src/types/balance_set.nr b/noir-projects/noir-contracts/contracts/spam_contract/src/types/balance_set.nr index c9526d85c49..0c0f724c487 100644 --- a/noir-projects/noir-contracts/contracts/spam_contract/src/types/balance_set.nr +++ b/noir-projects/noir-contracts/contracts/spam_contract/src/types/balance_set.nr @@ -3,7 +3,9 @@ use crate::types::token_note::OwnedNote; use dep::aztec::{ context::{PrivateContext, UnconstrainedContext}, note::note_emission::OuterNoteEmission, - protocol_types::{constants::MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, public_keys::NpkM}, + protocol_types::{ + address::AztecAddress, constants::MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, public_keys::NpkM, + }, }; use dep::aztec::prelude::{ NoteGetterOptions, NoteInterface, NoteViewerOptions, NullifiableNote, PrivateSet, @@ -56,7 +58,7 @@ impl BalanceSet { impl BalanceSet { pub fn add( self: Self, - owner_npk_m: NpkM, + owner: AztecAddress, addend: U128, ) -> OuterNoteEmission where @@ -65,8 +67,7 @@ impl BalanceSet { if addend == U128::from_integer(0) { OuterNoteEmission::new(Option::none()) } else { - // We fetch the nullifier public key hash from the registry / from our PXE - let mut addend_note = T::new(addend, owner_npk_m.hash()); + let mut addend_note = T::new(addend, owner); // docs:start:insert OuterNoteEmission::new(Option::some(self.set.insert(&mut addend_note))) @@ -76,7 +77,7 @@ impl BalanceSet { pub fn sub( self: Self, - owner_npk_m: NpkM, + owner: AztecAddress, amount: U128, ) -> OuterNoteEmission where @@ -87,7 +88,7 @@ impl BalanceSet { // try_sub may have substracted more or less than amount. We must ensure that we subtracted at least as much as // we needed, and then create a new note for the owner for the change (if any). assert(subtracted >= amount, "Balance too low"); - self.add(owner_npk_m, subtracted - amount) + self.add(owner, subtracted - amount) } // Attempts to remove 'target_amount' from the owner's balance. try_sub returns how much was actually subtracted diff --git a/noir-projects/noir-contracts/contracts/spam_contract/src/types/token_note.nr b/noir-projects/noir-contracts/contracts/spam_contract/src/types/token_note.nr index 3b60ed16816..5b06e7fde18 100644 --- a/noir-projects/noir-contracts/contracts/spam_contract/src/types/token_note.nr +++ b/noir-projects/noir-contracts/contracts/spam_contract/src/types/token_note.nr @@ -1,16 +1,17 @@ use dep::aztec::{ - keys::getters::get_nsk_app, + keys::getters::{get_nsk_app, get_public_keys}, macros::notes::note, note::utils::compute_note_hash_for_nullify, oracle::random::random, prelude::{NoteHeader, NullifiableNote, PrivateContext}, protocol_types::{ - constants::GENERATOR_INDEX__NOTE_NULLIFIER, hash::poseidon2_hash_with_separator, + address::AztecAddress, constants::GENERATOR_INDEX__NOTE_NULLIFIER, + hash::poseidon2_hash_with_separator, }, }; trait OwnedNote { - fn new(amount: U128, owner_npk_m_hash: Field) -> Self; + fn new(amount: U128, owner: AztecAddress) -> Self; fn get_amount(self) -> U128; } // docs:start:TokenNote @@ -19,7 +20,7 @@ pub struct TokenNote { // The amount of tokens in the note amount: U128, // The nullifying public key hash is used with the nsk_app to ensure that the note can be privately spent. - npk_m_hash: Field, + owner: AztecAddress, // Randomness of the note to hide its contents randomness: Field, } @@ -32,7 +33,8 @@ impl NullifiableNote for TokenNote { context: &mut PrivateContext, note_hash_for_nullify: Field, ) -> Field { - let secret = context.request_nsk_app(self.npk_m_hash); + let owner_npk_m_hash: Field = get_public_keys(self.owner).npk_m.hash(); + let secret = context.request_nsk_app(owner_npk_m_hash); poseidon2_hash_with_separator( [note_hash_for_nullify, secret], GENERATOR_INDEX__NOTE_NULLIFIER as Field, @@ -42,7 +44,8 @@ impl NullifiableNote for TokenNote { unconstrained fn compute_nullifier_without_context(self) -> Field { let note_hash_for_nullify = compute_note_hash_for_nullify(self); - let secret = get_nsk_app(self.npk_m_hash); + let owner_npk_m_hash: Field = get_public_keys(self.owner).npk_m.hash(); + let secret = get_nsk_app(owner_npk_m_hash); poseidon2_hash_with_separator( [note_hash_for_nullify, secret], GENERATOR_INDEX__NOTE_NULLIFIER, @@ -53,19 +56,19 @@ impl NullifiableNote for TokenNote { impl Eq for TokenNote { fn eq(self, other: Self) -> bool { (self.amount == other.amount) - & (self.npk_m_hash == other.npk_m_hash) + & (self.owner == other.owner) & (self.randomness == other.randomness) } } impl OwnedNote for TokenNote { - fn new(amount: U128, owner_npk_m_hash: Field) -> Self { + fn new(amount: U128, owner: AztecAddress) -> Self { // We use the randomness to preserve the privacy of the note recipient by preventing brute-forcing, so a // malicious sender could use non-random values to make the note less private. But they already know the full // note pre-image anyway, and so the recipient already trusts them to not disclose this information. We can // therefore assume that the sender will cooperate in the random value generation. let randomness = unsafe { random() }; - Self { amount, npk_m_hash: owner_npk_m_hash, randomness, header: NoteHeader::empty() } + Self { amount, owner, randomness, header: NoteHeader::empty() } } fn get_amount(self) -> U128 { diff --git a/noir-projects/noir-contracts/contracts/static_child_contract/src/main.nr b/noir-projects/noir-contracts/contracts/static_child_contract/src/main.nr index 3a82896ff64..418c6a9c281 100644 --- a/noir-projects/noir-contracts/contracts/static_child_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/static_child_contract/src/main.nr @@ -45,14 +45,12 @@ contract StaticChild { #[private] #[view] fn private_illegal_set_value(new_value: Field, owner: AztecAddress) -> Field { - let msg_sender_keys = get_public_keys(context.msg_sender()); - let owner_keys = get_public_keys(owner); - - let mut note = ValueNote::new(new_value, owner_keys.npk_m.hash()); + let mut note = ValueNote::new(new_value, owner); + let msg_sender_ovpk_m = get_public_keys(context.msg_sender()).ovpk_m; storage.a_private_value.insert(&mut note).emit(encode_and_encrypt_note( &mut context, - msg_sender_keys.ovpk_m, + msg_sender_ovpk_m, owner, )); new_value @@ -65,13 +63,12 @@ contract StaticChild { owner: AztecAddress, outgoing_viewer: AztecAddress, ) -> Field { - let owner_keys = get_public_keys(owner); - let outgoing_viewer_keys = get_public_keys(outgoing_viewer); + let mut note = ValueNote::new(new_value, owner); - let mut note = ValueNote::new(new_value, owner_keys.npk_m.hash()); + let outgoing_viewer_ovpk_m = get_public_keys(outgoing_viewer).ovpk_m; storage.a_private_value.insert(&mut note).emit(encode_and_encrypt_note( &mut context, - outgoing_viewer_keys.ovpk_m, + outgoing_viewer_ovpk_m, owner, )); new_value @@ -81,11 +78,10 @@ contract StaticChild { #[private] #[view] fn private_get_value(amount: Field, owner: AztecAddress) -> Field { - let owner_npk_m_hash = get_public_keys(owner).npk_m.hash(); let mut options = NoteGetterOptions::new(); options = options .select(ValueNote::properties().value, Comparator.EQ, amount) - .select(ValueNote::properties().npk_m_hash, Comparator.EQ, owner_npk_m_hash) + .select(ValueNote::properties().owner, Comparator.EQ, owner) .set_limit(1); let notes = storage.a_private_value.get_notes(options); notes.get(0).value diff --git a/noir-projects/noir-contracts/contracts/test_contract/src/main.nr b/noir-projects/noir-contracts/contracts/test_contract/src/main.nr index e11c3a4c88e..1305b464478 100644 --- a/noir-projects/noir-contracts/contracts/test_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/test_contract/src/main.nr @@ -102,13 +102,12 @@ contract Test { "this storage slot is reserved for example_constant", ); - let outgoing_viewer_keys = get_public_keys(outgoing_viewer); - let owner_keys = get_public_keys(owner); + let outgoing_viewer_ovpk_m = get_public_keys(outgoing_viewer).ovpk_m; - let mut note = ValueNote::new(value, owner_keys.npk_m.hash()); + let mut note = ValueNote::new(value, owner); create_note(&mut context, storage_slot, &mut note).emit(encode_and_encrypt_note( &mut context, - outgoing_viewer_keys.ovpk_m, + outgoing_viewer_ovpk_m, owner, )); } @@ -337,13 +336,12 @@ contract Test { .call(&mut context); storage_slot += 1; - let msg_sender_keys = get_public_keys(context.msg_sender()); - let owner_keys = get_public_keys(owner); + let msg_sender_ovpk_m = get_public_keys(context.msg_sender()).ovpk_m; - let mut note = ValueNote::new(value + 1, owner_keys.npk_m.hash()); + let mut note = ValueNote::new(value + 1, owner); create_note(&mut context, storage_slot, &mut note).emit(encode_and_encrypt_note( &mut context, - msg_sender_keys.ovpk_m, + msg_sender_ovpk_m, owner, )); storage_slot += 1; diff --git a/noir-projects/noir-contracts/contracts/test_log_contract/src/main.nr b/noir-projects/noir-contracts/contracts/test_log_contract/src/main.nr index 5bdcb8cab54..8c3f65d38fd 100644 --- a/noir-projects/noir-contracts/contracts/test_log_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/test_log_contract/src/main.nr @@ -39,14 +39,14 @@ contract TestLog { fn emit_encrypted_events(other: AztecAddress, randomness: [Field; 2], preimages: [Field; 4]) { let event0 = ExampleEvent0 { value0: preimages[0], value1: preimages[1] }; - let other_keys = get_public_keys(other); - let msg_sender_keys = get_public_keys(context.msg_sender()); + let other_ovpk_m = get_public_keys(other).ovpk_m; + let msg_sender_ovpk_m = get_public_keys(context.msg_sender()).ovpk_m; event0.emit(encode_and_encrypt_event_with_randomness( &mut context, randomness[0], // outgoing is set to other, incoming is set to msg sender - other_keys.ovpk_m, + other_ovpk_m, context.msg_sender(), )); @@ -55,7 +55,7 @@ contract TestLog { &mut context, randomness[0], // outgoing is set to msg sender, incoming is set to other - msg_sender_keys.ovpk_m, + msg_sender_ovpk_m, other, )); @@ -68,7 +68,7 @@ contract TestLog { &mut context, randomness[1], // outgoing is set to other, incoming is set to msg sender - other_keys.ovpk_m, + other_ovpk_m, context.msg_sender(), )); } diff --git a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/main.nr b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/main.nr index be008b542a0..765d8530ae9 100644 --- a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/main.nr @@ -187,12 +187,11 @@ contract TokenBlacklist { assert(notes.len() == 1, "note not popped"); // Add the token note to user's balances set - let msg_sender_keys = get_public_keys(context.msg_sender()); - let to_keys = get_public_keys(to); + let msg_sender_ovpk_m = get_public_keys(context.msg_sender()).ovpk_m; // TODO: constrain encryption below - we are using unconstrained here only becuase of the following Noir issue // https://github.com/noir-lang/noir/issues/5771 storage.balances.add(to, U128::from_integer(amount)).emit( - encode_and_encrypt_note_unconstrained(&mut context, msg_sender_keys.ovpk_m, to), + encode_and_encrypt_note_unconstrained(&mut context, msg_sender_ovpk_m, to), ); } @@ -209,11 +208,11 @@ contract TokenBlacklist { assert(nonce == 0, "invalid nonce"); } - let from_keys = get_public_keys(from); + let from_ovpk_m = get_public_keys(from).ovpk_m; // TODO: constrain encryption below - we are using unconstrained here only becuase of the following Noir issue // https://github.com/noir-lang/noir/issues/5771 storage.balances.sub(from, U128::from_integer(amount)).emit( - encode_and_encrypt_note_unconstrained(&mut context, from_keys.ovpk_m, from), + encode_and_encrypt_note_unconstrained(&mut context, from_ovpk_m, from), ); TokenBlacklist::at(context.this_address())._increase_public_balance(to, amount).enqueue( @@ -235,18 +234,17 @@ contract TokenBlacklist { assert(nonce == 0, "invalid nonce"); } - let from_keys = get_public_keys(from); - let to_keys = get_public_keys(to); + let from_ovpk_m = get_public_keys(from).ovpk_m; let amount = U128::from_integer(amount); storage.balances.sub(from, amount).emit(encode_and_encrypt_note_unconstrained( &mut context, - from_keys.ovpk_m, + from_ovpk_m, from, )); storage.balances.add(to, amount).emit(encode_and_encrypt_note_unconstrained( &mut context, - from_keys.ovpk_m, + from_ovpk_m, to, )); } @@ -262,11 +260,11 @@ contract TokenBlacklist { assert(nonce == 0, "invalid nonce"); } - let from_keys = get_public_keys(from); + let from_ovpk_m = get_public_keys(from).ovpk_m; // TODO: constrain encryption below - we are using unconstrained here only becuase of the following Noir issue // https://github.com/noir-lang/noir/issues/5771 storage.balances.sub(from, U128::from_integer(amount)).emit( - encode_and_encrypt_note_unconstrained(&mut context, from_keys.ovpk_m, from), + encode_and_encrypt_note_unconstrained(&mut context, from_ovpk_m, from), ); TokenBlacklist::at(context.this_address())._reduce_total_supply(amount).enqueue(&mut context); diff --git a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/balances_map.nr b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/balances_map.nr index 8c1d84c3cef..b2e4dcbd004 100644 --- a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/balances_map.nr +++ b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/balances_map.nr @@ -1,7 +1,6 @@ use crate::types::token_note::OwnedNote; use dep::aztec::{ context::{PrivateContext, UnconstrainedContext}, - keys::getters::get_public_keys, note::note_emission::OuterNoteEmission, protocol_types::constants::MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, }; @@ -79,9 +78,7 @@ impl BalancesMap { } else { let context = self.map.context; - // We fetch the nullifier public key hash from the registry / from our PXE - let owner_npk_m_hash = get_public_keys(owner).npk_m.hash(); - let mut addend_note = T::new(addend, owner_npk_m_hash); + let mut addend_note = T::new(addend, owner); // docs:start:insert OuterNoteEmission::new(Option::some(self.map.at(owner).insert(&mut addend_note))) diff --git a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/token_note.nr b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/token_note.nr index b36d5316324..298835848f8 100644 --- a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/token_note.nr +++ b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/token_note.nr @@ -1,16 +1,17 @@ use dep::aztec::{ - keys::getters::get_nsk_app, + keys::getters::{get_nsk_app, get_public_keys}, macros::notes::note, note::utils::compute_note_hash_for_nullify, oracle::random::random, prelude::{NoteHeader, NullifiableNote, PrivateContext}, protocol_types::{ - constants::GENERATOR_INDEX__NOTE_NULLIFIER, hash::poseidon2_hash_with_separator, + address::AztecAddress, constants::GENERATOR_INDEX__NOTE_NULLIFIER, + hash::poseidon2_hash_with_separator, }, }; trait OwnedNote { - fn new(amount: U128, owner_npk_m_hash: Field) -> Self; + fn new(amount: U128, owner: AztecAddress) -> Self; fn get_amount(self) -> U128; } @@ -18,8 +19,7 @@ trait OwnedNote { pub struct TokenNote { // The amount of tokens in the note amount: U128, - // The nullifying public key hash is used with the nsk_app to ensure that the note can be privately spent. - npk_m_hash: Field, + owner: AztecAddress, // Randomness of the note to hide its contents randomness: Field, } @@ -31,7 +31,8 @@ impl NullifiableNote for TokenNote { context: &mut PrivateContext, note_hash_for_nullify: Field, ) -> Field { - let secret = context.request_nsk_app(self.npk_m_hash); + let owner_npk_m_hash: Field = get_public_keys(self.owner).npk_m.hash(); + let secret = context.request_nsk_app(owner_npk_m_hash); poseidon2_hash_with_separator( [note_hash_for_nullify, secret], GENERATOR_INDEX__NOTE_NULLIFIER as Field, @@ -41,7 +42,8 @@ impl NullifiableNote for TokenNote { unconstrained fn compute_nullifier_without_context(self) -> Field { let note_hash_for_nullify = compute_note_hash_for_nullify(self); - let secret = get_nsk_app(self.npk_m_hash); + let owner_npk_m_hash: Field = get_public_keys(self.owner).npk_m.hash(); + let secret = get_nsk_app(owner_npk_m_hash); poseidon2_hash_with_separator( [note_hash_for_nullify, secret], GENERATOR_INDEX__NOTE_NULLIFIER as Field, @@ -52,19 +54,19 @@ impl NullifiableNote for TokenNote { impl Eq for TokenNote { fn eq(self, other: Self) -> bool { (self.amount == other.amount) - & (self.npk_m_hash == other.npk_m_hash) + & (self.owner == other.owner) & (self.randomness == other.randomness) } } impl OwnedNote for TokenNote { - fn new(amount: U128, owner_npk_m_hash: Field) -> Self { + fn new(amount: U128, owner: AztecAddress) -> Self { // We use the randomness to preserve the privacy of the note recipient by preventing brute-forcing, so a // malicious sender could use non-random values to make the note less private. But they already know the full // note pre-image anyway, and so the recipient already trusts them to not disclose this information. We can // therefore assume that the sender will cooperate in the random value generation. let randomness = unsafe { random() }; - Self { amount, npk_m_hash: owner_npk_m_hash, randomness, header: NoteHeader::empty() } + Self { amount, owner, randomness, header: NoteHeader::empty() } } fn get_amount(self) -> U128 { diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/main.nr b/noir-projects/noir-contracts/contracts/token_contract/src/main.nr index d7ee6ea8a86..b6ffdd199cf 100644 --- a/noir-projects/noir-contracts/contracts/token_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/token_contract/src/main.nr @@ -224,9 +224,9 @@ contract Token { #[private] fn privately_mint_private_note(amount: Field) { let caller = context.msg_sender(); - let caller_keys = get_public_keys(caller); - storage.balances.at(caller).add(caller_keys.npk_m, U128::from_integer(amount)).emit( - encode_and_encrypt_note(&mut context, caller_keys.ovpk_m, caller), + let caller_ovpk_m = get_public_keys(caller).ovpk_m; + storage.balances.at(caller).add(caller, U128::from_integer(amount)).emit( + encode_and_encrypt_note(&mut context, caller_ovpk_m, caller), ); Token::at(context.this_address()) .assert_minter_and_mint(context.msg_sender(), amount) @@ -305,11 +305,12 @@ contract Token { // Note: Using context.msg_sender() as a sender below makes this incompatible with escrows because we send // outgoing logs to that address and to send outgoing logs you need to get a hold of ovsk_m. let from = context.msg_sender(); - let from_keys = get_public_keys(from); - let to_keys = get_public_keys(to); - storage.balances.at(to).add(to_keys.npk_m, U128::from_integer(amount)).emit( - encode_and_encrypt_note(&mut context, from_keys.ovpk_m, to), - ); + let from_ovpk_m = get_public_keys(from).ovpk_m; + storage.balances.at(to).add(to, U128::from_integer(amount)).emit(encode_and_encrypt_note( + &mut context, + from_ovpk_m, + to, + )); } // docs:end:redeem_shield // docs:start:unshield @@ -321,11 +322,11 @@ contract Token { assert(nonce == 0, "invalid nonce"); } - let from_keys = get_public_keys(from); + let from_ovpk_m = get_public_keys(from).ovpk_m; // TODO: constrain encryption below - we are using unconstrained here only becuase of the following Noir issue // https://github.com/noir-lang/noir/issues/5771 - storage.balances.at(from).sub(from_keys.npk_m, U128::from_integer(amount)).emit( - encode_and_encrypt_note_unconstrained(&mut context, from_keys.ovpk_m, from), + storage.balances.at(from).sub(from, U128::from_integer(amount)).emit( + encode_and_encrypt_note_unconstrained(&mut context, from_ovpk_m, from), ); Token::at(context.this_address())._increase_public_balance(to, amount).enqueue(&mut context); } @@ -335,8 +336,7 @@ contract Token { fn transfer(to: AztecAddress, amount: Field) { let from = context.msg_sender(); - let from_keys = get_public_keys(from); - let to_keys = get_public_keys(to); + let from_ovpk_m = get_public_keys(from).ovpk_m; let amount = U128::from_integer(amount); // We reduce `from`'s balance by amount by recursively removing notes over potentially multiple calls. This @@ -352,18 +352,22 @@ contract Token { amount, INITIAL_TRANSFER_CALL_MAX_NOTES, ); - storage.balances.at(from).add(from_keys.npk_m, change).emit( - encode_and_encrypt_note_unconstrained(&mut context, from_keys.ovpk_m, from), - ); - storage.balances.at(to).add(to_keys.npk_m, amount).emit( - encode_and_encrypt_note_unconstrained(&mut context, from_keys.ovpk_m, to), - ); + storage.balances.at(from).add(from, change).emit(encode_and_encrypt_note_unconstrained( + &mut context, + from_ovpk_m, + from, + )); + storage.balances.at(to).add(to, amount).emit(encode_and_encrypt_note_unconstrained( + &mut context, + from_ovpk_m, + to, + )); // We don't constrain encryption of the note log in `transfer` (unlike in `transfer_from`) because the transfer // function is only designed to be used in situations where the event is not strictly necessary (e.g. payment to // another person where the payment is considered to be successful when the other party successfully decrypts a // note). Transfer { from, to, amount: amount.to_field() }.emit( - encode_and_encrypt_event_unconstrained(&mut context, from_keys.ovpk_m, to), + encode_and_encrypt_event_unconstrained(&mut context, from_ovpk_m, to), ); } // docs:end:transfer @@ -437,24 +441,27 @@ contract Token { assert(nonce == 0, "invalid nonce"); } // docs:end:assert_current_call_valid_authwit - let from_keys = get_public_keys(from); - let to_keys = get_public_keys(to); + let from_ovpk_m = get_public_keys(from).ovpk_m; let amount = U128::from_integer(amount); // docs:start:increase_private_balance // docs:start:encrypted // TODO: constrain encryption below - we are using unconstrained here only becuase of the following Noir issue // https://github.com/noir-lang/noir/issues/5771 - storage.balances.at(from).sub(from_keys.npk_m, amount).emit( - encode_and_encrypt_note_unconstrained(&mut context, from_keys.ovpk_m, from), - ); + storage.balances.at(from).sub(from, amount).emit(encode_and_encrypt_note_unconstrained( + &mut context, + from_ovpk_m, + from, + )); // docs:end:encrypted // docs:end:increase_private_balance // TODO: constrain encryption below - we are using unconstrained here only becuase of the following Noir issue // https://github.com/noir-lang/noir/issues/5771 - storage.balances.at(to).add(to_keys.npk_m, amount).emit( - encode_and_encrypt_note_unconstrained(&mut context, from_keys.ovpk_m, to), - ); + storage.balances.at(to).add(to, amount).emit(encode_and_encrypt_note_unconstrained( + &mut context, + from_ovpk_m, + to, + )); } // docs:end:transfer_from // docs:start:burn @@ -465,11 +472,11 @@ contract Token { } else { assert(nonce == 0, "invalid nonce"); } - let from_keys = get_public_keys(from); + let from_ovpk_m = get_public_keys(from).ovpk_m; // TODO: constrain encryption below - we are using unconstrained here only becuase of the following Noir issue // https://github.com/noir-lang/noir/issues/5771 - storage.balances.at(from).sub(from_keys.npk_m, U128::from_integer(amount)).emit( - encode_and_encrypt_note_unconstrained(&mut context, from_keys.ovpk_m, from), + storage.balances.at(from).sub(from, U128::from_integer(amount)).emit( + encode_and_encrypt_note_unconstrained(&mut context, from_ovpk_m, from), ); Token::at(context.this_address())._reduce_total_supply(amount).enqueue(&mut context); } @@ -508,9 +515,6 @@ contract Token { let fee_payer_keys = get_public_keys(fee_payer); let user_keys = get_public_keys(user); - let fee_payer_npk_m_hash = fee_payer_keys.npk_m.hash(); - let user_npk_m_hash = user_keys.npk_m.hash(); - // 3. Deduct the funded amount from the user's balance - this is a maximum fee a user is willing to pay // (called fee limit in aztec spec). The difference between fee limit and the actual tx fee will be refunded // to the user in the `complete_refund(...)` function. @@ -521,9 +525,11 @@ contract Token { U128::from_integer(funded_amount), INITIAL_TRANSFER_CALL_MAX_NOTES, ); - storage.balances.at(user).add(user_keys.npk_m, change).emit( - encode_and_encrypt_note_unconstrained(&mut context, user_keys.ovpk_m, user), - ); + storage.balances.at(user).add(user, change).emit(encode_and_encrypt_note_unconstrained( + &mut context, + user_keys.ovpk_m, + user, + )); // 4. Now we get the partial payloads // TODO(#7775): Manually fetching the randomness here is not great. If we decide to include randomness in all @@ -532,13 +538,13 @@ contract Token { let user_randomness = unsafe { random() }; let fee_payer_setup_payload = UintNote::setup_payload().new( - fee_payer_npk_m_hash, + fee_payer, fee_payer_randomness, storage.balances.at(fee_payer).set.storage_slot, ); let user_setup_payload = UintNote::setup_payload().new( - user_npk_m_hash, + user, user_randomness, storage.balances.at(user).set.storage_slot, ); diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/test/burn.nr b/noir-projects/noir-contracts/contracts/token_contract/src/test/burn.nr index daa91a0d26c..151ef95a506 100644 --- a/noir-projects/noir-contracts/contracts/token_contract/src/test/burn.nr +++ b/noir-projects/noir-contracts/contracts/token_contract/src/test/burn.nr @@ -6,7 +6,7 @@ use dep::aztec::oracle::random::random; #[test] unconstrained fn burn_public_success() { let (env, token_contract_address, owner, recipient, mint_amount) = - utils::setup_and_mint(/* with_account_contracts */ false); + utils::setup_and_mint_public(/* with_account_contracts */ false); let burn_amount = mint_amount / 10; // Burn less than balance @@ -17,7 +17,7 @@ unconstrained fn burn_public_success() { #[test] unconstrained fn burn_public_on_behalf_of_other() { let (env, token_contract_address, owner, recipient, mint_amount) = - utils::setup_and_mint(/* with_account_contracts */ true); + utils::setup_and_mint_public(/* with_account_contracts */ true); let burn_amount = mint_amount / 10; // Burn on behalf of other @@ -38,7 +38,7 @@ unconstrained fn burn_public_on_behalf_of_other() { #[test(should_fail_with = "attempt to subtract with underflow")] unconstrained fn burn_public_failure_more_than_balance() { let (env, token_contract_address, owner, _, mint_amount) = - utils::setup_and_mint(/* with_account_contracts */ false); + utils::setup_and_mint_public(/* with_account_contracts */ false); // Burn more than balance let burn_amount = mint_amount * 10; @@ -49,7 +49,7 @@ unconstrained fn burn_public_failure_more_than_balance() { #[test(should_fail_with = "invalid nonce")] unconstrained fn burn_public_failure_on_behalf_of_self_non_zero_nonce() { let (env, token_contract_address, owner, _, mint_amount) = - utils::setup_and_mint(/* with_account_contracts */ false); + utils::setup_and_mint_public(/* with_account_contracts */ false); // Burn on behalf of self with non-zero nonce let burn_amount = mint_amount / 10; @@ -62,7 +62,7 @@ unconstrained fn burn_public_failure_on_behalf_of_self_non_zero_nonce() { #[test(should_fail_with = "unauthorized")] unconstrained fn burn_public_failure_on_behalf_of_other_without_approval() { let (env, token_contract_address, owner, recipient, mint_amount) = - utils::setup_and_mint(/* with_account_contracts */ true); + utils::setup_and_mint_public(/* with_account_contracts */ true); // Burn on behalf of other without approval let burn_amount = mint_amount / 10; @@ -76,7 +76,7 @@ unconstrained fn burn_public_failure_on_behalf_of_other_without_approval() { #[test(should_fail_with = "unauthorized")] unconstrained fn burn_public_failure_on_behalf_of_other_wrong_caller() { let (env, token_contract_address, owner, recipient, mint_amount) = - utils::setup_and_mint(/* with_account_contracts */ true); + utils::setup_and_mint_public(/* with_account_contracts */ true); // Burn on behalf of other, wrong designated caller let burn_amount = mint_amount / 10; @@ -91,7 +91,7 @@ unconstrained fn burn_public_failure_on_behalf_of_other_wrong_caller() { #[test] unconstrained fn burn_private_on_behalf_of_self() { let (env, token_contract_address, owner, _, mint_amount) = - utils::setup_and_mint(/* with_account_contracts */ false); + utils::setup_and_mint_private(/* with_account_contracts */ false); let burn_amount = mint_amount / 10; // Burn less than balance @@ -102,7 +102,7 @@ unconstrained fn burn_private_on_behalf_of_self() { #[test] unconstrained fn burn_private_on_behalf_of_other() { let (env, token_contract_address, owner, recipient, mint_amount) = - utils::setup_and_mint(/* with_account_contracts */ true); + utils::setup_and_mint_private(/* with_account_contracts */ true); let burn_amount = mint_amount / 10; // Burn on behalf of other @@ -122,7 +122,7 @@ unconstrained fn burn_private_on_behalf_of_other() { #[test(should_fail_with = "Balance too low")] unconstrained fn burn_private_failure_more_than_balance() { let (env, token_contract_address, owner, _, mint_amount) = - utils::setup_and_mint(/* with_account_contracts */ false); + utils::setup_and_mint_public(/* with_account_contracts */ false); // Burn more than balance let burn_amount = mint_amount * 10; @@ -132,7 +132,7 @@ unconstrained fn burn_private_failure_more_than_balance() { #[test(should_fail_with = "invalid nonce")] unconstrained fn burn_private_failure_on_behalf_of_self_non_zero_nonce() { let (env, token_contract_address, owner, _, mint_amount) = - utils::setup_and_mint(/* with_account_contracts */ false); + utils::setup_and_mint_public(/* with_account_contracts */ false); // Burn more than balance let burn_amount = mint_amount / 10; @@ -142,7 +142,7 @@ unconstrained fn burn_private_failure_on_behalf_of_self_non_zero_nonce() { #[test(should_fail_with = "Balance too low")] unconstrained fn burn_private_failure_on_behalf_of_other_more_than_balance() { let (env, token_contract_address, owner, recipient, mint_amount) = - utils::setup_and_mint(/* with_account_contracts */ true); + utils::setup_and_mint_public(/* with_account_contracts */ true); // Burn more than balance let burn_amount = mint_amount * 10; @@ -161,7 +161,7 @@ unconstrained fn burn_private_failure_on_behalf_of_other_more_than_balance() { #[test(should_fail_with = "Authorization not found for message hash")] unconstrained fn burn_private_failure_on_behalf_of_other_without_approval() { let (env, token_contract_address, owner, recipient, mint_amount) = - utils::setup_and_mint(/* with_account_contracts */ true); + utils::setup_and_mint_public(/* with_account_contracts */ true); // Burn more than balance let burn_amount = mint_amount / 10; @@ -175,7 +175,7 @@ unconstrained fn burn_private_failure_on_behalf_of_other_without_approval() { #[test(should_fail_with = "Authorization not found for message hash")] unconstrained fn burn_private_failure_on_behalf_of_other_wrong_designated_caller() { let (env, token_contract_address, owner, recipient, mint_amount) = - utils::setup_and_mint(/* with_account_contracts */ true); + utils::setup_and_mint_public(/* with_account_contracts */ true); // Burn more than balance let burn_amount = mint_amount / 10; diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/test/refunds.nr b/noir-projects/noir-contracts/contracts/token_contract/src/test/refunds.nr index 2163f0d3e9a..e52d6fb44fa 100644 --- a/noir-projects/noir-contracts/contracts/token_contract/src/test/refunds.nr +++ b/noir-projects/noir-contracts/contracts/token_contract/src/test/refunds.nr @@ -1,16 +1,14 @@ use crate::{test::utils, Token}; use dep::authwit::cheatcodes as authwit_cheatcodes; -use dep::aztec::{ - keys::getters::get_public_keys, prelude::NoteHeader, - protocol_types::storage::map::derive_storage_slot_in_map, -}; +use dep::aztec::{prelude::NoteHeader, protocol_types::storage::map::derive_storage_slot_in_map}; use dep::uint_note::uint_note::UintNote; use std::test::OracleMock; #[test] unconstrained fn setup_refund_success() { - let (env, token_contract_address, owner, recipient, mint_amount) = utils::setup_and_mint(true); + let (env, token_contract_address, owner, recipient, mint_amount) = + utils::setup_and_mint_private(true); // Renaming owner and recipient to match naming in Token let user = owner; @@ -36,8 +34,6 @@ unconstrained fn setup_refund_success() { env.impersonate(fee_payer); setup_refund_from_call_interface.call(&mut env.private()); - let user_npk_m_hash = get_public_keys(user).npk_m.hash(); - let fee_payer_npk_m_hash = get_public_keys(fee_payer).npk_m.hash(); let fee_payer_balances_slot = derive_storage_slot_in_map(Token::storage_layout().balances.slot, fee_payer); @@ -51,7 +47,7 @@ unconstrained fn setup_refund_success() { env.add_note( &mut UintNote { value: U128::from_integer(funded_amount - 1), - npk_m_hash: user_npk_m_hash, + owner: user, randomness: user_randomness, header: NoteHeader::empty(), }, @@ -61,7 +57,7 @@ unconstrained fn setup_refund_success() { env.add_note( &mut UintNote { value: U128::from_integer(1), - npk_m_hash: fee_payer_npk_m_hash, + owner: fee_payer, randomness: fee_payer_randomness, header: NoteHeader::empty(), }, @@ -78,7 +74,8 @@ unconstrained fn setup_refund_success() { //#[test(should_fail_with="funded amount not enough to cover tx fee")] #[test(should_fail_with = "Balance too low")] unconstrained fn setup_refund_insufficient_funded_amount() { - let (env, token_contract_address, owner, recipient, _mint_amount) = utils::setup_and_mint(true); + let (env, token_contract_address, owner, recipient, _mint_amount) = + utils::setup_and_mint_private(true); // Renaming owner and recipient to match naming in Token let user = owner; diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/test/shielding.nr b/noir-projects/noir-contracts/contracts/token_contract/src/test/shielding.nr index a4b5832e579..aef1d98f9cc 100644 --- a/noir-projects/noir-contracts/contracts/token_contract/src/test/shielding.nr +++ b/noir-projects/noir-contracts/contracts/token_contract/src/test/shielding.nr @@ -7,7 +7,7 @@ use dep::aztec::{hash::compute_secret_hash, oracle::random::random}; unconstrained fn shielding_on_behalf_of_self() { // Setup without account contracts. We are not using authwits here, so dummy accounts are enough let (env, token_contract_address, owner, _, mint_amount) = - utils::setup_and_mint(/* with_account_contracts */ false); + utils::setup_and_mint_public(/* with_account_contracts */ false); let secret = random(); let secret_hash = compute_secret_hash(secret); // Shield tokens @@ -30,13 +30,13 @@ unconstrained fn shielding_on_behalf_of_self() { // Check balances utils::check_public_balance(token_contract_address, owner, mint_amount - shield_amount); - utils::check_private_balance(token_contract_address, owner, mint_amount + shield_amount); + utils::check_private_balance(token_contract_address, owner, shield_amount); } #[test] unconstrained fn shielding_on_behalf_of_other() { let (env, token_contract_address, owner, recipient, mint_amount) = - utils::setup_and_mint(/* with_account_contracts */ true); + utils::setup_and_mint_public(/* with_account_contracts */ true); let secret = random(); let secret_hash = compute_secret_hash(secret); @@ -70,14 +70,14 @@ unconstrained fn shielding_on_behalf_of_other() { // Check balances utils::check_public_balance(token_contract_address, owner, mint_amount - shield_amount); - utils::check_private_balance(token_contract_address, owner, mint_amount + shield_amount); + utils::check_private_balance(token_contract_address, owner, shield_amount); } #[test] unconstrained fn shielding_failure_on_behalf_of_self_more_than_balance() { // Setup without account contracts. We are not using authwits here, so dummy accounts are enough let (env, token_contract_address, owner, _, mint_amount) = - utils::setup_and_mint(/* with_account_contracts */ true); + utils::setup_and_mint_public(/* with_account_contracts */ true); let secret = random(); let secret_hash = compute_secret_hash(secret); // Shield tokens @@ -88,14 +88,14 @@ unconstrained fn shielding_failure_on_behalf_of_self_more_than_balance() { // Check balances utils::check_public_balance(token_contract_address, owner, mint_amount); - utils::check_private_balance(token_contract_address, owner, mint_amount); + utils::check_private_balance(token_contract_address, owner, 0); } #[test] unconstrained fn shielding_failure_on_behalf_of_self_invalid_nonce() { // Setup without account contracts. We are not using authwits here, so dummy accounts are enough let (env, token_contract_address, owner, _, mint_amount) = - utils::setup_and_mint(/* with_account_contracts */ true); + utils::setup_and_mint_public(/* with_account_contracts */ true); let secret = random(); let secret_hash = compute_secret_hash(secret); // Shield tokens @@ -106,14 +106,14 @@ unconstrained fn shielding_failure_on_behalf_of_self_invalid_nonce() { // Check balances utils::check_public_balance(token_contract_address, owner, mint_amount); - utils::check_private_balance(token_contract_address, owner, mint_amount); + utils::check_private_balance(token_contract_address, owner, 0); } #[test] unconstrained fn shielding_failure_on_behalf_of_other_more_than_balance() { // Setup without account contracts. We are not using authwits here, so dummy accounts are enough let (env, token_contract_address, owner, recipient, mint_amount) = - utils::setup_and_mint(/* with_account_contracts */ true); + utils::setup_and_mint_public(/* with_account_contracts */ true); let secret = random(); let secret_hash = compute_secret_hash(secret); // Shield tokens on behalf of owner @@ -132,14 +132,14 @@ unconstrained fn shielding_failure_on_behalf_of_other_more_than_balance() { // Check balances utils::check_public_balance(token_contract_address, owner, mint_amount); - utils::check_private_balance(token_contract_address, owner, mint_amount); + utils::check_private_balance(token_contract_address, owner, 0); } #[test] unconstrained fn shielding_failure_on_behalf_of_other_wrong_caller() { // Setup without account contracts. We are not using authwits here, so dummy accounts are enough let (env, token_contract_address, owner, recipient, mint_amount) = - utils::setup_and_mint(/* with_account_contracts */ true); + utils::setup_and_mint_public(/* with_account_contracts */ true); let secret = random(); let secret_hash = compute_secret_hash(secret); // Shield tokens on behalf of owner @@ -154,14 +154,14 @@ unconstrained fn shielding_failure_on_behalf_of_other_wrong_caller() { // Check balances utils::check_public_balance(token_contract_address, owner, mint_amount); - utils::check_private_balance(token_contract_address, owner, mint_amount); + utils::check_private_balance(token_contract_address, owner, 0); } #[test] unconstrained fn shielding_failure_on_behalf_of_other_without_approval() { // Setup without account contracts. We are not using authwits here, so dummy accounts are enough let (env, token_contract_address, owner, recipient, mint_amount) = - utils::setup_and_mint(/* with_account_contracts */ true); + utils::setup_and_mint_public(/* with_account_contracts */ true); let secret = random(); let secret_hash = compute_secret_hash(secret); // Shield tokens on behalf of owner @@ -175,5 +175,5 @@ unconstrained fn shielding_failure_on_behalf_of_other_without_approval() { // Check balances utils::check_public_balance(token_contract_address, owner, mint_amount); - utils::check_private_balance(token_contract_address, owner, mint_amount); + utils::check_private_balance(token_contract_address, owner, 0); } diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/test/transfer_private.nr b/noir-projects/noir-contracts/contracts/token_contract/src/test/transfer_private.nr index 66d6d13bd0e..11f32bba6ec 100644 --- a/noir-projects/noir-contracts/contracts/token_contract/src/test/transfer_private.nr +++ b/noir-projects/noir-contracts/contracts/token_contract/src/test/transfer_private.nr @@ -7,7 +7,7 @@ use dep::aztec::test::helpers::cheatcodes; unconstrained fn transfer_private() { // Setup without account contracts. We are not using authwits here, so dummy accounts are enough let (env, token_contract_address, owner, recipient, mint_amount) = - utils::setup_and_mint(/* with_account_contracts */ false); + utils::setup_and_mint_private(/* with_account_contracts */ false); // docs:start:txe_test_transfer_private // Transfer tokens @@ -23,7 +23,7 @@ unconstrained fn transfer_private() { unconstrained fn transfer_private_to_self() { // Setup without account contracts. We are not using authwits here, so dummy accounts are enough let (env, token_contract_address, owner, _, mint_amount) = - utils::setup_and_mint(/* with_account_contracts */ false); + utils::setup_and_mint_private(/* with_account_contracts */ false); // Transfer tokens let transfer_amount = 1000; Token::at(token_contract_address).transfer(owner, transfer_amount).call(&mut env.private()); @@ -36,7 +36,7 @@ unconstrained fn transfer_private_to_self() { unconstrained fn transfer_private_to_non_deployed_account() { // Setup without account contracts. We are not using authwits here, so dummy accounts are enough let (env, token_contract_address, owner, _, mint_amount) = - utils::setup_and_mint(/* with_account_contracts */ false); + utils::setup_and_mint_private(/* with_account_contracts */ false); let not_deployed = cheatcodes::create_account(); // Transfer tokens let transfer_amount = 1000; @@ -57,7 +57,7 @@ unconstrained fn transfer_private_to_non_deployed_account() { unconstrained fn transfer_private_on_behalf_of_other() { // Setup with account contracts. Slower since we actually deploy them, but needed for authwits. let (env, token_contract_address, owner, recipient, mint_amount) = - utils::setup_and_mint(/* with_account_contracts */ true); + utils::setup_and_mint_private(/* with_account_contracts */ true); // Add authwit // docs:start:private_authwit let transfer_amount = 1000; @@ -82,7 +82,7 @@ unconstrained fn transfer_private_on_behalf_of_other() { unconstrained fn transfer_private_failure_more_than_balance() { // Setup without account contracts. We are not using authwits here, so dummy accounts are enough let (env, token_contract_address, _, recipient, mint_amount) = - utils::setup_and_mint(/* with_account_contracts */ false); + utils::setup_and_mint_private(/* with_account_contracts */ false); // Transfer tokens let transfer_amount = mint_amount + 1; Token::at(token_contract_address).transfer(recipient, transfer_amount).call(&mut env.private()); @@ -93,7 +93,7 @@ unconstrained fn transfer_private_failure_more_than_balance() { unconstrained fn transfer_private_failure_on_behalf_of_self_non_zero_nonce() { // Setup without account contracts. We are not using authwits here, so dummy accounts are enough let (env, token_contract_address, owner, recipient, _) = - utils::setup_and_mint(/* with_account_contracts */ false); + utils::setup_and_mint_private(/* with_account_contracts */ false); // Add authwit let transfer_amount = 1000; let transfer_private_from_call_interface = @@ -112,7 +112,7 @@ unconstrained fn transfer_private_failure_on_behalf_of_self_non_zero_nonce() { unconstrained fn transfer_private_failure_on_behalf_of_more_than_balance() { // Setup with account contracts. Slower since we actually deploy them, but needed for authwits. let (env, token_contract_address, owner, recipient, mint_amount) = - utils::setup_and_mint(/* with_account_contracts */ true); + utils::setup_and_mint_private(/* with_account_contracts */ true); // Add authwit let transfer_amount = mint_amount + 1; let transfer_private_from_call_interface = @@ -132,7 +132,7 @@ unconstrained fn transfer_private_failure_on_behalf_of_more_than_balance() { unconstrained fn transfer_private_failure_on_behalf_of_other_without_approval() { // Setup with account contracts. Slower since we actually deploy them, but needed for authwits. let (env, token_contract_address, owner, recipient, _) = - utils::setup_and_mint(/* with_account_contracts */ true); + utils::setup_and_mint_private(/* with_account_contracts */ true); // Add authwit let transfer_amount = 1000; let transfer_private_from_call_interface = @@ -147,7 +147,7 @@ unconstrained fn transfer_private_failure_on_behalf_of_other_without_approval() unconstrained fn transfer_private_failure_on_behalf_of_other_wrong_caller() { // Setup with account contracts. Slower since we actually deploy them, but needed for authwits. let (env, token_contract_address, owner, recipient, _) = - utils::setup_and_mint(/* with_account_contracts */ true); + utils::setup_and_mint_private(/* with_account_contracts */ true); // Add authwit let transfer_amount = 1000; let transfer_private_from_call_interface = diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/test/transfer_public.nr b/noir-projects/noir-contracts/contracts/token_contract/src/test/transfer_public.nr index 72a6eb3f029..5dddac32573 100644 --- a/noir-projects/noir-contracts/contracts/token_contract/src/test/transfer_public.nr +++ b/noir-projects/noir-contracts/contracts/token_contract/src/test/transfer_public.nr @@ -7,7 +7,7 @@ use dep::aztec::oracle::random::random; unconstrained fn public_transfer() { // Setup without account contracts. We are not using authwits here, so dummy accounts are enough let (env, token_contract_address, owner, recipient, mint_amount) = - utils::setup_and_mint(/* with_account_contracts */ false); + utils::setup_and_mint_public(/* with_account_contracts */ false); // Transfer tokens let transfer_amount = mint_amount / 10; Token::at(token_contract_address).transfer_public(owner, recipient, transfer_amount, 0).call( @@ -23,7 +23,7 @@ unconstrained fn public_transfer() { unconstrained fn public_transfer_to_self() { // Setup without account contracts. We are not using authwits here, so dummy accounts are enough let (env, token_contract_address, owner, _, mint_amount) = - utils::setup_and_mint(/* with_account_contracts */ false); + utils::setup_and_mint_public(/* with_account_contracts */ false); // Transfer tokens let transfer_amount = mint_amount / 10; // docs:start:call_public @@ -39,7 +39,7 @@ unconstrained fn public_transfer_to_self() { unconstrained fn public_transfer_on_behalf_of_other() { // Setup with account contracts. Slower since we actually deploy them, but needed for authwits. let (env, token_contract_address, owner, recipient, mint_amount) = - utils::setup_and_mint(/* with_account_contracts */ true); + utils::setup_and_mint_public(/* with_account_contracts */ true); let transfer_amount = mint_amount / 10; let public_transfer_from_call_interface = Token::at(token_contract_address).transfer_public(owner, recipient, transfer_amount, 1); @@ -61,7 +61,7 @@ unconstrained fn public_transfer_on_behalf_of_other() { unconstrained fn public_transfer_failure_more_than_balance() { // Setup without account contracts. We are not using authwits here, so dummy accounts are enough let (env, token_contract_address, owner, recipient, mint_amount) = - utils::setup_and_mint(/* with_account_contracts */ false); + utils::setup_and_mint_public(/* with_account_contracts */ false); // Transfer tokens let transfer_amount = mint_amount + 1; let public_transfer_call_interface = @@ -74,7 +74,7 @@ unconstrained fn public_transfer_failure_more_than_balance() { unconstrained fn public_transfer_failure_on_behalf_of_self_non_zero_nonce() { // Setup without account contracts. We are not using authwits here, so dummy accounts are enough let (env, token_contract_address, owner, recipient, mint_amount) = - utils::setup_and_mint(/* with_account_contracts */ false); + utils::setup_and_mint_public(/* with_account_contracts */ false); // Transfer tokens let transfer_amount = mint_amount / 10; let public_transfer_call_interface = Token::at(token_contract_address).transfer_public( @@ -96,7 +96,7 @@ unconstrained fn public_transfer_failure_on_behalf_of_self_non_zero_nonce() { unconstrained fn public_transfer_failure_on_behalf_of_other_without_approval() { // Setup with account contracts. Slower since we actually deploy them, but needed for authwits. let (env, token_contract_address, owner, recipient, mint_amount) = - utils::setup_and_mint(/* with_account_contracts */ true); + utils::setup_and_mint_public(/* with_account_contracts */ true); let transfer_amount = mint_amount / 10; let public_transfer_from_call_interface = Token::at(token_contract_address).transfer_public(owner, recipient, transfer_amount, 1); @@ -110,7 +110,7 @@ unconstrained fn public_transfer_failure_on_behalf_of_other_without_approval() { unconstrained fn public_transfer_failure_on_behalf_of_other_more_than_balance() { // Setup with account contracts. Slower since we actually deploy them, but needed for authwits. let (env, token_contract_address, owner, recipient, mint_amount) = - utils::setup_and_mint(/* with_account_contracts */ true); + utils::setup_and_mint_public(/* with_account_contracts */ true); let transfer_amount = mint_amount + 1; // docs:start:public_authwit let public_transfer_from_call_interface = @@ -131,7 +131,7 @@ unconstrained fn public_transfer_failure_on_behalf_of_other_more_than_balance() unconstrained fn public_transfer_failure_on_behalf_of_other_wrong_caller() { // Setup with account contracts. Slower since we actually deploy them, but needed for authwits. let (env, token_contract_address, owner, recipient, mint_amount) = - utils::setup_and_mint(/* with_account_contracts */ true); + utils::setup_and_mint_public(/* with_account_contracts */ true); let transfer_amount = mint_amount / 10; let public_transfer_from_call_interface = Token::at(token_contract_address).transfer_public(owner, recipient, transfer_amount, 1); diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/test/unshielding.nr b/noir-projects/noir-contracts/contracts/token_contract/src/test/unshielding.nr index ffe3e55b89c..9d7f4f23c1c 100644 --- a/noir-projects/noir-contracts/contracts/token_contract/src/test/unshielding.nr +++ b/noir-projects/noir-contracts/contracts/token_contract/src/test/unshielding.nr @@ -7,20 +7,20 @@ use dep::aztec::oracle::random::random; unconstrained fn unshield_on_behalf_of_self() { // Setup without account contracts. We are not using authwits here, so dummy accounts are enough let (env, token_contract_address, owner, _, mint_amount) = - utils::setup_and_mint(/* with_account_contracts */ false); + utils::setup_and_mint_private(/* with_account_contracts */ false); let unshield_amount = mint_amount / 10; Token::at(token_contract_address).unshield(owner, owner, unshield_amount, 0).call( &mut env.private(), ); utils::check_private_balance(token_contract_address, owner, mint_amount - unshield_amount); - utils::check_public_balance(token_contract_address, owner, mint_amount + unshield_amount); + utils::check_public_balance(token_contract_address, owner, unshield_amount); } #[test] unconstrained fn unshield_on_behalf_of_other() { let (env, token_contract_address, owner, recipient, mint_amount) = - utils::setup_and_mint(/* with_account_contracts */ true); + utils::setup_and_mint_private(/* with_account_contracts */ true); let unshield_amount = mint_amount / 10; let unshield_call_interface = @@ -42,7 +42,7 @@ unconstrained fn unshield_on_behalf_of_other() { unconstrained fn unshield_failure_more_than_balance() { // Setup without account contracts. We are not using authwits here, so dummy accounts are enough let (env, token_contract_address, owner, _, mint_amount) = - utils::setup_and_mint(/* with_account_contracts */ false); + utils::setup_and_mint_private(/* with_account_contracts */ false); let unshield_amount = mint_amount + 1; Token::at(token_contract_address).unshield(owner, owner, unshield_amount, 0).call( @@ -54,7 +54,7 @@ unconstrained fn unshield_failure_more_than_balance() { unconstrained fn unshield_failure_on_behalf_of_self_non_zero_nonce() { // Setup without account contracts. We are not using authwits here, so dummy accounts are enough let (env, token_contract_address, owner, _, mint_amount) = - utils::setup_and_mint(/* with_account_contracts */ false); + utils::setup_and_mint_private(/* with_account_contracts */ false); let unshield_amount = mint_amount + 1; Token::at(token_contract_address).unshield(owner, owner, unshield_amount, random()).call( @@ -65,7 +65,7 @@ unconstrained fn unshield_failure_on_behalf_of_self_non_zero_nonce() { #[test(should_fail_with = "Balance too low")] unconstrained fn unshield_failure_on_behalf_of_other_more_than_balance() { let (env, token_contract_address, owner, recipient, mint_amount) = - utils::setup_and_mint(/* with_account_contracts */ true); + utils::setup_and_mint_private(/* with_account_contracts */ true); let unshield_amount = mint_amount + 1; let unshield_call_interface = @@ -84,7 +84,7 @@ unconstrained fn unshield_failure_on_behalf_of_other_more_than_balance() { #[test(should_fail_with = "Authorization not found for message hash")] unconstrained fn unshield_failure_on_behalf_of_other_invalid_designated_caller() { let (env, token_contract_address, owner, recipient, mint_amount) = - utils::setup_and_mint(/* with_account_contracts */ true); + utils::setup_and_mint_private(/* with_account_contracts */ true); let unshield_amount = mint_amount + 1; let unshield_call_interface = @@ -103,7 +103,7 @@ unconstrained fn unshield_failure_on_behalf_of_other_invalid_designated_caller() #[test(should_fail_with = "Authorization not found for message hash")] unconstrained fn unshield_failure_on_behalf_of_other_no_approval() { let (env, token_contract_address, owner, recipient, mint_amount) = - utils::setup_and_mint(/* with_account_contracts */ true); + utils::setup_and_mint_private(/* with_account_contracts */ true); let unshield_amount = mint_amount + 1; let unshield_call_interface = diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/test/utils.nr b/noir-projects/noir-contracts/contracts/token_contract/src/test/utils.nr index c3f93777556..34e731443b8 100644 --- a/noir-projects/noir-contracts/contracts/token_contract/src/test/utils.nr +++ b/noir-projects/noir-contracts/contracts/token_contract/src/test/utils.nr @@ -44,7 +44,19 @@ pub unconstrained fn setup( (&mut env, token_contract_address, owner, recipient) } -pub unconstrained fn setup_and_mint( +pub unconstrained fn setup_and_mint_public( + with_account_contracts: bool, +) -> (&mut TestEnvironment, AztecAddress, AztecAddress, AztecAddress, Field) { + // Setup + let (env, token_contract_address, owner, recipient) = setup(with_account_contracts); + let mint_amount = 10000; + // Mint some tokens + Token::at(token_contract_address).mint_public(owner, mint_amount).call(&mut env.public()); + + (env, token_contract_address, owner, recipient, mint_amount) +} + +pub unconstrained fn setup_and_mint_private( with_account_contracts: bool, ) -> (&mut TestEnvironment, AztecAddress, AztecAddress, AztecAddress, Field) { // Setup @@ -54,10 +66,6 @@ pub unconstrained fn setup_and_mint( let secret = random(); let secret_hash = compute_secret_hash(secret); Token::at(token_contract_address).mint_private(mint_amount, secret_hash).call(&mut env.public()); - Token::at(token_contract_address).mint_public(owner, mint_amount).call(&mut env.public()); - - // Time travel so we can read keys from the registry - env.advance_block_by(6); // docs:start:txe_test_add_note // We need to manually add the note to TXE because `TransparentNote` does not support automatic note log delivery. diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/types/balance_set.nr b/noir-projects/noir-contracts/contracts/token_contract/src/types/balance_set.nr index 0c854f2eaf9..505b19653e1 100644 --- a/noir-projects/noir-contracts/contracts/token_contract/src/types/balance_set.nr +++ b/noir-projects/noir-contracts/contracts/token_contract/src/types/balance_set.nr @@ -1,7 +1,9 @@ use dep::aztec::{ context::{PrivateContext, UnconstrainedContext}, note::note_emission::OuterNoteEmission, - protocol_types::{constants::MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, public_keys::NpkM}, + protocol_types::{ + address::AztecAddress, constants::MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, public_keys::NpkM, + }, }; use dep::aztec::prelude::{NoteGetterOptions, NoteViewerOptions, PrivateSet}; use dep::uint_note::uint_note::UintNote; @@ -42,12 +44,12 @@ impl BalanceSet { } impl BalanceSet<&mut PrivateContext> { - pub fn add(self: Self, owner_npk_m: NpkM, addend: U128) -> OuterNoteEmission { + pub fn add(self: Self, owner: AztecAddress, addend: U128) -> OuterNoteEmission { if addend == U128::from_integer(0) { OuterNoteEmission::new(Option::none()) } else { // We fetch the nullifier public key hash from the registry / from our PXE - let mut addend_note = UintNote::new(addend, owner_npk_m.hash()); + let mut addend_note = UintNote::new(addend, owner); // docs:start:insert OuterNoteEmission::new(Option::some(self.set.insert(&mut addend_note))) @@ -55,13 +57,13 @@ impl BalanceSet<&mut PrivateContext> { } } - pub fn sub(self: Self, owner_npk_m: NpkM, amount: U128) -> OuterNoteEmission { + pub fn sub(self: Self, owner: AztecAddress, amount: U128) -> OuterNoteEmission { let subtracted = self.try_sub(amount, MAX_NOTE_HASH_READ_REQUESTS_PER_CALL); // try_sub may have substracted more or less than amount. We must ensure that we subtracted at least as much as // we needed, and then create a new note for the owner for the change (if any). assert(subtracted >= amount, "Balance too low"); - self.add(owner_npk_m, subtracted - amount) + self.add(owner, subtracted - amount) } // Attempts to remove 'target_amount' from the owner's balance. try_sub returns how much was actually subtracted diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr index a3b3c16c11f..1e61784737f 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr @@ -479,7 +479,7 @@ global TUBE_PROOF_LENGTH: u32 = RECURSIVE_PROOF_LENGTH; // in the future these c global HONK_VERIFICATION_KEY_LENGTH_IN_FIELDS: u32 = 128; -global CLIENT_IVC_VERIFICATION_KEY_LENGTH_IN_FIELDS: u32 = 145; +global CLIENT_IVC_VERIFICATION_KEY_LENGTH_IN_FIELDS: u32 = 143; // VK is composed of // - circuit size encoded as a fr field element (32 bytes) // - num of inputs encoded as a fr field element (32 bytes) diff --git a/scripts/ci/get_e2e_jobs.sh b/scripts/ci/get_e2e_jobs.sh index ffd09503d2e..cc8468935ba 100755 --- a/scripts/ci/get_e2e_jobs.sh +++ b/scripts/ci/get_e2e_jobs.sh @@ -7,46 +7,54 @@ cd "$(dirname "$0")"/../.. BRANCH=$1 LABELS=$2 +# Function to parse YAML and extract test names +get_test_names() { + yq e '.tests | keys | .[]' yarn-project/end-to-end/scripts/e2e_test_config.yml +} + +# Read the full list from the YAML file +full_list=$(get_test_names) + # Define the jobs that will run on every PR allow_list=( - "e2e-2-pxes" - "e2e-authwit" - "e2e-avm-simulator" - "e2e-block-building" - "e2e-cross-chain-messaging" - "e2e-deploy-contract" - "e2e-fees" - "e2e-fees-gas-estimation" - "e2e-fees-private-payments" - "e2e-max-block-number" - "e2e-nested-contract" - "e2e-ordering" - "e2e-static-calls" - "integration-l1-publisher" - "e2e-cheat-codes" - "e2e-prover-fake-proofs" - "e2e-prover-coordination" - "e2e-lending-contract" - "kind-network-smoke" + "e2e_2_pxes" + "e2e_authwit" + "e2e_avm_simulator" + "e2e_block_building" + "e2e_cross_chain_messaging" + "e2e_deploy_contract" + "e2e_fees" + "e2e_fees_gas_estimation" + "e2e_fees_private_payments" + "e2e_max_block_number" + "e2e_nested_contract" + "e2e_ordering" + "e2e_static_calls" + "integration_l1_publisher" + "e2e_cheat_codes" + "e2e_prover_fake_proofs" + "e2e_prover_coordination" + "e2e_lending_contract" + "kind_network_smoke" ) # Add labels from input to the allow_list -IFS=',' read -r -a input_labels <<< "$LABELS" +IFS=',' read -r -a input_labels <<<"$LABELS" allow_list+=("${input_labels[@]}") # Generate full list of targets, excluding specific entries, on one line -full_list=$(earthly ls ./yarn-project/end-to-end | grep -v '+base' | grep -v '+bench' | grep -v "+network" | grep -v 'devnet' | sed 's/+//' | xargs echo) +test_list=$(echo "${full_list[@]}" | grep -v 'base' | grep -v 'bench' | grep -v "network" | grep -v 'devnet' | xargs echo) -# If branch is master or allow_list contains 'e2e-all', return full list +# # If branch is master or allow_list contains 'e2e-all', return full list if [[ "$BRANCH" == "master" ]] || [[ " ${allow_list[@]} " =~ "e2e-all" ]]; then # print as JSON list - echo "$full_list" | jq -Rc 'split(" ")' + echo "$test_list" | jq -Rc 'split(" ")' exit 0 fi -# Filter the full_list to include only items in the allow_list +# # Filter the test_list to include only items in the allow_list filtered_list=() -for item in $full_list; do +for item in $test_list; do for allowed in "${allow_list[@]}"; do if [[ "$item" == "$allowed" ]]; then filtered_list+=("$item") @@ -54,5 +62,5 @@ for item in $full_list; do done done -# Print the filtered list in JSON format +# # Print the filtered list in JSON format echo ${filtered_list[@]} | jq -Rc 'split(" ")' diff --git a/scripts/ci/select_runner.sh b/scripts/ci/select_runner.sh new file mode 100755 index 00000000000..a4db64dbd99 --- /dev/null +++ b/scripts/ci/select_runner.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +# Check if the test requires a prover +requires_prover() { + local test_name=$1 + [[ $test_name == *"prover"* ]] +} + +test_name=$1 + +if requires_prover "$test_name"; then + echo "64core-tester-x86" +else + if [[ $test_name == *"bench"* ]]; then + echo "16core-tester-x86" + else + echo "8core-tester-x86" + fi +fi diff --git a/spartan/chaos-mesh/Chart.yaml b/spartan/chaos-mesh/Chart.yaml index e1bb55990f0..c24b7e2e92b 100644 --- a/spartan/chaos-mesh/Chart.yaml +++ b/spartan/chaos-mesh/Chart.yaml @@ -1,6 +1,6 @@ apiVersion: v2 -name: chaos-mesh -description: A Helm chart for Kubernetes with chaos-mesh +name: chaos +description: A Helm chart for Kubernetes with chaos type: application version: 0.1.0 diff --git a/spartan/chaos-mesh/install.sh b/spartan/chaos-mesh/install.sh index e89ba671c90..53a9e4793c1 100755 --- a/spartan/chaos-mesh/install.sh +++ b/spartan/chaos-mesh/install.sh @@ -4,4 +4,4 @@ helm repo add chaos-mesh https://charts.chaos-mesh.org helm dependency update -helm upgrade chaos-mesh . -n chaos-mesh --install --create-namespace --atomic \ No newline at end of file +helm upgrade chaos . -n chaos-mesh --install --create-namespace --atomic \ No newline at end of file diff --git a/spartan/chaos-mesh/values.yaml b/spartan/chaos-mesh/values.yaml index c2b58cc4324..9a91dedaf47 100644 --- a/spartan/chaos-mesh/values.yaml +++ b/spartan/chaos-mesh/values.yaml @@ -9,4 +9,16 @@ chaos-mesh: subPath: "" # Disable security mode when running locally, DO NOT DEPLOY THIS CHART IN PRODUCTION + # We disable locally so the local dashboard does not require configuring authentication securityMode: false + + chaosDaemon: + privileged: true + runtime: "containerd" + socketPath: "/run/containerd/containerd.sock" + + dnsServer: + create: true + + podSecurityPolicy: + enabled: false diff --git a/spartan/network-shaping/Chart.yaml b/spartan/network-shaping/Chart.yaml new file mode 100644 index 00000000000..854dc4672e8 --- /dev/null +++ b/spartan/network-shaping/Chart.yaml @@ -0,0 +1,6 @@ +apiVersion: v2 +name: network-shaping +description: Network shaping for spartan using chaos-mesh +type: application +version: 0.1.0 +appVersion: "1.0.0" \ No newline at end of file diff --git a/spartan/network-shaping/scripts/apply_network_shaping.sh b/spartan/network-shaping/scripts/apply_network_shaping.sh new file mode 100644 index 00000000000..becb34cf163 --- /dev/null +++ b/spartan/network-shaping/scripts/apply_network_shaping.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +helm upgrade chaos-mesh . -n chaos-mesh --install --atomic \ No newline at end of file diff --git a/spartan/network-shaping/scripts/stop_experiments.sh b/spartan/network-shaping/scripts/stop_experiments.sh new file mode 100755 index 00000000000..ae748f1036b --- /dev/null +++ b/spartan/network-shaping/scripts/stop_experiments.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +# Delete all actively running chaos experiments +kubectl delete networkchaos,podchaos,iochaos,httpchaos --all --all-namespaces \ No newline at end of file diff --git a/spartan/network-shaping/templates/_helpers.tpl b/spartan/network-shaping/templates/_helpers.tpl new file mode 100644 index 00000000000..2239bfc3a7e --- /dev/null +++ b/spartan/network-shaping/templates/_helpers.tpl @@ -0,0 +1,33 @@ +{{/* +Create a default fully qualified app name. +*/}} +{{- define "network-shaping.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "chaos-mesh.selectorLabels" -}} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "network-shaping.labels" -}} +app.kubernetes.io/name: {{ include "network-shaping.fullname" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} diff --git a/spartan/network-shaping/templates/network-chaos.yaml b/spartan/network-shaping/templates/network-chaos.yaml new file mode 100644 index 00000000000..f18ee2b8d71 --- /dev/null +++ b/spartan/network-shaping/templates/network-chaos.yaml @@ -0,0 +1,74 @@ +{{- if .Values.networkShaping.enabled }} +{{- if .Values.networkShaping.conditions.latency.enabled }} +--- +apiVersion: chaos-mesh.org/v1alpha1 +kind: NetworkChaos +metadata: + name: {{ .Values.global.namespace }}-latency + namespace: {{ .Values.global.chaosMeshNamespace }} + labels: + {{- include "network-shaping.labels" . | nindent 4 }} + annotations: + "helm.sh/hook": post-install,post-upgrade + "helm.sh/hook-weight": "0" + "helm.sh/resource-policy": keep +spec: + action: delay + mode: all + selector: + namespaces: + - {{ .Values.global.targetNamespace }} + delay: + {{- toYaml .Values.networkShaping.conditions.latency.delay | nindent 4 }} + duration: 8760h # 1 year +{{- end }} + +{{- if .Values.networkShaping.conditions.bandwidth.enabled }} +--- +apiVersion: chaos-mesh.org/v1alpha1 +kind: NetworkChaos +metadata: + name: {{ .Values.global.namespace }}-bandwidth + namespace: {{ .Values.global.chaosMeshNamespace }} + labels: + {{- include "network-shaping.labels" . | nindent 4 }} + annotations: + "helm.sh/hook": post-install,post-upgrade + "helm.sh/hook-weight": "0" + "helm.sh/resource-policy": keep +spec: + action: bandwidth + mode: all + selector: + namespaces: + - {{ .Values.global.targetNamespace }} + bandwidth: + rate: {{ .Values.networkShaping.conditions.bandwidth.rate }} + limit: {{ .Values.networkShaping.conditions.bandwidth.limit }} + buffer: {{ .Values.networkShaping.conditions.bandwidth.buffer }} + duration: 8760h +{{- end }} + +{{- if .Values.networkShaping.conditions.packetLoss.enabled }} +--- +apiVersion: chaos-mesh.org/v1alpha1 +kind: NetworkChaos +metadata: + name: {{ .Values.global.namespace }}-packet-loss + namespace: {{ .Values.global.chaosMeshNamespace }} + labels: + {{- include "network-shaping.labels" . | nindent 4 }} + annotations: + "helm.sh/resource-policy": keep +spec: + action: loss + mode: all + selector: + namespaces: + - {{ .Values.global.targetNamespace }} + loss: + loss: {{ .Values.networkShaping.conditions.packetLoss.loss | quote }} + correlation: {{ .Values.networkShaping.conditions.packetLoss.correlation | quote }} + duration: 8760h +{{- end }} +{{- end }} \ No newline at end of file diff --git a/spartan/network-shaping/values.yaml b/spartan/network-shaping/values.yaml new file mode 100644 index 00000000000..4518c645fbe --- /dev/null +++ b/spartan/network-shaping/values.yaml @@ -0,0 +1,102 @@ +global: + # When deploying, override the namespace to where spartan will deploy to, this will apply all chaos experiments to all pods within that namespace + # run deployment with --values global.namespace=your-namespace + targetNamespace: smoke + chaosMeshNamespace: chaos-mesh + +# Network shaping configuration +networkShaping: + # Master switch to enable network shaping + enabled: true + + # Default settings + defaultSettings: + mode: all + # Set duration to 1 year so the the experiment will run indefinitely unless overridden + duration: 8760h + + # Network conditions to apply + conditions: + # Latency Simulation + latency: + # Enable / disable latency configuration + enabled: false + delay: + # Base latency of all network traffic + # can be defined in ms / s + latency: "100ms" + + # Random variation in latency + # Actual will be latency +- jitter + jitter: "50ms" + + # Correlation + # This means previous delays will impact the immediate next delay + # Eg: 75 means the current delay will be 75% influenced by the previous delay + correlation: "75" + + + packetLoss: + # Enable / disable packet loss configuration + enabled: false + # Packet drop percentage + # 2 = 2% of packets will disappear into the ether + loss: "2" + + # Correlation + # Higher values mean packet losses happen in bursts + # 25 = 25% influenced by the previous loss + correlation: "25" + + bandwidth: + # Enable / disable bandwidth configuration + enabled: false + + # Target bandwidth rate + # kbps, mbps, gbps + rate: "1024kbps" + + # Burst size, buffer to allow before bandwidth limiting is applied + # Not a string! + limit: 20971520 + + # Buffer = smoother bandwidth restriction but higher memory usage + buffer: 1000 + + + +## Here are some exciting example configurations created by claude: +# Example use cases for different configurations: + +# High latency network simulation (e.g., satellite) +# latency: +# enabled: true +# delay: +# latency: 500ms +# jitter: 50ms +# correlation: "75" + +# Mobile network simulation (3G) +# bandwidth: +# enabled: true +# rate: 1500kbps +# limit: 1500kb +# buffer: 1000 +# latency: +# enabled: true +# delay: +# latency: 100ms +# jitter: 40ms +# correlation: "75" + +# Unreliable network simulation +# packetLoss: +# enabled: true +# loss: "5" +# correlation: "75" +# latency: +# enabled: true +# delay: +# latency: 150ms +# jitter: 30ms +# correlation: "75" \ No newline at end of file diff --git a/spartan/network-shaping/values/hard.yaml b/spartan/network-shaping/values/hard.yaml new file mode 100644 index 00000000000..e7c1c201cc0 --- /dev/null +++ b/spartan/network-shaping/values/hard.yaml @@ -0,0 +1,25 @@ +# Simulates global network conditions +# High latency, moderate bandwidth +global: + namespace: "smoke" + +networkShaping: + enabled: true + conditions: + latency: + enabled: true + delay: + # Global network latency (e.g., intercontinental) + latency: 200ms + jitter: 40ms + correlation: "75" + bandwidth: + enabled: true + # 20Mbps + rate: 20mbps + limit: 10000000 # 10 MB + buffer: 4000 + packetLoss: + enabled: true + loss: "1" + correlation: "70" \ No newline at end of file diff --git a/spartan/network-shaping/values/mild.yaml b/spartan/network-shaping/values/mild.yaml new file mode 100644 index 00000000000..f125d10b10b --- /dev/null +++ b/spartan/network-shaping/values/mild.yaml @@ -0,0 +1,25 @@ + +# Moderate latency, very high bandwidth +global: + namespace: "smoke" + +networkShaping: + enabled: true + conditions: + latency: + enabled: true + delay: + # Typical datacenter-to-datacenter latency + latency: 50ms + jitter: 10ms + correlation: "75" + bandwidth: + enabled: true + # 100Mbps + rate: 100mbps + limit: 50000000 # 50 MB + buffer: 8000 + packetLoss: + enabled: true + loss: "0.1" + correlation: "50" diff --git a/spartan/network-shaping/values/moderate.yaml b/spartan/network-shaping/values/moderate.yaml new file mode 100644 index 00000000000..a32d4a09ff5 --- /dev/null +++ b/spartan/network-shaping/values/moderate.yaml @@ -0,0 +1,25 @@ +# Simulates regional network conditions +# Higher latency, good bandwidth +global: + namespace: "smoke" + +networkShaping: + enabled: true + conditions: + latency: + enabled: true + delay: + # Regional network latency (e.g., cross-country) + latency: 100ms + jitter: 20ms + correlation: "75" + bandwidth: + enabled: true + # 50Mbps + rate: 50mbps + limit: 25000000 # 25 MB + buffer: 5000 + packetLoss: + enabled: true + loss: "0.5" + correlation: "60" \ No newline at end of file diff --git a/spartan/network-shaping/values/rough.yaml b/spartan/network-shaping/values/rough.yaml new file mode 100644 index 00000000000..968826ccbcc --- /dev/null +++ b/spartan/network-shaping/values/rough.yaml @@ -0,0 +1,25 @@ +# Simulates congested network conditions +# High latency, limited bandwidth, packet loss +global: + namespace: "smoke" + +networkShaping: + enabled: true + conditions: + latency: + enabled: true + delay: + # Congested network latency + latency: 300ms + jitter: 100ms + correlation: "80" + bandwidth: + enabled: true + # 5Mbps + rate: 5mbps + limit: 2000000 # 2 MB + buffer: 2000 + packetLoss: + enabled: true + loss: "2" + correlation: "75" \ No newline at end of file diff --git a/yarn-project/circuits.js/src/constants.gen.ts b/yarn-project/circuits.js/src/constants.gen.ts index 29c6cc91ae3..32813affa18 100644 --- a/yarn-project/circuits.js/src/constants.gen.ts +++ b/yarn-project/circuits.js/src/constants.gen.ts @@ -221,7 +221,7 @@ export const RECURSIVE_PROOF_LENGTH = 463; export const NESTED_RECURSIVE_PROOF_LENGTH = 463; export const TUBE_PROOF_LENGTH = 463; export const HONK_VERIFICATION_KEY_LENGTH_IN_FIELDS = 128; -export const CLIENT_IVC_VERIFICATION_KEY_LENGTH_IN_FIELDS = 145; +export const CLIENT_IVC_VERIFICATION_KEY_LENGTH_IN_FIELDS = 143; export const AVM_VERIFICATION_KEY_LENGTH_IN_FIELDS = 86; export const AVM_PROOF_LENGTH_IN_FIELDS = 4166; export const AVM_PUBLIC_COLUMN_MAX_SIZE = 1024; diff --git a/yarn-project/end-to-end/Earthfile b/yarn-project/end-to-end/Earthfile deleted file mode 100644 index bafa08e967d..00000000000 --- a/yarn-project/end-to-end/Earthfile +++ /dev/null @@ -1,295 +0,0 @@ -VERSION 0.8 - -# Flakey, TODO(https://github.com/AztecProtocol/aztec-packages/issues/9164) -# e2e-p2p: -# LOCALLY -# RUN ./scripts/e2e_test.sh ./src/e2e_p2p/ --runInBand - -e2e-l1-with-wall-time: - LOCALLY - RUN ./scripts/e2e_test.sh ./src/e2e_l1_with_wall_time.test.ts - -e2e-synching: - LOCALLY - RUN ./scripts/e2e_test.sh ./src/e2e_synching.test.ts - -e2e-2-pxes: - LOCALLY - RUN ./scripts/e2e_test.sh ./src/e2e_2_pxes.test.ts - -e2e-nft: - LOCALLY - RUN ./scripts/e2e_test.sh ./src/e2e_nft.test.ts - -e2e-prover-full: - LOCALLY - RUN HARDWARE_CONCURRENCY=${HARDWARE_CONCURRENCY:-32} ./scripts/e2e_test.sh ./src/e2e_prover/full - -e2e-prover-fake-proofs: - LOCALLY - RUN FAKE_PROOFS=1 ./scripts/e2e_test.sh ./src/e2e_prover/full - -e2e-prover-coordination: - LOCALLY - RUN ./scripts/e2e_test.sh ./src/prover-coordination - -e2e-account-contracts: - LOCALLY - RUN ./scripts/e2e_test.sh ./src/e2e_account_contracts.test.ts - -e2e-authwit: - LOCALLY - RUN ./scripts/e2e_test.sh ./src/e2e_authwit.test.ts - -e2e-avm-simulator: - LOCALLY - RUN ./scripts/e2e_test.sh ./src/e2e_avm_simulator.test.ts - -e2e-blacklist-token-contract: - LOCALLY - RUN ./scripts/e2e_test.sh ./src/e2e_blacklist_token_contract - -e2e-block-building: - LOCALLY - RUN ./scripts/e2e_test.sh ./src/e2e_block_building.test.ts - -e2e-bot: - LOCALLY - RUN ./scripts/e2e_test.sh ./src/e2e_bot.test.ts - -e2e-card-game: - LOCALLY - RUN ./scripts/e2e_test.sh ./src/e2e_card_game.test.ts - -e2e-cheat-codes: - LOCALLY - RUN ./scripts/e2e_test.sh ./src/e2e_cheat_codes.test.ts - -e2e-crowdfunding-and-claim: - LOCALLY - RUN ./scripts/e2e_test.sh ./src/e2e_crowdfunding_and_claim.test.ts - -e2e-deploy-contract: - LOCALLY - RUN ./scripts/e2e_test.sh ./src/e2e_deploy_contract - -e2e-escrow-contract: - LOCALLY - RUN ./scripts/e2e_test.sh ./src/e2e_escrow_contract.test.ts - -e2e-keys: - LOCALLY - RUN ./scripts/e2e_test.sh ./src/e2e_keys.test.ts - -e2e-lending-contract: - LOCALLY - RUN ./scripts/e2e_test.sh ./src/e2e_lending_contract.test.ts - -e2e-max-block-number: - LOCALLY - RUN ./scripts/e2e_test.sh ./src/e2e_max_block_number.test.ts - -e2e-multiple-accounts-1-enc-key: - LOCALLY - RUN ./scripts/e2e_test.sh ./src/e2e_multiple_accounts_1_enc_key.test.ts - -e2e-nested-contract: - LOCALLY - RUN ./scripts/e2e_test.sh ./src/e2e_nested_contract - -e2e-non-contract-account: - LOCALLY - RUN ./scripts/e2e_test.sh ./src/e2e_non_contract_account.test.ts - -e2e-note-getter: - LOCALLY - RUN ./scripts/e2e_test.sh ./src/e2e_note_getter.test.ts - -e2e-ordering: - LOCALLY - RUN ./scripts/e2e_test.sh ./src/e2e_ordering.test.ts - -e2e-outbox: - LOCALLY - RUN ./scripts/e2e_test.sh ./src/e2e_outbox.test.ts - -e2e-pending-note-hashes-contract: - LOCALLY - RUN ./scripts/e2e_test.sh ./src/e2e_pending_note_hashes_contract.test.ts - -e2e-private-voting-contract: - LOCALLY - RUN ./scripts/e2e_test.sh ./src/e2e_private_voting_contract.test.ts - -e2e-fees-private-payments: - LOCALLY - RUN ./scripts/e2e_test.sh ./src/e2e_fees/private_payments.test.ts - -e2e-fees-private-refunds: - LOCALLY - RUN ./scripts/e2e_test.sh ./src/e2e_fees/private_refunds.test.ts - -e2e-fees-gas-estimation: - LOCALLY - RUN ./scripts/e2e_test.sh ./src/e2e_fees/gas_estimation.test.ts - -e2e-fees-dapp-subscription: - LOCALLY - RUN ./scripts/e2e_test.sh ./src/e2e_fees/dapp_subscription.test.ts - -e2e-fees-failures: - LOCALLY - RUN ./scripts/e2e_test.sh ./src/e2e_fees/failures.test.ts - -e2e-fees-fee-juice-payments: - LOCALLY - RUN ./scripts/e2e_test.sh ./src/e2e_fees/fee_juice_payments.test.ts - -e2e-fees-account-init: - LOCALLY - RUN ./scripts/e2e_test.sh ./src/e2e_fees/account_init.test.ts - -e2e-cross-chain-messaging: - LOCALLY - RUN ./scripts/e2e_test.sh ./src/e2e_cross_chain_messaging - -e2e-state-vars: - LOCALLY - RUN ./scripts/e2e_test.sh ./src/e2e_state_vars.test.ts - -e2e-logs: - LOCALLY - RUN ./scripts/e2e_test.sh ./src/e2e_event_logs.test.ts - -e2e-static-calls: - LOCALLY - RUN ./scripts/e2e_test.sh ./src/e2e_static_calls.test.ts - -e2e-token-contract: - LOCALLY - RUN ./scripts/e2e_test.sh ./src/e2e_token_contract - -# https://github.com/AztecProtocol/aztec-packages/issues/8925 -# e2e-prover-coordination: -# LOCALLY -# RUN ./scripts/e2e_test.sh ./src/prover-coordination/e2e_json_coordination.test.ts - -e2e-public-testnet: - ARG L1_CHAIN_ID="31337" - # automatically exported as ENV variables for below - ARG ETHEREUM_HOST - ARG SEQ_PUBLISHER_PRIVATE_KEY - ARG PROVER_PUBLISHER_PRIVATE_KEY - LOCALLY - RUN ./scripts/e2e_test_public_testnet.sh ./src/public-testnet - -flakey-e2e-tests: - LOCALLY - RUN ./scripts/e2e_test.sh ./src/flakey || true - -e2e-sandbox-example: - LOCALLY - RUN ./scripts/e2e_compose_test.sh e2e_sandbox_example.test.ts - -uniswap-trade-on-l1-from-l2: - LOCALLY - RUN ./scripts/e2e_compose_test.sh uniswap_trade_on_l1_from_l2.test.ts - -integration-l1-publisher: - LOCALLY - RUN ./scripts/e2e_compose_test.sh integration_l1_publisher.test.ts - -# Disabled, TODO https://github.com/AztecProtocol/aztec-packages/issues/6624 -# integration-proof-verification: -# LOCALLY -# RUN COMPOSE_FILE=./scripts/docker-compose-no-sandbox.yml ./scripts/e2e_compose_test.sh integration_proof_verification.test.ts - -e2e-browser: - LOCALLY - RUN ./scripts/e2e_compose_test.sh e2e_aztec_js_browser.test.ts - -pxe: - LOCALLY - RUN ./scripts/e2e_compose_test.sh pxe.test.ts - -e2e-docs-examples: - LOCALLY - RUN ./scripts/e2e_compose_test.sh docs_examples.test.ts - -guides-writing-an-account-contract: - LOCALLY - RUN ./scripts/e2e_compose_test.sh guides/writing_an_account_contract.test.ts - -guides-dapp-testing: - LOCALLY - RUN ./scripts/e2e_compose_test.sh guides/dapp_testing.test.ts - -# The two tests below need to be separated, because there is some crosstalk between the two. TODO (#8813): Figure out why. -guides-sample-dapp-ci: - LOCALLY - RUN ./scripts/e2e_compose_test.sh sample-dapp/ci/index.test.mjs - -guides-sample-dapp: - LOCALLY - RUN ./scripts/e2e_compose_test.sh sample-dapp/index.test.mjs - -guides-up-quick-start: - LOCALLY - RUN ./scripts/e2e_compose_test.sh guides/up_quick_start.test.ts - -bench-publish-rollup: - LOCALLY - ENV COMPOSE_FILE=scripts/docker-compose-no-sandbox.yml - ENV DEBUG="aztec:benchmarks:*,aztec:sequencer,aztec:sequencer:*,aztec:world_state,aztec:merkle_trees" - ENV HARDWARE_CONCURRENCY=${HARDWARE_CONCURRENCY:-32} - # redundant, but just to be explicit: - ENV PULL_REQUEST=$PULL_REQUEST - ENV BRANCH=$BRANCH - ENV COMMIT_HASH=$COMMIT_HASH - RUN ./scripts/e2e_compose_test.sh benchmarks/bench_publish_rollup.test.ts - DO ../../+UPLOAD_LOGS --PULL_REQUEST=$PULL_REQUEST --BRANCH=$BRANCH --COMMIT_HASH=$COMMIT_HASH - -# TODO(#9359): regressed seemingly after changes to reorgs -#bench-process-history: -# LOCALLY -# ENV COMPOSE_FILE=scripts/docker-compose-no-sandbox.yml -# ENV DEBUG="aztec:benchmarks:*,aztec:sequencer,aztec:sequencer:*,aztec:world_state,aztec:merkle_trees" -# ENV HARDWARE_CONCURRENCY=${HARDWARE_CONCURRENCY:-32} -# # redundant, but just to be explicit: -# ENV PULL_REQUEST=$PULL_REQUEST -# ENV BRANCH=$BRANCH -# ENV COMMIT_HASH=$COMMIT_HASH -# RUN ./scripts/e2e_compose_test.sh benchmarks/bench_process_history.test.ts -# DO ../../+UPLOAD_LOGS --PULL_REQUEST=$PULL_REQUEST --BRANCH=$BRANCH --COMMIT_HASH=$COMMIT_HASH - -bench-tx-size: - LOCALLY - ENV COMPOSE_FILE=scripts/docker-compose-no-sandbox.yml - ENV DEBUG="aztec:benchmarks:*,aztec:sequencer,aztec:sequencer:*,aztec:world_state,aztec:merkle_trees" - ENV HARDWARE_CONCURRENCY=${HARDWARE_CONCURRENCY:-32} - # redundant, but just to be explicit: - ENV PULL_REQUEST=$PULL_REQUEST - ENV BRANCH=$BRANCH - ENV COMMIT_HASH=$COMMIT_HASH - RUN ./scripts/e2e_compose_test.sh benchmarks/bench_tx_size_fees.test.ts - DO ../../+UPLOAD_LOGS --PULL_REQUEST=$PULL_REQUEST --BRANCH=$BRANCH --COMMIT_HASH=$COMMIT_HASH - -bench-prover: - LOCALLY - ENV COMPOSE_FILE=scripts/docker-compose-no-sandbox.yml - ENV DEBUG="aztec:benchmarks:*,aztec:sequencer,aztec:sequencer:*,aztec:world_state,aztec:merkle_trees" - ENV HARDWARE_CONCURRENCY=${HARDWARE_CONCURRENCY:-32} - # redundant, but just to be explicit: - ENV PULL_REQUEST=$PULL_REQUEST - ENV BRANCH=$BRANCH - ENV COMMIT_HASH=$COMMIT_HASH - RUN ./scripts/e2e_compose_test.sh bench_prover - DO ../../+UPLOAD_LOGS --PULL_REQUEST=$PULL_REQUEST --BRANCH=$BRANCH --COMMIT_HASH=$COMMIT_HASH - -e2e-devnet-smoke: - LOCALLY - RUN COMPOSE_FILE=scripts/docker-compose-devnet.yml ./scripts/e2e_compose_test.sh devnet/e2e_smoke.test.ts - -e2e-cli-wallet: - LOCALLY - RUN COMPOSE_FILE=scripts/docker-compose-wallet.yml ./scripts/e2e_compose_test.sh e2e_cli_wallet diff --git a/yarn-project/end-to-end/scripts/e2e_compose_test.sh b/yarn-project/end-to-end/scripts/e2e_compose_test.sh index eb3e419f614..531230b83a6 100755 --- a/yarn-project/end-to-end/scripts/e2e_compose_test.sh +++ b/yarn-project/end-to-end/scripts/e2e_compose_test.sh @@ -23,9 +23,9 @@ export AZTEC_DOCKER_TAG="${AZTEC_DOCKER_TAG:-$(git rev-parse HEAD)}" # Set the ARCH_TAG variable for docker compose ARCH=$(uname -m) if [ "$ARCH" = "arm64" ] || [ "$ARCH" = "aarch64" ]; then - export ARCH_TAG="arm64" + export ARCH_TAG="arm64" else - export ARCH_TAG="amd64" + export ARCH_TAG="amd64" fi FORCE_BUILD="${FORCE_BUILD:-true}" @@ -34,15 +34,15 @@ FORCE_BUILD="${FORCE_BUILD:-true}" export JOB_NAME=$(echo "$TEST" | sed 's/\./_/g' | sed 's/\//_/g') # Determine CMD -if docker compose > /dev/null 2>&1; then +if docker compose >/dev/null 2>&1; then CMD="docker compose" else CMD="docker-compose" fi # Optimize image building -if ! docker image ls --format '{{.Repository}}:{{.Tag}}' | grep -q "aztecprotocol/aztec:$AZTEC_DOCKER_TAG" || \ - ! docker image ls --format '{{.Repository}}:{{.Tag}}' | grep -q "aztecprotocol/end-to-end:$AZTEC_DOCKER_TAG"; then +if ! docker image ls --format '{{.Repository}}:{{.Tag}}' | grep -q "aztecprotocol/aztec:$AZTEC_DOCKER_TAG" || + ! docker image ls --format '{{.Repository}}:{{.Tag}}' | grep -q "aztecprotocol/end-to-end:$AZTEC_DOCKER_TAG"; then echo "Docker images not found. They need to be built with 'earthly ./yarn-project/+export-test-images' or otherwise tagged with aztecprotocol/aztec:$AZTEC_DOCKER_TAG and aztecprotocol/end-to-end:$AZTEC_DOCKER_TAG." exit 1 fi diff --git a/yarn-project/end-to-end/scripts/e2e_test.sh b/yarn-project/end-to-end/scripts/e2e_test.sh index 3dcf49edfac..61871b7bbb0 100755 --- a/yarn-project/end-to-end/scripts/e2e_test.sh +++ b/yarn-project/end-to-end/scripts/e2e_test.sh @@ -3,21 +3,75 @@ # Usage: ./e2e_test.sh <...extra_args> # Optional environment variables: # HARDWARE_CONCURRENCY (default: "") +# FAKE_PROOFS (default: "") +# COMPOSE_FILE (default: "./scripts/docker-compose.yml") set -eu # Main positional parameter -TEST="$1" +export TEST="$1" shift # Default values for environment variables -HARDWARE_CONCURRENCY="${HARDWARE_CONCURRENCY:-}" -FAKE_PROOFS="${FAKE_PROOFS:-}" -AZTEC_DOCKER_TAG=$(git rev-parse HEAD) +export HARDWARE_CONCURRENCY="${HARDWARE_CONCURRENCY:-}" +export FAKE_PROOFS="${FAKE_PROOFS:-}" +export COMPOSE_FILE="${COMPOSE_FILE:-./scripts/docker-compose.yml}" +export AZTEC_DOCKER_TAG=$(git rev-parse HEAD) +# Function to load test configuration +load_test_config() { + local test_name="$1" + yq e ".tests.${test_name}" "$(dirname "$0")/e2e_test_config.yml" +} + +# Check if Docker images exist if ! docker image ls --format '{{.Repository}}:{{.Tag}}' | grep -q "aztecprotocol/end-to-end:$AZTEC_DOCKER_TAG"; then echo "Docker images not found. They need to be built with 'earthly ./yarn-project/+export-end-to-end' or otherwise tagged with aztecprotocol/end-to-end:$AZTEC_DOCKER_TAG." exit 1 fi -docker run -e HARDWARE_CONCURRENCY="$HARDWARE_CONCURRENCY" -e FAKE_PROOFS="$FAKE_PROOFS" --rm aztecprotocol/end-to-end:$AZTEC_DOCKER_TAG "$TEST" $@ +# Load test configuration +test_config=$(load_test_config "$TEST") + +# Determine the test path +test_path=$(echo "$test_config" | yq e '.test_path // ""' -) +if [ -z "$test_path" ]; then + test_path="${TEST}" +fi + +# Check for ignore_failures +ignore_failures=$(echo "$test_config" | yq e '.ignore_failures // false' -) +if [ "$ignore_failures" = "true" ]; then + echo "Ignoring failures for test $TEST" +fi + +# Check if the test uses docker compose +if [ "$(echo "$test_config" | yq e '.use_compose // false' -)" = "true" ]; then + $(dirname "$0")/e2e_compose_test.sh "$test_path" "$@" || [ "$ignore_failures" = "true" ] +else + # Set environment variables + while IFS='=' read -r key value; do + export "$key=$value" + done < <(echo "$test_config" | yq e '.env // {} | to_entries | .[] | .key + "=" + .value' -) + + # Check for custom command + custom_command=$(echo "$test_config" | yq e '.command // ""' -) + env_args=$(echo "$test_config" | yq e '.env // {} | to_entries | .[] | "-e " + .key + "=" + .value' - | tr '\n' ' ') + if [ -n "$custom_command" ]; then + # Run the docker command + docker run \ + -e HARDWARE_CONCURRENCY="$HARDWARE_CONCURRENCY" \ + -e FAKE_PROOFS="$FAKE_PROOFS" \ + $env_args \ + --rm aztecprotocol/end-to-end:$AZTEC_DOCKER_TAG \ + /bin/bash -c "$custom_command" || [ "$ignore_failures" = "true" ] + else + # Run the default docker command + docker run \ + -e HARDWARE_CONCURRENCY="$HARDWARE_CONCURRENCY" \ + -e FAKE_PROOFS="$FAKE_PROOFS" \ + $env_args \ + --rm aztecprotocol/end-to-end:$AZTEC_DOCKER_TAG \ + "$test_path" "$@" || [ "$ignore_failures" = "true" ] + fi +fi diff --git a/yarn-project/end-to-end/scripts/e2e_test_config.yml b/yarn-project/end-to-end/scripts/e2e_test_config.yml new file mode 100644 index 00000000000..2f7c718c14c --- /dev/null +++ b/yarn-project/end-to-end/scripts/e2e_test_config.yml @@ -0,0 +1,126 @@ +tests: + base: {} + bench_prover: + env: + HARDWARE_CONCURRENCY: "32" + COMPOSE_FILE: "scripts/docker-compose-no-sandbox.yml" + DEBUG: "aztec:benchmarks:*,aztec:sequencer,aztec:sequencer:*,aztec:world_state,aztec:merkle_trees" + command: "./scripts/e2e_compose_test.sh bench_prover" + bench_publish_rollup: + env: + HARDWARE_CONCURRENCY: "32" + COMPOSE_FILE: "scripts/docker-compose-no-sandbox.yml" + DEBUG: "aztec:benchmarks:*,aztec:sequencer,aztec:sequencer:*,aztec:world_state,aztec:merkle_trees" + command: "./scripts/e2e_compose_test.sh bench_publish_rollup" + bench_tx_size: + env: + HARDWARE_CONCURRENCY: "32" + COMPOSE_FILE: "scripts/docker-compose-no-sandbox.yml" + DEBUG: "aztec:benchmarks:*,aztec:sequencer,aztec:sequencer:*,aztec:world_state,aztec:merkle_trees" + command: "./scripts/e2e_compose_test.sh bench_tx_size" + e2e_2_pxes: {} + e2e_account_contracts: {} + e2e_authwit: {} + e2e_avm_simulator: {} + e2e_blacklist_token_contract: {} + e2e_block_building: {} + e2e_bot: {} + e2e_aztec_js_browser: + use_compose: true + e2e_card_game: {} + e2e_cheat_codes: {} + e2e_cross_chain_messaging: {} + e2e_crowdfunding_and_claim: {} + e2e_deploy_contract: {} + e2e_devnet_smoke: {} + docs_examples: + use_compose: true + e2e_escrow_contract: {} + e2e_fees_account_init: + test_path: "e2e_fees/account_init.test.ts" + # TODO(https://github.com/AztecProtocol/aztec-packages/issues/9488): reenable + # e2e_fees_dapp_subscription: + # test_path: "e2e_fees/dapp_subscription.test.ts" + e2e_fees_failures: + test_path: "e2e_fees/failures.test.ts" + e2e_fees_fee_juice_payments: + test_path: "e2e_fees/fee_juice_payments.test.ts" + e2e_fees_gas_estimation: + test_path: "e2e_fees/gas_estimation.test.ts" + e2e_fees_private_payments: + test_path: "e2e_fees/private_payments.test.ts" + e2e_fees_private_refunds: + test_path: "e2e_fees/private_refunds.test.ts" + e2e_keys: {} + e2e_l1_with_wall_time: {} + e2e_lending_contract: {} + e2e_event_logs: {} + e2e_max_block_number: {} + e2e_multiple_accounts_1_enc_key: {} + e2e_nested_contract: {} + e2e_nft: {} + e2e_non_contract_account: {} + e2e_note_getter: {} + e2e_ordering: {} + e2e_outbox: {} + e2e_pending_note_hashes_contract: {} + e2e_private_voting_contract: {} + e2e_prover_coordination: {} + e2e_prover_fake_proofs: + test_path: "e2e_prover/full.test.ts" + env: + FAKE_PROOFS: "1" + e2e_prover_full: + test_path: "e2e_prover/full.test.ts" + env: + HARDWARE_CONCURRENCY: "32" + e2e_public_testnet: {} + e2e_sandbox_example: + use_compose: true + e2e_state_vars: {} + e2e_static_calls: {} + e2e_synching: {} + e2e_token_contract: {} + flakey_e2e_tests: + test_path: "./src/flakey" + ignore_failures: true + guides_dapp_testing: + use_compose: true + test_path: "guides/dapp_testing.test.ts" + guides_sample_dapp: + use_compose: true + test_path: "sample-dapp/index.test.mjs" + guides_sample_dapp_ci: + use_compose: true + test_path: "sample-dapp/ci/index.test.mjs" + guides_up_quick_start: + use_compose: true + test_path: "guides/up_quick_start.test.ts" + guides_writing_an_account_contract: + use_compose: true + test_path: "guides/writing_an_account_contract.test.ts" + integration_l1_publisher: + use_compose: true + kind_network_4epochs: + env: + NAMESPACE: "smoke" + FRESH_INSTALL: "true" + VALUES_FILE: "$-default.yaml" + command: "./scripts/network_test.sh ./src/spartan/4epochs.test.ts" + ignore_failures: true + kind_network_smoke: + env: + NAMESPACE: "smoke" + FRESH_INSTALL: "true" + VALUES_FILE: "$-default.yaml" + command: "./scripts/network_test.sh ./src/spartan/smoke.test.ts" + kind_network_transfer: + env: + NAMESPACE: "transfer" + FRESH_INSTALL: "true" + VALUES_FILE: "$-default.yaml" + command: "./scripts/network_test.sh ./src/spartan/smoke.test.ts" + pxe: + use_compose: true + uniswap_trade_on_l1_from_l2: + use_compose: true diff --git a/yarn-project/end-to-end/scripts/network_test.sh b/yarn-project/end-to-end/scripts/network_test.sh index b2a83d4b8ef..c5969fbf1b3 100755 --- a/yarn-project/end-to-end/scripts/network_test.sh +++ b/yarn-project/end-to-end/scripts/network_test.sh @@ -5,6 +5,7 @@ # NAMESPACE # Optional environment variables: # VALUES_FILE (default: "default.yaml") +# INSTALL_CHAOS_MESH (default: "") # CHAOS_VALUES (default: "") # FRESH_INSTALL (default: "false") # AZTEC_DOCKER_TAG (default: current git commit) @@ -25,6 +26,7 @@ fi # Default values for environment variables VALUES_FILE="${VALUES_FILE:-default.yaml}" +INSTALL_CHAOS_MESH="${INSTALL_CHAOS_MESH:-}" CHAOS_VALUES="${CHAOS_VALUES:-}" FRESH_INSTALL="${FRESH_INSTALL:-false}" AZTEC_DOCKER_TAG=${AZTEC_DOCKER_TAG:-$(git rev-parse HEAD)} @@ -61,6 +63,42 @@ function show_status_until_pxe_ready() { done } +# Handle and check chaos mesh setup +handle_network_shaping() { + if [ -n "${CHAOS_VALUES:-}" ]; then + echo "Checking chaos-mesh setup..." + + if ! kubectl get service chaos-daemon -n chaos-mesh &>/dev/null; then + # If chaos mesh is not installed, we check the INSTALL_CHAOS_MESH flag + # to determine if we should install it. + if [ "$INSTALL_CHAOS_MESH" ]; then + echo "Installing chaos-mesh..." + cd "$REPO/spartan/chaos-mesh" && ./install.sh + else + echo "Error: chaos-mesh namespace not found!" + echo "Please set up chaos-mesh first. You can do this by running:" + echo "cd $REPO/spartan/chaos-mesh && ./install.sh" + exit 1 + fi + fi + + echo "Deploying network shaping configuration..." + if ! helm upgrade --install network-shaping "$REPO/spartan/network-shaping/" \ + --namespace chaos-mesh \ + --values "$REPO/spartan/network-shaping/values/$CHAOS_VALUES" \ + --set global.targetNamespace="$NAMESPACE" \ + --wait \ + --timeout=5m; then + echo "Error: failed to deploy network shaping configuration!" + return 1 + fi + + echo "Network shaping configuration applied successfully" + return 0 + fi + return 0 +} + show_status_until_pxe_ready & function cleanup() { @@ -91,6 +129,17 @@ ANVIL_PORT=$(echo $FREE_PORTS | awk '{print $2}') # Namespace variable (assuming it's set) NAMESPACE=${NAMESPACE:-default} +# If we are unable to apply network shaping, as we cannot change existing chaos configurations, then delete existing configurations and try again +if ! handle_network_shaping; then + echo "Deleting existing network chaos experiments..." + kubectl delete networkchaos --all --all-namespaces + + if ! handle_network_shaping; then + echo "Error: failed to apply network shaping configuration!" + exit 1 + fi +fi + # Start port-forwarding with dynamically allocated free ports (kubectl port-forward --namespace $NAMESPACE svc/spartan-aztec-network-pxe $PXE_PORT:8080 2>/dev/null >/dev/null || true) & (kubectl port-forward --namespace $NAMESPACE svc/spartan-aztec-network-ethereum $ANVIL_PORT:8545 2>/dev/null >/dev/null || true) & diff --git a/yarn-project/end-to-end/src/e2e_crowdfunding_and_claim.test.ts b/yarn-project/end-to-end/src/e2e_crowdfunding_and_claim.test.ts index 42af1309103..2470786a0d0 100644 --- a/yarn-project/end-to-end/src/e2e_crowdfunding_and_claim.test.ts +++ b/yarn-project/end-to-end/src/e2e_crowdfunding_and_claim.test.ts @@ -195,7 +195,7 @@ describe('e2e_crowdfunding_and_claim', () => { }, value: uniqueNote.note.items[0], // eslint-disable-next-line camelcase - npk_m_hash: uniqueNote.note.items[1], + owner: uniqueNote.note.items[1], randomness: uniqueNote.note.items[2], }; }; @@ -322,7 +322,7 @@ describe('e2e_crowdfunding_and_claim', () => { .methods.claim(anotherDonationNote, unrelatedWallet.getAddress()) .send() .wait(), - ).rejects.toThrow('Could not find key prefix.'); + ).rejects.toThrow('No public key registered for address'); } }); diff --git a/yarn-project/protocol-contracts/src/protocol_contract_data.ts b/yarn-project/protocol-contracts/src/protocol_contract_data.ts index 11810f96b37..8512d948c85 100644 --- a/yarn-project/protocol-contracts/src/protocol_contract_data.ts +++ b/yarn-project/protocol-contracts/src/protocol_contract_data.ts @@ -55,9 +55,9 @@ export const ProtocolContractLeaf = { ContractClassRegisterer: Fr.fromString('0x147ba3294403576dbad10f86d3ffd4eb83fb230ffbcd5c8b153dd02942d0611f'), MultiCallEntrypoint: Fr.fromString('0x154b701b41d6cf6da7204fef36b2ee9578b449d21b3792a9287bf45eba48fd26'), FeeJuice: Fr.fromString('0x21c9ab2e339c9b3394e4e1ff3b7cf37be4e0fc0bc177a192d287d98963b9b254'), - Router: Fr.fromString('0x2779d7e4ccba389da358a0c9362364d0c65e14cd4d9df929e6722187e808e068'), + Router: Fr.fromString('0x2b0b558e92b7a13cde0a2ecc7570c181a6fbae2bdc6f966cacfc39a784635394'), }; export const protocolContractTreeRoot = Fr.fromString( - '0x00724e4de088411c873c3d6975491eb48889bfa51bc854744a4fcc307ee9abd8', + '0x0d560ad12f14dd5026070bc037ac343535db339212f0904dfc96c4aea4dcc8ab', ); diff --git a/yarn-project/simulator/src/avm/avm_simulator.ts b/yarn-project/simulator/src/avm/avm_simulator.ts index 9a6012ef566..a6dd4c636a1 100644 --- a/yarn-project/simulator/src/avm/avm_simulator.ts +++ b/yarn-project/simulator/src/avm/avm_simulator.ts @@ -6,6 +6,7 @@ import { strict as assert } from 'assert'; import { SideEffectLimitReachedError } from '../public/side_effect_errors.js'; import type { AvmContext } from './avm_context.js'; import { AvmContractCallResult } from './avm_contract_call_result.js'; +import { type Gas } from './avm_gas.js'; import { isAvmBytecode } from './bytecode_utils.js'; import { AvmExecutionError, @@ -17,9 +18,21 @@ import { import type { Instruction } from './opcodes/index.js'; import { decodeFromBytecode } from './serialization/bytecode_serialization.js'; +type OpcodeTally = { + count: number; + gas: Gas; +}; +type PcTally = { + opcode: string; + count: number; + gas: Gas; +}; + export class AvmSimulator { private log: DebugLogger; private bytecode: Buffer | undefined; + public opcodeTallies: Map = new Map(); + public pcTallies: Map = new Map(); constructor(private context: AvmContext) { assert( @@ -79,13 +92,24 @@ export class AvmSimulator { 'AVM attempted to execute non-existent instruction. This should never happen (invalid bytecode or AVM simulator bug)!', ); - const gasLeft = `l2=${machineState.l2GasLeft} da=${machineState.daGasLeft}`; - this.log.debug(`@${machineState.pc} ${instruction.toString()} (${gasLeft})`); + const instrStartGas = machineState.gasLeft; // Save gas before executing instruction (for profiling) + const instrPc = machineState.pc; // Save PC before executing instruction (for profiling) + + this.log.debug( + `@${machineState.pc} ${instruction.toString()} (l2=${machineState.l2GasLeft} da=${machineState.daGasLeft})`, + ); // Execute the instruction. // Normal returns and reverts will return normally here. // "Exceptional halts" will throw. await instruction.execute(this.context); + // gas used by this instruction - used for profiling/tallying + const gasUsed: Gas = { + l2Gas: instrStartGas.l2Gas - machineState.l2GasLeft, + daGas: instrStartGas.daGas - machineState.daGasLeft, + }; + this.tallyInstruction(instrPc, instruction.constructor.name, gasUsed); + if (machineState.pc >= instructions.length) { this.log.warn('Passed end of program'); throw new InvalidProgramCounterError(machineState.pc, /*max=*/ instructions.length); @@ -97,6 +121,8 @@ export class AvmSimulator { const revertReason = reverted ? revertReasonFromExplicitRevert(output, this.context) : undefined; const results = new AvmContractCallResult(reverted, output, revertReason); this.log.debug(`Context execution results: ${results.toString()}`); + + this.printOpcodeTallies(); // Return results for processing by calling context return results; } catch (err: any) { @@ -110,8 +136,45 @@ export class AvmSimulator { // Note: "exceptional halts" cannot return data, hence [] const results = new AvmContractCallResult(/*reverted=*/ true, /*output=*/ [], revertReason); this.log.debug(`Context execution results: ${results.toString()}`); + + this.printOpcodeTallies(); // Return results for processing by calling context return results; } } + + private tallyInstruction(pc: number, opcode: string, gasUsed: Gas) { + const opcodeTally = this.opcodeTallies.get(opcode) || ({ count: 0, gas: { l2Gas: 0, daGas: 0 } } as OpcodeTally); + opcodeTally.count++; + opcodeTally.gas.l2Gas += gasUsed.l2Gas; + opcodeTally.gas.daGas += gasUsed.daGas; + this.opcodeTallies.set(opcode, opcodeTally); + + const pcTally = this.pcTallies.get(pc) || ({ opcode: opcode, count: 0, gas: { l2Gas: 0, daGas: 0 } } as PcTally); + pcTally.count++; + pcTally.gas.l2Gas += gasUsed.l2Gas; + pcTally.gas.daGas += gasUsed.daGas; + this.pcTallies.set(pc, pcTally); + } + + private printOpcodeTallies() { + this.log.debug(`Printing tallies per opcode sorted by gas...`); + // sort descending by L2 gas consumed + const sortedOpcodes = Array.from(this.opcodeTallies.entries()).sort((a, b) => b[1].gas.l2Gas - a[1].gas.l2Gas); + for (const [opcode, tally] of sortedOpcodes) { + // NOTE: don't care to clutter the logs with DA gas for now + this.log.debug(`${opcode} executed ${tally.count} times consuming a total of ${tally.gas.l2Gas} L2 gas`); + } + + this.log.debug(`Printing tallies per PC sorted by #times each PC was executed...`); + const sortedPcs = Array.from(this.pcTallies.entries()) + .sort((a, b) => b[1].count - a[1].count) + .filter((_, i) => i < 20); + for (const [pc, tally] of sortedPcs) { + // NOTE: don't care to clutter the logs with DA gas for now + this.log.debug( + `PC:${pc} containing opcode ${tally.opcode} executed ${tally.count} times consuming a total of ${tally.gas.l2Gas} L2 gas`, + ); + } + } } diff --git a/yarn-project/simulator/src/client/private_execution.test.ts b/yarn-project/simulator/src/client/private_execution.test.ts index b72a52b1861..3b19bed0414 100644 --- a/yarn-project/simulator/src/client/private_execution.test.ts +++ b/yarn-project/simulator/src/client/private_execution.test.ts @@ -401,8 +401,8 @@ describe('Private Execution test suite', () => { ); const notes = [ - buildNote(60n, ownerCompleteAddress.publicKeys.masterNullifierPublicKey.hash(), storageSlot, valueNoteTypeId), - buildNote(80n, ownerCompleteAddress.publicKeys.masterNullifierPublicKey.hash(), storageSlot, valueNoteTypeId), + buildNote(60n, ownerCompleteAddress.address, storageSlot, valueNoteTypeId), + buildNote(80n, ownerCompleteAddress.address, storageSlot, valueNoteTypeId), ]; oracle.getNotes.mockResolvedValue(notes); @@ -468,14 +468,7 @@ describe('Private Execution test suite', () => { const storageSlot = deriveStorageSlotInMap(new Fr(1n), owner); - const notes = [ - buildNote( - balance, - ownerCompleteAddress.publicKeys.masterNullifierPublicKey.hash(), - storageSlot, - valueNoteTypeId, - ), - ]; + const notes = [buildNote(balance, ownerCompleteAddress.address, storageSlot, valueNoteTypeId)]; oracle.getNotes.mockResolvedValue(notes); const consumedNotes = await asyncMap(notes, ({ nonce, note }) =>