diff --git a/.github/workflows/devnet-deploys.yml b/.github/workflows/devnet-deploys.yml index a2b09291c1e..1120fef4628 100644 --- a/.github/workflows/devnet-deploys.yml +++ b/.github/workflows/devnet-deploys.yml @@ -3,6 +3,10 @@ on: push: branches: [devnet] +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + env: DOCKERHUB_PASSWORD: ${{ secrets.DOCKERHUB_PASSWORD }} GIT_COMMIT: ${{ github.sha }} @@ -56,10 +60,10 @@ jobs: aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} aws-region: us-west-2 - - name: Deploy Bootstrap Nodes - working-directory: ./yarn-project/aztec/terraform/node + - name: Deploy P2P Bootstrap Nodes + working-directory: ./yarn-project/p2p-bootstrap/terraform run: | - terraform init -input=false -backend-config="key=devnet/aztec-node" + terraform init -input=false -backend-config="key=devnet/p2p-bootstrap" terraform apply -input=false -auto-approve - name: Deploy Aztec Nodes @@ -67,3 +71,9 @@ jobs: run: | terraform init -input=false -backend-config="key=devnet/aztec-node" terraform apply -input=false -auto-approve + + - name: Deploy Provers + working-directory: ./yarn-project/aztec/terraform/prover + run: | + terraform init -input=false -backend-config="key=devnet/prover" + terraform apply -input=false -auto-approve diff --git a/.vscode/settings.json b/.vscode/settings.json index 86a0427f790..630178ad32a 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -169,4 +169,5 @@ "**/noir/noir-repo/docs/versioned_docs/**": true }, "cmake.sourceDirectory": "${workspaceFolder}/barretenberg/cpp", + "typescript.tsserver.maxTsServerMemory": 4096, } diff --git a/avm-transpiler/src/opcodes.rs b/avm-transpiler/src/opcodes.rs index 11cd956237d..d1e510699e8 100644 --- a/avm-transpiler/src/opcodes.rs +++ b/avm-transpiler/src/opcodes.rs @@ -23,15 +23,15 @@ pub enum AvmOpcode { ADDRESS, STORAGEADDRESS, SENDER, - FEEPERL2GAS, - FEEPERDAGAS, + FUNCTIONSELECTOR, TRANSACTIONFEE, - CONTRACTCALLDEPTH, CHAINID, VERSION, BLOCKNUMBER, TIMESTAMP, COINBASE, + FEEPERL2GAS, + FEEPERDAGAS, BLOCKL2GASLIMIT, BLOCKDAGASLIMIT, CALLDATACOPY, @@ -106,16 +106,16 @@ impl AvmOpcode { AvmOpcode::ADDRESS => "ADDRESS", AvmOpcode::STORAGEADDRESS => "STORAGEADDRESS", AvmOpcode::SENDER => "SENDER", - AvmOpcode::FEEPERL2GAS => "FEEPERL2GAS", - AvmOpcode::FEEPERDAGAS => "FEEPERDAGAS", + AvmOpcode::FUNCTIONSELECTOR => "FUNCTIONSELECTOR", AvmOpcode::TRANSACTIONFEE => "TRANSACTIONFEE", - AvmOpcode::CONTRACTCALLDEPTH => "CONTRACTCALLDEPTH", // Execution Environment - Globals AvmOpcode::CHAINID => "CHAINID", AvmOpcode::VERSION => "VERSION", AvmOpcode::BLOCKNUMBER => "BLOCKNUMBER", AvmOpcode::TIMESTAMP => "TIMESTAMP", AvmOpcode::COINBASE => "COINBASE", + AvmOpcode::FEEPERL2GAS => "FEEPERL2GAS", + AvmOpcode::FEEPERDAGAS => "FEEPERDAGAS", AvmOpcode::BLOCKL2GASLIMIT => "BLOCKL2GASLIMIT", AvmOpcode::BLOCKDAGASLIMIT => "BLOCKDAGASLIMIT", // Execution Environment - Calldata diff --git a/avm-transpiler/src/transpile.rs b/avm-transpiler/src/transpile.rs index 22e5cbcd8ca..f8c0d882bf6 100644 --- a/avm-transpiler/src/transpile.rs +++ b/avm-transpiler/src/transpile.rs @@ -263,8 +263,8 @@ fn handle_foreign_call( "avmOpcodeGetContractInstance" => { handle_get_contract_instance(avm_instrs, destinations, inputs); } - "storageRead" => handle_storage_read(avm_instrs, destinations, inputs), - "storageWrite" => handle_storage_write(avm_instrs, destinations, inputs), + "avmOpcodeStorageRead" => handle_storage_read(avm_instrs, destinations, inputs), + "avmOpcodeStorageWrite" => handle_storage_write(avm_instrs, destinations, inputs), "debugLog" => handle_debug_log(avm_instrs, destinations, inputs), // Getters. _ if inputs.is_empty() && destinations.len() == 1 => { @@ -314,11 +314,9 @@ fn handle_external_call( ValueOrArray::HeapVector(HeapVector { pointer, size }) => (pointer.0 as u32, size.0 as u32), _ => panic!("Call instruction's args input should be a HeapVector input"), }; - let temporary_function_selector_offset = match &inputs[4] { + let function_selector_offset = match &inputs[4] { ValueOrArray::MemoryAddress(offset) => offset.to_usize() as u32, - _ => panic!( - "Call instruction's temporary function selector input should be a basic MemoryAddress", - ), + _ => panic!("Call instruction's function selector input should be a basic MemoryAddress",), }; let ret_offset_maybe = destinations[0]; @@ -351,7 +349,7 @@ fn handle_external_call( AvmOperand::U32 { value: ret_offset }, AvmOperand::U32 { value: ret_size }, AvmOperand::U32 { value: success_offset }, - AvmOperand::U32 { value: temporary_function_selector_offset }, + AvmOperand::U32 { value: function_selector_offset }, ], ..Default::default() }); @@ -650,6 +648,7 @@ fn handle_getter_instruction( "avmOpcodeTimestamp" => AvmOpcode::TIMESTAMP, "avmOpcodeL2GasLeft" => AvmOpcode::L2GASLEFT, "avmOpcodeDaGasLeft" => AvmOpcode::DAGASLEFT, + "avmOpcodeFunctionSelector" => AvmOpcode::FUNCTIONSELECTOR, // "callStackDepth" => AvmOpcode::CallStackDepth, _ => panic!("Transpiler doesn't know how to process ForeignCall function {:?}", function), }; @@ -926,7 +925,7 @@ fn handle_storage_write( inputs: &Vec, ) { assert!(inputs.len() == 2); - assert!(destinations.len() == 1); + assert!(destinations.len() == 0); let slot_offset_maybe = inputs[0]; let slot_offset = match slot_offset_maybe { @@ -992,8 +991,8 @@ fn handle_storage_read( inputs: &Vec, ) { // For the foreign calls we want to handle, we do not want inputs, as they are getters - assert!(inputs.len() == 2); // output, len - but we dont use this len - its for the oracle - assert!(destinations.len() == 1); + assert!(inputs.len() == 1); // storage_slot + assert!(destinations.len() == 1); // return values let slot_offset_maybe = inputs[0]; let slot_offset = match slot_offset_maybe { diff --git a/barretenberg/.gitrepo b/barretenberg/.gitrepo index dd00b977b67..d65386ea822 100644 --- a/barretenberg/.gitrepo +++ b/barretenberg/.gitrepo @@ -6,7 +6,7 @@ [subrepo] remote = https://github.com/AztecProtocol/barretenberg branch = master - commit = 44c9c7e368c0b33a4096a359e7b2b0d45f8bfea1 - parent = c5dc0946f4d300df5c6a70026e102de8e69f020b + commit = c0a5796c6a7664918b3b5bd9a76e63ed61f1f2ce + parent = fa15a450408181ffc50946ee56c4ae0fd8c5a61f method = merge cmdver = 0.4.6 diff --git a/barretenberg/Earthfile b/barretenberg/Earthfile index 73dc1443992..1eb57ff2507 100644 --- a/barretenberg/Earthfile +++ b/barretenberg/Earthfile @@ -42,7 +42,7 @@ barretenberg-acir-tests-bb: RUN FLOW=prove_and_verify_mega_honk_program ./run_acir_tests.sh # Fold and verify an ACIR program stack using ClientIvc RUN FLOW=fold_and_verify_program ./run_acir_tests.sh fold_basic - # Fold and verify an ACIR program stack using ClientIvc, recursively verify as part of the Tube circuit and produce and verify a Honk proof + # Fold and verify an ACIR program stack using ClientIvc, recursively verify as part of the Tube circuit and produce and verify a Honk proof RUN FLOW=prove_then_verify_tube ./run_acir_tests.sh fold_basic # Construct and separately verify a UltraHonk proof for a single program that recursively verifies a Honk proof RUN FLOW=prove_then_verify_ultra_honk ./run_acir_tests.sh verify_honk_proof diff --git a/barretenberg/acir_tests/flows/prove_then_verify_ultra_honk.sh b/barretenberg/acir_tests/flows/prove_then_verify_ultra_honk.sh index fd559e256c6..ac3bb9bc962 100755 --- a/barretenberg/acir_tests/flows/prove_then_verify_ultra_honk.sh +++ b/barretenberg/acir_tests/flows/prove_then_verify_ultra_honk.sh @@ -1,5 +1,5 @@ #!/bin/sh -set -eu +set -eux VFLAG=${VERBOSE:+-v} BFLAG="-b ./target/program.json" diff --git a/barretenberg/acir_tests/reset_acir_tests.sh b/barretenberg/acir_tests/reset_acir_tests.sh index e83bea9189e..dffb4d43837 100755 --- a/barretenberg/acir_tests/reset_acir_tests.sh +++ b/barretenberg/acir_tests/reset_acir_tests.sh @@ -1,7 +1,8 @@ -cd ~/aztec-packages/noir/noir-repo +# Run from barretenberg/acir_tests +cd ../../noir/noir-repo cargo clean noirup -p . cd test_programs && ./rebuild.sh -cd ~/aztec-packages/barretenberg/acir_tests +cd ../../../barretenberg/acir_tests rm -rf acir_tests diff --git a/barretenberg/cpp/pil/avm/constants.pil b/barretenberg/cpp/pil/avm/constants.pil index 6de0cfb9e77..f0f54bd873c 100644 --- a/barretenberg/cpp/pil/avm/constants.pil +++ b/barretenberg/cpp/pil/avm/constants.pil @@ -1,43 +1,45 @@ // NOTE: the constants in this file line up to the indexes of values in the -// `PublicKernelInputs.nr` object +// `PublicCircuitPublicInputs` object namespace constants(256); - // From Public Context Inputs + // From PublicCircuitPublicInputs's CallContext member pol SENDER_SELECTOR = 0; + // "address" actually does not exist in PublicCircuitPublicInputs, + // so this is just an alias to "storage address" for now pol ADDRESS_SELECTOR = 1; - pol STORAGE_ADDRESS_SELECTOR = 2; + pol STORAGE_ADDRESS_SELECTOR = 1; + pol FUNCTION_SELECTOR_SELECTOR = 2; // NOTE: constant expression evaluation does not seem to be supported yet in pil // pol START_GLOBAL_VARIABLES = CALL_CONTEXT_LENGTH + HEADER_LENGTH = 6 + 23 = 29 + // From PublicCircuitPublicInputs's GlobalVariables member // Global Variables pol CHAIN_ID_SELECTOR = 29; pol VERSION_SELECTOR = 30; pol BLOCK_NUMBER_SELECTOR = 31; pol TIMESTAMP_SELECTOR = 32; pol COINBASE_SELECTOR = 33; - - pol END_GLOBAL_VARIABLES = 29 + 8; // We only use the first 5 of 8 global variables for now - - // Gas - // TODO(https://github.com/AztecProtocol/aztec-packages/issues/6715): This has since moved into the global variables + // Global Variables - fees pol FEE_PER_DA_GAS_SELECTOR = 35; pol FEE_PER_L2_GAS_SELECTOR = 36; - pol START_SIDE_EFFECT_COUNTER = 37; + pol END_GLOBAL_VARIABLES = 29 + 8; // We only use the first 5 of 8 global variables for now + // Top-level PublicCircuitPublicInputs members + pol START_SIDE_EFFECT_COUNTER = 37; pol TRANSACTION_FEE_SELECTOR = 40; // Other AVM specific constants pol INTERNAL_CALL_SPACE_ID = 255; // Lengths of kernel output vectors + // (vectors in PublicCircuitPublicInputs to be processed by kernel) // Read requests pol MAX_NULLIFIER_READ_REQUESTS_PER_CALL = 32; pol MAX_NOTE_HASH_READ_REQUESTS_PER_CALL = 32; pol MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL = 32; pol MAX_PUBLIC_DATA_READS_PER_CALL = 32; - // Emitting Data pol MAX_NEW_NOTE_HASHES_PER_CALL = 16; pol MAX_NEW_NULLIIFIERS_PER_CALL = 16; diff --git a/barretenberg/cpp/pil/avm/main.pil b/barretenberg/cpp/pil/avm/main.pil index 19e445d6290..63615604b19 100644 --- a/barretenberg/cpp/pil/avm/main.pil +++ b/barretenberg/cpp/pil/avm/main.pil @@ -17,28 +17,31 @@ namespace main(256); pol constant sel_first = [1] + [0]*; // Used mostly to toggle off the first row consisting // only in first element of shifted polynomials. + //===== PUBLIC COLUMNS========================================================= + pol public calldata; + //===== KERNEL INPUTS ========================================================= // Kernel lookup selector opcodes pol commit sel_q_kernel_lookup; - // CALL CONTEXT - pol commit sel_op_sender; + // CONTEXT - ENVIRONMENT pol commit sel_op_address; pol commit sel_op_storage_address; - - // FEES - pol commit sel_op_fee_per_l2_gas; - pol commit sel_op_fee_per_da_gas; + pol commit sel_op_sender; + pol commit sel_op_function_selector; pol commit sel_op_transaction_fee; - - // GLOBALS + + // CONTEXT - ENVIRONMENT - GLOBALS pol commit sel_op_chain_id; pol commit sel_op_version; pol commit sel_op_block_number; pol commit sel_op_coinbase; pol commit sel_op_timestamp; + // CONTEXT - ENVIRONMENT - GLOBALS - FEES + pol commit sel_op_fee_per_l2_gas; + pol commit sel_op_fee_per_da_gas; - // MACHINE STATE - GAS + // CONTEXT - MACHINE STATE - GAS pol commit sel_op_l2gasleft; pol commit sel_op_dagasleft; @@ -259,9 +262,11 @@ namespace main(256); // Relations on type constraints // TODO: Very likely, we can remove these constraints as the selectors should be derived during // opcode decomposition. - sel_op_sender * (1 - sel_op_sender) = 0; sel_op_address * (1 - sel_op_address) = 0; sel_op_storage_address * (1 - sel_op_storage_address) = 0; + sel_op_sender * (1 - sel_op_sender) = 0; + sel_op_function_selector * (1 - sel_op_function_selector) = 0; + sel_op_transaction_fee * (1 - sel_op_transaction_fee) = 0; sel_op_chain_id * (1 - sel_op_chain_id) = 0; sel_op_version * (1 - sel_op_version) = 0; sel_op_block_number * (1 - sel_op_block_number) = 0; @@ -269,7 +274,6 @@ namespace main(256); sel_op_timestamp * (1 - sel_op_timestamp) = 0; sel_op_fee_per_l2_gas * (1 - sel_op_fee_per_l2_gas) = 0; sel_op_fee_per_da_gas * (1 - sel_op_fee_per_da_gas) = 0; - sel_op_transaction_fee * (1 - sel_op_transaction_fee) = 0; // MACHINE STATE - GAS sel_op_l2gasleft * (1 - sel_op_l2gasleft) = 0; @@ -407,8 +411,9 @@ namespace main(256); //===== KERNEL LOOKUPS ======================================================= pol KERNEL_INPUT_SELECTORS = ( - sel_op_sender + sel_op_address + sel_op_storage_address + sel_op_chain_id + sel_op_version + sel_op_block_number + sel_op_coinbase + - sel_op_timestamp + sel_op_fee_per_l2_gas + sel_op_fee_per_da_gas + sel_op_transaction_fee + sel_op_address + sel_op_storage_address + sel_op_sender + sel_op_function_selector + sel_op_transaction_fee + + sel_op_chain_id + sel_op_version + sel_op_block_number + sel_op_coinbase + sel_op_timestamp + + sel_op_fee_per_l2_gas + sel_op_fee_per_da_gas ); // Ensure that only one kernel lookup is active when the kernel_in_offset is active #[KERNEL_INPUT_ACTIVE_CHECK] @@ -565,27 +570,23 @@ namespace main(256); // We can lookup into a fixed index of this polynomial by including constraints that force the value // of kernel_in_offset to the value relevant to the given opcode that is active - // CALL CONTEXT - #[SENDER_KERNEL] - sel_op_sender * (kernel.kernel_in_offset - constants.SENDER_SELECTOR) = 0; - + // CONTEXT - ENVIRONMENT #[ADDRESS_KERNEL] sel_op_address * (kernel.kernel_in_offset - constants.ADDRESS_SELECTOR) = 0; #[STORAGE_ADDRESS_KERNEL] sel_op_storage_address * (kernel.kernel_in_offset - constants.STORAGE_ADDRESS_SELECTOR) = 0; - // FEES - #[FEE_DA_GAS_KERNEL] - sel_op_fee_per_da_gas * (kernel.kernel_in_offset - constants.FEE_PER_DA_GAS_SELECTOR) = 0; + #[SENDER_KERNEL] + sel_op_sender * (kernel.kernel_in_offset - constants.SENDER_SELECTOR) = 0; - #[FEE_L2_GAS_KERNEL] - sel_op_fee_per_l2_gas * (kernel.kernel_in_offset - constants.FEE_PER_L2_GAS_SELECTOR) = 0; + #[FUNCTION_SELECTOR_KERNEL] + sel_op_function_selector * (kernel.kernel_in_offset - constants.FUNCTION_SELECTOR_SELECTOR) = 0; #[FEE_TRANSACTION_FEE_KERNEL] sel_op_transaction_fee * (kernel.kernel_in_offset - constants.TRANSACTION_FEE_SELECTOR) = 0; - // GLOBALS + // CONTEXT - ENVIRONMENT - GLOBALS #[CHAIN_ID_KERNEL] sel_op_chain_id * (kernel.kernel_in_offset - constants.CHAIN_ID_SELECTOR) = 0; @@ -595,11 +596,18 @@ namespace main(256); #[BLOCK_NUMBER_KERNEL] sel_op_block_number * (kernel.kernel_in_offset - constants.BLOCK_NUMBER_SELECTOR) = 0; + #[TIMESTAMP_KERNEL] + sel_op_timestamp * (kernel.kernel_in_offset - constants.TIMESTAMP_SELECTOR) = 0; + #[COINBASE_KERNEL] sel_op_coinbase * (kernel.kernel_in_offset - constants.COINBASE_SELECTOR) = 0; - #[TIMESTAMP_KERNEL] - sel_op_timestamp * (kernel.kernel_in_offset - constants.TIMESTAMP_SELECTOR) = 0; + // CONTEXT - ENVIRONMENT - GLOBALS - FEES + #[FEE_DA_GAS_KERNEL] + sel_op_fee_per_da_gas * (kernel.kernel_in_offset - constants.FEE_PER_DA_GAS_SELECTOR) = 0; + + #[FEE_L2_GAS_KERNEL] + sel_op_fee_per_l2_gas * (kernel.kernel_in_offset - constants.FEE_PER_L2_GAS_SELECTOR) = 0; // OUTPUTS LOOKUPS // Constrain the value of kernel_out_offset to be the correct offset for the operation being performed diff --git a/barretenberg/cpp/src/CMakeLists.txt b/barretenberg/cpp/src/CMakeLists.txt index be6d254b723..077d20a4c3b 100644 --- a/barretenberg/cpp/src/CMakeLists.txt +++ b/barretenberg/cpp/src/CMakeLists.txt @@ -56,6 +56,7 @@ add_subdirectory(barretenberg/bb) add_subdirectory(barretenberg/circuit_checker) add_subdirectory(barretenberg/client_ivc) add_subdirectory(barretenberg/commitment_schemes) +add_subdirectory(barretenberg/commitment_schemes_recursion) add_subdirectory(barretenberg/common) add_subdirectory(barretenberg/crypto) add_subdirectory(barretenberg/dsl) diff --git a/barretenberg/cpp/src/barretenberg/bb/main.cpp b/barretenberg/cpp/src/barretenberg/bb/main.cpp index 114e2f0caf2..1045d543d21 100644 --- a/barretenberg/cpp/src/barretenberg/bb/main.cpp +++ b/barretenberg/cpp/src/barretenberg/bb/main.cpp @@ -741,18 +741,15 @@ bool avm_verify(const std::filesystem::path& proof_path, const std::filesystem:: #endif /** - * @brief Creates a proof for an ACIR circuit - * - * Communication: - * - stdout: The proof is written to stdout as a byte array - * - Filesystem: The proof is written to the path specified by outputPath + * @brief Create a Honk a prover from program bytecode and an optional witness * - * @param bytecodePath Path to the file containing the serialized circuit - * @param witnessPath Path to the file containing the serialized witness - * @param outputPath Path to write the proof to + * @tparam Flavor + * @param bytecodePath + * @param witnessPath + * @return UltraProver_ */ -template -void prove_honk(const std::string& bytecodePath, const std::string& witnessPath, const std::string& outputPath) +template +UltraProver_ compute_valid_prover(const std::string& bytecodePath, const std::string& witnessPath) { using Builder = Flavor::CircuitBuilder; using Prover = UltraProver_; @@ -762,7 +759,10 @@ void prove_honk(const std::string& bytecodePath, const std::string& witnessPath, honk_recursion = true; } auto constraint_system = get_constraint_system(bytecodePath, honk_recursion); - auto witness = get_witness(witnessPath); + acir_format::WitnessVector witness = {}; + if (!witnessPath.empty()) { + witness = get_witness(witnessPath); + } auto builder = acir_format::create_circuit(constraint_system, 0, witness, honk_recursion); @@ -770,8 +770,29 @@ void prove_honk(const std::string& bytecodePath, const std::string& witnessPath, size_t srs_size = builder.get_circuit_subgroup_size(builder.get_total_circuit_size() + num_extra_gates); init_bn254_crs(srs_size); - // Construct Honk proof Prover prover{ builder }; + return prover; +} + +/** + * @brief Creates a proof for an ACIR circuit + * + * Communication: + * - stdout: The proof is written to stdout as a byte array + * - Filesystem: The proof is written to the path specified by outputPath + * + * @param bytecodePath Path to the file containing the serialized circuit + * @param witnessPath Path to the file containing the serialized witness + * @param outputPath Path to write the proof to + */ +template +void prove_honk(const std::string& bytecodePath, const std::string& witnessPath, const std::string& outputPath) +{ + // using Builder = Flavor::CircuitBuilder; + using Prover = UltraProver_; + + // Construct Honk proof + Prover prover = compute_valid_prover(bytecodePath, witnessPath); auto proof = prover.construct_proof(); if (outputPath == "-") { @@ -807,10 +828,9 @@ template bool verify_honk(const std::string& proof_path, auto g2_data = get_bn254_g2_data(CRS_PATH); srs::init_crs_factory({}, g2_data); auto proof = from_buffer>(read_file(proof_path)); - auto verification_key = std::make_shared(from_buffer(read_file(vk_path))); - verification_key->pcs_verification_key = std::make_shared(); - - Verifier verifier{ verification_key }; + auto vk = std::make_shared(from_buffer(read_file(vk_path))); + vk->pcs_verification_key = std::make_shared(); + Verifier verifier{ vk }; bool verified = verifier.verify_proof(proof); @@ -830,22 +850,12 @@ template bool verify_honk(const std::string& proof_path, */ template void write_vk_honk(const std::string& bytecodePath, const std::string& outputPath) { - using Builder = Flavor::CircuitBuilder; + using Prover = UltraProver_; using ProverInstance = ProverInstance_; using VerificationKey = Flavor::VerificationKey; - bool honk_recursion = false; - if constexpr (IsAnyOf) { - honk_recursion = true; - } - auto constraint_system = get_constraint_system(bytecodePath, honk_recursion); - auto builder = acir_format::create_circuit(constraint_system, 0, {}, honk_recursion); - - auto num_extra_gates = builder.get_num_gates_added_to_ensure_nonzero_polynomials(); - size_t srs_size = builder.get_circuit_subgroup_size(builder.get_total_circuit_size() + num_extra_gates); - init_bn254_crs(srs_size); - - ProverInstance prover_inst(builder); + Prover prover = compute_valid_prover(bytecodePath, ""); + ProverInstance& prover_inst = *prover.instance; VerificationKey vk( prover_inst.proving_key); // uses a partial form of the proving key which only has precomputed entities diff --git a/barretenberg/cpp/src/barretenberg/benchmark/goblin_bench/goblin.bench.cpp b/barretenberg/cpp/src/barretenberg/benchmark/goblin_bench/goblin.bench.cpp deleted file mode 100644 index 5ad7944451a..00000000000 --- a/barretenberg/cpp/src/barretenberg/benchmark/goblin_bench/goblin.bench.cpp +++ /dev/null @@ -1,144 +0,0 @@ - -#include - -#include "barretenberg/common/op_count_google_bench.hpp" -#include "barretenberg/goblin/goblin.hpp" -#include "barretenberg/goblin/mock_circuits.hpp" -#include "barretenberg/stdlib_circuit_builders/ultra_circuit_builder.hpp" - -using namespace benchmark; -using namespace bb; - -namespace { - -class GoblinBench : public benchmark::Fixture { - public: - GoblinAccumulationOutput kernel_accum; - - // Number of function circuits to accumulate(based on Zacs target numbers) - static constexpr size_t NUM_ITERATIONS_MEDIUM_COMPLEXITY = 6; - - void SetUp([[maybe_unused]] const ::benchmark::State& state) override - { - bb::srs::init_crs_factory("../srs_db/ignition"); - bb::srs::init_grumpkin_crs_factory("../srs_db/grumpkin"); - } - - /** - * @brief Perform a specified number of function circuit accumulation rounds - * @details Each round "accumulates" a mock function circuit and a mock kernel circuit. Each round thus consists of - * the generation of two circuits, two MegaHonk proofs and two Merge proofs. To match the sizes called out in the - * spec - * (https://github.com/AztecProtocol/aztec-packages/blob/master/yellow-paper/docs/cryptography/performance-targets.md) - * we set the size of the function circuit to be 2^17 except for the first one which is 2^19. - * - * @param state - */ - void perform_goblin_accumulation_rounds(State& state, GoblinProver& goblin) - { - auto NUM_CIRCUITS = static_cast(state.range(0)); - for (size_t circuit_idx = 0; circuit_idx < NUM_CIRCUITS; ++circuit_idx) { - - // Construct and accumulate a mock function circuit - MegaCircuitBuilder function_circuit{ goblin.op_queue }; - // On the first iteration construct a "large" function circuit (2^19), otherwise medium (2^17) - GoblinMockCircuits::construct_mock_function_circuit(function_circuit, /*large=*/circuit_idx == 0); - auto function_accum = goblin.accumulate(function_circuit); - - // Construct and accumulate the mock kernel circuit - // Note: in first round, kernel_accum is empty since there is no previous kernel to recursively verify - MegaCircuitBuilder circuit_builder{ goblin.op_queue }; - GoblinMockCircuits::construct_mock_recursion_kernel_circuit( - circuit_builder, - { function_accum.proof, function_accum.verification_key }, - { kernel_accum.proof, kernel_accum.verification_key }); - kernel_accum = goblin.accumulate(circuit_builder); - } - } -}; - -/** - * @brief Benchmark the full Goblin IVC protocol - * - */ -BENCHMARK_DEFINE_F(GoblinBench, GoblinFull)(benchmark::State& state) -{ - GoblinProver goblin; - - for (auto _ : state) { - BB_REPORT_OP_COUNT_IN_BENCH(state); - // Perform a specified number of iterations of function/kernel accumulation - perform_goblin_accumulation_rounds(state, goblin); - - // Construct proofs for ECCVM and Translator - goblin.prove(); - } -} - -/** - * @brief Benchmark only the accumulation rounds - * - */ -BENCHMARK_DEFINE_F(GoblinBench, GoblinAccumulate)(benchmark::State& state) -{ - GoblinProver goblin; - - // Perform a specified number of iterations of function/kernel accumulation - for (auto _ : state) { - perform_goblin_accumulation_rounds(state, goblin); - } -} - -/** - * @brief Benchmark only the ECCVM component - * - */ -BENCHMARK_DEFINE_F(GoblinBench, GoblinECCVMProve)(benchmark::State& state) -{ - GoblinProver goblin; - - // Perform a specified number of iterations of function/kernel accumulation - perform_goblin_accumulation_rounds(state, goblin); - - // Prove ECCVM only - for (auto _ : state) { - goblin.prove_eccvm(); - } -} - -/** - * @brief Benchmark only the Translator component - * - */ -BENCHMARK_DEFINE_F(GoblinBench, TranslatorProve)(benchmark::State& state) -{ - GoblinProver goblin; - - // Perform a specified number of iterations of function/kernel accumulation - perform_goblin_accumulation_rounds(state, goblin); - - // Prove ECCVM (unmeasured) and Translator (measured) - goblin.prove_eccvm(); - for (auto _ : state) { - goblin.prove_translator(); - } -} - -#define ARGS \ - Arg(GoblinBench::NUM_ITERATIONS_MEDIUM_COMPLEXITY) \ - ->Arg(1 << 0) \ - ->Arg(1 << 1) \ - ->Arg(1 << 2) \ - ->Arg(1 << 3) \ - ->Arg(1 << 4) \ - ->Arg(1 << 5) \ - ->Arg(1 << 6) - -BENCHMARK_REGISTER_F(GoblinBench, GoblinFull)->Unit(benchmark::kMillisecond)->ARGS; -BENCHMARK_REGISTER_F(GoblinBench, GoblinAccumulate)->Unit(benchmark::kMillisecond)->ARGS; -BENCHMARK_REGISTER_F(GoblinBench, GoblinECCVMProve)->Unit(benchmark::kMillisecond)->ARGS; -BENCHMARK_REGISTER_F(GoblinBench, TranslatorProve)->Unit(benchmark::kMillisecond)->ARGS; - -} // namespace - -BENCHMARK_MAIN(); diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/verification_key.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/verification_key.hpp index 23fb76a9502..909a40cd439 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/verification_key.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/verification_key.hpp @@ -29,11 +29,11 @@ template class VerifierCommitmentKey; * @tparam curve::BN254 */ template <> class VerifierCommitmentKey { + public: using Curve = curve::BN254; using GroupElement = typename Curve::Element; using Commitment = typename Curve::AffineElement; - public: VerifierCommitmentKey() { srs::init_crs_factory("../srs_db/ignition"); @@ -69,11 +69,11 @@ template <> class VerifierCommitmentKey { * @tparam curve::Grumpkin */ template <> class VerifierCommitmentKey { + public: using Curve = curve::Grumpkin; using GroupElement = typename Curve::Element; using Commitment = typename Curve::AffineElement; - public: /** * @brief Construct a new IPA Verification Key object from existing SRS * diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/zeromorph/zeromorph.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/zeromorph/zeromorph.hpp index f6a77ba302c..2b507523865 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/zeromorph/zeromorph.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/zeromorph/zeromorph.hpp @@ -6,6 +6,8 @@ #include "barretenberg/common/ref_vector.hpp" #include "barretenberg/common/zip_view.hpp" #include "barretenberg/polynomials/polynomial.hpp" +#include "barretenberg/stdlib/primitives/biggroup/biggroup.hpp" +#include "barretenberg/stdlib/primitives/witness/witness.hpp" #include "barretenberg/transcript/transcript.hpp" namespace bb { @@ -69,9 +71,6 @@ template class ZeroMorphProver_ { std::span u_challenge) { size_t log_N = numeric::get_msb(polynomial.size()); - // The size of the multilinear challenge must equal the log of the polynomial size - ASSERT(log_N == u_challenge.size()); - // Define the vector of quotients q_k, k = 0, ..., log_N-1 std::vector quotients; for (size_t k = 0; k < log_N; ++k) { @@ -323,7 +322,8 @@ template class ZeroMorphProver_ { * * @todo https://github.com/AztecProtocol/barretenberg/issues/1030: document concatenation trick */ - static OpeningClaim prove(RefSpan f_polynomials, + static OpeningClaim prove(FF circuit_size, + RefSpan f_polynomials, RefSpan g_polynomials, RefSpan f_evaluations, RefSpan g_shift_evaluations, @@ -339,7 +339,7 @@ template class ZeroMorphProver_ { // Extract multilinear challenge u and claimed multilinear evaluations from Sumcheck output std::span u_challenge = multilinear_challenge; - size_t log_N = u_challenge.size(); + size_t log_N = numeric::get_msb(static_cast(circuit_size)); size_t N = 1 << log_N; // Compute batching of unshifted polynomials f_i and to-be-shifted polynomials g_i: @@ -392,15 +392,18 @@ template class ZeroMorphProver_ { f_polynomial += concatenated_batched; // Compute the multilinear quotients q_k = q_k(X_0, ..., X_{k-1}) - auto quotients = compute_multilinear_quotients(f_polynomial, u_challenge); - + std::vector quotients = compute_multilinear_quotients(f_polynomial, u_challenge); // Compute and send commitments C_{q_k} = [q_k], k = 0,...,d-1 - std::vector q_k_commitments; - q_k_commitments.reserve(log_N); for (size_t idx = 0; idx < log_N; ++idx) { - q_k_commitments[idx] = commitment_key->commit(quotients[idx]); + Commitment q_k_commitment = commitment_key->commit(quotients[idx]); std::string label = "ZM:C_q_" + std::to_string(idx); - transcript->send_to_verifier(label, q_k_commitments[idx]); + transcript->send_to_verifier(label, q_k_commitment); + } + // Add buffer elements to remove log_N dependence in proof + for (size_t idx = log_N; idx < CONST_PROOF_SIZE_LOG_N; ++idx) { + auto buffer_element = Commitment::one(); + std::string label = "ZM:C_q_" + std::to_string(idx); + transcript->send_to_verifier(label, buffer_element); } // Get challenge y @@ -462,10 +465,19 @@ template class ZeroMorphVerifier_ { static Commitment compute_C_zeta_x(const Commitment& C_q, std::vector& C_q_k, FF y_challenge, - FF x_challenge) + FF x_challenge, + const FF log_circuit_size, + const FF circuit_size) { - size_t log_N = C_q_k.size(); - size_t N = 1 << log_N; + size_t N{ 0 }; + size_t log_N{ 0 }; + if constexpr (Curve::is_stdlib_type) { + N = static_cast(circuit_size.get_value()); + log_N = static_cast(log_circuit_size.get_value()); + } else { + N = static_cast(circuit_size); + log_N = static_cast(log_circuit_size); + } // Instantiate containers for input to batch mul std::vector scalars; @@ -480,21 +492,40 @@ template class ZeroMorphVerifier_ { } commitments.emplace_back(C_q); - // Contribution from C_q_k, k = 0,...,log_N - for (size_t k = 0; k < log_N; ++k) { + // Contribution from C_q_k, k = 0,...,log_N-1 + for (size_t k = 0; k < CONST_PROOF_SIZE_LOG_N; ++k) { + // Utilize dummy rounds in order to make verifier circuit independent of proof size + bool is_dummy_round = k >= log_N; auto deg_k = static_cast((1 << k) - 1); // Compute scalar y^k * x^{N - deg_k - 1} - auto scalar = y_challenge.pow(k); - scalar *= x_challenge.pow(N - deg_k - 1); + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1039): pow may not add proper constraints + FF scalar = y_challenge.pow(k); + size_t x_exponent = is_dummy_round ? 0 : N - deg_k - 1; + scalar *= x_challenge.pow(x_exponent); scalar *= FF(-1); - + if constexpr (Curve::is_stdlib_type) { + auto builder = x_challenge.get_context(); + FF zero = FF::from_witness(builder, 0); + stdlib::bool_t dummy_round = stdlib::witness_t(builder, is_dummy_round); + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1039): is it kosher to reassign like this? + scalar = FF::conditional_assign(dummy_round, zero, scalar); + } else { + if (is_dummy_round) { + scalar = 0; + } + } scalars.emplace_back(scalar); commitments.emplace_back(C_q_k[k]); } // Compute batch mul to get the result if constexpr (Curve::is_stdlib_type) { - return Commitment::batch_mul(commitments, scalars); + // If Ultra and using biggroup, handle edge cases in batch_mul + if constexpr (IsUltraBuilder && stdlib::IsBigGroup) { + return Commitment::batch_mul(commitments, scalars, /*max_num_bits=*/0, /*with_edgecases=*/true); + } else { + return Commitment::batch_mul(commitments, scalars); + } } else { return batch_mul_native(commitments, scalars); } @@ -533,15 +564,25 @@ template class ZeroMorphVerifier_ { FF batched_evaluation, FF x_challenge, std::span u_challenge, + const FF log_circuit_size, + const FF circuit_size, const std::vector>& concatenation_groups_commitments = {}) { - size_t log_N = C_q_k.size(); - size_t N = 1 << log_N; + size_t N{ 0 }; + size_t log_N{ 0 }; + if constexpr (Curve::is_stdlib_type) { + N = static_cast(circuit_size.get_value()); + log_N = static_cast(log_circuit_size.get_value()); + } else { + N = static_cast(circuit_size); + log_N = static_cast(log_circuit_size); + } std::vector scalars; std::vector commitments; // Phi_n(x) = (x^N - 1) / (x - 1) + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1039): pow may not add proper constraints auto phi_numerator = x_challenge.pow(N) - 1; // x^N - 1 auto phi_n_x = phi_numerator / (x_challenge - 1); @@ -590,26 +631,57 @@ template class ZeroMorphVerifier_ { // scalar = -x * (x^{2^k} * \Phi_{n-k-1}(x^{2^{k+1}}) - u_k * \Phi_{n-k}(x^{2^k})) auto x_pow_2k = x_challenge; // x^{2^k} auto x_pow_2kp1 = x_challenge * x_challenge; // x^{2^{k + 1}} - for (size_t k = 0; k < log_N; ++k) { - - auto phi_term_1 = phi_numerator / (x_pow_2kp1 - 1); // \Phi_{n-k-1}(x^{2^{k + 1}}) - auto phi_term_2 = phi_numerator / (x_pow_2k - 1); // \Phi_{n-k}(x^{2^k}) - - auto scalar = x_pow_2k * phi_term_1; - scalar -= u_challenge[k] * phi_term_2; - scalar *= x_challenge; - scalar *= FF(-1); - - scalars.emplace_back(scalar); - commitments.emplace_back(C_q_k[k]); - - // Update powers of challenge x - x_pow_2k = x_pow_2kp1; - x_pow_2kp1 *= x_pow_2kp1; + for (size_t k = 0; k < CONST_PROOF_SIZE_LOG_N; ++k) { + // Utilize dummy rounds in order to make verifier circuit independent of proof size + bool is_dummy_round = k >= log_N; + if constexpr (Curve::is_stdlib_type) { + auto builder = x_challenge.get_context(); + stdlib::bool_t dummy_scalar = stdlib::witness_t(builder, is_dummy_round); + auto phi_term_1 = phi_numerator / (x_pow_2kp1 - 1); // \Phi_{n-k-1}(x^{2^{k + 1}}) + auto phi_term_2 = phi_numerator / (x_pow_2k - 1); // \Phi_{n-k}(x^{2^k}) + + auto scalar = x_pow_2k * phi_term_1; + scalar -= u_challenge[k] * phi_term_2; + scalar *= x_challenge; + scalar *= -FF(1); + + FF zero = FF::from_witness(builder, 0); + scalar = FF::conditional_assign(dummy_scalar, zero, scalar); + scalars.emplace_back(scalar); + commitments.emplace_back(C_q_k[k]); + + x_pow_2k = FF::conditional_assign(dummy_scalar, x_pow_2k, x_pow_2kp1); + x_pow_2kp1 = FF::conditional_assign(dummy_scalar, x_pow_2kp1, x_pow_2kp1 * x_pow_2kp1); + } else { + if (is_dummy_round) { + scalars.emplace_back(0); + commitments.emplace_back(C_q_k[k]); + } else { + auto phi_term_1 = phi_numerator / (x_pow_2kp1 - 1); // \Phi_{n-k-1}(x^{2^{k + 1}}) + auto phi_term_2 = phi_numerator / (x_pow_2k - 1); // \Phi_{n-k}(x^{2^k}) + + auto scalar = x_pow_2k * phi_term_1; + scalar -= u_challenge[k] * phi_term_2; + scalar *= x_challenge; + scalar *= FF(-1); + + scalars.emplace_back(scalar); + commitments.emplace_back(C_q_k[k]); + + // Update powers of challenge x + x_pow_2k = x_pow_2kp1; + x_pow_2kp1 *= x_pow_2kp1; + } + } } if constexpr (Curve::is_stdlib_type) { - return Commitment::batch_mul(commitments, scalars); + // If Ultra and using biggroup, handle edge cases in batch_mul + if constexpr (IsUltraBuilder && stdlib::IsBigGroup) { + return Commitment::batch_mul(commitments, scalars, /*max_num_bits=*/0, /*with_edgecases=*/true); + } else { + return Commitment::batch_mul(commitments, scalars); + } } else { return batch_mul_native(commitments, scalars); } @@ -638,7 +710,8 @@ template class ZeroMorphVerifier_ { * @param transcript * @return VerifierAccumulator Inputs to the final PCS verification check that will be accumulated */ - static OpeningClaim verify(RefSpan unshifted_commitments, + static OpeningClaim verify(FF circuit_size, + RefSpan unshifted_commitments, RefSpan to_be_shifted_commitments, RefSpan unshifted_evaluations, RefSpan shifted_evaluations, @@ -648,7 +721,13 @@ template class ZeroMorphVerifier_ { const std::vector>& concatenation_group_commitments = {}, RefSpan concatenated_evaluations = {}) { - size_t log_N = multivariate_challenge.size(); + FF log_N; + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1039): Connect witness log_N to circuit size + if constexpr (Curve::is_stdlib_type) { + log_N = FF(static_cast(numeric::get_msb(static_cast(circuit_size.get_value())))); + } else { + log_N = numeric::get_msb(static_cast(circuit_size)); + } FF rho = transcript->template get_challenge("rho"); // Construct batched evaluation v = sum_{i=0}^{m-1}\rho^i*f_i(u) + sum_{i=0}^{l-1}\rho^{m+i}*h_i(u) @@ -669,8 +748,8 @@ template class ZeroMorphVerifier_ { // Receive commitments [q_k] std::vector C_q_k; - C_q_k.reserve(log_N); - for (size_t i = 0; i < log_N; ++i) { + C_q_k.reserve(CONST_PROOF_SIZE_LOG_N); + for (size_t i = 0; i < CONST_PROOF_SIZE_LOG_N; ++i) { C_q_k.emplace_back(transcript->template receive_from_prover("ZM:C_q_" + std::to_string(i))); } @@ -684,7 +763,7 @@ template class ZeroMorphVerifier_ { auto [x_challenge, z_challenge] = transcript->template get_challenges("ZM:x", "ZM:z"); // Compute commitment C_{\zeta_x} - auto C_zeta_x = compute_C_zeta_x(C_q, C_q_k, y_challenge, x_challenge); + auto C_zeta_x = compute_C_zeta_x(C_q, C_q_k, y_challenge, x_challenge, log_N, circuit_size); // Compute commitment C_{Z_x} Commitment C_Z_x = compute_C_Z_x(g1_identity, @@ -695,17 +774,23 @@ template class ZeroMorphVerifier_ { batched_evaluation, x_challenge, multivariate_challenge, + log_N, + circuit_size, concatenation_group_commitments); // Compute commitment C_{\zeta,Z} Commitment C_zeta_Z; if constexpr (Curve::is_stdlib_type) { - // Express operation as a batch_mul in order to use Goblinization if available auto builder = z_challenge.get_context(); std::vector scalars = { FF(builder, 1), z_challenge }; std::vector points = { C_zeta_x, C_Z_x }; - C_zeta_Z = Commitment::batch_mul(points, scalars); + // If Ultra and using biggroup, handle edge cases in batch_mul + if constexpr (IsUltraBuilder && stdlib::IsBigGroup) { + C_zeta_Z = Commitment::batch_mul(points, scalars, /*max_num_bits=*/0, /*with_edgecases=*/true); + } else { + C_zeta_Z = Commitment::batch_mul(points, scalars); + } } else { C_zeta_Z = C_zeta_x + C_Z_x * z_challenge; } diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/zeromorph/zeromorph.test.cpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/zeromorph/zeromorph.test.cpp index 122fcb1187f..146ce53b461 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/zeromorph/zeromorph.test.cpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/zeromorph/zeromorph.test.cpp @@ -1,9 +1,7 @@ #include "zeromorph.hpp" -#include "../commitment_key.test.hpp" +#include "barretenberg/commitment_schemes/commitment_key.test.hpp" #include "barretenberg/commitment_schemes/ipa/ipa.hpp" #include "barretenberg/commitment_schemes/kzg/kzg.hpp" -#include "barretenberg/transcript/transcript.hpp" - #include namespace bb { @@ -89,10 +87,10 @@ template class ZeroMorphTest : public CommitmentTest class ZeroMorphTest : public CommitmentTest u_challenge) { auto prover_transcript = NativeTranscript::prover_init_empty(); // Execute Prover protocol - auto prover_opening_claim = ZeroMorphProver::prove(RefVector(unshifted.polynomials), // unshifted + auto prover_opening_claim = ZeroMorphProver::prove(N, + RefVector(unshifted.polynomials), // unshifted RefVector(shifted.polynomials), // to-be shifted RefVector(unshifted.evaluations), // unshifted RefVector(shifted.evaluations), // shifted @@ -224,7 +224,8 @@ template class ZeroMorphTest : public CommitmentTest class ZeroMorphTest : public CommitmentTest u_challenge, size_t NUM_CONCATENATED) @@ -261,7 +263,8 @@ template class ZeroMorphTest : public CommitmentTest class ZeroMorphTest : public CommitmentTestexecute_zeromorph_protocol(num_unshifted, num_shifted, num_concatenated); EXPECT_TRUE(verified); } -} // namespace bb +} // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes_recursion/CMakeLists.txt b/barretenberg/cpp/src/barretenberg/commitment_schemes_recursion/CMakeLists.txt new file mode 100644 index 00000000000..71ce791bd34 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes_recursion/CMakeLists.txt @@ -0,0 +1 @@ +barretenberg_module(commitment_schemes_recursion commitment_schemes stdlib_primitives) \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes_recursion/zeromorph.test.cpp b/barretenberg/cpp/src/barretenberg/commitment_schemes_recursion/zeromorph.test.cpp new file mode 100644 index 00000000000..93cfbc82d89 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes_recursion/zeromorph.test.cpp @@ -0,0 +1,140 @@ +#include "barretenberg/commitment_schemes/zeromorph/zeromorph.hpp" +#include "barretenberg/circuit_checker/circuit_checker.hpp" +#include "barretenberg/commitment_schemes/commitment_key.test.hpp" +#include "barretenberg/commitment_schemes/ipa/ipa.hpp" +#include "barretenberg/commitment_schemes/kzg/kzg.hpp" +#include "barretenberg/srs/global_crs.hpp" +#include "barretenberg/stdlib/honk_recursion/transcript/transcript.hpp" +#include "barretenberg/stdlib/primitives/curves/bn254.hpp" +#include "barretenberg/stdlib/primitives/curves/grumpkin.hpp" +#include "barretenberg/stdlib_circuit_builders/ultra_circuit_builder.hpp" +#include + +#include + +using namespace bb; + +template class ZeroMorphRecursionTest : public CommitmentTest {}; + +numeric::RNG& engine = numeric::get_debug_randomness(); + +/** + * @brief Test full Prover/Verifier protocol for proving single multilinear evaluation + * + */ +TEST(ZeroMorphRecursionTest, ProveAndVerifySingle) +{ + // Define some useful type aliases + using Builder = UltraCircuitBuilder; + using Curve = typename stdlib::bn254; + using NativeCurve = typename Curve::NativeCurve; + using Commitment = typename Curve::AffineElement; + using NativeCommitment = typename Curve::AffineElementNative; + using NativeCurve = typename Curve::NativeCurve; + using NativePCS = std::conditional_t, KZG, IPA>; + using CommitmentKey = typename NativePCS::CK; + using ZeroMorphProver = ZeroMorphProver_; + using Fr = typename Curve::ScalarField; + using NativeFr = typename Curve::NativeCurve::ScalarField; + using Polynomial = bb::Polynomial; + using ZeroMorphVerifier = ZeroMorphVerifier_; + using Transcript = bb::BaseTranscript>; + + constexpr size_t N = 2; + constexpr size_t NUM_UNSHIFTED = 1; + constexpr size_t NUM_SHIFTED = 0; + + srs::init_crs_factory("../srs_db/ignition"); + + std::vector u_challenge = { NativeFr::random_element(&engine) }; + + // Construct some random multilinear polynomials f_i and their evaluations v_i = f_i(u) + std::vector f_polynomials; // unshifted polynomials + std::vector v_evaluations; + for (size_t i = 0; i < NUM_UNSHIFTED; ++i) { + f_polynomials.emplace_back(Polynomial::random(N)); + f_polynomials[i][0] = NativeFr(0); // ensure f is "shiftable" + v_evaluations.emplace_back(f_polynomials[i].evaluate_mle(u_challenge)); + } + + // Construct some "shifted" multilinear polynomials h_i as the left-shift-by-1 of f_i + std::vector g_polynomials; // to-be-shifted polynomials + std::vector h_polynomials; // shifts of the to-be-shifted polynomials + std::vector w_evaluations; + for (size_t i = 0; i < NUM_SHIFTED; ++i) { + g_polynomials.emplace_back(f_polynomials[i]); + h_polynomials.emplace_back(g_polynomials[i].shifted()); + w_evaluations.emplace_back(h_polynomials[i].evaluate_mle(u_challenge)); + } + + // Compute commitments [f_i] + std::vector f_commitments; + auto commitment_key = std::make_shared(1024); + for (size_t i = 0; i < NUM_UNSHIFTED; ++i) { + f_commitments.emplace_back(commitment_key->commit(f_polynomials[i])); + } + + // Construct container of commitments of the "to-be-shifted" polynomials [g_i] (= [f_i]) + std::vector g_commitments; + for (size_t i = 0; i < NUM_SHIFTED; ++i) { + g_commitments.emplace_back(f_commitments[i]); + } + + // Initialize an empty NativeTranscript + auto prover_transcript = NativeTranscript::prover_init_empty(); + + // Execute Prover protocol + ZeroMorphProver::prove(N, + RefVector(f_polynomials), + RefVector(g_polynomials), + RefVector(v_evaluations), + RefVector(w_evaluations), + u_challenge, + commitment_key, + prover_transcript); + + Builder builder; + StdlibProof stdlib_proof = bb::convert_proof_to_witness(&builder, prover_transcript->proof_data); + auto stdlib_verifier_transcript = std::make_shared(stdlib_proof); + [[maybe_unused]] auto _ = stdlib_verifier_transcript->template receive_from_prover("Init"); + + // Execute Verifier protocol without the need for vk prior the final check + const auto commitments_to_witnesses = [&builder](const auto& commitments) { + std::vector commitments_in_biggroup(commitments.size()); + std::transform(commitments.begin(), + commitments.end(), + commitments_in_biggroup.begin(), + [&builder](const auto& native_commitment) { + return Commitment::from_witness(&builder, native_commitment); + }); + return commitments_in_biggroup; + }; + const auto elements_to_witness = [&](const auto& elements) { + std::vector elements_in_circuit(elements.size()); + std::transform(elements.begin(), + elements.end(), + elements_in_circuit.begin(), + [&builder](const auto& native_element) { return Fr::from_witness(&builder, native_element); }); + return elements_in_circuit; + }; + auto stdlib_f_commitments = commitments_to_witnesses(f_commitments); + auto stdlib_g_commitments = commitments_to_witnesses(g_commitments); + auto stdlib_v_evaluations = elements_to_witness(v_evaluations); + auto stdlib_w_evaluations = elements_to_witness(w_evaluations); + + std::vector u_challenge_in_circuit(CONST_PROOF_SIZE_LOG_N); + std::fill_n(u_challenge_in_circuit.begin(), CONST_PROOF_SIZE_LOG_N, Fr::from_witness(&builder, 0)); + u_challenge_in_circuit[0] = Fr::from_witness(&builder, u_challenge[0]); + + [[maybe_unused]] auto opening_claim = ZeroMorphVerifier::verify(Fr::from_witness(&builder, N), + RefVector(stdlib_f_commitments), // unshifted + RefVector(stdlib_g_commitments), // to-be-shifted + RefVector(stdlib_v_evaluations), // unshifted + RefVector(stdlib_w_evaluations), // shifted + u_challenge_in_circuit, + Commitment::one(&builder), + stdlib_verifier_transcript, + {}, + {}); + EXPECT_TRUE(CircuitChecker::check(builder)); +} diff --git a/barretenberg/cpp/src/barretenberg/constants.hpp b/barretenberg/cpp/src/barretenberg/constants.hpp new file mode 100644 index 00000000000..4adf2c4a6b1 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/constants.hpp @@ -0,0 +1,7 @@ +#pragma once +#include + +namespace bb { +// The log of the max circuit size assumed in order to achieve constant sized proofs +static constexpr uint32_t CONST_PROOF_SIZE_LOG_N = 28; +} // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp index bcfcce6776f..528fd947ed3 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp @@ -341,7 +341,7 @@ void build_constraints(Builder& builder, // Add recursion constraints for (size_t i = 0; i < constraint_system.honk_recursion_constraints.size(); ++i) { - auto constraint = constraint_system.honk_recursion_constraints.at(i); + auto& constraint = constraint_system.honk_recursion_constraints.at(i); // A proof passed into the constraint should be stripped of its inner public inputs, but not the // nested aggregation object itself. The verifier circuit requires that the indices to a nested // proof aggregation state are a circuit constant. The user tells us they how they want these diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/honk_recursion_constraint.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/honk_recursion_constraint.cpp index 4b32ec0a14f..fb778929845 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/honk_recursion_constraint.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/honk_recursion_constraint.cpp @@ -117,8 +117,6 @@ std::array create_ho } } - // Recursively verify the proof - auto vkey = std::make_shared(builder, key_fields); if (!has_valid_witness_assignments) { // Set vkey->circuit_size correctly based on the proof size size_t num_frs_comm = bb::field_conversion::calc_num_bn254_frs(); @@ -128,14 +126,86 @@ std::array create_ho 2 * num_frs_comm) % (num_frs_comm + num_frs_fr * UltraFlavor::BATCHED_RELATION_PARTIAL_LENGTH) == 0); - vkey->log_circuit_size = (input.proof.size() - HonkRecursionConstraint::inner_public_input_offset - - UltraFlavor::NUM_WITNESS_ENTITIES * num_frs_comm - - UltraFlavor::NUM_ALL_ENTITIES * num_frs_fr - 2 * num_frs_comm) / - (num_frs_comm + num_frs_fr * UltraFlavor::BATCHED_RELATION_PARTIAL_LENGTH); - vkey->circuit_size = (1 << vkey->log_circuit_size); - vkey->num_public_inputs = input.public_inputs.size(); - vkey->pub_inputs_offset = UltraFlavor::has_zero_row ? 1 : 0; + // Note: this computation should always result in log_circuit_size = CONST_PROOF_SIZE_LOG_N + auto log_circuit_size = (input.proof.size() - HonkRecursionConstraint::inner_public_input_offset - + UltraFlavor::NUM_WITNESS_ENTITIES * num_frs_comm - + UltraFlavor::NUM_ALL_ENTITIES * num_frs_fr - 2 * num_frs_comm) / + (num_frs_comm + num_frs_fr * UltraFlavor::BATCHED_RELATION_PARTIAL_LENGTH); + builder.assert_equal(builder.add_variable(1 << log_circuit_size), key_fields[0].witness_index); + builder.assert_equal(builder.add_variable(input.public_inputs.size()), key_fields[1].witness_index); + builder.assert_equal(builder.add_variable(UltraFlavor::has_zero_row ? 1 : 0), key_fields[2].witness_index); + uint32_t offset = 3; + + for (size_t i = 0; i < Flavor::NUM_PRECOMPUTED_ENTITIES; ++i) { + auto comm = curve::BN254::AffineElement::one() * fr::random_element(); + auto frs = field_conversion::convert_to_bn254_frs(comm); + builder.assert_equal(builder.add_variable(frs[0]), key_fields[offset].witness_index); + builder.assert_equal(builder.add_variable(frs[1]), key_fields[offset + 1].witness_index); + builder.assert_equal(builder.add_variable(frs[2]), key_fields[offset + 2].witness_index); + builder.assert_equal(builder.add_variable(frs[3]), key_fields[offset + 3].witness_index); + offset += 4; + } + + offset = HonkRecursionConstraint::inner_public_input_offset; + // first 3 things + builder.assert_equal(builder.add_variable(1 << log_circuit_size), proof_fields[0].witness_index); + builder.assert_equal(builder.add_variable(input.public_inputs.size()), proof_fields[1].witness_index); + builder.assert_equal(builder.add_variable(UltraFlavor::has_zero_row ? 1 : 0), proof_fields[2].witness_index); + + // the public inputs + for (size_t i = 0; i < input.public_inputs.size(); i++) { + builder.assert_equal(builder.add_variable(fr::random_element()), proof_fields[offset].witness_index); + offset++; + } + + // first 7 commitments + for (size_t i = 0; i < Flavor::NUM_WITNESS_ENTITIES; i++) { + auto comm = curve::BN254::AffineElement::one() * fr::random_element(); + auto frs = field_conversion::convert_to_bn254_frs(comm); + builder.assert_equal(builder.add_variable(frs[0]), proof_fields[offset].witness_index); + builder.assert_equal(builder.add_variable(frs[1]), proof_fields[offset + 1].witness_index); + builder.assert_equal(builder.add_variable(frs[2]), proof_fields[offset + 2].witness_index); + builder.assert_equal(builder.add_variable(frs[3]), proof_fields[offset + 3].witness_index); + offset += 4; + } + + // now the univariates, which can just be 0s (7*CONST_PROOF_SIZE_LOG_N Frs) + for (size_t i = 0; i < CONST_PROOF_SIZE_LOG_N * Flavor::BATCHED_RELATION_PARTIAL_LENGTH; i++) { + builder.assert_equal(builder.add_variable(fr::random_element()), proof_fields[offset].witness_index); + offset++; + } + + // now the sumcheck evalutions, which is just 43 0s + for (size_t i = 0; i < Flavor::NUM_ALL_ENTITIES; i++) { + builder.assert_equal(builder.add_variable(fr::random_element()), proof_fields[offset].witness_index); + offset++; + } + + // now the zeromorph commitments, which are CONST_PROOF_SIZE_LOG_N comms + for (size_t i = 0; i < CONST_PROOF_SIZE_LOG_N; i++) { + auto comm = curve::BN254::AffineElement::one() * fr::random_element(); + auto frs = field_conversion::convert_to_bn254_frs(comm); + builder.assert_equal(builder.add_variable(frs[0]), proof_fields[offset].witness_index); + builder.assert_equal(builder.add_variable(frs[1]), proof_fields[offset + 1].witness_index); + builder.assert_equal(builder.add_variable(frs[2]), proof_fields[offset + 2].witness_index); + builder.assert_equal(builder.add_variable(frs[3]), proof_fields[offset + 3].witness_index); + offset += 4; + } + + // lastly the 2 commitments + for (size_t i = 0; i < 2; i++) { + auto comm = curve::BN254::AffineElement::one() * fr::random_element(); + auto frs = field_conversion::convert_to_bn254_frs(comm); + builder.assert_equal(builder.add_variable(frs[0]), proof_fields[offset].witness_index); + builder.assert_equal(builder.add_variable(frs[1]), proof_fields[offset + 1].witness_index); + builder.assert_equal(builder.add_variable(frs[2]), proof_fields[offset + 2].witness_index); + builder.assert_equal(builder.add_variable(frs[3]), proof_fields[offset + 3].witness_index); + offset += 4; + } + ASSERT(offset == input.proof.size() + input.public_inputs.size()); } + // Recursively verify the proof + auto vkey = std::make_shared(builder, key_fields); RecursiveVerifier verifier(&builder, vkey); std::array pairing_points = verifier.verify_proof(proof_fields); diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_flavor.hpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_flavor.hpp index 4a87e300d09..bdb969415cb 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_flavor.hpp @@ -936,7 +936,6 @@ class ECCVMFlavor { size_t num_frs_read = 0; circuit_size = NativeTranscript::template deserialize_from_buffer(NativeTranscript::proof_data, num_frs_read); - size_t log_n = numeric::get_msb(circuit_size); transcript_add_comm = NativeTranscript::template deserialize_from_buffer( NativeTranscript::proof_data, num_frs_read); transcript_mul_comm = NativeTranscript::template deserialize_from_buffer( @@ -1113,14 +1112,14 @@ class ECCVMFlavor { NativeTranscript::proof_data, num_frs_read); z_perm_comm = NativeTranscript::template deserialize_from_buffer(NativeTranscript::proof_data, num_frs_read); - for (size_t i = 0; i < log_n; ++i) { + for (size_t i = 0; i < CONST_PROOF_SIZE_LOG_N; ++i) { sumcheck_univariates.emplace_back(NativeTranscript::template deserialize_from_buffer< bb::Univariate>( NativeTranscript::proof_data, num_frs_read)); } sumcheck_evaluations = NativeTranscript::template deserialize_from_buffer>( NativeTranscript::proof_data, num_frs_read); - for (size_t i = 0; i < log_n; ++i) { + for (size_t i = 0; i < CONST_PROOF_SIZE_LOG_N; ++i) { zm_cq_comms.push_back( NativeTranscript::template deserialize_from_buffer(proof_data, num_frs_read)); } @@ -1164,7 +1163,6 @@ class ECCVMFlavor { NativeTranscript::proof_data.clear(); NativeTranscript::template serialize_to_buffer(circuit_size, NativeTranscript::proof_data); - size_t log_n = numeric::get_msb(circuit_size); NativeTranscript::template serialize_to_buffer(transcript_add_comm, NativeTranscript::proof_data); NativeTranscript::template serialize_to_buffer(transcript_mul_comm, NativeTranscript::proof_data); @@ -1264,11 +1262,11 @@ class ECCVMFlavor { NativeTranscript::proof_data); NativeTranscript::template serialize_to_buffer(lookup_inverses_comm, NativeTranscript::proof_data); NativeTranscript::template serialize_to_buffer(z_perm_comm, NativeTranscript::proof_data); - for (size_t i = 0; i < log_n; ++i) { + for (size_t i = 0; i < CONST_PROOF_SIZE_LOG_N; ++i) { NativeTranscript::template serialize_to_buffer(sumcheck_univariates[i], NativeTranscript::proof_data); } NativeTranscript::template serialize_to_buffer(sumcheck_evaluations, NativeTranscript::proof_data); - for (size_t i = 0; i < log_n; ++i) { + for (size_t i = 0; i < CONST_PROOF_SIZE_LOG_N; ++i) { NativeTranscript::template serialize_to_buffer(zm_cq_comms[i], NativeTranscript::proof_data); } NativeTranscript::template serialize_to_buffer(zm_cq_comm, NativeTranscript::proof_data); diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp index 7d049b16970..830eb760683 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp @@ -121,7 +121,8 @@ void ECCVMProver::execute_pcs_rounds() // Execute the ZeroMorph protocol to produce a univariate opening claim for the multilinear evaluations produced by // Sumcheck auto multivariate_to_univariate_opening_claim = - ZeroMorph::prove(key->polynomials.get_unshifted(), + ZeroMorph::prove(key->circuit_size, + key->polynomials.get_unshifted(), key->polynomials.get_to_be_shifted(), sumcheck_output.claimed_evaluations.get_unshifted(), sumcheck_output.claimed_evaluations.get_shifted(), diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_transcript.test.cpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_transcript.test.cpp index 9eaedc9df93..2f8999ada5d 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_transcript.test.cpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_transcript.test.cpp @@ -140,7 +140,7 @@ class ECCVMTranscriptTests : public ::testing::Test { manifest_expected.add_challenge(round, label); } - for (size_t i = 0; i < log_n; ++i) { + for (size_t i = 0; i < CONST_PROOF_SIZE_LOG_N; ++i) { round++; std::string idx = std::to_string(i); manifest_expected.add_entry(round, "Sumcheck:univariate_" + idx, frs_per_uni); @@ -153,7 +153,7 @@ class ECCVMTranscriptTests : public ::testing::Test { manifest_expected.add_challenge(round, "rho"); round++; - for (size_t i = 0; i < log_n; ++i) { + for (size_t i = 0; i < CONST_PROOF_SIZE_LOG_N; ++i) { std::string idx = std::to_string(i); manifest_expected.add_entry(round, "ZM:C_q_" + idx, frs_per_G); } diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_verifier.cpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_verifier.cpp index 2c1e3d6dc57..26bd5ac6ce6 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_verifier.cpp @@ -61,7 +61,8 @@ bool ECCVMVerifier::verify_proof(const HonkProof& proof) } // Reduce the multivariate evaluation claims produced by sumcheck to a single univariate opening claim - auto multivariate_to_univariate_opening_claim = ZeroMorph::verify(commitments.get_unshifted(), + auto multivariate_to_univariate_opening_claim = ZeroMorph::verify(circuit_size, + commitments.get_unshifted(), commitments.get_to_be_shifted(), claimed_evaluations.get_unshifted(), claimed_evaluations.get_shifted(), diff --git a/barretenberg/cpp/src/barretenberg/eccvm_recursion/eccvm_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/eccvm_recursion/eccvm_recursive_verifier.cpp index 4ceb6478179..e2821b7789b 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm_recursion/eccvm_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/eccvm_recursion/eccvm_recursive_verifier.cpp @@ -31,7 +31,11 @@ template void ECCVMRecursiveVerifier_::verify_proof(co VerifierCommitments commitments{ key }; CommitmentLabels commitment_labels; - const auto circuit_size = transcript->template receive_from_prover("circuit_size"); + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1040): Extract circuit size as BF (field_t) then + // convert to FF (bigfield fq) since this is what's expected by ZM. See issue for more details. + const BF circuit_size_bf = transcript->template receive_from_prover("circuit_size"); + const FF circuit_size{ static_cast(static_cast(circuit_size_bf.get_value())) }; + for (auto [comm, label] : zip_view(commitments.get_wires(), commitment_labels.get_wires())) { comm = transcript->template receive_from_prover(label); // TODO(https://github.com/AztecProtocol/barretenberg/issues/1017): This is a hack to ensure zero commitments @@ -75,7 +79,8 @@ template void ECCVMRecursiveVerifier_::verify_proof(co auto [multivariate_challenge, claimed_evaluations, sumcheck_verified] = sumcheck.verify(relation_parameters, alpha, gate_challenges); - auto multivariate_to_univariate_opening_claim = ZeroMorph::verify(commitments.get_unshifted(), + auto multivariate_to_univariate_opening_claim = ZeroMorph::verify(circuit_size, + commitments.get_unshifted(), commitments.get_to_be_shifted(), claimed_evaluations.get_unshifted(), claimed_evaluations.get_shifted(), diff --git a/barretenberg/cpp/src/barretenberg/eccvm_recursion/verifier_commitment_key.hpp b/barretenberg/cpp/src/barretenberg/eccvm_recursion/verifier_commitment_key.hpp index 5dcb13ffacb..b25e5369adb 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm_recursion/verifier_commitment_key.hpp +++ b/barretenberg/cpp/src/barretenberg/eccvm_recursion/verifier_commitment_key.hpp @@ -7,12 +7,13 @@ namespace bb { * * @tparam Builder */ -template class VerifierCommitmentKey { +template class VerifierCommitmentKey { + public: + using Curve = Curve_; using Builder = Curve::Builder; using Commitment = Curve::AffineElement; using NativeEmbeddedCurve = typename Builder::EmbeddedCurve; - public: /** * @brief Construct a new Verifier Commitment Key object from its native counterpart. instantiated on Grumpkin. * This will be part of the ECCVMRecursiveFlavor once implemented. The Grumpkin SRS points are represented after diff --git a/barretenberg/cpp/src/barretenberg/flavor/flavor.hpp b/barretenberg/cpp/src/barretenberg/flavor/flavor.hpp index 301597a6299..0059b7e166f 100644 --- a/barretenberg/cpp/src/barretenberg/flavor/flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/flavor/flavor.hpp @@ -68,6 +68,9 @@ #include "barretenberg/common/std_array.hpp" #include "barretenberg/common/std_vector.hpp" #include "barretenberg/common/zip_view.hpp" +#include "barretenberg/constants.hpp" +#include "barretenberg/crypto/sha256/sha256.hpp" +#include "barretenberg/ecc/fields/field_conversion.hpp" #include "barretenberg/plonk_honk_shared/types/circuit_type.hpp" #include "barretenberg/polynomials/barycentric.hpp" #include "barretenberg/polynomials/evaluation_domain.hpp" @@ -181,6 +184,8 @@ class ProvingKeyAvm_ : public PrecomputedPolynomials, public WitnessPolynomials template class VerificationKey_ : public PrecomputedCommitments { public: + using FF = typename VerifierCommitmentKey::Curve::ScalarField; + using Commitment = typename VerifierCommitmentKey::Commitment; std::shared_ptr pcs_verification_key; uint64_t pub_inputs_offset = 0; @@ -191,6 +196,46 @@ class VerificationKey_ : public PrecomputedCommitments { this->log_circuit_size = numeric::get_msb(circuit_size); this->num_public_inputs = num_public_inputs; }; + + /** + * @brief Serialize verification key to field elements + * + * @return std::vector + */ + std::vector to_field_elements() + { + std::vector elements; + std::vector circuit_size_elements = bb::field_conversion::convert_to_bn254_frs(this->circuit_size); + elements.insert(elements.end(), circuit_size_elements.begin(), circuit_size_elements.end()); + // do the same for the rest of the fields + std::vector num_public_inputs_elements = + bb::field_conversion::convert_to_bn254_frs(this->num_public_inputs); + elements.insert(elements.end(), num_public_inputs_elements.begin(), num_public_inputs_elements.end()); + std::vector pub_inputs_offset_elements = + bb::field_conversion::convert_to_bn254_frs(this->pub_inputs_offset); + elements.insert(elements.end(), pub_inputs_offset_elements.begin(), pub_inputs_offset_elements.end()); + + for (Commitment& comm : this->get_all()) { + std::vector comm_elements = bb::field_conversion::convert_to_bn254_frs(comm); + elements.insert(elements.end(), comm_elements.begin(), comm_elements.end()); + } + return elements; + } + + uint256_t hash() + { + std::vector field_elements = to_field_elements(); + std::vector to_hash(field_elements.size() * sizeof(FF)); + + const auto convert_and_insert = [&to_hash](auto& vector) { + std::vector buffer = to_buffer(vector); + to_hash.insert(to_hash.end(), buffer.begin(), buffer.end()); + }; + + convert_and_insert(field_elements); + + return from_buffer(crypto::sha256(to_hash)); + } }; // Because of how Gemini is written, is importat to put the polynomials out in this order. diff --git a/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp b/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp index 0fbdef6204f..9e696ae3580 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp +++ b/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp @@ -136,41 +136,6 @@ class GoblinMockCircuits { MockCircuits::construct_arithmetic_circuit(builder); } - /** - * @brief Construct a size 2^17 mock kernel circuit based on vanilla recursion for benchmarking - * @details This circuit contains (1) some arbitrary operations representing general kernel logic, (2) recursive - * verification of a function circuit proof, and optionally (3) recursive verification of a previous kernel circuit - * proof. The arbitrary kernel logic is structured to bring the final dyadic circuit size of the kernel to 2^17. - * - * TODO(https://github.com/AztecProtocol/barretenberg/issues/801): Pairing point aggregation not implemented - * @param builder - * @param function_accum {proof, vkey} for function circuit to be recursively verified - * @param prev_kernel_accum {proof, vkey} for previous kernel circuit to be recursively verified - */ - static void construct_mock_recursion_kernel_circuit(MegaBuilder& builder, - const KernelInput& function_accum, - const KernelInput& prev_kernel_accum) - { - // Add operations representing general kernel logic e.g. state updates. Note: these are structured to make the - // kernel "full" within the dyadic size 2^17 (130914 gates) - const size_t NUM_MERKLE_CHECKS = 40; - const size_t NUM_ECDSA_VERIFICATIONS = 1; - const size_t NUM_SHA_HASHES = 1; - stdlib::generate_merkle_membership_test_circuit(builder, NUM_MERKLE_CHECKS); - stdlib::generate_ecdsa_verification_test_circuit(builder, NUM_ECDSA_VERIFICATIONS); - stdlib::generate_sha256_test_circuit(builder, NUM_SHA_HASHES); - - // Execute recursive aggregation of function proof - RecursiveVerifier verifier1{ &builder, function_accum.verification_key }; - verifier1.verify_proof(function_accum.proof); - - // Execute recursive aggregation of previous kernel proof if one exists - if (!prev_kernel_accum.proof.empty()) { - RecursiveVerifier verifier2{ &builder, prev_kernel_accum.verification_key }; - verifier2.verify_proof(prev_kernel_accum.proof); - } - } - /** * @brief Construct a mock kernel circuit * @details Construct an arbitrary circuit meant to represent the aztec private function execution kernel. Recursive diff --git a/barretenberg/cpp/src/barretenberg/goblin/mock_circuits_pinning.test.cpp b/barretenberg/cpp/src/barretenberg/goblin/mock_circuits_pinning.test.cpp index a31ee0cc09b..b37cdd16206 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/mock_circuits_pinning.test.cpp +++ b/barretenberg/cpp/src/barretenberg/goblin/mock_circuits_pinning.test.cpp @@ -32,31 +32,4 @@ TEST_F(MegaMockCircuitsPinning, FunctionSizes) }; run_test(true); run_test(false); -} - -TEST_F(MegaMockCircuitsPinning, RecursionKernelSizes) -{ - const auto run_test = [](bool large) { - { - GoblinProver goblin; - GoblinAccumulationOutput kernel_accum; - MegaCircuitBuilder app_circuit{ goblin.op_queue }; - GoblinMockCircuits::construct_mock_function_circuit(app_circuit, large); - auto function_accum = goblin.accumulate(app_circuit); - MegaCircuitBuilder kernel_circuit{ goblin.op_queue }; - GoblinMockCircuits::construct_mock_recursion_kernel_circuit( - kernel_circuit, - { function_accum.proof, function_accum.verification_key }, - { kernel_accum.proof, kernel_accum.verification_key }); - - auto instance = std::make_shared(kernel_circuit); - if (large) { - EXPECT_EQ(instance->proving_key.log_circuit_size, 17); - } else { - EXPECT_EQ(instance->proving_key.log_circuit_size, 17); - }; - } - }; - run_test(true); - run_test(false); } \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_delta.hpp b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_delta.hpp index a68b398b118..b967dc0e93a 100644 --- a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_delta.hpp +++ b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_delta.hpp @@ -61,26 +61,4 @@ typename Flavor::FF compute_public_input_delta(std::span -Field compute_lookup_grand_product_delta(const Field& beta, const Field& gamma, const auto domain_size) -{ - Field gamma_by_one_plus_beta = gamma * (Field(1) + beta); // γ(1 + β) - return gamma_by_one_plus_beta.pow(domain_size); // (γ(1 + β))^n -} - } // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/polynomials/pow.hpp b/barretenberg/cpp/src/barretenberg/polynomials/pow.hpp index 583a9d3ddf1..7dda9aaa485 100644 --- a/barretenberg/cpp/src/barretenberg/polynomials/pow.hpp +++ b/barretenberg/cpp/src/barretenberg/polynomials/pow.hpp @@ -2,6 +2,7 @@ #include "barretenberg/common/compiler_hints.hpp" #include "barretenberg/common/op_count.hpp" #include "barretenberg/common/thread.hpp" +#include "barretenberg/stdlib/primitives/bool/bool.hpp" #include #include @@ -63,6 +64,21 @@ template struct PowPolynomial { */ FF univariate_eval(FF challenge) const { return (FF(1) + (challenge * (betas[current_element_idx] - FF(1)))); }; + /** + * @brief Evaluate \f$ ((1−X_{i}) + X_{i}\cdot \beta_{i})\f$ at the challenge point \f$ X_{i}=u_{i} \f$. + */ + template FF univariate_eval(const FF& challenge, const Bool& dummy_round) const + { + FF beta_or_dummy; + if (!dummy_round.get_value()) { + beta_or_dummy = betas[current_element_idx]; + } else { + beta_or_dummy = FF::from_witness(challenge.get_context(), 1); + } + FF beta_val = FF::conditional_assign(dummy_round, FF::from_witness(challenge.get_context(), 1), beta_or_dummy); + return (FF(1) + (challenge * (beta_val - FF(1)))); + } + /** * @brief Partially evaluate the \f$pow_{\beta} \f$-polynomial at the new challenge and update \f$ c_i \f$ * @details Update the constant \f$c_{i} \to c_{i+1} \f$ multiplying it by \f$pow_{\beta}\f$'s factor \f$\left( @@ -77,6 +93,22 @@ template struct PowPolynomial { periodicity *= 2; } + /** + * @brief Partially evaluate the \f$pow_{\beta} \f$-polynomial at the new challenge and update \f$ c_i \f$ + * @details Update the constant \f$c_{i} \to c_{i+1} \f$ multiplying it by \f$pow_{\beta}\f$'s factor \f$\left( + * (1-X_i) + X_i\cdot \beta_i\right)\vert_{X_i = u_i}\f$ computed by \ref univariate_eval. + * @param challenge \f$ i \f$-th verifier challenge \f$ u_{i}\f$ + */ + template void partially_evaluate(const FF& challenge, const stdlib::bool_t& dummy) + { + FF current_univariate_eval = univariate_eval(challenge, dummy); + // If dummy round, make no update to the partial_evaluation_result + partial_evaluation_result = FF::conditional_assign( + dummy, partial_evaluation_result, partial_evaluation_result * current_univariate_eval); + current_element_idx++; + periodicity *= 2; + } + /** * @brief Given \f$ \vec\beta = (\beta_0,...,\beta_{d-1})\f$ compute \f$ pow_{\ell}(\vec \beta) = pow_{\beta}(\vec * \ell)\f$ for \f$ \ell =0,\ldots,2^{d}-1\f$. diff --git a/barretenberg/cpp/src/barretenberg/protogalaxy/decider_verifier.cpp b/barretenberg/cpp/src/barretenberg/protogalaxy/decider_verifier.cpp index 5ae609a0e9a..080a4f322f0 100644 --- a/barretenberg/cpp/src/barretenberg/protogalaxy/decider_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/protogalaxy/decider_verifier.cpp @@ -44,12 +44,14 @@ template bool DeciderVerifier_::verify_proof(const Hon // If Sumcheck did not verify, return false if (sumcheck_verified.has_value() && !sumcheck_verified.value()) { + info("Sumcheck verification failed."); return false; } // Execute ZeroMorph rounds. See https://hackmd.io/dlf9xEwhTQyE3hiGbq4FsA?view for a complete description of the // unrolled protocol. - auto opening_claim = ZeroMorph::verify(commitments.get_unshifted(), + auto opening_claim = ZeroMorph::verify(accumulator->verification_key->circuit_size, + commitments.get_unshifted(), commitments.get_to_be_shifted(), claimed_evaluations.get_unshifted(), claimed_evaluations.get_shifted(), diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/declare_views.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/declare_views.hpp index 2cdb82e6d1e..c50b8825f71 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/declare_views.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/declare_views.hpp @@ -8,6 +8,7 @@ [[maybe_unused]] auto kernel_kernel_value_out = View(new_term.kernel_kernel_value_out); \ [[maybe_unused]] auto kernel_kernel_side_effect_out = View(new_term.kernel_kernel_side_effect_out); \ [[maybe_unused]] auto kernel_kernel_metadata_out = View(new_term.kernel_kernel_metadata_out); \ + [[maybe_unused]] auto main_calldata = View(new_term.main_calldata); \ [[maybe_unused]] auto alu_a_hi = View(new_term.alu_a_hi); \ [[maybe_unused]] auto alu_a_lo = View(new_term.alu_a_lo); \ [[maybe_unused]] auto alu_b_hi = View(new_term.alu_b_hi); \ @@ -210,6 +211,7 @@ [[maybe_unused]] auto main_sel_op_fdiv = View(new_term.main_sel_op_fdiv); \ [[maybe_unused]] auto main_sel_op_fee_per_da_gas = View(new_term.main_sel_op_fee_per_da_gas); \ [[maybe_unused]] auto main_sel_op_fee_per_l2_gas = View(new_term.main_sel_op_fee_per_l2_gas); \ + [[maybe_unused]] auto main_sel_op_function_selector = View(new_term.main_sel_op_function_selector); \ [[maybe_unused]] auto main_sel_op_get_contract_instance = View(new_term.main_sel_op_get_contract_instance); \ [[maybe_unused]] auto main_sel_op_halt = View(new_term.main_sel_op_halt); \ [[maybe_unused]] auto main_sel_op_internal_call = View(new_term.main_sel_op_internal_call); \ diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/main.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/main.hpp index 360aa5af82b..5491bd8a586 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/main.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/main.hpp @@ -84,6 +84,7 @@ template struct MainRow { FF main_sel_op_fdiv{}; FF main_sel_op_fee_per_da_gas{}; FF main_sel_op_fee_per_l2_gas{}; + FF main_sel_op_function_selector{}; FF main_sel_op_get_contract_instance{}; FF main_sel_op_halt{}; FF main_sel_op_internal_call{}; @@ -144,80 +145,77 @@ inline std::string get_relation_label_main(int index) case 5: return "DA_GAS_INACTIVE"; - case 74: + case 75: return "OUTPUT_U8"; - case 75: + case 76: return "SUBOP_FDIV"; - case 76: + case 77: return "SUBOP_FDIV_ZERO_ERR1"; - case 77: + case 78: return "SUBOP_FDIV_ZERO_ERR2"; - case 78: + case 79: return "SUBOP_FDIV_R_IN_TAG_FF"; - case 79: + case 80: return "SUBOP_FDIV_W_IN_TAG_FF"; - case 80: + case 81: return "SUBOP_ERROR_RELEVANT_OP"; - case 81: + case 82: return "KERNEL_INPUT_ACTIVE_CHECK"; - case 82: + case 83: return "KERNEL_OUTPUT_ACTIVE_CHECK"; - case 83: + case 84: return "PC_JUMP"; - case 84: + case 85: return "PC_JUMPI"; - case 85: + case 86: return "RETURN_POINTER_INCREMENT"; - case 91: + case 92: return "RETURN_POINTER_DECREMENT"; - case 97: + case 98: return "PC_INCREMENT"; - case 98: + case 99: return "INTERNAL_RETURN_POINTER_CONSISTENCY"; - case 99: + case 100: return "SPACE_ID_INTERNAL"; - case 100: + case 101: return "SPACE_ID_STANDARD_OPCODES"; - case 101: + case 102: return "CMOV_CONDITION_RES_1"; - case 102: + case 103: return "CMOV_CONDITION_RES_2"; - case 105: + case 106: return "MOV_SAME_VALUE_A"; - case 106: + case 107: return "MOV_SAME_VALUE_B"; - case 107: + case 108: return "MOV_MAIN_SAME_TAG"; - case 111: - return "L2GASLEFT"; - case 112: - return "DAGASLEFT"; + return "L2GASLEFT"; case 113: - return "SENDER_KERNEL"; + return "DAGASLEFT"; case 114: return "ADDRESS_KERNEL"; @@ -226,10 +224,10 @@ inline std::string get_relation_label_main(int index) return "STORAGE_ADDRESS_KERNEL"; case 116: - return "FEE_DA_GAS_KERNEL"; + return "SENDER_KERNEL"; case 117: - return "FEE_L2_GAS_KERNEL"; + return "FUNCTION_SELECTOR_KERNEL"; case 118: return "FEE_TRANSACTION_FEE_KERNEL"; @@ -244,42 +242,48 @@ inline std::string get_relation_label_main(int index) return "BLOCK_NUMBER_KERNEL"; case 122: - return "COINBASE_KERNEL"; + return "TIMESTAMP_KERNEL"; case 123: - return "TIMESTAMP_KERNEL"; + return "COINBASE_KERNEL"; case 124: - return "NOTE_HASH_KERNEL_OUTPUT"; + return "FEE_DA_GAS_KERNEL"; + + case 125: + return "FEE_L2_GAS_KERNEL"; case 126: - return "EMIT_NOTE_HASH_KERNEL_OUTPUT"; + return "NOTE_HASH_KERNEL_OUTPUT"; case 128: + return "EMIT_NOTE_HASH_KERNEL_OUTPUT"; + + case 130: return "NULLIFIER_EXISTS_KERNEL_OUTPUT"; - case 131: + case 133: return "EMIT_NULLIFIER_KERNEL_OUTPUT"; - case 133: + case 135: return "L1_TO_L2_MSG_EXISTS_KERNEL_OUTPUT"; - case 135: + case 137: return "EMIT_UNENCRYPTED_LOG_KERNEL_OUTPUT"; - case 137: + case 139: return "EMIT_L2_TO_L1_MSGS_KERNEL_OUTPUT"; - case 139: + case 141: return "SLOAD_KERNEL_OUTPUT"; - case 141: + case 143: return "SSTORE_KERNEL_OUTPUT"; - case 144: + case 146: return "BIN_SEL_1"; - case 145: + case 147: return "BIN_SEL_2"; } return std::to_string(index); @@ -289,11 +293,11 @@ template class mainImpl { public: using FF = FF_; - static constexpr std::array SUBRELATION_PARTIAL_LENGTHS{ + static constexpr std::array SUBRELATION_PARTIAL_LENGTHS{ 3, 3, 3, 3, 3, 3, 5, 5, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 5, 4, 4, 3, 3, 3, 3, 3, 3, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 5, 3, 3, 3, 4, 4, 3, 3, 3, 3, 3, 4, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, + 3, 3, 5, 4, 4, 3, 3, 3, 3, 3, 3, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 5, 3, 3, 3, 4, 4, 3, 3, 3, 3, 3, 4, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, }; template @@ -379,7 +383,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(8); - auto tmp = (main_sel_op_sender * (-main_sel_op_sender + FF(1))); + auto tmp = (main_sel_op_address * (-main_sel_op_address + FF(1))); tmp *= scaling_factor; std::get<8>(evals) += tmp; } @@ -387,7 +391,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(9); - auto tmp = (main_sel_op_address * (-main_sel_op_address + FF(1))); + auto tmp = (main_sel_op_storage_address * (-main_sel_op_storage_address + FF(1))); tmp *= scaling_factor; std::get<9>(evals) += tmp; } @@ -395,7 +399,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(10); - auto tmp = (main_sel_op_storage_address * (-main_sel_op_storage_address + FF(1))); + auto tmp = (main_sel_op_sender * (-main_sel_op_sender + FF(1))); tmp *= scaling_factor; std::get<10>(evals) += tmp; } @@ -403,7 +407,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(11); - auto tmp = (main_sel_op_chain_id * (-main_sel_op_chain_id + FF(1))); + auto tmp = (main_sel_op_function_selector * (-main_sel_op_function_selector + FF(1))); tmp *= scaling_factor; std::get<11>(evals) += tmp; } @@ -411,7 +415,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(12); - auto tmp = (main_sel_op_version * (-main_sel_op_version + FF(1))); + auto tmp = (main_sel_op_transaction_fee * (-main_sel_op_transaction_fee + FF(1))); tmp *= scaling_factor; std::get<12>(evals) += tmp; } @@ -419,7 +423,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(13); - auto tmp = (main_sel_op_block_number * (-main_sel_op_block_number + FF(1))); + auto tmp = (main_sel_op_chain_id * (-main_sel_op_chain_id + FF(1))); tmp *= scaling_factor; std::get<13>(evals) += tmp; } @@ -427,7 +431,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(14); - auto tmp = (main_sel_op_coinbase * (-main_sel_op_coinbase + FF(1))); + auto tmp = (main_sel_op_version * (-main_sel_op_version + FF(1))); tmp *= scaling_factor; std::get<14>(evals) += tmp; } @@ -435,7 +439,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(15); - auto tmp = (main_sel_op_timestamp * (-main_sel_op_timestamp + FF(1))); + auto tmp = (main_sel_op_block_number * (-main_sel_op_block_number + FF(1))); tmp *= scaling_factor; std::get<15>(evals) += tmp; } @@ -443,7 +447,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(16); - auto tmp = (main_sel_op_fee_per_l2_gas * (-main_sel_op_fee_per_l2_gas + FF(1))); + auto tmp = (main_sel_op_coinbase * (-main_sel_op_coinbase + FF(1))); tmp *= scaling_factor; std::get<16>(evals) += tmp; } @@ -451,7 +455,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(17); - auto tmp = (main_sel_op_fee_per_da_gas * (-main_sel_op_fee_per_da_gas + FF(1))); + auto tmp = (main_sel_op_timestamp * (-main_sel_op_timestamp + FF(1))); tmp *= scaling_factor; std::get<17>(evals) += tmp; } @@ -459,7 +463,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(18); - auto tmp = (main_sel_op_transaction_fee * (-main_sel_op_transaction_fee + FF(1))); + auto tmp = (main_sel_op_fee_per_l2_gas * (-main_sel_op_fee_per_l2_gas + FF(1))); tmp *= scaling_factor; std::get<18>(evals) += tmp; } @@ -467,7 +471,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(19); - auto tmp = (main_sel_op_l2gasleft * (-main_sel_op_l2gasleft + FF(1))); + auto tmp = (main_sel_op_fee_per_da_gas * (-main_sel_op_fee_per_da_gas + FF(1))); tmp *= scaling_factor; std::get<19>(evals) += tmp; } @@ -475,7 +479,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(20); - auto tmp = (main_sel_op_dagasleft * (-main_sel_op_dagasleft + FF(1))); + auto tmp = (main_sel_op_l2gasleft * (-main_sel_op_l2gasleft + FF(1))); tmp *= scaling_factor; std::get<20>(evals) += tmp; } @@ -483,7 +487,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(21); - auto tmp = (main_sel_op_note_hash_exists * (-main_sel_op_note_hash_exists + FF(1))); + auto tmp = (main_sel_op_dagasleft * (-main_sel_op_dagasleft + FF(1))); tmp *= scaling_factor; std::get<21>(evals) += tmp; } @@ -491,7 +495,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(22); - auto tmp = (main_sel_op_emit_note_hash * (-main_sel_op_emit_note_hash + FF(1))); + auto tmp = (main_sel_op_note_hash_exists * (-main_sel_op_note_hash_exists + FF(1))); tmp *= scaling_factor; std::get<22>(evals) += tmp; } @@ -499,7 +503,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(23); - auto tmp = (main_sel_op_nullifier_exists * (-main_sel_op_nullifier_exists + FF(1))); + auto tmp = (main_sel_op_emit_note_hash * (-main_sel_op_emit_note_hash + FF(1))); tmp *= scaling_factor; std::get<23>(evals) += tmp; } @@ -507,7 +511,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(24); - auto tmp = (main_sel_op_emit_nullifier * (-main_sel_op_emit_nullifier + FF(1))); + auto tmp = (main_sel_op_nullifier_exists * (-main_sel_op_nullifier_exists + FF(1))); tmp *= scaling_factor; std::get<24>(evals) += tmp; } @@ -515,7 +519,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(25); - auto tmp = (main_sel_op_l1_to_l2_msg_exists * (-main_sel_op_l1_to_l2_msg_exists + FF(1))); + auto tmp = (main_sel_op_emit_nullifier * (-main_sel_op_emit_nullifier + FF(1))); tmp *= scaling_factor; std::get<25>(evals) += tmp; } @@ -523,7 +527,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(26); - auto tmp = (main_sel_op_emit_unencrypted_log * (-main_sel_op_emit_unencrypted_log + FF(1))); + auto tmp = (main_sel_op_l1_to_l2_msg_exists * (-main_sel_op_l1_to_l2_msg_exists + FF(1))); tmp *= scaling_factor; std::get<26>(evals) += tmp; } @@ -531,7 +535,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(27); - auto tmp = (main_sel_op_emit_l2_to_l1_msg * (-main_sel_op_emit_l2_to_l1_msg + FF(1))); + auto tmp = (main_sel_op_emit_unencrypted_log * (-main_sel_op_emit_unencrypted_log + FF(1))); tmp *= scaling_factor; std::get<27>(evals) += tmp; } @@ -539,7 +543,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(28); - auto tmp = (main_sel_op_get_contract_instance * (-main_sel_op_get_contract_instance + FF(1))); + auto tmp = (main_sel_op_emit_l2_to_l1_msg * (-main_sel_op_emit_l2_to_l1_msg + FF(1))); tmp *= scaling_factor; std::get<28>(evals) += tmp; } @@ -547,7 +551,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(29); - auto tmp = (main_sel_op_sload * (-main_sel_op_sload + FF(1))); + auto tmp = (main_sel_op_get_contract_instance * (-main_sel_op_get_contract_instance + FF(1))); tmp *= scaling_factor; std::get<29>(evals) += tmp; } @@ -555,7 +559,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(30); - auto tmp = (main_sel_op_sstore * (-main_sel_op_sstore + FF(1))); + auto tmp = (main_sel_op_sload * (-main_sel_op_sload + FF(1))); tmp *= scaling_factor; std::get<30>(evals) += tmp; } @@ -563,7 +567,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(31); - auto tmp = (main_sel_op_radix_le * (-main_sel_op_radix_le + FF(1))); + auto tmp = (main_sel_op_sstore * (-main_sel_op_sstore + FF(1))); tmp *= scaling_factor; std::get<31>(evals) += tmp; } @@ -571,7 +575,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(32); - auto tmp = (main_sel_op_sha256 * (-main_sel_op_sha256 + FF(1))); + auto tmp = (main_sel_op_radix_le * (-main_sel_op_radix_le + FF(1))); tmp *= scaling_factor; std::get<32>(evals) += tmp; } @@ -579,7 +583,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(33); - auto tmp = (main_sel_op_poseidon2 * (-main_sel_op_poseidon2 + FF(1))); + auto tmp = (main_sel_op_sha256 * (-main_sel_op_sha256 + FF(1))); tmp *= scaling_factor; std::get<33>(evals) += tmp; } @@ -587,7 +591,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(34); - auto tmp = (main_sel_op_keccak * (-main_sel_op_keccak + FF(1))); + auto tmp = (main_sel_op_poseidon2 * (-main_sel_op_poseidon2 + FF(1))); tmp *= scaling_factor; std::get<34>(evals) += tmp; } @@ -595,7 +599,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(35); - auto tmp = (main_sel_op_pedersen * (-main_sel_op_pedersen + FF(1))); + auto tmp = (main_sel_op_keccak * (-main_sel_op_keccak + FF(1))); tmp *= scaling_factor; std::get<35>(evals) += tmp; } @@ -603,7 +607,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(36); - auto tmp = (main_sel_op_add * (-main_sel_op_add + FF(1))); + auto tmp = (main_sel_op_pedersen * (-main_sel_op_pedersen + FF(1))); tmp *= scaling_factor; std::get<36>(evals) += tmp; } @@ -611,7 +615,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(37); - auto tmp = (main_sel_op_sub * (-main_sel_op_sub + FF(1))); + auto tmp = (main_sel_op_add * (-main_sel_op_add + FF(1))); tmp *= scaling_factor; std::get<37>(evals) += tmp; } @@ -619,7 +623,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(38); - auto tmp = (main_sel_op_mul * (-main_sel_op_mul + FF(1))); + auto tmp = (main_sel_op_sub * (-main_sel_op_sub + FF(1))); tmp *= scaling_factor; std::get<38>(evals) += tmp; } @@ -627,7 +631,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(39); - auto tmp = (main_sel_op_div * (-main_sel_op_div + FF(1))); + auto tmp = (main_sel_op_mul * (-main_sel_op_mul + FF(1))); tmp *= scaling_factor; std::get<39>(evals) += tmp; } @@ -635,7 +639,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(40); - auto tmp = (main_sel_op_fdiv * (-main_sel_op_fdiv + FF(1))); + auto tmp = (main_sel_op_div * (-main_sel_op_div + FF(1))); tmp *= scaling_factor; std::get<40>(evals) += tmp; } @@ -643,7 +647,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(41); - auto tmp = (main_sel_op_not * (-main_sel_op_not + FF(1))); + auto tmp = (main_sel_op_fdiv * (-main_sel_op_fdiv + FF(1))); tmp *= scaling_factor; std::get<41>(evals) += tmp; } @@ -651,7 +655,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(42); - auto tmp = (main_sel_op_eq * (-main_sel_op_eq + FF(1))); + auto tmp = (main_sel_op_not * (-main_sel_op_not + FF(1))); tmp *= scaling_factor; std::get<42>(evals) += tmp; } @@ -659,7 +663,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(43); - auto tmp = (main_sel_op_and * (-main_sel_op_and + FF(1))); + auto tmp = (main_sel_op_eq * (-main_sel_op_eq + FF(1))); tmp *= scaling_factor; std::get<43>(evals) += tmp; } @@ -667,7 +671,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(44); - auto tmp = (main_sel_op_or * (-main_sel_op_or + FF(1))); + auto tmp = (main_sel_op_and * (-main_sel_op_and + FF(1))); tmp *= scaling_factor; std::get<44>(evals) += tmp; } @@ -675,7 +679,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(45); - auto tmp = (main_sel_op_xor * (-main_sel_op_xor + FF(1))); + auto tmp = (main_sel_op_or * (-main_sel_op_or + FF(1))); tmp *= scaling_factor; std::get<45>(evals) += tmp; } @@ -683,7 +687,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(46); - auto tmp = (main_sel_op_cast * (-main_sel_op_cast + FF(1))); + auto tmp = (main_sel_op_xor * (-main_sel_op_xor + FF(1))); tmp *= scaling_factor; std::get<46>(evals) += tmp; } @@ -691,7 +695,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(47); - auto tmp = (main_sel_op_lt * (-main_sel_op_lt + FF(1))); + auto tmp = (main_sel_op_cast * (-main_sel_op_cast + FF(1))); tmp *= scaling_factor; std::get<47>(evals) += tmp; } @@ -699,7 +703,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(48); - auto tmp = (main_sel_op_lte * (-main_sel_op_lte + FF(1))); + auto tmp = (main_sel_op_lt * (-main_sel_op_lt + FF(1))); tmp *= scaling_factor; std::get<48>(evals) += tmp; } @@ -707,7 +711,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(49); - auto tmp = (main_sel_op_shl * (-main_sel_op_shl + FF(1))); + auto tmp = (main_sel_op_lte * (-main_sel_op_lte + FF(1))); tmp *= scaling_factor; std::get<49>(evals) += tmp; } @@ -715,7 +719,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(50); - auto tmp = (main_sel_op_shr * (-main_sel_op_shr + FF(1))); + auto tmp = (main_sel_op_shl * (-main_sel_op_shl + FF(1))); tmp *= scaling_factor; std::get<50>(evals) += tmp; } @@ -723,7 +727,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(51); - auto tmp = (main_sel_op_internal_call * (-main_sel_op_internal_call + FF(1))); + auto tmp = (main_sel_op_shr * (-main_sel_op_shr + FF(1))); tmp *= scaling_factor; std::get<51>(evals) += tmp; } @@ -731,7 +735,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(52); - auto tmp = (main_sel_op_internal_return * (-main_sel_op_internal_return + FF(1))); + auto tmp = (main_sel_op_internal_call * (-main_sel_op_internal_call + FF(1))); tmp *= scaling_factor; std::get<52>(evals) += tmp; } @@ -739,7 +743,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(53); - auto tmp = (main_sel_op_jump * (-main_sel_op_jump + FF(1))); + auto tmp = (main_sel_op_internal_return * (-main_sel_op_internal_return + FF(1))); tmp *= scaling_factor; std::get<53>(evals) += tmp; } @@ -747,7 +751,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(54); - auto tmp = (main_sel_op_jumpi * (-main_sel_op_jumpi + FF(1))); + auto tmp = (main_sel_op_jump * (-main_sel_op_jump + FF(1))); tmp *= scaling_factor; std::get<54>(evals) += tmp; } @@ -755,7 +759,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(55); - auto tmp = (main_sel_op_halt * (-main_sel_op_halt + FF(1))); + auto tmp = (main_sel_op_jumpi * (-main_sel_op_jumpi + FF(1))); tmp *= scaling_factor; std::get<55>(evals) += tmp; } @@ -763,7 +767,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(56); - auto tmp = (main_sel_op_external_call * (-main_sel_op_external_call + FF(1))); + auto tmp = (main_sel_op_halt * (-main_sel_op_halt + FF(1))); tmp *= scaling_factor; std::get<56>(evals) += tmp; } @@ -771,7 +775,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(57); - auto tmp = (main_sel_op_mov * (-main_sel_op_mov + FF(1))); + auto tmp = (main_sel_op_external_call * (-main_sel_op_external_call + FF(1))); tmp *= scaling_factor; std::get<57>(evals) += tmp; } @@ -779,7 +783,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(58); - auto tmp = (main_sel_op_cmov * (-main_sel_op_cmov + FF(1))); + auto tmp = (main_sel_op_mov * (-main_sel_op_mov + FF(1))); tmp *= scaling_factor; std::get<58>(evals) += tmp; } @@ -787,7 +791,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(59); - auto tmp = (main_op_err * (-main_op_err + FF(1))); + auto tmp = (main_sel_op_cmov * (-main_sel_op_cmov + FF(1))); tmp *= scaling_factor; std::get<59>(evals) += tmp; } @@ -795,7 +799,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(60); - auto tmp = (main_tag_err * (-main_tag_err + FF(1))); + auto tmp = (main_op_err * (-main_op_err + FF(1))); tmp *= scaling_factor; std::get<60>(evals) += tmp; } @@ -803,7 +807,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(61); - auto tmp = (main_id_zero * (-main_id_zero + FF(1))); + auto tmp = (main_tag_err * (-main_tag_err + FF(1))); tmp *= scaling_factor; std::get<61>(evals) += tmp; } @@ -811,7 +815,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(62); - auto tmp = (main_sel_mem_op_a * (-main_sel_mem_op_a + FF(1))); + auto tmp = (main_id_zero * (-main_id_zero + FF(1))); tmp *= scaling_factor; std::get<62>(evals) += tmp; } @@ -819,7 +823,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(63); - auto tmp = (main_sel_mem_op_b * (-main_sel_mem_op_b + FF(1))); + auto tmp = (main_sel_mem_op_a * (-main_sel_mem_op_a + FF(1))); tmp *= scaling_factor; std::get<63>(evals) += tmp; } @@ -827,7 +831,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(64); - auto tmp = (main_sel_mem_op_c * (-main_sel_mem_op_c + FF(1))); + auto tmp = (main_sel_mem_op_b * (-main_sel_mem_op_b + FF(1))); tmp *= scaling_factor; std::get<64>(evals) += tmp; } @@ -835,7 +839,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(65); - auto tmp = (main_sel_mem_op_d * (-main_sel_mem_op_d + FF(1))); + auto tmp = (main_sel_mem_op_c * (-main_sel_mem_op_c + FF(1))); tmp *= scaling_factor; std::get<65>(evals) += tmp; } @@ -843,7 +847,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(66); - auto tmp = (main_rwa * (-main_rwa + FF(1))); + auto tmp = (main_sel_mem_op_d * (-main_sel_mem_op_d + FF(1))); tmp *= scaling_factor; std::get<66>(evals) += tmp; } @@ -851,7 +855,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(67); - auto tmp = (main_rwb * (-main_rwb + FF(1))); + auto tmp = (main_rwa * (-main_rwa + FF(1))); tmp *= scaling_factor; std::get<67>(evals) += tmp; } @@ -859,7 +863,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(68); - auto tmp = (main_rwc * (-main_rwc + FF(1))); + auto tmp = (main_rwb * (-main_rwb + FF(1))); tmp *= scaling_factor; std::get<68>(evals) += tmp; } @@ -867,7 +871,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(69); - auto tmp = (main_rwd * (-main_rwd + FF(1))); + auto tmp = (main_rwc * (-main_rwc + FF(1))); tmp *= scaling_factor; std::get<69>(evals) += tmp; } @@ -875,7 +879,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(70); - auto tmp = (main_sel_resolve_ind_addr_a * (-main_sel_resolve_ind_addr_a + FF(1))); + auto tmp = (main_rwd * (-main_rwd + FF(1))); tmp *= scaling_factor; std::get<70>(evals) += tmp; } @@ -883,7 +887,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(71); - auto tmp = (main_sel_resolve_ind_addr_b * (-main_sel_resolve_ind_addr_b + FF(1))); + auto tmp = (main_sel_resolve_ind_addr_a * (-main_sel_resolve_ind_addr_a + FF(1))); tmp *= scaling_factor; std::get<71>(evals) += tmp; } @@ -891,7 +895,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(72); - auto tmp = (main_sel_resolve_ind_addr_c * (-main_sel_resolve_ind_addr_c + FF(1))); + auto tmp = (main_sel_resolve_ind_addr_b * (-main_sel_resolve_ind_addr_b + FF(1))); tmp *= scaling_factor; std::get<72>(evals) += tmp; } @@ -899,7 +903,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(73); - auto tmp = (main_sel_resolve_ind_addr_d * (-main_sel_resolve_ind_addr_d + FF(1))); + auto tmp = (main_sel_resolve_ind_addr_c * (-main_sel_resolve_ind_addr_c + FF(1))); tmp *= scaling_factor; std::get<73>(evals) += tmp; } @@ -907,7 +911,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(74); - auto tmp = (((main_sel_op_eq + main_sel_op_lte) + main_sel_op_lt) * (main_w_in_tag - FF(1))); + auto tmp = (main_sel_resolve_ind_addr_d * (-main_sel_resolve_ind_addr_d + FF(1))); tmp *= scaling_factor; std::get<74>(evals) += tmp; } @@ -915,7 +919,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(75); - auto tmp = ((main_sel_op_fdiv * (-main_op_err + FF(1))) * ((main_ic * main_ib) - main_ia)); + auto tmp = (((main_sel_op_eq + main_sel_op_lte) + main_sel_op_lt) * (main_w_in_tag - FF(1))); tmp *= scaling_factor; std::get<75>(evals) += tmp; } @@ -923,7 +927,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(76); - auto tmp = ((main_sel_op_fdiv + main_sel_op_div) * (((main_ib * main_inv) - FF(1)) + main_op_err)); + auto tmp = ((main_sel_op_fdiv * (-main_op_err + FF(1))) * ((main_ic * main_ib) - main_ia)); tmp *= scaling_factor; std::get<76>(evals) += tmp; } @@ -931,7 +935,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(77); - auto tmp = (((main_sel_op_fdiv + main_sel_op_div) * main_op_err) * (-main_inv + FF(1))); + auto tmp = ((main_sel_op_fdiv + main_sel_op_div) * (((main_ib * main_inv) - FF(1)) + main_op_err)); tmp *= scaling_factor; std::get<77>(evals) += tmp; } @@ -939,7 +943,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(78); - auto tmp = (main_sel_op_fdiv * (main_r_in_tag - FF(6))); + auto tmp = (((main_sel_op_fdiv + main_sel_op_div) * main_op_err) * (-main_inv + FF(1))); tmp *= scaling_factor; std::get<78>(evals) += tmp; } @@ -947,7 +951,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(79); - auto tmp = (main_sel_op_fdiv * (main_w_in_tag - FF(6))); + auto tmp = (main_sel_op_fdiv * (main_r_in_tag - FF(6))); tmp *= scaling_factor; std::get<79>(evals) += tmp; } @@ -955,7 +959,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(80); - auto tmp = (main_op_err * ((main_sel_op_fdiv + main_sel_op_div) - FF(1))); + auto tmp = (main_sel_op_fdiv * (main_w_in_tag - FF(6))); tmp *= scaling_factor; std::get<80>(evals) += tmp; } @@ -963,16 +967,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(81); - auto tmp = (((((((((((main_sel_op_sender + main_sel_op_address) + main_sel_op_storage_address) + - main_sel_op_chain_id) + - main_sel_op_version) + - main_sel_op_block_number) + - main_sel_op_coinbase) + - main_sel_op_timestamp) + - main_sel_op_fee_per_l2_gas) + - main_sel_op_fee_per_da_gas) + - main_sel_op_transaction_fee) * - (-main_sel_q_kernel_lookup + FF(1))); + auto tmp = (main_op_err * ((main_sel_op_fdiv + main_sel_op_div) - FF(1))); tmp *= scaling_factor; std::get<81>(evals) += tmp; } @@ -980,13 +975,17 @@ template class mainImpl { { Avm_DECLARE_VIEWS(82); - auto tmp = - (((((((main_sel_op_note_hash_exists + main_sel_op_emit_note_hash) + main_sel_op_nullifier_exists) + - main_sel_op_emit_nullifier) + - main_sel_op_l1_to_l2_msg_exists) + - main_sel_op_emit_unencrypted_log) + - main_sel_op_emit_l2_to_l1_msg) * - (-main_sel_q_kernel_output_lookup + FF(1))); + auto tmp = ((((((((((((main_sel_op_address + main_sel_op_storage_address) + main_sel_op_sender) + + main_sel_op_function_selector) + + main_sel_op_transaction_fee) + + main_sel_op_chain_id) + + main_sel_op_version) + + main_sel_op_block_number) + + main_sel_op_coinbase) + + main_sel_op_timestamp) + + main_sel_op_fee_per_l2_gas) + + main_sel_op_fee_per_da_gas) * + (-main_sel_q_kernel_lookup + FF(1))); tmp *= scaling_factor; std::get<82>(evals) += tmp; } @@ -994,7 +993,13 @@ template class mainImpl { { Avm_DECLARE_VIEWS(83); - auto tmp = (main_sel_op_jump * (main_pc_shift - main_ia)); + auto tmp = + (((((((main_sel_op_note_hash_exists + main_sel_op_emit_note_hash) + main_sel_op_nullifier_exists) + + main_sel_op_emit_nullifier) + + main_sel_op_l1_to_l2_msg_exists) + + main_sel_op_emit_unencrypted_log) + + main_sel_op_emit_l2_to_l1_msg) * + (-main_sel_q_kernel_output_lookup + FF(1))); tmp *= scaling_factor; std::get<83>(evals) += tmp; } @@ -1002,8 +1007,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(84); - auto tmp = (main_sel_op_jumpi * (((-main_id_zero + FF(1)) * (main_pc_shift - main_ia)) + - (main_id_zero * ((main_pc_shift - main_pc) - FF(1))))); + auto tmp = (main_sel_op_jump * (main_pc_shift - main_ia)); tmp *= scaling_factor; std::get<84>(evals) += tmp; } @@ -1011,8 +1015,8 @@ template class mainImpl { { Avm_DECLARE_VIEWS(85); - auto tmp = - (main_sel_op_internal_call * (main_internal_return_ptr_shift - (main_internal_return_ptr + FF(1)))); + auto tmp = (main_sel_op_jumpi * (((-main_id_zero + FF(1)) * (main_pc_shift - main_ia)) + + (main_id_zero * ((main_pc_shift - main_pc) - FF(1))))); tmp *= scaling_factor; std::get<85>(evals) += tmp; } @@ -1020,7 +1024,8 @@ template class mainImpl { { Avm_DECLARE_VIEWS(86); - auto tmp = (main_sel_op_internal_call * (main_internal_return_ptr - main_mem_addr_b)); + auto tmp = + (main_sel_op_internal_call * (main_internal_return_ptr_shift - (main_internal_return_ptr + FF(1)))); tmp *= scaling_factor; std::get<86>(evals) += tmp; } @@ -1028,7 +1033,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(87); - auto tmp = (main_sel_op_internal_call * (main_pc_shift - main_ia)); + auto tmp = (main_sel_op_internal_call * (main_internal_return_ptr - main_mem_addr_b)); tmp *= scaling_factor; std::get<87>(evals) += tmp; } @@ -1036,7 +1041,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(88); - auto tmp = (main_sel_op_internal_call * ((main_pc + FF(1)) - main_ib)); + auto tmp = (main_sel_op_internal_call * (main_pc_shift - main_ia)); tmp *= scaling_factor; std::get<88>(evals) += tmp; } @@ -1044,7 +1049,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(89); - auto tmp = (main_sel_op_internal_call * (main_rwb - FF(1))); + auto tmp = (main_sel_op_internal_call * ((main_pc + FF(1)) - main_ib)); tmp *= scaling_factor; std::get<89>(evals) += tmp; } @@ -1052,7 +1057,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(90); - auto tmp = (main_sel_op_internal_call * (main_sel_mem_op_b - FF(1))); + auto tmp = (main_sel_op_internal_call * (main_rwb - FF(1))); tmp *= scaling_factor; std::get<90>(evals) += tmp; } @@ -1060,8 +1065,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(91); - auto tmp = - (main_sel_op_internal_return * (main_internal_return_ptr_shift - (main_internal_return_ptr - FF(1)))); + auto tmp = (main_sel_op_internal_call * (main_sel_mem_op_b - FF(1))); tmp *= scaling_factor; std::get<91>(evals) += tmp; } @@ -1069,7 +1073,8 @@ template class mainImpl { { Avm_DECLARE_VIEWS(92); - auto tmp = (main_sel_op_internal_return * ((main_internal_return_ptr - FF(1)) - main_mem_addr_a)); + auto tmp = + (main_sel_op_internal_return * (main_internal_return_ptr_shift - (main_internal_return_ptr - FF(1)))); tmp *= scaling_factor; std::get<92>(evals) += tmp; } @@ -1077,7 +1082,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(93); - auto tmp = (main_sel_op_internal_return * (main_pc_shift - main_ia)); + auto tmp = (main_sel_op_internal_return * ((main_internal_return_ptr - FF(1)) - main_mem_addr_a)); tmp *= scaling_factor; std::get<93>(evals) += tmp; } @@ -1085,7 +1090,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(94); - auto tmp = (main_sel_op_internal_return * main_rwa); + auto tmp = (main_sel_op_internal_return * (main_pc_shift - main_ia)); tmp *= scaling_factor; std::get<94>(evals) += tmp; } @@ -1093,7 +1098,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(95); - auto tmp = (main_sel_op_internal_return * (main_sel_mem_op_a - FF(1))); + auto tmp = (main_sel_op_internal_return * main_rwa); tmp *= scaling_factor; std::get<95>(evals) += tmp; } @@ -1101,6 +1106,14 @@ template class mainImpl { { Avm_DECLARE_VIEWS(96); + auto tmp = (main_sel_op_internal_return * (main_sel_mem_op_a - FF(1))); + tmp *= scaling_factor; + std::get<96>(evals) += tmp; + } + // Contribution 97 + { + Avm_DECLARE_VIEWS(97); + auto tmp = (((((main_sel_gas_accounting_active - (((((((main_sel_op_fdiv + @@ -1116,15 +1129,16 @@ template class mainImpl { (main_sel_op_cmov + main_sel_op_mov)) + ((((main_sel_op_radix_le + main_sel_op_sha256) + main_sel_op_poseidon2) + main_sel_op_keccak) + main_sel_op_pedersen)) + - ((((((((((main_sel_op_sender + main_sel_op_address) + main_sel_op_storage_address) + - main_sel_op_chain_id) + - main_sel_op_version) + - main_sel_op_block_number) + - main_sel_op_coinbase) + - main_sel_op_timestamp) + - main_sel_op_fee_per_l2_gas) + - main_sel_op_fee_per_da_gas) + - main_sel_op_transaction_fee)) + + (((((((((((main_sel_op_address + main_sel_op_storage_address) + main_sel_op_sender) + + main_sel_op_function_selector) + + main_sel_op_transaction_fee) + + main_sel_op_chain_id) + + main_sel_op_version) + + main_sel_op_block_number) + + main_sel_op_coinbase) + + main_sel_op_timestamp) + + main_sel_op_fee_per_l2_gas) + + main_sel_op_fee_per_da_gas)) + ((((((main_sel_op_note_hash_exists + main_sel_op_emit_note_hash) + main_sel_op_nullifier_exists) + main_sel_op_emit_nullifier) + @@ -1138,11 +1152,11 @@ template class mainImpl { main_sel_op_sstore) - main_sel_mem_op_activate_gas); tmp *= scaling_factor; - std::get<96>(evals) += tmp; + std::get<97>(evals) += tmp; } - // Contribution 97 + // Contribution 98 { - Avm_DECLARE_VIEWS(97); + Avm_DECLARE_VIEWS(98); auto tmp = ((((-main_sel_first + FF(1)) * (-main_sel_op_halt + FF(1))) * @@ -1159,15 +1173,16 @@ template class mainImpl { (main_sel_op_cmov + main_sel_op_mov)) + ((((main_sel_op_radix_le + main_sel_op_sha256) + main_sel_op_poseidon2) + main_sel_op_keccak) + main_sel_op_pedersen)) + - ((((((((((main_sel_op_sender + main_sel_op_address) + main_sel_op_storage_address) + - main_sel_op_chain_id) + - main_sel_op_version) + - main_sel_op_block_number) + - main_sel_op_coinbase) + - main_sel_op_timestamp) + - main_sel_op_fee_per_l2_gas) + - main_sel_op_fee_per_da_gas) + - main_sel_op_transaction_fee)) + + (((((((((((main_sel_op_address + main_sel_op_storage_address) + main_sel_op_sender) + + main_sel_op_function_selector) + + main_sel_op_transaction_fee) + + main_sel_op_chain_id) + + main_sel_op_version) + + main_sel_op_block_number) + + main_sel_op_coinbase) + + main_sel_op_timestamp) + + main_sel_op_fee_per_l2_gas) + + main_sel_op_fee_per_da_gas)) + ((((((main_sel_op_note_hash_exists + main_sel_op_emit_note_hash) + main_sel_op_nullifier_exists) + main_sel_op_emit_nullifier) + main_sel_op_l1_to_l2_msg_exists) + @@ -1176,30 +1191,30 @@ template class mainImpl { (main_sel_op_dagasleft + main_sel_op_l2gasleft))) * (main_pc_shift - (main_pc + FF(1)))); tmp *= scaling_factor; - std::get<97>(evals) += tmp; + std::get<98>(evals) += tmp; } - // Contribution 98 + // Contribution 99 { - Avm_DECLARE_VIEWS(98); + Avm_DECLARE_VIEWS(99); auto tmp = ((-(((main_sel_first + main_sel_op_internal_call) + main_sel_op_internal_return) + main_sel_op_halt) + FF(1)) * (main_internal_return_ptr_shift - main_internal_return_ptr)); tmp *= scaling_factor; - std::get<98>(evals) += tmp; + std::get<99>(evals) += tmp; } - // Contribution 99 + // Contribution 100 { - Avm_DECLARE_VIEWS(99); + Avm_DECLARE_VIEWS(100); auto tmp = ((main_sel_op_internal_call + main_sel_op_internal_return) * (main_space_id - FF(255))); tmp *= scaling_factor; - std::get<99>(evals) += tmp; + std::get<100>(evals) += tmp; } - // Contribution 100 + // Contribution 101 { - Avm_DECLARE_VIEWS(100); + Avm_DECLARE_VIEWS(101); auto tmp = ((((((((main_sel_op_fdiv + @@ -1215,15 +1230,16 @@ template class mainImpl { (main_sel_op_cmov + main_sel_op_mov)) + ((((main_sel_op_radix_le + main_sel_op_sha256) + main_sel_op_poseidon2) + main_sel_op_keccak) + main_sel_op_pedersen)) + - ((((((((((main_sel_op_sender + main_sel_op_address) + main_sel_op_storage_address) + - main_sel_op_chain_id) + - main_sel_op_version) + - main_sel_op_block_number) + - main_sel_op_coinbase) + - main_sel_op_timestamp) + - main_sel_op_fee_per_l2_gas) + - main_sel_op_fee_per_da_gas) + - main_sel_op_transaction_fee)) + + (((((((((((main_sel_op_address + main_sel_op_storage_address) + main_sel_op_sender) + + main_sel_op_function_selector) + + main_sel_op_transaction_fee) + + main_sel_op_chain_id) + + main_sel_op_version) + + main_sel_op_block_number) + + main_sel_op_coinbase) + + main_sel_op_timestamp) + + main_sel_op_fee_per_l2_gas) + + main_sel_op_fee_per_da_gas)) + ((((((main_sel_op_note_hash_exists + main_sel_op_emit_note_hash) + main_sel_op_nullifier_exists) + main_sel_op_emit_nullifier) + main_sel_op_l1_to_l2_msg_exists) + @@ -1232,21 +1248,13 @@ template class mainImpl { (main_sel_op_dagasleft + main_sel_op_l2gasleft)) * (main_call_ptr - main_space_id)); tmp *= scaling_factor; - std::get<100>(evals) += tmp; - } - // Contribution 101 - { - Avm_DECLARE_VIEWS(101); - - auto tmp = ((main_sel_op_cmov + main_sel_op_jumpi) * (((main_id * main_inv) - FF(1)) + main_id_zero)); - tmp *= scaling_factor; std::get<101>(evals) += tmp; } // Contribution 102 { Avm_DECLARE_VIEWS(102); - auto tmp = (((main_sel_op_cmov + main_sel_op_jumpi) * main_id_zero) * (-main_inv + FF(1))); + auto tmp = ((main_sel_op_cmov + main_sel_op_jumpi) * (((main_id * main_inv) - FF(1)) + main_id_zero)); tmp *= scaling_factor; std::get<102>(evals) += tmp; } @@ -1254,7 +1262,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(103); - auto tmp = (main_sel_mov_ia_to_ic - (main_sel_op_mov + (main_sel_op_cmov * (-main_id_zero + FF(1))))); + auto tmp = (((main_sel_op_cmov + main_sel_op_jumpi) * main_id_zero) * (-main_inv + FF(1))); tmp *= scaling_factor; std::get<103>(evals) += tmp; } @@ -1262,7 +1270,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(104); - auto tmp = (main_sel_mov_ib_to_ic - (main_sel_op_cmov * main_id_zero)); + auto tmp = (main_sel_mov_ia_to_ic - (main_sel_op_mov + (main_sel_op_cmov * (-main_id_zero + FF(1))))); tmp *= scaling_factor; std::get<104>(evals) += tmp; } @@ -1270,7 +1278,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(105); - auto tmp = (main_sel_mov_ia_to_ic * (main_ia - main_ic)); + auto tmp = (main_sel_mov_ib_to_ic - (main_sel_op_cmov * main_id_zero)); tmp *= scaling_factor; std::get<105>(evals) += tmp; } @@ -1278,7 +1286,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(106); - auto tmp = (main_sel_mov_ib_to_ic * (main_ib - main_ic)); + auto tmp = (main_sel_mov_ia_to_ic * (main_ia - main_ic)); tmp *= scaling_factor; std::get<106>(evals) += tmp; } @@ -1286,7 +1294,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(107); - auto tmp = ((main_sel_op_mov + main_sel_op_cmov) * (main_r_in_tag - main_w_in_tag)); + auto tmp = (main_sel_mov_ib_to_ic * (main_ib - main_ic)); tmp *= scaling_factor; std::get<107>(evals) += tmp; } @@ -1294,6 +1302,14 @@ template class mainImpl { { Avm_DECLARE_VIEWS(108); + auto tmp = ((main_sel_op_mov + main_sel_op_cmov) * (main_r_in_tag - main_w_in_tag)); + tmp *= scaling_factor; + std::get<108>(evals) += tmp; + } + // Contribution 109 + { + Avm_DECLARE_VIEWS(109); + auto tmp = (main_sel_alu - ((((((((((((main_sel_op_add + main_sel_op_sub) + main_sel_op_mul) + main_sel_op_div) + main_sel_op_not) + @@ -1306,11 +1322,11 @@ template class mainImpl { (-main_tag_err + FF(1))) * (-main_op_err + FF(1)))); tmp *= scaling_factor; - std::get<108>(evals) += tmp; + std::get<109>(evals) += tmp; } - // Contribution 109 + // Contribution 110 { - Avm_DECLARE_VIEWS(109); + Avm_DECLARE_VIEWS(110); auto tmp = ((((((((((main_sel_op_add + main_sel_op_sub) + main_sel_op_mul) + main_sel_op_div) + main_sel_op_not) + @@ -1321,21 +1337,13 @@ template class mainImpl { main_sel_op_shl) * (main_alu_in_tag - main_r_in_tag)); tmp *= scaling_factor; - std::get<109>(evals) += tmp; - } - // Contribution 110 - { - Avm_DECLARE_VIEWS(110); - - auto tmp = (main_sel_op_cast * (main_alu_in_tag - main_w_in_tag)); - tmp *= scaling_factor; std::get<110>(evals) += tmp; } // Contribution 111 { Avm_DECLARE_VIEWS(111); - auto tmp = (main_sel_op_l2gasleft * (main_ia - main_l2_gas_remaining_shift)); + auto tmp = (main_sel_op_cast * (main_alu_in_tag - main_w_in_tag)); tmp *= scaling_factor; std::get<111>(evals) += tmp; } @@ -1343,7 +1351,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(112); - auto tmp = (main_sel_op_dagasleft * (main_ia - main_da_gas_remaining_shift)); + auto tmp = (main_sel_op_l2gasleft * (main_ia - main_l2_gas_remaining_shift)); tmp *= scaling_factor; std::get<112>(evals) += tmp; } @@ -1351,7 +1359,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(113); - auto tmp = (main_sel_op_sender * kernel_kernel_in_offset); + auto tmp = (main_sel_op_dagasleft * (main_ia - main_da_gas_remaining_shift)); tmp *= scaling_factor; std::get<113>(evals) += tmp; } @@ -1367,7 +1375,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(115); - auto tmp = (main_sel_op_storage_address * (kernel_kernel_in_offset - FF(2))); + auto tmp = (main_sel_op_storage_address * (kernel_kernel_in_offset - FF(1))); tmp *= scaling_factor; std::get<115>(evals) += tmp; } @@ -1375,7 +1383,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(116); - auto tmp = (main_sel_op_fee_per_da_gas * (kernel_kernel_in_offset - FF(35))); + auto tmp = (main_sel_op_sender * kernel_kernel_in_offset); tmp *= scaling_factor; std::get<116>(evals) += tmp; } @@ -1383,7 +1391,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(117); - auto tmp = (main_sel_op_fee_per_l2_gas * (kernel_kernel_in_offset - FF(36))); + auto tmp = (main_sel_op_function_selector * (kernel_kernel_in_offset - FF(2))); tmp *= scaling_factor; std::get<117>(evals) += tmp; } @@ -1423,7 +1431,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(122); - auto tmp = (main_sel_op_coinbase * (kernel_kernel_in_offset - FF(33))); + auto tmp = (main_sel_op_timestamp * (kernel_kernel_in_offset - FF(32))); tmp *= scaling_factor; std::get<122>(evals) += tmp; } @@ -1431,7 +1439,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(123); - auto tmp = (main_sel_op_timestamp * (kernel_kernel_in_offset - FF(32))); + auto tmp = (main_sel_op_coinbase * (kernel_kernel_in_offset - FF(33))); tmp *= scaling_factor; std::get<123>(evals) += tmp; } @@ -1439,8 +1447,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(124); - auto tmp = (main_sel_op_note_hash_exists * - (kernel_kernel_out_offset - (kernel_note_hash_exist_write_offset + FF(0)))); + auto tmp = (main_sel_op_fee_per_da_gas * (kernel_kernel_in_offset - FF(35))); tmp *= scaling_factor; std::get<124>(evals) += tmp; } @@ -1448,7 +1455,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(125); - auto tmp = (main_sel_first * kernel_note_hash_exist_write_offset); + auto tmp = (main_sel_op_fee_per_l2_gas * (kernel_kernel_in_offset - FF(36))); tmp *= scaling_factor; std::get<125>(evals) += tmp; } @@ -1456,8 +1463,8 @@ template class mainImpl { { Avm_DECLARE_VIEWS(126); - auto tmp = (main_sel_op_emit_note_hash * - (kernel_kernel_out_offset - (kernel_emit_note_hash_write_offset + FF(176)))); + auto tmp = (main_sel_op_note_hash_exists * + (kernel_kernel_out_offset - (kernel_note_hash_exist_write_offset + FF(0)))); tmp *= scaling_factor; std::get<126>(evals) += tmp; } @@ -1465,7 +1472,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(127); - auto tmp = (main_sel_first * kernel_emit_note_hash_write_offset); + auto tmp = (main_sel_first * kernel_note_hash_exist_write_offset); tmp *= scaling_factor; std::get<127>(evals) += tmp; } @@ -1473,10 +1480,8 @@ template class mainImpl { { Avm_DECLARE_VIEWS(128); - auto tmp = (main_sel_op_nullifier_exists * - (kernel_kernel_out_offset - - ((main_ib * (kernel_nullifier_exists_write_offset + FF(32))) + - ((-main_ib + FF(1)) * (kernel_nullifier_non_exists_write_offset + FF(64)))))); + auto tmp = (main_sel_op_emit_note_hash * + (kernel_kernel_out_offset - (kernel_emit_note_hash_write_offset + FF(176)))); tmp *= scaling_factor; std::get<128>(evals) += tmp; } @@ -1484,7 +1489,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(129); - auto tmp = (main_sel_first * kernel_nullifier_exists_write_offset); + auto tmp = (main_sel_first * kernel_emit_note_hash_write_offset); tmp *= scaling_factor; std::get<129>(evals) += tmp; } @@ -1492,7 +1497,10 @@ template class mainImpl { { Avm_DECLARE_VIEWS(130); - auto tmp = (main_sel_first * kernel_nullifier_non_exists_write_offset); + auto tmp = (main_sel_op_nullifier_exists * + (kernel_kernel_out_offset - + ((main_ib * (kernel_nullifier_exists_write_offset + FF(32))) + + ((-main_ib + FF(1)) * (kernel_nullifier_non_exists_write_offset + FF(64)))))); tmp *= scaling_factor; std::get<130>(evals) += tmp; } @@ -1500,8 +1508,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(131); - auto tmp = (main_sel_op_emit_nullifier * - (kernel_kernel_out_offset - (kernel_emit_nullifier_write_offset + FF(192)))); + auto tmp = (main_sel_first * kernel_nullifier_exists_write_offset); tmp *= scaling_factor; std::get<131>(evals) += tmp; } @@ -1509,7 +1516,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(132); - auto tmp = (main_sel_first * kernel_emit_nullifier_write_offset); + auto tmp = (main_sel_first * kernel_nullifier_non_exists_write_offset); tmp *= scaling_factor; std::get<132>(evals) += tmp; } @@ -1517,8 +1524,8 @@ template class mainImpl { { Avm_DECLARE_VIEWS(133); - auto tmp = (main_sel_op_l1_to_l2_msg_exists * - (kernel_kernel_out_offset - (kernel_l1_to_l2_msg_exists_write_offset + FF(96)))); + auto tmp = (main_sel_op_emit_nullifier * + (kernel_kernel_out_offset - (kernel_emit_nullifier_write_offset + FF(192)))); tmp *= scaling_factor; std::get<133>(evals) += tmp; } @@ -1526,7 +1533,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(134); - auto tmp = (main_sel_first * kernel_l1_to_l2_msg_exists_write_offset); + auto tmp = (main_sel_first * kernel_emit_nullifier_write_offset); tmp *= scaling_factor; std::get<134>(evals) += tmp; } @@ -1534,8 +1541,8 @@ template class mainImpl { { Avm_DECLARE_VIEWS(135); - auto tmp = (main_sel_op_emit_unencrypted_log * - (kernel_kernel_out_offset - (kernel_emit_unencrypted_log_write_offset + FF(210)))); + auto tmp = (main_sel_op_l1_to_l2_msg_exists * + (kernel_kernel_out_offset - (kernel_l1_to_l2_msg_exists_write_offset + FF(96)))); tmp *= scaling_factor; std::get<135>(evals) += tmp; } @@ -1543,7 +1550,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(136); - auto tmp = (main_sel_first * kernel_emit_unencrypted_log_write_offset); + auto tmp = (main_sel_first * kernel_l1_to_l2_msg_exists_write_offset); tmp *= scaling_factor; std::get<136>(evals) += tmp; } @@ -1551,8 +1558,8 @@ template class mainImpl { { Avm_DECLARE_VIEWS(137); - auto tmp = (main_sel_op_emit_l2_to_l1_msg * - (kernel_kernel_out_offset - (kernel_emit_l2_to_l1_msg_write_offset + FF(208)))); + auto tmp = (main_sel_op_emit_unencrypted_log * + (kernel_kernel_out_offset - (kernel_emit_unencrypted_log_write_offset + FF(210)))); tmp *= scaling_factor; std::get<137>(evals) += tmp; } @@ -1560,7 +1567,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(138); - auto tmp = (main_sel_first * kernel_emit_l2_to_l1_msg_write_offset); + auto tmp = (main_sel_first * kernel_emit_unencrypted_log_write_offset); tmp *= scaling_factor; std::get<138>(evals) += tmp; } @@ -1568,7 +1575,8 @@ template class mainImpl { { Avm_DECLARE_VIEWS(139); - auto tmp = (main_sel_op_sload * (kernel_kernel_out_offset - (kernel_sload_write_offset + FF(144)))); + auto tmp = (main_sel_op_emit_l2_to_l1_msg * + (kernel_kernel_out_offset - (kernel_emit_l2_to_l1_msg_write_offset + FF(208)))); tmp *= scaling_factor; std::get<139>(evals) += tmp; } @@ -1576,7 +1584,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(140); - auto tmp = (main_sel_first * kernel_sload_write_offset); + auto tmp = (main_sel_first * kernel_emit_l2_to_l1_msg_write_offset); tmp *= scaling_factor; std::get<140>(evals) += tmp; } @@ -1584,7 +1592,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(141); - auto tmp = (main_sel_op_sstore * (kernel_kernel_out_offset - (kernel_sstore_write_offset + FF(112)))); + auto tmp = (main_sel_op_sload * (kernel_kernel_out_offset - (kernel_sload_write_offset + FF(144)))); tmp *= scaling_factor; std::get<141>(evals) += tmp; } @@ -1592,7 +1600,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(142); - auto tmp = (main_sel_first * kernel_sstore_write_offset); + auto tmp = (main_sel_first * kernel_sload_write_offset); tmp *= scaling_factor; std::get<142>(evals) += tmp; } @@ -1600,6 +1608,22 @@ template class mainImpl { { Avm_DECLARE_VIEWS(143); + auto tmp = (main_sel_op_sstore * (kernel_kernel_out_offset - (kernel_sstore_write_offset + FF(112)))); + tmp *= scaling_factor; + std::get<143>(evals) += tmp; + } + // Contribution 144 + { + Avm_DECLARE_VIEWS(144); + + auto tmp = (main_sel_first * kernel_sstore_write_offset); + tmp *= scaling_factor; + std::get<144>(evals) += tmp; + } + // Contribution 145 + { + Avm_DECLARE_VIEWS(145); + auto tmp = (((((((main_sel_op_note_hash_exists + main_sel_op_emit_note_hash) + main_sel_op_nullifier_exists) + main_sel_op_emit_nullifier) + @@ -1608,23 +1632,23 @@ template class mainImpl { main_sel_op_emit_l2_to_l1_msg) * (kernel_side_effect_counter_shift - (kernel_side_effect_counter + FF(1)))); tmp *= scaling_factor; - std::get<143>(evals) += tmp; + std::get<145>(evals) += tmp; } - // Contribution 144 + // Contribution 146 { - Avm_DECLARE_VIEWS(144); + Avm_DECLARE_VIEWS(146); auto tmp = (main_bin_op_id - (main_sel_op_or + (main_sel_op_xor * FF(2)))); tmp *= scaling_factor; - std::get<144>(evals) += tmp; + std::get<146>(evals) += tmp; } - // Contribution 145 + // Contribution 147 { - Avm_DECLARE_VIEWS(145); + Avm_DECLARE_VIEWS(147); auto tmp = (main_sel_bin - ((main_sel_op_and + main_sel_op_or) + main_sel_op_xor)); tmp *= scaling_factor; - std::get<145>(evals) += tmp; + std::get<147>(evals) += tmp; } } }; diff --git a/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/transcript/transcript.hpp b/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/transcript/transcript.hpp index 6b09876cd15..5aeeaf8a6c6 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/transcript/transcript.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/transcript/transcript.hpp @@ -17,6 +17,7 @@ template struct StdlibTranscriptParams { Builder* builder = data[0].get_context(); return stdlib::poseidon2::hash(*builder, data); } else { + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1035): Add constraints for hashing in Ultra using NativeFr = bb::fr; ASSERT(!data.empty() && data[0].get_context() != nullptr); Builder* builder = data[0].get_context(); diff --git a/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/decider_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/decider_recursive_verifier.cpp index 44c083a544c..e3d29e360a5 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/decider_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/decider_recursive_verifier.cpp @@ -33,7 +33,8 @@ std::array DeciderRecursiveVerifier_:: // Execute ZeroMorph rounds. See https://hackmd.io/dlf9xEwhTQyE3hiGbq4FsA?view for a complete description of the // unrolled protocol. - auto opening_claim = ZeroMorph::verify(commitments.get_unshifted(), + auto opening_claim = ZeroMorph::verify(accumulator->verification_key->circuit_size, + commitments.get_unshifted(), commitments.get_to_be_shifted(), claimed_evaluations.get_unshifted(), claimed_evaluations.get_shifted(), diff --git a/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/protogalaxy_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/protogalaxy_recursive_verifier.cpp index 0a1b48068bd..bac5ef6dd7b 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/protogalaxy_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/protogalaxy_recursive_verifier.cpp @@ -91,10 +91,7 @@ void ProtoGalaxyRecursiveVerifier_::receive_and_finalise_inst gamma, inst->verification_key->circuit_size, static_cast(inst->verification_key->pub_inputs_offset)); - const FF lookup_grand_product_delta = - compute_lookup_grand_product_delta(beta, gamma, inst->verification_key->circuit_size); - inst->relation_parameters = - RelationParameters{ eta, eta_two, eta_three, beta, gamma, public_input_delta, lookup_grand_product_delta }; + inst->relation_parameters = RelationParameters{ eta, eta_two, eta_three, beta, gamma, public_input_delta }; // Get the relation separation challenges for (size_t idx = 0; idx < NUM_SUBRELATIONS - 1; idx++) { diff --git a/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/ultra_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/ultra_recursive_verifier.cpp index f609464efec..38100654bd9 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/ultra_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/ultra_recursive_verifier.cpp @@ -53,7 +53,7 @@ std::array UltraRecursiveVerifier_::ve VerifierCommitments commitments{ key }; CommitmentLabels commitment_labels; - transcript->template receive_from_prover("circuit_size"); + FF circuit_size = transcript->template receive_from_prover("circuit_size"); transcript->template receive_from_prover("public_input_size"); transcript->template receive_from_prover("pub_inputs_offset"); @@ -117,15 +117,12 @@ std::array UltraRecursiveVerifier_::ve commitments.return_data_inverses = transcript->template receive_from_prover(commitment_labels.return_data_inverses); } - const FF public_input_delta = compute_public_input_delta( - public_inputs, beta, gamma, key->circuit_size, static_cast(key->pub_inputs_offset)); - const FF lookup_grand_product_delta = compute_lookup_grand_product_delta(beta, gamma, key->circuit_size); + public_inputs, beta, gamma, circuit_size, static_cast(key->pub_inputs_offset)); relation_parameters.beta = beta; relation_parameters.gamma = gamma; relation_parameters.public_input_delta = public_input_delta; - relation_parameters.lookup_grand_product_delta = lookup_grand_product_delta; // Get commitment to permutation and lookup grand products commitments.z_perm = transcript->template receive_from_prover(commitment_labels.z_perm); @@ -139,6 +136,9 @@ std::array UltraRecursiveVerifier_::ve alpha[idx] = transcript->template get_challenge("alpha_" + std::to_string(idx)); } + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1041): Once hashing produces constraints for Ultra in + // the transcript, a fixed number of gate_challenges must be generated by the prover/verifier in order to achieve a + // verification circuit that is independent of proof size. auto gate_challenges = std::vector(log_circuit_size); for (size_t idx = 0; idx < log_circuit_size; idx++) { gate_challenges[idx] = transcript->template get_challenge("Sumcheck:gate_challenge_" + std::to_string(idx)); @@ -147,7 +147,8 @@ std::array UltraRecursiveVerifier_::ve sumcheck.verify(relation_parameters, alpha, gate_challenges); // Execute ZeroMorph to produce an opening claim subsequently verified by a univariate PCS - auto opening_claim = ZeroMorph::verify(commitments.get_unshifted(), + auto opening_claim = ZeroMorph::verify(circuit_size, + commitments.get_unshifted(), commitments.get_to_be_shifted(), claimed_evaluations.get_unshifted(), claimed_evaluations.get_shifted(), diff --git a/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/verifier.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/verifier.test.cpp index 605b44b702f..c1d2acecf79 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/verifier.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/verifier.test.cpp @@ -50,19 +50,12 @@ template class RecursiveVerifierTest : public testing */ static InnerBuilder create_inner_circuit(size_t log_num_gates = 10) { - using fr_ct = InnerCurve::ScalarField; - using fq_ct = InnerCurve::BaseField; - using point_ct = InnerCurve::AffineElement; - using public_witness_ct = InnerCurve::public_witness_ct; - using witness_ct = InnerCurve::witness_ct; - using byte_array_ct = InnerCurve::byte_array_ct; using fr = typename InnerCurve::ScalarFieldNative; - using point = typename InnerCurve::GroupNative::affine_element; InnerBuilder builder; // Create 2^log_n many add gates based on input log num gates - const size_t num_gates = 1 << log_num_gates; + const size_t num_gates = (1 << log_num_gates); for (size_t i = 0; i < num_gates; ++i) { fr a = fr::random_element(); uint32_t a_idx = builder.add_variable(a); @@ -77,39 +70,6 @@ template class RecursiveVerifierTest : public testing builder.create_big_add_gate({ a_idx, b_idx, c_idx, d_idx, fr(1), fr(1), fr(1), fr(-1), fr(0) }); } - // Perform a batch mul which will add some arbitrary goblin-style ECC op gates if the circuit arithmetic is - // goblinisied otherwise it will add the conventional nonnative gates - size_t num_points = 5; - std::vector circuit_points; - std::vector circuit_scalars; - for (size_t i = 0; i < num_points; ++i) { - circuit_points.push_back(point_ct::from_witness(&builder, point::random_element())); - circuit_scalars.push_back(fr_ct::from_witness(&builder, fr::random_element())); - } - point_ct::batch_mul(circuit_points, circuit_scalars); - - // Define some additional arbitrary convetional circuit logic - fr_ct a(public_witness_ct(&builder, fr::random_element())); - fr_ct b(public_witness_ct(&builder, fr::random_element())); - fr_ct c(public_witness_ct(&builder, fr::random_element())); - - for (size_t i = 0; i < 32; ++i) { - a = (a * b) + b + a; - a = a.madd(b, c); - } - pedersen_hash::hash({ a, b }); - byte_array_ct to_hash(&builder, "nonsense test data"); - blake3s(to_hash); - - fr bigfield_data = fr::random_element(); - fr bigfield_data_a{ bigfield_data.data[0], bigfield_data.data[1], 0, 0 }; - fr bigfield_data_b{ bigfield_data.data[2], bigfield_data.data[3], 0, 0 }; - - fq_ct big_a(fr_ct(witness_ct(&builder, bigfield_data_a.to_montgomery_form())), fr_ct(witness_ct(&builder, 0))); - fq_ct big_b(fr_ct(witness_ct(&builder, bigfield_data_b.to_montgomery_form())), fr_ct(witness_ct(&builder, 0))); - - big_a* big_b; - return builder; }; @@ -156,6 +116,52 @@ template class RecursiveVerifierTest : public testing } } + static void test_independent_vk_hash() + { + auto get_blocks = [](size_t inner_size) { // Create an arbitrary inner circuit + auto inner_circuit = create_inner_circuit(inner_size); + + // Generate a proof over the inner circuit + auto instance = std::make_shared(inner_circuit); + InnerProver inner_prover(instance); + info("test circuit size: ", instance->proving_key.circuit_size); + auto verification_key = std::make_shared(instance->proving_key); + auto inner_proof = inner_prover.construct_proof(); + + // Create a recursive verification circuit for the proof of the inner circuit + OuterBuilder outer_circuit; + RecursiveVerifier verifier{ &outer_circuit, verification_key }; + [[maybe_unused]] auto pairing_points = verifier.verify_proof(inner_proof); + return outer_circuit.blocks; + }; + + bool broke(false); + auto check_eq = [&broke](auto& p1, auto& p2) { + for (size_t idx = 0; idx < p1.size(); idx++) { + if (p1[idx] != p2[idx]) { + broke = true; + info("discrepancy at value index: ", idx); + break; + } + } + }; + + auto blocks_10 = get_blocks(10); + auto blocks_11 = get_blocks(11); + size_t block_idx = 0; + for (auto [b_10, b_11] : zip_view(blocks_10.get(), blocks_11.get())) { + info("block index: ", block_idx); + size_t sel_idx = 0; + for (auto [p_10, p_11] : zip_view(b_10.selectors, b_11.selectors)) { + info("sel index: ", sel_idx); + check_eq(p_10, p_11); + sel_idx++; + } + block_idx++; + } + EXPECT_FALSE(broke); + } + /** * @brief Construct a recursive verification circuit for the proof of an inner circuit then call check_circuit on * it. @@ -269,6 +275,15 @@ HEAVY_TYPED_TEST(RecursiveVerifierTest, SingleRecursiveVerification) TestFixture::test_recursive_verification(); }; +HEAVY_TYPED_TEST(RecursiveVerifierTest, IndependentVKHash) +{ + if constexpr (std::same_as>) { + TestFixture::test_independent_vk_hash(); + } else { + GTEST_SKIP() << "Not built for this parameter"; + } +}; + HEAVY_TYPED_TEST(RecursiveVerifierTest, SingleRecursiveVerificationFailure) { TestFixture::test_recursive_verification_fails(); diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/biggroup/biggroup.hpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/biggroup/biggroup.hpp index f73d389cab0..83ce2a6c7de 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/biggroup/biggroup.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/biggroup/biggroup.hpp @@ -22,6 +22,7 @@ namespace bb::stdlib { template class element { public: using bool_ct = stdlib::bool_t; + using biggroup_tag = element; // Facilitates a constexpr check IsBigGroup struct secp256k1_wnaf { std::vector> wnaf; @@ -937,6 +938,9 @@ template class element { typename std::conditional, batch_lookup_table_plookup<>, batch_lookup_table_base>::type; }; +template +concept IsBigGroup = std::is_same_v; + template inline std::ostream& operator<<(std::ostream& os, element const& v) { diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/biggroup/biggroup.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/biggroup/biggroup.test.cpp index 49c8a471ca5..84359b97214 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/biggroup/biggroup.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/biggroup/biggroup.test.cpp @@ -443,6 +443,8 @@ template class stdlib_biggroup : public testing::Test { static void test_batch_mul() { + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1043): this test will fail with num_points is 1 + // (and this case gets hit sometimes when handling points at infinity). const size_t num_points = 5; Builder builder; std::vector points; diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/curves/bn254.hpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/curves/bn254.hpp index d437cee5044..83b8f3b70b1 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/curves/bn254.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/curves/bn254.hpp @@ -12,6 +12,7 @@ template struct bn254 { // classes are instantiated with "native" curve types. Eventually, the verifier classes will be instantiated only // with stdlib types, and "native" verification will be acheived via a simulated builder. static constexpr bool is_stdlib_type = true; + using NativeCurve = curve::BN254; // Corresponding native types (used exclusively for testing) using ScalarFieldNative = curve::BN254::ScalarField; diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/curves/grumpkin.hpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/curves/grumpkin.hpp index 66c704e9d9b..8f8555886e6 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/curves/grumpkin.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/curves/grumpkin.hpp @@ -14,8 +14,8 @@ namespace bb::stdlib { */ template struct grumpkin { static constexpr bool is_stdlib_type = true; - using Builder = CircuitBuilder; + using NativeCurve = curve::Grumpkin; // Stdlib types corresponding to those defined in the native description of the curve. // Note: its useful to have these type names match the native analog exactly so that components that digest a diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/field/field.cpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/field/field.cpp index 44da799f729..5d84e42450f 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/field/field.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/field/field.cpp @@ -388,6 +388,19 @@ template field_t field_t::pow(const field_t return accumulator; } +/** + * @brief raise a field_t to a power of an exponent (field_t). Note that the exponent must not exceed 32 bits and is + * implicitly range constrained. + * + * @returns this ** (exponent) + */ +template field_t field_t::pow(const size_t exponent) const +{ + auto* ctx = get_context(); + auto exponent_field_elt = field_t::from_witness(ctx, exponent); + return pow(exponent_field_elt); +} + /** * @returns `this * to_mul + to_add` */ diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/field/field.hpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/field/field.hpp index c3c4a19c140..2bbfe93989b 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/field/field.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/field/field.hpp @@ -129,6 +129,9 @@ template class field_t { // N.B. we implicitly range-constrain 'exponent' to be a 32-bit integer! field_t pow(const field_t& exponent) const; + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1039): Use of this function in ZM verifier is insecure. + field_t pow(size_t exponent) const; + field_t operator+=(const field_t& other) { *this = *this + other; 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 45467f78325..37680a5c543 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_flavor.hpp @@ -416,9 +416,6 @@ class MegaFlavor { this->circuit_size, this->pub_inputs_offset); relation_parameters.public_input_delta = public_input_delta; - auto lookup_grand_product_delta = compute_lookup_grand_product_delta( - relation_parameters.beta, relation_parameters.gamma, this->circuit_size); - relation_parameters.lookup_grand_product_delta = lookup_grand_product_delta; // Compute permutation and lookup grand product polynomials compute_grand_products(this->polynomials, relation_parameters); @@ -560,31 +557,6 @@ class MegaFlavor { lagrange_last, lagrange_ecc_op, databus_id); - - /** - * @brief Serialize verification key to field elements - * - * @return std::vector - */ - std::vector to_field_elements() - { - std::vector elements; - std::vector circuit_size_elements = bb::field_conversion::convert_to_bn254_frs(this->circuit_size); - elements.insert(elements.end(), circuit_size_elements.begin(), circuit_size_elements.end()); - // do the same for the rest of the fields - std::vector num_public_inputs_elements = - bb::field_conversion::convert_to_bn254_frs(this->num_public_inputs); - elements.insert(elements.end(), num_public_inputs_elements.begin(), num_public_inputs_elements.end()); - std::vector pub_inputs_offset_elements = - bb::field_conversion::convert_to_bn254_frs(this->pub_inputs_offset); - elements.insert(elements.end(), pub_inputs_offset_elements.begin(), pub_inputs_offset_elements.end()); - - for (Commitment& comm : this->get_all()) { - std::vector comm_elements = bb::field_conversion::convert_to_bn254_frs(comm); - elements.insert(elements.end(), comm_elements.begin(), comm_elements.end()); - } - return elements; - } }; /** * @brief A container for storing the partially evaluated multivariates produced by sumcheck. @@ -814,7 +786,6 @@ class MegaFlavor { // take current proof and put them into the struct size_t num_frs_read = 0; circuit_size = deserialize_from_buffer(proof_data, num_frs_read); - size_t log_n = numeric::get_msb(circuit_size); public_input_size = deserialize_from_buffer(proof_data, num_frs_read); pub_inputs_offset = deserialize_from_buffer(proof_data, num_frs_read); @@ -839,13 +810,13 @@ class MegaFlavor { w_4_comm = deserialize_from_buffer(proof_data, num_frs_read); lookup_inverses_comm = deserialize_from_buffer(proof_data, num_frs_read); z_perm_comm = deserialize_from_buffer(proof_data, num_frs_read); - for (size_t i = 0; i < log_n; ++i) { + for (size_t i = 0; i < CONST_PROOF_SIZE_LOG_N; ++i) { sumcheck_univariates.push_back( deserialize_from_buffer>(proof_data, num_frs_read)); } sumcheck_evaluations = deserialize_from_buffer>(proof_data, num_frs_read); - for (size_t i = 0; i < log_n; ++i) { + for (size_t i = 0; i < CONST_PROOF_SIZE_LOG_N; ++i) { zm_cq_comms.push_back(deserialize_from_buffer(proof_data, num_frs_read)); } zm_cq_comm = deserialize_from_buffer(proof_data, num_frs_read); @@ -856,7 +827,6 @@ class MegaFlavor { { size_t old_proof_length = proof_data.size(); proof_data.clear(); - size_t log_n = numeric::get_msb(circuit_size); serialize_to_buffer(circuit_size, proof_data); serialize_to_buffer(public_input_size, proof_data); serialize_to_buffer(pub_inputs_offset, proof_data); @@ -881,11 +851,11 @@ class MegaFlavor { serialize_to_buffer(w_4_comm, proof_data); serialize_to_buffer(lookup_inverses_comm, proof_data); serialize_to_buffer(z_perm_comm, proof_data); - for (size_t i = 0; i < log_n; ++i) { + for (size_t i = 0; i < CONST_PROOF_SIZE_LOG_N; ++i) { serialize_to_buffer(sumcheck_univariates[i], proof_data); } serialize_to_buffer(sumcheck_evaluations, proof_data); - for (size_t i = 0; i < log_n; ++i) { + for (size_t i = 0; i < CONST_PROOF_SIZE_LOG_N; ++i) { serialize_to_buffer(zm_cq_comms[i], proof_data); } serialize_to_buffer(zm_cq_comm, proof_data); diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_flavor.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_flavor.hpp index 6ca68d7037e..d9b010c320d 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_flavor.hpp @@ -344,9 +344,6 @@ class UltraFlavor { this->circuit_size, this->pub_inputs_offset); relation_parameters.public_input_delta = public_input_delta; - auto lookup_grand_product_delta = compute_lookup_grand_product_delta( - relation_parameters.beta, relation_parameters.gamma, this->circuit_size); - relation_parameters.lookup_grand_product_delta = lookup_grand_product_delta; // Compute permutation and lookup grand product polynomials compute_grand_products(this->polynomials, relation_parameters); @@ -361,7 +358,6 @@ class UltraFlavor { * that, and split out separate PrecomputedPolynomials/Commitments data for clarity but also for portability of our * circuits. */ - // using VerificationKey = VerificationKey_, VerifierCommitmentKey>; class VerificationKey : public VerificationKey_, VerifierCommitmentKey> { public: VerificationKey() = default; @@ -472,31 +468,6 @@ class UltraFlavor { table_4, lagrange_first, lagrange_last); - - /** - * @brief Serialize verification key to field elements - * - * @return std::vector - */ - std::vector to_field_elements() - { - std::vector elements; - std::vector circuit_size_elements = bb::field_conversion::convert_to_bn254_frs(this->circuit_size); - elements.insert(elements.end(), circuit_size_elements.begin(), circuit_size_elements.end()); - // do the same for the rest of the fields - std::vector num_public_inputs_elements = - bb::field_conversion::convert_to_bn254_frs(this->num_public_inputs); - elements.insert(elements.end(), num_public_inputs_elements.begin(), num_public_inputs_elements.end()); - std::vector pub_inputs_offset_elements = - bb::field_conversion::convert_to_bn254_frs(this->pub_inputs_offset); - elements.insert(elements.end(), pub_inputs_offset_elements.begin(), pub_inputs_offset_elements.end()); - - for (Commitment& comm : this->get_all()) { - std::vector comm_elements = bb::field_conversion::convert_to_bn254_frs(comm); - elements.insert(elements.end(), comm_elements.begin(), comm_elements.end()); - } - return elements; - } }; /** @@ -696,7 +667,6 @@ class UltraFlavor { // take current proof and put them into the struct size_t num_frs_read = 0; circuit_size = deserialize_from_buffer(proof_data, num_frs_read); - size_t log_n = numeric::get_msb(circuit_size); public_input_size = deserialize_from_buffer(proof_data, num_frs_read); pub_inputs_offset = deserialize_from_buffer(proof_data, num_frs_read); @@ -711,13 +681,13 @@ class UltraFlavor { w_4_comm = deserialize_from_buffer(proof_data, num_frs_read); lookup_inverses_comm = deserialize_from_buffer(proof_data, num_frs_read); z_perm_comm = deserialize_from_buffer(proof_data, num_frs_read); - for (size_t i = 0; i < log_n; ++i) { + for (size_t i = 0; i < CONST_PROOF_SIZE_LOG_N; ++i) { sumcheck_univariates.push_back( deserialize_from_buffer>(proof_data, num_frs_read)); } sumcheck_evaluations = deserialize_from_buffer>(proof_data, num_frs_read); - for (size_t i = 0; i < log_n; ++i) { + for (size_t i = 0; i < CONST_PROOF_SIZE_LOG_N; ++i) { zm_cq_comms.push_back(deserialize_from_buffer(proof_data, num_frs_read)); } zm_cq_comm = deserialize_from_buffer(proof_data, num_frs_read); @@ -733,7 +703,6 @@ class UltraFlavor { { size_t old_proof_length = proof_data.size(); proof_data.clear(); // clear proof_data so the rest of the function can replace it - size_t log_n = numeric::get_msb(circuit_size); serialize_to_buffer(circuit_size, proof_data); serialize_to_buffer(public_input_size, proof_data); serialize_to_buffer(pub_inputs_offset, proof_data); @@ -748,11 +717,11 @@ class UltraFlavor { serialize_to_buffer(w_4_comm, proof_data); serialize_to_buffer(lookup_inverses_comm, proof_data); serialize_to_buffer(z_perm_comm, proof_data); - for (size_t i = 0; i < log_n; ++i) { + for (size_t i = 0; i < CONST_PROOF_SIZE_LOG_N; ++i) { serialize_to_buffer(sumcheck_univariates[i], proof_data); } serialize_to_buffer(sumcheck_evaluations, proof_data); - for (size_t i = 0; i < log_n; ++i) { + for (size_t i = 0; i < CONST_PROOF_SIZE_LOG_N; ++i) { serialize_to_buffer(zm_cq_comms[i], proof_data); } serialize_to_buffer(zm_cq_comm, proof_data); diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp index 71918f18a98..d5f71eec3c1 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp @@ -213,6 +213,12 @@ template class SumcheckProver { pow_univariate.partially_evaluate(round_challenge); round.round_size = round.round_size >> 1; } + auto zero_univariate = bb::Univariate::zero(); + for (size_t idx = multivariate_d; idx < CONST_PROOF_SIZE_LOG_N; idx++) { + transcript->send_to_verifier("Sumcheck:univariate_" + std::to_string(idx), zero_univariate); + FF round_challenge = transcript->template get_challenge("Sumcheck:u_" + std::to_string(idx)); + multivariate_challenge.emplace_back(round_challenge); + } // Final round: Extract multivariate evaluations from #partially_evaluated_polynomials and add to transcript ClaimedEvaluations multivariate_evaluations; @@ -385,21 +391,39 @@ template class SumcheckVerifier { std::vector multivariate_challenge; multivariate_challenge.reserve(multivariate_d); - - for (size_t round_idx = 0; round_idx < multivariate_d; round_idx++) { + for (size_t round_idx = 0; round_idx < CONST_PROOF_SIZE_LOG_N; round_idx++) { // Obtain the round univariate from the transcript std::string round_univariate_label = "Sumcheck:univariate_" + std::to_string(round_idx); auto round_univariate = transcript->template receive_from_prover>( round_univariate_label); - - bool checked = round.check_sum(round_univariate); - verified = verified && checked; FF round_challenge = transcript->template get_challenge("Sumcheck:u_" + std::to_string(round_idx)); - multivariate_challenge.emplace_back(round_challenge); - round.compute_next_target_sum(round_univariate, round_challenge); - pow_univariate.partially_evaluate(round_challenge); + if constexpr (IsRecursiveFlavor) { + typename Flavor::CircuitBuilder* builder = round_challenge.get_context(); + stdlib::bool_t dummy_round = stdlib::witness_t(builder, round_idx >= multivariate_d); + bool checked = round.check_sum(round_univariate, dummy_round); + // Only utilize the checked value if this is not a constant proof size padding round + if (round_idx < multivariate_d) { + verified = verified && checked; + } + multivariate_challenge.emplace_back(round_challenge); + + round.compute_next_target_sum(round_univariate, round_challenge, dummy_round); + pow_univariate.partially_evaluate(round_challenge, dummy_round); + + } else { + if (round_idx < multivariate_d) { + bool checked = round.check_sum(round_univariate); + verified = verified && checked; + multivariate_challenge.emplace_back(round_challenge); + + round.compute_next_target_sum(round_univariate, round_challenge); + pow_univariate.partially_evaluate(round_challenge); + } else { + multivariate_challenge.emplace_back(round_challenge); + } + } } // Final round diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp index 41aead2179a..6b014b66378 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp @@ -5,6 +5,7 @@ #include "barretenberg/relations/relation_parameters.hpp" #include "barretenberg/relations/relation_types.hpp" #include "barretenberg/relations/utils.hpp" +#include "barretenberg/stdlib/primitives/bool/bool.hpp" namespace bb { @@ -393,6 +394,42 @@ template class SumcheckVerifierRound { return !sumcheck_round_failed; }; + /** + * @brief Check that the round target sum is correct + * @details The verifier receives the claimed evaluations of the round univariate \f$ \tilde{S}^i \f$ at \f$X_i = + * 0,\ldots, D \f$ and checks \f$\sigma_i = \tilde{S}^{i-1}(u_{i-1}) \stackrel{?}{=} \tilde{S}^i(0) + \tilde{S}^i(1) + * \f$ + * @param univariate Round univariate \f$\tilde{S}^{i}\f$ represented by its evaluations over \f$0,\ldots,D\f$. + * + */ + template + bool check_sum(bb::Univariate& univariate, stdlib::bool_t dummy_round) + { + FF total_sum = + FF::conditional_assign(dummy_round, target_total_sum, univariate.value_at(0) + univariate.value_at(1)); + // TODO(#673): Conditionals like this can go away once native verification is is just recursive verification + // with a simulated builder. + bool sumcheck_round_failed(false); + if constexpr (IsRecursiveFlavor) { + if constexpr (IsECCVMRecursiveFlavor) { + // https://github.com/AztecProtocol/barretenberg/issues/998): Avoids the scenario where the assert_equal + // below fails because we are comparing a constant against a non-constant value and the non-constant + // value is in relaxed form. This happens at the first round when target_total_sum is initially set to + // 0. + total_sum.self_reduce(); + } + target_total_sum.assert_equal(total_sum); + if (!dummy_round.get_value()) { + sumcheck_round_failed = (target_total_sum.get_value() != total_sum.get_value()); + } + } else { + sumcheck_round_failed = (target_total_sum != total_sum); + } + + round_failed = round_failed || sumcheck_round_failed; + return !sumcheck_round_failed; + }; + /** * @brief After checking that the univariate is good for this round, compute the next target sum. * @@ -407,6 +444,23 @@ template class SumcheckVerifierRound { return target_total_sum; } + /** + * @brief After checking that the univariate is good for this round, compute the next target sum. + * + * @param univariate \f$ \tilde{S}^i(X) \f$, given by its evaluations over \f$ \{0,1,2,\ldots, D\}\f$. + * @param round_challenge \f$ u_i\f$ + * @return FF \f$ \sigma_{i+1} = \tilde{S}^i(u_i)\f$ + */ + template + FF compute_next_target_sum(bb::Univariate& univariate, + FF& round_challenge, + stdlib::bool_t dummy_round) + { + // Evaluate \f$\tilde{S}^{i}(u_{i}) \f$ + target_total_sum = FF::conditional_assign(dummy_round, target_total_sum, univariate.evaluate(round_challenge)); + return target_total_sum; + } + /** * @brief Given the evaluations \f$P_1(u_0,\ldots, u_{d-1}), \ldots, P_N(u_0,\ldots, u_{d-1}) \f$ of the * ProverPolynomials at the challenge point \f$(u_0,\ldots, u_{d-1})\f$ stored in \p purported_evaluations, this @@ -425,8 +479,8 @@ template class SumcheckVerifierRound { Utils::template accumulate_relation_evaluations_without_skipping<>( purported_evaluations, relation_evaluations, relation_parameters, pow_polynomial.partial_evaluation_result); - auto running_challenge = FF(1); - auto output = FF(0); + FF running_challenge{ 1 }; + FF output{ 0 }; Utils::scale_and_batch_elements(relation_evaluations, alpha, running_challenge, output); return output; } diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.cpp index 0d103c30291..560b208f605 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.cpp @@ -173,7 +173,8 @@ void TranslatorProver::execute_pcs_rounds() using Curve = typename Flavor::Curve; using ZeroMorph = ZeroMorphProver_; auto prover_opening_claim = - ZeroMorph::prove(key->polynomials.get_unshifted_without_concatenated(), + ZeroMorph::prove(key->circuit_size, + key->polynomials.get_unshifted_without_concatenated(), key->polynomials.get_to_be_shifted(), sumcheck_output.claimed_evaluations.get_unshifted_without_concatenated(), sumcheck_output.claimed_evaluations.get_shifted(), diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp index cfae12f3a5c..59429a35927 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp @@ -113,7 +113,8 @@ bool TranslatorVerifier::verify_proof(const HonkProof& proof) // Execute ZeroMorph rounds. See https://hackmd.io/dlf9xEwhTQyE3hiGbq4FsA?view for a complete description ofthe // unrolled protocol. - auto opening_claim = ZeroMorph::verify(commitments.get_unshifted_without_concatenated(), + auto opening_claim = ZeroMorph::verify(circuit_size, + commitments.get_unshifted_without_concatenated(), commitments.get_to_be_shifted(), claimed_evaluations.get_unshifted_without_concatenated(), claimed_evaluations.get_shifted(), diff --git a/barretenberg/cpp/src/barretenberg/translator_vm_recursion/translator_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/translator_vm_recursion/translator_recursive_verifier.cpp index bf171d2c4a1..a34af2cf2fa 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm_recursion/translator_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm_recursion/translator_recursive_verifier.cpp @@ -73,7 +73,7 @@ std::array TranslatorRecursiveVerifier_template receive_from_prover("circuit_size"); + const FF circuit_size = transcript->template receive_from_prover("circuit_size"); ASSERT(static_cast(circuit_size.get_value()) == key->circuit_size); evaluation_input_x = transcript->template receive_from_prover("evaluation_input_x"); @@ -113,7 +113,8 @@ std::array TranslatorRecursiveVerifier_ void DeciderProver_::execute_relation_ch template void DeciderProver_::execute_pcs_rounds() { using ZeroMorph = ZeroMorphProver_; - auto prover_opening_claim = ZeroMorph::prove(accumulator->proving_key.polynomials.get_unshifted(), + auto prover_opening_claim = ZeroMorph::prove(accumulator->proving_key.circuit_size, + accumulator->proving_key.polynomials.get_unshifted(), accumulator->proving_key.polynomials.get_to_be_shifted(), sumcheck_output.claimed_evaluations.get_unshifted(), sumcheck_output.claimed_evaluations.get_shifted(), diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/mega_transcript.test.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/mega_transcript.test.cpp index 8dfc816e01a..87dcb15cebe 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/mega_transcript.test.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/mega_transcript.test.cpp @@ -88,7 +88,7 @@ class MegaTranscriptTests : public ::testing::Test { round++; } - for (size_t i = 0; i < log_n; ++i) { + for (size_t i = 0; i < CONST_PROOF_SIZE_LOG_N; ++i) { std::string idx = std::to_string(i); manifest_expected.add_entry(round, "Sumcheck:univariate_" + idx, frs_per_uni); std::string label = "Sumcheck:u_" + idx; @@ -100,7 +100,7 @@ class MegaTranscriptTests : public ::testing::Test { manifest_expected.add_challenge(round, "rho"); round++; - for (size_t i = 0; i < log_n; ++i) { + for (size_t i = 0; i < CONST_PROOF_SIZE_LOG_N; ++i) { std::string idx = std::to_string(i); manifest_expected.add_entry(round, "ZM:C_q_" + idx, frs_per_G); } diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/oink_verifier.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/oink_verifier.cpp index 0a5a1810e4c..c3d89c226df 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/oink_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/oink_verifier.cpp @@ -136,11 +136,8 @@ template void OinkVerifier::execute_grand_product relation_parameters.gamma, key->circuit_size, static_cast(key->pub_inputs_offset)); - const FF lookup_grand_product_delta = - compute_lookup_grand_product_delta(relation_parameters.beta, relation_parameters.gamma, key->circuit_size); relation_parameters.public_input_delta = public_input_delta; - relation_parameters.lookup_grand_product_delta = lookup_grand_product_delta; // Get commitment to permutation and lookup grand products witness_comms.z_perm = transcript->template receive_from_prover(domain_separator + comm_labels.z_perm); diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_transcript.test.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_transcript.test.cpp index df541aeb2df..5124a0f64eb 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_transcript.test.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_transcript.test.cpp @@ -79,7 +79,7 @@ class UltraTranscriptTests : public ::testing::Test { round++; } - for (size_t i = 0; i < log_n; ++i) { + for (size_t i = 0; i < CONST_PROOF_SIZE_LOG_N; ++i) { std::string idx = std::to_string(i); manifest_expected.add_entry(round, "Sumcheck:univariate_" + idx, frs_per_uni); std::string label = "Sumcheck:u_" + idx; @@ -91,7 +91,7 @@ class UltraTranscriptTests : public ::testing::Test { manifest_expected.add_challenge(round, "rho"); round++; - for (size_t i = 0; i < log_n; ++i) { + for (size_t i = 0; i < CONST_PROOF_SIZE_LOG_N; ++i) { std::string idx = std::to_string(i); manifest_expected.add_entry(round, "ZM:C_q_" + idx, frs_per_G); } diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_verifier.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_verifier.cpp index 942af05365b..6804be61836 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_verifier.cpp @@ -70,12 +70,14 @@ template bool UltraVerifier_::verify_proof(const HonkP // If Sumcheck did not verify, return false if (sumcheck_verified.has_value() && !sumcheck_verified.value()) { + info("Sumcheck verification failed."); return false; } // Execute ZeroMorph rounds to produce an opening claim and verify it with a univariate PCS. See // https://hackmd.io/dlf9xEwhTQyE3hiGbq4FsA?view for a complete description of the unrolled protocol. - auto opening_claim = ZeroMorph::verify(commitments.get_unshifted(), + auto opening_claim = ZeroMorph::verify(key->circuit_size, + commitments.get_unshifted(), commitments.get_to_be_shifted(), claimed_evaluations.get_unshifted(), claimed_evaluations.get_shifted(), @@ -83,7 +85,6 @@ template bool UltraVerifier_::verify_proof(const HonkP Commitment::one(), transcript); auto pairing_points = PCS::reduce_verify(opening_claim, transcript); - auto pcs_verified = key->pcs_verification_key->pairing_check(pairing_points[0], pairing_points[1]); return sumcheck_verified.value() && pcs_verified; } diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_deserialization.cpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_deserialization.cpp index f3908d89e2b..1663491d3ab 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_deserialization.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_deserialization.cpp @@ -57,89 +57,84 @@ const std::unordered_map> OPCODE_WIRE_FORMAT = { OpCode::SHR, three_operand_format }, // Compute - Type Conversions { OpCode::CAST, { OperandType::INDIRECT, OperandType::TAG, OperandType::UINT32, OperandType::UINT32 } }, + // Execution Environment - Globals { OpCode::ADDRESS, getter_format }, { OpCode::STORAGEADDRESS, getter_format }, { OpCode::SENDER, getter_format }, - { OpCode::FEEPERL2GAS, getter_format }, - { OpCode::FEEPERDAGAS, getter_format }, + { OpCode::FUNCTIONSELECTOR, getter_format }, { OpCode::TRANSACTIONFEE, getter_format }, - - { OpCode::GETCONTRACTINSTANCE, { OperandType::INDIRECT, OperandType::UINT32, OperandType::UINT32 } }, - // TODO: ordering inline with spec - { OpCode::EMITNOTEHASH, - { - OperandType::INDIRECT, - OperandType::UINT32, - } }, // TODO: new format for these - { OpCode::EMITNULLIFIER, - { - OperandType::INDIRECT, - OperandType::UINT32, - } }, // TODO: new format for these - { OpCode::EMITUNENCRYPTEDLOG, - { - OperandType::INDIRECT, - OperandType::UINT32, - OperandType::UINT32, - } }, - { OpCode::SENDL2TOL1MSG, { OperandType::INDIRECT, OperandType::UINT32, OperandType::UINT32 } }, - { OpCode::SLOAD, { OperandType::INDIRECT, OperandType::UINT32, OperandType::UINT32, OperandType::UINT32 } }, - { OpCode::SSTORE, { OperandType::INDIRECT, OperandType::UINT32, OperandType::UINT32, OperandType::UINT32 } }, - /*TODO: leafIndexOffset is not constrained*/ - { OpCode::NOTEHASHEXISTS, - { OperandType::INDIRECT, - OperandType::UINT32, - /*TODO: leafIndexOffset is not constrained*/ OperandType::UINT32, - OperandType::UINT32 } }, - - { OpCode::NULLIFIEREXISTS, - { OperandType::INDIRECT, - OperandType::UINT32, - /*TODO: Address is not constrained*/ OperandType::UINT32, - OperandType::UINT32 } }, - { OpCode::L1TOL2MSGEXISTS, - { OperandType::INDIRECT, - OperandType::UINT32, - /*TODO: leafIndexOffset is not constrained*/ OperandType::UINT32, - OperandType::UINT32 } }, - // CONTRACTCALLDEPTH, -- not in simulator // Execution Environment - Globals { OpCode::CHAINID, getter_format }, { OpCode::VERSION, getter_format }, { OpCode::BLOCKNUMBER, getter_format }, - { OpCode::TIMESTAMP, getter_format }, // COINBASE, -- not in simulator + { OpCode::TIMESTAMP, getter_format }, + // Execution Environment - Globals - Gas + { OpCode::FEEPERL2GAS, getter_format }, + { OpCode::FEEPERDAGAS, getter_format }, // BLOCKL2GASLIMIT, -- not in simulator // BLOCKDAGASLIMIT, -- not in simulator + // // Execution Environment - Calldata { OpCode::CALLDATACOPY, { OperandType::INDIRECT, OperandType::UINT32, OperandType::UINT32, OperandType::UINT32 } }, + // Machine State - Gas { OpCode::L2GASLEFT, getter_format }, { OpCode::DAGASLEFT, getter_format }, + // Machine State - Internal Control Flow { OpCode::JUMP, { OperandType::UINT32 } }, { OpCode::JUMPI, { OperandType::INDIRECT, OperandType::UINT32, OperandType::UINT32 } }, { OpCode::INTERNALCALL, { OperandType::UINT32 } }, { OpCode::INTERNALRETURN, {} }, + // Machine State - Memory // OpCode::SET is handled differently { OpCode::MOV, { OperandType::INDIRECT, OperandType::UINT32, OperandType::UINT32 } }, { OpCode::CMOV, { OperandType::INDIRECT, OperandType::UINT32, OperandType::UINT32, OperandType::UINT32, OperandType::UINT32 } }, - // World State - // SLOAD, - // SSTORE, - // NOTEHASHEXISTS, - // EMITNOTEHASH, - // NULLIFIEREXISTS, - // EMITNULLIFIER, - // L1TOL2MSGEXISTS, - // HEADERMEMBER, - // GETCONTRACTINSTANCE, - // Accrued Substate - // EMITUNENCRYPTEDLOG, - // SENDL2TOL1MSG, + + // Side Effects - Public Storage + { OpCode::SLOAD, { OperandType::INDIRECT, OperandType::UINT32, OperandType::UINT32, OperandType::UINT32 } }, + { OpCode::SSTORE, { OperandType::INDIRECT, OperandType::UINT32, OperandType::UINT32, OperandType::UINT32 } }, + // Side Effects - Notes, Nullfiers, Logs, Messages + { OpCode::NOTEHASHEXISTS, + { OperandType::INDIRECT, + OperandType::UINT32, + /*TODO: leafIndexOffset is not constrained*/ OperandType::UINT32, + OperandType::UINT32 } }, + + { OpCode::EMITNOTEHASH, + { + OperandType::INDIRECT, + OperandType::UINT32, + } }, // TODO: new format for these + { OpCode::NULLIFIEREXISTS, + { OperandType::INDIRECT, + OperandType::UINT32, + /*TODO: Address is not constrained*/ OperandType::UINT32, + OperandType::UINT32 } }, + { OpCode::EMITNULLIFIER, + { + OperandType::INDIRECT, + OperandType::UINT32, + } }, // TODO: new format for these + /*TODO: leafIndexOffset is not constrained*/ + { OpCode::L1TOL2MSGEXISTS, + { OperandType::INDIRECT, + OperandType::UINT32, + /*TODO: leafIndexOffset is not constrained*/ OperandType::UINT32, + OperandType::UINT32 } }, + { OpCode::GETCONTRACTINSTANCE, { OperandType::INDIRECT, OperandType::UINT32, OperandType::UINT32 } }, + { OpCode::EMITUNENCRYPTEDLOG, + { + OperandType::INDIRECT, + OperandType::UINT32, + OperandType::UINT32, + } }, + { OpCode::SENDL2TOL1MSG, { OperandType::INDIRECT, OperandType::UINT32, OperandType::UINT32 } }, + // Control Flow - Contract Calls { OpCode::CALL, external_call_format }, // STATICCALL, @@ -147,15 +142,13 @@ const std::unordered_map> OPCODE_WIRE_FORMAT = { OpCode::RETURN, { OperandType::INDIRECT, OperandType::UINT32, OperandType::UINT32 } }, // REVERT, { OpCode::REVERT, { OperandType::INDIRECT, OperandType::UINT32, OperandType::UINT32 } }, + // Misc { OpCode::DEBUGLOG, { OperandType::INDIRECT, OperandType::UINT32, OperandType::UINT32, OperandType::UINT32, OperandType::UINT32 } }, + // Gadgets - // KECCAK, - // POSEIDON2, - // SHA256, - // PEDERSEN, - // Gadget - Hashing + // Gadgets - Hashing { OpCode::KECCAK, { OperandType::INDIRECT, OperandType::UINT32, OperandType::UINT32, OperandType::UINT32 } }, { OpCode::POSEIDON2, { OperandType::INDIRECT, OperandType::UINT32, OperandType::UINT32 } }, { OpCode::SHA256, { OperandType::INDIRECT, OperandType::UINT32, OperandType::UINT32, OperandType::UINT32 } }, @@ -176,6 +169,7 @@ const std::unordered_map> OPCODE_WIRE_FORMAT = // Gadget - Conversion { OpCode::TORADIXLE, { OperandType::INDIRECT, OperandType::UINT32, OperandType::UINT32, OperandType::UINT32, OperandType::UINT32 } }, + // Gadgets - Unused for now { OpCode::SHA256COMPRESSION, { OperandType::INDIRECT, OperandType::UINT32, OperandType::UINT32, OperandType::UINT32 } }, diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_execution.cpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_execution.cpp index f055af7abe1..fb59bdf1d6a 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_execution.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_execution.cpp @@ -1,6 +1,7 @@ #include "barretenberg/vm/avm_trace/avm_execution.hpp" #include "barretenberg/bb/log.hpp" #include "barretenberg/common/serialize.hpp" +#include "barretenberg/numeric/uint256/uint256.hpp" #include "barretenberg/vm/avm_trace/avm_common.hpp" #include "barretenberg/vm/avm_trace/avm_deserialization.hpp" #include "barretenberg/vm/avm_trace/avm_helper.hpp" @@ -78,10 +79,11 @@ std::tuple Execution::prove(std::vector const& public_in std::array& kernel_inputs = std::get(public_inputs); - // Copy the call context items - kernel_inputs[SENDER_SELECTOR] = public_inputs_vec[SENDER_SELECTOR]; // Sender - kernel_inputs[ADDRESS_SELECTOR] = public_inputs_vec[ADDRESS_SELECTOR]; // Address + // Copy items from PublicCircuitPublicInputs vector to public input columns + // PublicCircuitPublicInputs - CallContext + kernel_inputs[SENDER_SELECTOR] = public_inputs_vec[SENDER_SELECTOR]; // Sender + // NOTE: address has same position as storage address (they are the same for now...) + // kernel_inputs[ADDRESS_SELECTOR] = public_inputs_vec[ADDRESS_SELECTOR]; // Address kernel_inputs[STORAGE_ADDRESS_SELECTOR] = public_inputs_vec[STORAGE_ADDRESS_SELECTOR]; // Storage Address + kernel_inputs[FUNCTION_SELECTOR_SELECTOR] = public_inputs_vec[FUNCTION_SELECTOR_SELECTOR]; - // Global variables + // PublicCircuitPublicInputs - GlobalVariables kernel_inputs[CHAIN_ID_SELECTOR] = public_inputs_vec[CHAIN_ID_OFFSET]; // Chain ID kernel_inputs[VERSION_SELECTOR] = public_inputs_vec[VERSION_OFFSET]; // Version kernel_inputs[BLOCK_NUMBER_SELECTOR] = public_inputs_vec[BLOCK_NUMBER_OFFSET]; // Block Number kernel_inputs[TIMESTAMP_SELECTOR] = public_inputs_vec[TIMESTAMP_OFFSET]; // Timestamp kernel_inputs[COINBASE_SELECTOR] = public_inputs_vec[COINBASE_OFFSET]; // Coinbase - - // Fees + // PublicCircuitPublicInputs - GlobalVariables - GasFees kernel_inputs[FEE_PER_DA_GAS_SELECTOR] = public_inputs_vec[FEE_PER_DA_GAS_OFFSET]; kernel_inputs[FEE_PER_L2_GAS_SELECTOR] = public_inputs_vec[FEE_PER_L2_GAS_OFFSET]; @@ -261,14 +265,23 @@ bool Execution::verify(AvmFlavor::VerificationKey vk, HonkProof const& proof) // crs_factory_); // output_state.pcs_verification_key = std::move(pcs_verification_key); + // Proof structure: public_inputs | calldata_size | calldata | raw proof std::vector public_inputs_vec; + std::vector calldata; std::vector raw_proof; - std::copy( - proof.begin(), proof.begin() + PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH, std::back_inserter(public_inputs_vec)); - std::copy(proof.begin() + PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH, proof.end(), std::back_inserter(raw_proof)); + + // This can be made nicer using BB's serialize::read, probably. + const auto public_inputs_offset = proof.begin(); + const auto calldata_size_offset = public_inputs_offset + PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH; + const auto calldata_offset = calldata_size_offset + 1; + const auto raw_proof_offset = calldata_offset + static_cast(uint64_t(*calldata_size_offset)); + + std::copy(public_inputs_offset, calldata_size_offset, std::back_inserter(public_inputs_vec)); + std::copy(calldata_offset, raw_proof_offset, std::back_inserter(calldata)); + std::copy(raw_proof_offset, proof.end(), std::back_inserter(raw_proof)); VmPublicInputs public_inputs = convert_public_inputs(public_inputs_vec); - std::vector> public_inputs_columns = copy_public_inputs_columns(public_inputs); + std::vector> public_inputs_columns = copy_public_inputs_columns(public_inputs, calldata); return verifier.verify_proof(raw_proof, public_inputs_columns); } @@ -309,7 +322,7 @@ std::vector Execution::gen_trace(std::vector const& instructio uint32_t start_side_effect_counter = !public_inputs_vec.empty() ? static_cast(public_inputs_vec[PCPI_START_SIDE_EFFECT_COUNTER_OFFSET]) : 0; - AvmTraceBuilder trace_builder(public_inputs, execution_hints, start_side_effect_counter); + AvmTraceBuilder trace_builder(public_inputs, execution_hints, start_side_effect_counter, calldata); // Copied version of pc maintained in trace builder. The value of pc is evolving based // on opcode logic and therefore is not maintained here. However, the next opcode in the execution @@ -436,8 +449,7 @@ std::vector Execution::gen_trace(std::vector const& instructio trace_builder.op_calldata_copy(std::get(inst.operands.at(0)), std::get(inst.operands.at(1)), std::get(inst.operands.at(2)), - std::get(inst.operands.at(3)), - calldata); + std::get(inst.operands.at(3))); break; // Machine State - Gas case OpCode::L2GASLEFT: @@ -447,9 +459,6 @@ std::vector Execution::gen_trace(std::vector const& instructio trace_builder.op_dagasleft(std::get(inst.operands.at(0)), std::get(inst.operands.at(1))); break; // TODO(https://github.com/AztecProtocol/aztec-packages/issues/6284): support indirect for below - case OpCode::SENDER: - trace_builder.op_sender(std::get(inst.operands.at(0)), std::get(inst.operands.at(1))); - break; case OpCode::ADDRESS: trace_builder.op_address(std::get(inst.operands.at(0)), std::get(inst.operands.at(1))); break; @@ -457,13 +466,12 @@ std::vector Execution::gen_trace(std::vector const& instructio trace_builder.op_storage_address(std::get(inst.operands.at(0)), std::get(inst.operands.at(1))); break; - case OpCode::FEEPERL2GAS: - trace_builder.op_fee_per_l2_gas(std::get(inst.operands.at(0)), - std::get(inst.operands.at(1))); + case OpCode::SENDER: + trace_builder.op_sender(std::get(inst.operands.at(0)), std::get(inst.operands.at(1))); break; - case OpCode::FEEPERDAGAS: - trace_builder.op_fee_per_da_gas(std::get(inst.operands.at(0)), - std::get(inst.operands.at(1))); + case OpCode::FUNCTIONSELECTOR: + trace_builder.op_function_selector(std::get(inst.operands.at(0)), + std::get(inst.operands.at(1))); break; case OpCode::TRANSACTIONFEE: trace_builder.op_transaction_fee(std::get(inst.operands.at(0)), @@ -485,6 +493,14 @@ std::vector Execution::gen_trace(std::vector const& instructio case OpCode::TIMESTAMP: trace_builder.op_timestamp(std::get(inst.operands.at(0)), std::get(inst.operands.at(1))); break; + case OpCode::FEEPERL2GAS: + trace_builder.op_fee_per_l2_gas(std::get(inst.operands.at(0)), + std::get(inst.operands.at(1))); + break; + case OpCode::FEEPERDAGAS: + trace_builder.op_fee_per_da_gas(std::get(inst.operands.at(0)), + std::get(inst.operands.at(1))); + break; case OpCode::NOTEHASHEXISTS: trace_builder.op_note_hash_exists(std::get(inst.operands.at(0)), std::get(inst.operands.at(1)), diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_helper.cpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_helper.cpp index 8a508442aa5..231b62278a9 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_helper.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_helper.cpp @@ -136,7 +136,8 @@ bool is_operand_indirect(uint8_t ind_value, uint8_t operand_idx) return static_cast((ind_value & (1 << operand_idx)) >> operand_idx); } -std::vector> copy_public_inputs_columns(VmPublicInputs const& public_inputs) +std::vector> copy_public_inputs_columns(VmPublicInputs const& public_inputs, + std::vector const& calldata) { // We convert to a vector as the pil generated verifier is generic and unaware of the KERNEL_INPUTS_LENGTH // For each of the public input vectors @@ -158,7 +159,8 @@ std::vector> copy_public_inputs_columns(VmPublicInputs const& pu return { std::move(public_inputs_kernel_inputs), std::move(public_inputs_kernel_value_outputs), std::move(public_inputs_kernel_side_effect_outputs), - std::move(public_inputs_kernel_metadata_outputs) }; + std::move(public_inputs_kernel_metadata_outputs), + calldata }; } } // namespace bb::avm_trace diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_helper.hpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_helper.hpp index 105e1c529f7..d982ee258a9 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_helper.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_helper.hpp @@ -16,6 +16,7 @@ bool is_operand_indirect(uint8_t ind_value, uint8_t operand_idx); // There are 4 public input columns, one for inputs, and 3 for the kernel outputs {value, side effect counter, metadata} // The verifier is generic, and so accepts vectors of these values rather than the fixed length arrays that are used // during circuit building. This method copies each array into a vector to be used by the verifier. -std::vector> copy_public_inputs_columns(VmPublicInputs const& public_inputs); +std::vector> copy_public_inputs_columns(VmPublicInputs const& public_inputs, + std::vector const& calldata); } // namespace bb::avm_trace \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_kernel_trace.cpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_kernel_trace.cpp index 95aa16a1709..52fcc8c6d12 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_kernel_trace.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_kernel_trace.cpp @@ -49,11 +49,6 @@ void AvmKernelTraceBuilder::perform_kernel_output_lookup(uint32_t write_offset, // We want to be able to get the return value from the public inputs column // Get the return value, this will be places in ia // We read from the public inputs that were provided to the kernel -FF AvmKernelTraceBuilder::op_sender() -{ - return perform_kernel_input_lookup(SENDER_SELECTOR); -} - FF AvmKernelTraceBuilder::op_address() { return perform_kernel_input_lookup(ADDRESS_SELECTOR); @@ -63,14 +58,14 @@ FF AvmKernelTraceBuilder::op_storage_address() return perform_kernel_input_lookup(STORAGE_ADDRESS_SELECTOR); } -FF AvmKernelTraceBuilder::op_fee_per_da_gas() +FF AvmKernelTraceBuilder::op_sender() { - return perform_kernel_input_lookup(FEE_PER_DA_GAS_SELECTOR); + return perform_kernel_input_lookup(SENDER_SELECTOR); } -FF AvmKernelTraceBuilder::op_fee_per_l2_gas() +FF AvmKernelTraceBuilder::op_function_selector() { - return perform_kernel_input_lookup(FEE_PER_L2_GAS_SELECTOR); + return perform_kernel_input_lookup(FUNCTION_SELECTOR_SELECTOR); } FF AvmKernelTraceBuilder::op_transaction_fee() @@ -103,6 +98,16 @@ FF AvmKernelTraceBuilder::op_timestamp() return perform_kernel_input_lookup(TIMESTAMP_SELECTOR); } +FF AvmKernelTraceBuilder::op_fee_per_da_gas() +{ + return perform_kernel_input_lookup(FEE_PER_DA_GAS_SELECTOR); +} + +FF AvmKernelTraceBuilder::op_fee_per_l2_gas() +{ + return perform_kernel_input_lookup(FEE_PER_L2_GAS_SELECTOR); +} + // TODO(https://github.com/AztecProtocol/aztec-packages/issues/6481): need to process hint from avm in order to know if // output should be set to true or not void AvmKernelTraceBuilder::op_note_hash_exists(uint32_t clk, diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_kernel_trace.hpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_kernel_trace.hpp index a8c43f66046..b829ee1677f 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_kernel_trace.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_kernel_trace.hpp @@ -10,8 +10,11 @@ #include inline const uint32_t SENDER_SELECTOR = 0; +// address doesn't actually exist in PublicCircuitPublicInputs, but storageAddress does +// so we just make a address & storageAddress an alias of each other for now inline const uint32_t ADDRESS_SELECTOR = 1; -inline const uint32_t STORAGE_ADDRESS_SELECTOR = 2; +inline const uint32_t STORAGE_ADDRESS_SELECTOR = ADDRESS_SELECTOR; +inline const uint32_t FUNCTION_SELECTOR_SELECTOR = 2; inline const uint32_t START_GLOBAL_VARIABLES = CALL_CONTEXT_LENGTH + HEADER_LENGTH; @@ -20,21 +23,14 @@ inline const uint32_t VERSION_SELECTOR = START_GLOBAL_VARIABLES + 1; inline const uint32_t BLOCK_NUMBER_SELECTOR = START_GLOBAL_VARIABLES + 2; inline const uint32_t TIMESTAMP_SELECTOR = START_GLOBAL_VARIABLES + 3; inline const uint32_t COINBASE_SELECTOR = START_GLOBAL_VARIABLES + 4; +inline const uint32_t FEE_PER_DA_GAS_SELECTOR = START_GLOBAL_VARIABLES + 6; +inline const uint32_t FEE_PER_L2_GAS_SELECTOR = START_GLOBAL_VARIABLES + 7; inline const uint32_t END_GLOBAL_VARIABLES = START_GLOBAL_VARIABLES + GLOBAL_VARIABLES_LENGTH; inline const uint32_t START_SIDE_EFFECT_COUNTER = END_GLOBAL_VARIABLES; -// TODO(https://github.com/AztecProtocol/aztec-packages/issues/6715): update these to come from the global inputs -inline const uint32_t FEE_PER_DA_GAS_SELECTOR = START_GLOBAL_VARIABLES + 6; -inline const uint32_t FEE_PER_L2_GAS_SELECTOR = START_GLOBAL_VARIABLES + 7; inline const uint32_t TRANSACTION_FEE_SELECTOR = KERNEL_INPUTS_LENGTH - 1; -const std::array KERNEL_INPUTS_SELECTORS = { - SENDER_SELECTOR, ADDRESS_SELECTOR, STORAGE_ADDRESS_SELECTOR, FEE_PER_DA_GAS_SELECTOR, - FEE_PER_L2_GAS_SELECTOR, TRANSACTION_FEE_SELECTOR, CHAIN_ID_SELECTOR, VERSION_SELECTOR, - BLOCK_NUMBER_SELECTOR, COINBASE_SELECTOR, TIMESTAMP_SELECTOR -}; - namespace bb::avm_trace { class AvmKernelTraceBuilder { @@ -75,13 +71,10 @@ class AvmKernelTraceBuilder { std::vector finalize(); // Context - FF op_sender(); FF op_address(); FF op_storage_address(); - - // Fees - FF op_fee_per_da_gas(); - FF op_fee_per_l2_gas(); + FF op_sender(); + FF op_function_selector(); FF op_transaction_fee(); // Globals @@ -90,19 +83,21 @@ class AvmKernelTraceBuilder { FF op_block_number(); FF op_coinbase(); FF op_timestamp(); + // Globals - Gas + FF op_fee_per_da_gas(); + FF op_fee_per_l2_gas(); // Outputs // Each returns the selector that was used + void op_sload(uint32_t clk, uint32_t side_effect_counter, const FF& slot, const FF& value); + void op_sstore(uint32_t clk, uint32_t side_effect_counter, const FF& slot, const FF& value); void op_note_hash_exists(uint32_t clk, uint32_t side_effect_counter, const FF& note_hash, uint32_t result); void op_emit_note_hash(uint32_t clk, uint32_t side_effect_counter, const FF& note_hash); void op_nullifier_exists(uint32_t clk, uint32_t side_effect_counter, const FF& nullifier, uint32_t result); void op_emit_nullifier(uint32_t clk, uint32_t side_effect_counter, const FF& nullifier); void op_l1_to_l2_msg_exists(uint32_t clk, uint32_t side_effect_counter, const FF& message, uint32_t result); void op_emit_unencrypted_log(uint32_t clk, uint32_t side_effect_counter, const FF& log_hash); - void op_emit_l2_to_l1_msg(uint32_t clk, uint32_t side_effect_counter, const FF& message, const FF& recipient); - - void op_sload(uint32_t clk, uint32_t side_effect_counter, const FF& slot, const FF& value); - void op_sstore(uint32_t clk, uint32_t side_effect_counter, const FF& slot, const FF& value); + void op_emit_l2_to_l1_msg(uint32_t clk, uint32_t side_effect_counter, const FF& l2_to_l1_msg, const FF& recipient); // TODO: Move into constants.hpp? static const uint32_t START_NOTE_HASH_EXISTS_WRITE_OFFSET = 0; diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_opcode.cpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_opcode.cpp index 2439fd4e0a2..f137128d9f0 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_opcode.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_opcode.cpp @@ -60,14 +60,10 @@ std::string to_string(OpCode opcode) return "STORAGEADDRESS"; case OpCode::SENDER: return "SENDER"; - case OpCode::FEEPERL2GAS: - return "FEEPERL2GAS"; - case OpCode::FEEPERDAGAS: - return "FEEPERDAGAS"; + case OpCode::FUNCTIONSELECTOR: + return "FUNCTIONSELECTOR"; case OpCode::TRANSACTIONFEE: return "TRANSACTIONFEE"; - case OpCode::CONTRACTCALLDEPTH: - return "CONTRACTCALLDEPTH"; case OpCode::CHAINID: return "CHAINID"; case OpCode::VERSION: @@ -78,6 +74,10 @@ std::string to_string(OpCode opcode) return "TIMESTAMP"; case OpCode::COINBASE: return "COINBASE"; + case OpCode::FEEPERL2GAS: + return "FEEPERL2GAS"; + case OpCode::FEEPERDAGAS: + return "FEEPERDAGAS"; case OpCode::BLOCKL2GASLIMIT: return "BLOCKL2GASLIMIT"; case OpCode::BLOCKDAGASLIMIT: diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_opcode.hpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_opcode.hpp index e3ced1a03e7..f2beb29d32f 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_opcode.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_opcode.hpp @@ -45,16 +45,16 @@ enum class OpCode : uint8_t { ADDRESS, STORAGEADDRESS, SENDER, - FEEPERL2GAS, - FEEPERDAGAS, + FUNCTIONSELECTOR, TRANSACTIONFEE, - CONTRACTCALLDEPTH, // Execution Environment - Globals CHAINID, VERSION, BLOCKNUMBER, TIMESTAMP, COINBASE, + FEEPERL2GAS, + FEEPERDAGAS, BLOCKL2GASLIMIT, BLOCKDAGASLIMIT, // Execution Environment - Calldata diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.cpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.cpp index b1f7109c6d5..55b22de128d 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.cpp @@ -32,9 +32,11 @@ namespace bb::avm_trace { */ AvmTraceBuilder::AvmTraceBuilder(VmPublicInputs public_inputs, ExecutionHints execution_hints, - uint32_t side_effect_counter) + uint32_t side_effect_counter, + std::vector calldata) // NOTE: we initialise the environment builder here as it requires public inputs : kernel_trace_builder(std::move(public_inputs)) + , calldata(std::move(calldata)) , side_effect_counter(side_effect_counter) , initial_side_effect_counter(side_effect_counter) , execution_hints(std::move(execution_hints)) @@ -1186,6 +1188,18 @@ Row AvmTraceBuilder::create_kernel_lookup_opcode( }; } +void AvmTraceBuilder::op_address(uint8_t indirect, uint32_t dst_offset) +{ + FF ia_value = kernel_trace_builder.op_address(); + Row row = create_kernel_lookup_opcode(indirect, dst_offset, ADDRESS_SELECTOR, ia_value, AvmMemoryTag::FF); + row.main_sel_op_address = FF(1); + + // Constrain gas cost + gas_trace_builder.constrain_gas_lookup(static_cast(row.main_clk), OpCode::ADDRESS); + + main_trace.push_back(row); +} + void AvmTraceBuilder::op_storage_address(uint8_t indirect, uint32_t dst_offset) { FF ia_value = kernel_trace_builder.op_storage_address(); @@ -1210,38 +1224,15 @@ void AvmTraceBuilder::op_sender(uint8_t indirect, uint32_t dst_offset) main_trace.push_back(row); } -void AvmTraceBuilder::op_address(uint8_t indirect, uint32_t dst_offset) -{ - FF ia_value = kernel_trace_builder.op_address(); - Row row = create_kernel_lookup_opcode(indirect, dst_offset, ADDRESS_SELECTOR, ia_value, AvmMemoryTag::FF); - row.main_sel_op_address = FF(1); - - // Constrain gas cost - gas_trace_builder.constrain_gas_lookup(static_cast(row.main_clk), OpCode::ADDRESS); - - main_trace.push_back(row); -} - -void AvmTraceBuilder::op_fee_per_da_gas(uint8_t indirect, uint32_t dst_offset) +void AvmTraceBuilder::op_function_selector(uint8_t indirect, uint32_t dst_offset) { - FF ia_value = kernel_trace_builder.op_fee_per_da_gas(); - Row row = create_kernel_lookup_opcode(indirect, dst_offset, FEE_PER_DA_GAS_SELECTOR, ia_value, AvmMemoryTag::FF); - row.main_sel_op_fee_per_da_gas = FF(1); - - // Constrain gas cost - gas_trace_builder.constrain_gas_lookup(static_cast(row.main_clk), OpCode::FEEPERDAGAS); - - main_trace.push_back(row); -} - -void AvmTraceBuilder::op_fee_per_l2_gas(uint8_t indirect, uint32_t dst_offset) -{ - FF ia_value = kernel_trace_builder.op_fee_per_l2_gas(); - Row row = create_kernel_lookup_opcode(indirect, dst_offset, FEE_PER_L2_GAS_SELECTOR, ia_value, AvmMemoryTag::FF); - row.main_sel_op_fee_per_l2_gas = FF(1); + FF ia_value = kernel_trace_builder.op_function_selector(); + Row row = + create_kernel_lookup_opcode(indirect, dst_offset, FUNCTION_SELECTOR_SELECTOR, ia_value, AvmMemoryTag::U32); + row.main_sel_op_function_selector = FF(1); // Constrain gas cost - gas_trace_builder.constrain_gas_lookup(static_cast(row.main_clk), OpCode::FEEPERL2GAS); + gas_trace_builder.constrain_gas_lookup(static_cast(row.main_clk), OpCode::FUNCTIONSELECTOR); main_trace.push_back(row); } @@ -1318,6 +1309,30 @@ void AvmTraceBuilder::op_timestamp(uint8_t indirect, uint32_t dst_offset) main_trace.push_back(row); } +void AvmTraceBuilder::op_fee_per_da_gas(uint8_t indirect, uint32_t dst_offset) +{ + FF ia_value = kernel_trace_builder.op_fee_per_da_gas(); + Row row = create_kernel_lookup_opcode(indirect, dst_offset, FEE_PER_DA_GAS_SELECTOR, ia_value, AvmMemoryTag::FF); + row.main_sel_op_fee_per_da_gas = FF(1); + + // Constrain gas cost + gas_trace_builder.constrain_gas_lookup(static_cast(row.main_clk), OpCode::FEEPERDAGAS); + + main_trace.push_back(row); +} + +void AvmTraceBuilder::op_fee_per_l2_gas(uint8_t indirect, uint32_t dst_offset) +{ + FF ia_value = kernel_trace_builder.op_fee_per_l2_gas(); + Row row = create_kernel_lookup_opcode(indirect, dst_offset, FEE_PER_L2_GAS_SELECTOR, ia_value, AvmMemoryTag::FF); + row.main_sel_op_fee_per_l2_gas = FF(1); + + // Constrain gas cost + gas_trace_builder.constrain_gas_lookup(static_cast(row.main_clk), OpCode::FEEPERL2GAS); + + main_trace.push_back(row); +} + // Helper function to add kernel lookup operations into the main trace Row AvmTraceBuilder::create_kernel_output_opcode(uint8_t indirect, uint32_t clk, uint32_t data_offset) { @@ -1886,10 +1901,8 @@ void AvmTraceBuilder::op_div( * @param cd_offset The starting index of the region in calldata to be copied. * @param copy_size The number of finite field elements to be copied into memory. * @param dst_offset The starting index of memory where calldata will be copied to. - * @param call_data_mem The vector containing calldata. */ -void AvmTraceBuilder::op_calldata_copy( - uint8_t indirect, uint32_t cd_offset, uint32_t copy_size, uint32_t dst_offset, std::vector const& call_data_mem) +void AvmTraceBuilder::op_calldata_copy(uint8_t indirect, uint32_t cd_offset, uint32_t copy_size, uint32_t dst_offset) { // We parallelize storing memory operations in chunk of 3, i.e., 1 per intermediate register. // The variable pos is an index pointing to the first storing operation (pertaining to intermediate @@ -1912,7 +1925,7 @@ void AvmTraceBuilder::op_calldata_copy( uint32_t rwc(0); auto clk = static_cast(main_trace.size()) + 1; - FF ia = call_data_mem.at(cd_offset + pos); + FF ia = calldata.at(cd_offset + pos); uint32_t mem_op_a(1); uint32_t rwa = 1; @@ -1934,7 +1947,7 @@ void AvmTraceBuilder::op_calldata_copy( call_ptr, clk, IntermRegister::IA, mem_addr_a, ia, AvmMemoryTag::U0, AvmMemoryTag::FF); if (copy_size - pos > 1) { - ib = call_data_mem.at(cd_offset + pos + 1); + ib = calldata.at(cd_offset + pos + 1); mem_op_b = 1; mem_addr_b = direct_dst_offset + pos + 1; rwb = 1; @@ -1945,7 +1958,7 @@ void AvmTraceBuilder::op_calldata_copy( } if (copy_size - pos > 2) { - ic = call_data_mem.at(cd_offset + pos + 2); + ic = calldata.at(cd_offset + pos + 2); mem_op_c = 1; mem_addr_c = direct_dst_offset + pos + 2; rwc = 1; @@ -3762,7 +3775,9 @@ std::vector AvmTraceBuilder::finalize(uint32_t min_trace_size, bool range_c main_trace.at(*trace_size - 1).main_sel_last = FF(1); - // Memory trace inclusion + /********************************************************************************************** + * MEMORY TRACE INCLUSION + **********************************************************************************************/ // We compute in the main loop the timestamp and global address for next row. // Perform initialization for index 0 outside of the loop provided that mem trace exists. @@ -3866,7 +3881,10 @@ std::vector AvmTraceBuilder::finalize(uint32_t min_trace_size, bool range_c } } - // Alu trace inclusion + /********************************************************************************************** + * ALU TRACE INCLUSION + **********************************************************************************************/ + for (size_t i = 0; i < alu_trace_size; i++) { auto const& src = alu_trace.at(i); auto& dest = main_trace.at(i); @@ -4013,6 +4031,10 @@ std::vector AvmTraceBuilder::finalize(uint32_t min_trace_size, bool range_c } } + /********************************************************************************************** + * GADGET TABLES INCLUSION + **********************************************************************************************/ + // Add Conversion Gadget table for (size_t i = 0; i < conv_trace_size; i++) { auto const& src = conv_trace.at(i); @@ -4067,6 +4089,10 @@ std::vector AvmTraceBuilder::finalize(uint32_t min_trace_size, bool range_c dest.pedersen_sel_pedersen = FF(1); } + /********************************************************************************************** + * BINARY TRACE INCLUSION + **********************************************************************************************/ + // Add Binary Trace table for (size_t i = 0; i < bin_trace_size; i++) { auto const& src = bin_trace.at(i); @@ -4132,7 +4158,9 @@ std::vector AvmTraceBuilder::finalize(uint32_t min_trace_size, bool range_c } } - /////////// GAS ACCOUNTING ////////////////////////// + /********************************************************************************************** + * GAS TRACE INCLUSION + **********************************************************************************************/ // Add the gas cost table to the main trace // TODO: do i need a way to produce an interupt that will stop the execution of the trace when the gas left @@ -4222,11 +4250,14 @@ std::vector AvmTraceBuilder::finalize(uint32_t min_trace_size, bool range_c dest.main_da_gas_remaining = current_da_gas_remaining; } - /////////// END OF GAS ACCOUNTING ////////////////////////// - // Adding extra row for the shifted values at the top of the execution trace. Row first_row = Row{ .main_sel_first = FF(1), .mem_lastAccess = FF(1) }; main_trace.insert(main_trace.begin(), first_row); + + /********************************************************************************************** + * RANGE CHECKS AND SELECTORS INCLUSION + **********************************************************************************************/ + auto const old_trace_size = main_trace.size(); auto new_trace_size = range_check_required ? old_trace_size @@ -4316,6 +4347,10 @@ std::vector AvmTraceBuilder::finalize(uint32_t min_trace_size, bool range_c } } + /********************************************************************************************** + * KERNEL TRACE INCLUSION + **********************************************************************************************/ + // Write the kernel trace into the main trace // 1. The write offsets are constrained to be non changing over the entire trace, so we fill in the values // until we @@ -4494,6 +4529,11 @@ std::vector AvmTraceBuilder::finalize(uint32_t min_trace_size, bool range_c std::get(kernel_trace_builder.public_inputs).at(i); } + // calldata column inclusion + for (size_t i = 0; i < calldata.size(); i++) { + main_trace.at(i).main_calldata = calldata.at(i); + } + // Get tag_err counts from the mem_trace_builder if (range_check_required) { finalise_mem_trace_lookup_counts(); diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.hpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.hpp index 951dd1eb6d8..307943c8940 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.hpp @@ -39,7 +39,8 @@ class AvmTraceBuilder { public: AvmTraceBuilder(VmPublicInputs public_inputs = {}, ExecutionHints execution_hints = {}, - uint32_t side_effect_counter = 0); + uint32_t side_effect_counter = 0, + std::vector calldata = {}); std::vector finalize(uint32_t min_trace_size = 0, bool range_check_required = ENABLE_PROVING); void reset(); @@ -48,128 +49,99 @@ class AvmTraceBuilder { // Addition with direct or indirect memory access. void op_add(uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset, AvmMemoryTag in_tag); - // Subtraction with direct or indirect memory access. void op_sub(uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset, AvmMemoryTag in_tag); - // Multiplication with direct or indirect memory access. void op_mul(uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset, AvmMemoryTag in_tag); - + // Integer Division with direct or indirect memory access. + void op_div(uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset, AvmMemoryTag in_tag); // Finite field division with direct or indirect memory access. void op_fdiv(uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset); - // Bitwise not with direct or indirect memory access. - void op_not(uint8_t indirect, uint32_t a_offset, uint32_t dst_offset, AvmMemoryTag in_tag); - // Equality with direct or indirect memory access. void op_eq(uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset, AvmMemoryTag in_tag); + // Less Than with direct or indirect memory access. + void op_lt(uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset, AvmMemoryTag in_tag); + // Less Than or Equal to with direct or indirect memory access. + void op_lte(uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset, AvmMemoryTag in_tag); // Bitwise and with direct or indirect memory access. void op_and(uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset, AvmMemoryTag in_tag); - // Bitwise or with direct or indirect memory access. void op_or(uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset, AvmMemoryTag in_tag); - // Bitwise xor with direct or indirect memory access. void op_xor(uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset, AvmMemoryTag in_tag); - - // Less Than with direct or indirect memory access. - void op_lt(uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset, AvmMemoryTag in_tag); - - // Less Than or Equal to with direct or indirect memory access. - void op_lte(uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset, AvmMemoryTag in_tag); - - // Shift Right with direct or indirect memory access. - void op_shr(uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset, AvmMemoryTag in_tag); - + // Bitwise not with direct or indirect memory access. + void op_not(uint8_t indirect, uint32_t a_offset, uint32_t dst_offset, AvmMemoryTag in_tag); // Shift Left with direct or indirect memory access. void op_shl(uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset, AvmMemoryTag in_tag); + // Shift Right with direct or indirect memory access. + void op_shr(uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset, AvmMemoryTag in_tag); - // Set a constant from bytecode with direct or indirect memory access. - void op_set(uint8_t indirect, uint128_t val, uint32_t dst_offset, AvmMemoryTag in_tag); - - // Move (copy) the value and tag of a memory cell to another one. - void op_mov(uint8_t indirect, uint32_t src_offset, uint32_t dst_offset); - - // Move (copy) the value and tag of a memory cell to another one whereby the source - // is determined conditionally based on a conditional value determined by cond_offset. - void op_cmov(uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t cond_offset, uint32_t dst_offset); + // Cast an element pointed by the address a_offset into type specified by dst_tag and + // store the result in address given by dst_offset. + void op_cast(uint8_t indirect, uint32_t a_offset, uint32_t dst_offset, AvmMemoryTag dst_tag); - // Call Context - void op_storage_address(uint8_t indirect, uint32_t dst_offset); + // Context - Environment void op_sender(uint8_t indirect, uint32_t dst_offset); void op_address(uint8_t indirect, uint32_t dst_offset); - - // Fees - void op_fee_per_da_gas(uint8_t indirect, uint32_t dst_offset); - void op_fee_per_l2_gas(uint8_t indirect, uint32_t dst_offset); + void op_storage_address(uint8_t indirect, uint32_t dst_offset); void op_transaction_fee(uint8_t indirect, uint32_t dst_offset); + void op_function_selector(uint8_t indirect, uint32_t dst_offset); - // Globals + // Context - Environment - Globals void op_chain_id(uint8_t indirect, uint32_t dst_offset); void op_version(uint8_t indirect, uint32_t dst_offset); void op_block_number(uint8_t indirect, uint32_t dst_offset); void op_coinbase(uint8_t indirect, uint32_t dst_offset); void op_timestamp(uint8_t indirect, uint32_t dst_offset); + // Context - Environment - Globals - Gas + void op_fee_per_da_gas(uint8_t indirect, uint32_t dst_offset); + void op_fee_per_l2_gas(uint8_t indirect, uint32_t dst_offset); - // Outputs - // With single output values - void op_emit_note_hash(uint8_t indirect, uint32_t note_hash_offset); - void op_emit_nullifier(uint8_t indirect, uint32_t nullifier_offset); - void op_emit_unencrypted_log(uint8_t indirect, uint32_t log_offset, uint32_t log_size_offset); - void op_emit_l2_to_l1_msg(uint8_t indirect, uint32_t recipient_offset, uint32_t content_offset); - void op_get_contract_instance(uint8_t indirect, uint32_t address_offset, uint32_t dst_offset); - - // With additional metadata output - void op_l1_to_l2_msg_exists(uint8_t indirect, uint32_t log_offset, uint32_t dest_offset); - void op_note_hash_exists(uint8_t indirect, uint32_t note_hash_offset, uint32_t dest_offset); - void op_nullifier_exists(uint8_t indirect, uint32_t nullifier_offset, uint32_t dest_offset); - - void op_sload(uint8_t indirect, uint32_t slot_offset, uint32_t size, uint32_t dest_offset); - void op_sstore(uint8_t indirect, uint32_t src_offset, uint32_t size, uint32_t slot_offset); - - // Cast an element pointed by the address a_offset into type specified by dst_tag and - // store the result in address given by dst_offset. - void op_cast(uint8_t indirect, uint32_t a_offset, uint32_t dst_offset, AvmMemoryTag dst_tag); - - // Integer Division with direct or indirect memory access. - void op_div(uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset, AvmMemoryTag in_tag); + // Context - Environment - Calldata + // CALLDATACOPY opcode with direct/indirect memory access, i.e., + // direct: M[dst_offset:dst_offset+copy_size] = calldata[cd_offset:cd_offset+copy_size] + // indirect: M[M[dst_offset]:M[dst_offset]+copy_size] = calldata[cd_offset:cd_offset+copy_size] + void op_calldata_copy(uint8_t indirect, uint32_t cd_offset, uint32_t copy_size, uint32_t dst_offset); - // Machine State - Gas + // Context - Machine State - Gas void op_l2gasleft(uint8_t indirect, uint32_t dst_offset); void op_dagasleft(uint8_t indirect, uint32_t dst_offset); // Jump to a given program counter. void op_jump(uint32_t jmp_dest); - // Jump conditionally to a given program counter. void op_jumpi(uint8_t indirect, uint32_t jmp_dest, uint32_t cond_offset); - // Jump to a given program counter; storing the return location on a call stack. // TODO(md): this program counter MUST be an operand to the OPCODE. void op_internal_call(uint32_t jmp_dest); - - // Return from a jump. + // Return from an internal call. void op_internal_return(); - // Halt -> stop program execution. - void halt(); + // Set a constant from bytecode with direct or indirect memory access. + void op_set(uint8_t indirect, uint128_t val, uint32_t dst_offset, AvmMemoryTag in_tag); + // Move (copy) the value and tag of a memory cell to another one. + void op_mov(uint8_t indirect, uint32_t src_offset, uint32_t dst_offset); + // Move (copy) the value and tag of a memory cell to another one whereby the source + // is determined conditionally based on a conditional value determined by cond_offset. + void op_cmov(uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t cond_offset, uint32_t dst_offset); - // CALLDATACOPY opcode with direct/indirect memory access, i.e., - // direct: M[dst_offset:dst_offset+copy_size] = calldata[cd_offset:cd_offset+copy_size] - // indirect: M[M[dst_offset]:M[dst_offset]+copy_size] = calldata[cd_offset:cd_offset+copy_size] - void op_calldata_copy(uint8_t indirect, - uint32_t cd_offset, - uint32_t copy_size, - uint32_t dst_offset, - std::vector const& call_data_mem); + // Side Effects - Public Storage + void op_sload(uint8_t indirect, uint32_t slot_offset, uint32_t size, uint32_t dest_offset); + void op_sstore(uint8_t indirect, uint32_t src_offset, uint32_t size, uint32_t slot_offset); - // REVERT Opcode (that just call return under the hood for now) - std::vector op_revert(uint8_t indirect, uint32_t ret_offset, uint32_t ret_size); - // RETURN opcode with direct and indirect memory access, i.e., - // direct: return(M[ret_offset:ret_offset+ret_size]) - // indirect: return(M[M[ret_offset]:M[ret_offset]+ret_size]) - std::vector op_return(uint8_t indirect, uint32_t ret_offset, uint32_t ret_size); + // With single output values + void op_emit_note_hash(uint8_t indirect, uint32_t note_hash_offset); + void op_emit_nullifier(uint8_t indirect, uint32_t nullifier_offset); + void op_emit_unencrypted_log(uint8_t indirect, uint32_t log_offset, uint32_t log_size_offset); + void op_emit_l2_to_l1_msg(uint8_t indirect, uint32_t recipient_offset, uint32_t content_offset); + void op_get_contract_instance(uint8_t indirect, uint32_t address_offset, uint32_t dst_offset); + + // With additional metadata output + void op_l1_to_l2_msg_exists(uint8_t indirect, uint32_t log_offset, uint32_t dest_offset); + void op_note_hash_exists(uint8_t indirect, uint32_t note_hash_offset, uint32_t dest_offset); + void op_nullifier_exists(uint8_t indirect, uint32_t nullifier_offset, uint32_t dest_offset); // Calls void op_call(uint8_t indirect, @@ -182,6 +154,16 @@ class AvmTraceBuilder { uint32_t success_offset, uint32_t function_selector_offset); + // RETURN opcode with direct and indirect memory access, i.e., + // direct: return(M[ret_offset:ret_offset+ret_size]) + // indirect: return(M[M[ret_offset]:M[ret_offset]+ret_size]) + std::vector op_return(uint8_t indirect, uint32_t ret_offset, uint32_t ret_size); + // REVERT Opcode (that just call return under the hood for now) + std::vector op_revert(uint8_t indirect, uint32_t ret_offset, uint32_t ret_size); + + // (not an opcode) Halt -> stop program execution. + void halt(); + // Gadgets // --- Conversions // To Radix LE conversion operation. @@ -241,6 +223,8 @@ class AvmTraceBuilder { AvmPedersenTraceBuilder pedersen_trace_builder; AvmEccTraceBuilder ecc_trace_builder; + std::vector calldata{}; + /** * @brief Create a kernel lookup opcode object * diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/constants.hpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/constants.hpp index 4d60a7b0ad9..86c18af9fd9 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/constants.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/constants.hpp @@ -7,7 +7,7 @@ // NOTE(MD): for now we will only include the public inputs that are included in call_context // With more being added in subsequent prs -// KERNEL_INPUTS_LENGTH = CALL_CONTEXT_LENGTH + +// KERNEL_INPUTS_LENGTH = CALL_CONTEXT_LENGTH inline const std::size_t KERNEL_INPUTS_LENGTH = PUBLIC_CONTEXT_INPUTS_LENGTH; inline const std::size_t KERNEL_OUTPUTS_LENGTH = @@ -21,22 +21,24 @@ inline const std::size_t KERNEL_OUTPUTS_LENGTH = // https://github.com/AztecProtocol/aztec-packages/blob/master/yarn-project/circuits.js/src/structs/public_circuit_public_inputs.ts inline const uint32_t PCPI_GLOBALS_START = PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH - 7 - GLOBAL_VARIABLES_LENGTH; +// Global Variables inline const uint32_t CHAIN_ID_OFFSET = PCPI_GLOBALS_START; inline const uint32_t VERSION_OFFSET = PCPI_GLOBALS_START + 1; inline const uint32_t BLOCK_NUMBER_OFFSET = PCPI_GLOBALS_START + 2; inline const uint32_t TIMESTAMP_OFFSET = PCPI_GLOBALS_START + 3; inline const uint32_t COINBASE_OFFSET = PCPI_GLOBALS_START + 4; - +// Global Variables - fees inline const uint32_t FEE_PER_DA_GAS_OFFSET = PCPI_GLOBALS_START + 6; inline const uint32_t FEE_PER_L2_GAS_OFFSET = PCPI_GLOBALS_START + 7; -inline const uint32_t TRANSACTION_FEE_OFFSET = PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH - 1; +// Top-level PublicCircuitPublicInputs members inline const uint32_t DA_START_GAS_LEFT_PCPI_OFFSET = PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH - 3 - GAS_LENGTH; inline const uint32_t L2_START_GAS_LEFT_PCPI_OFFSET = PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH - 2 - GAS_LENGTH; +inline const uint32_t TRANSACTION_FEE_OFFSET = PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH - 1; // Kernel output pil offset (Where update objects are inlined) -// Kernel outputs public inputs offsets +// Side Effects (offsets to vectors in PublicCircuitPublicInputs) inline const uint32_t PCPI_NOTE_HASH_EXISTS_OFFSET = CALL_CONTEXT_LENGTH + 2; inline const uint32_t PCPI_NULLIFIER_EXISTS_OFFSET = PCPI_NOTE_HASH_EXISTS_OFFSET + (MAX_NOTE_HASH_READ_REQUESTS_PER_CALL * READ_REQUEST_LENGTH); diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/avm_circuit_builder.cpp b/barretenberg/cpp/src/barretenberg/vm/generated/avm_circuit_builder.cpp index 448bf350a0e..a1194d51e98 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/avm_circuit_builder.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/avm_circuit_builder.cpp @@ -24,6 +24,7 @@ template std::vector AvmFullRow::names() "kernel_kernel_value_out", "kernel_kernel_side_effect_out", "kernel_kernel_metadata_out", + "main_calldata", "alu_a_hi", "alu_a_lo", "alu_b_hi", @@ -220,6 +221,7 @@ template std::vector AvmFullRow::names() "main_sel_op_fdiv", "main_sel_op_fee_per_da_gas", "main_sel_op_fee_per_l2_gas", + "main_sel_op_function_selector", "main_sel_op_get_contract_instance", "main_sel_op_halt", "main_sel_op_internal_call", @@ -412,18 +414,19 @@ template std::ostream& operator<<(std::ostream& os, AvmFullRow << field_to_string(row.main_clk) << "," << field_to_string(row.main_sel_first) << "," << field_to_string(row.kernel_kernel_inputs) << "," << field_to_string(row.kernel_kernel_value_out) << "," << field_to_string(row.kernel_kernel_side_effect_out) << "," - << field_to_string(row.kernel_kernel_metadata_out) << "," << field_to_string(row.alu_a_hi) << "," - << field_to_string(row.alu_a_lo) << "," << field_to_string(row.alu_b_hi) << "," - << field_to_string(row.alu_b_lo) << "," << field_to_string(row.alu_borrow) << "," - << field_to_string(row.alu_cf) << "," << field_to_string(row.alu_clk) << "," - << field_to_string(row.alu_cmp_rng_ctr) << "," << field_to_string(row.alu_div_u16_r0) << "," - << field_to_string(row.alu_div_u16_r1) << "," << field_to_string(row.alu_div_u16_r2) << "," - << field_to_string(row.alu_div_u16_r3) << "," << field_to_string(row.alu_div_u16_r4) << "," - << field_to_string(row.alu_div_u16_r5) << "," << field_to_string(row.alu_div_u16_r6) << "," - << field_to_string(row.alu_div_u16_r7) << "," << field_to_string(row.alu_divisor_hi) << "," - << field_to_string(row.alu_divisor_lo) << "," << field_to_string(row.alu_ff_tag) << "," - << field_to_string(row.alu_ia) << "," << field_to_string(row.alu_ib) << "," << field_to_string(row.alu_ic) - << "," << field_to_string(row.alu_in_tag) << "," << field_to_string(row.alu_op_add) << "," + << field_to_string(row.kernel_kernel_metadata_out) << "," << field_to_string(row.main_calldata) << "," + << field_to_string(row.alu_a_hi) << "," << field_to_string(row.alu_a_lo) << "," + << field_to_string(row.alu_b_hi) << "," << field_to_string(row.alu_b_lo) << "," + << field_to_string(row.alu_borrow) << "," << field_to_string(row.alu_cf) << "," + << field_to_string(row.alu_clk) << "," << field_to_string(row.alu_cmp_rng_ctr) << "," + << field_to_string(row.alu_div_u16_r0) << "," << field_to_string(row.alu_div_u16_r1) << "," + << field_to_string(row.alu_div_u16_r2) << "," << field_to_string(row.alu_div_u16_r3) << "," + << field_to_string(row.alu_div_u16_r4) << "," << field_to_string(row.alu_div_u16_r5) << "," + << field_to_string(row.alu_div_u16_r6) << "," << field_to_string(row.alu_div_u16_r7) << "," + << field_to_string(row.alu_divisor_hi) << "," << field_to_string(row.alu_divisor_lo) << "," + << field_to_string(row.alu_ff_tag) << "," << field_to_string(row.alu_ia) << "," + << field_to_string(row.alu_ib) << "," << field_to_string(row.alu_ic) << "," + << field_to_string(row.alu_in_tag) << "," << field_to_string(row.alu_op_add) << "," << field_to_string(row.alu_op_cast) << "," << field_to_string(row.alu_op_cast_prev) << "," << field_to_string(row.alu_op_div) << "," << field_to_string(row.alu_op_div_a_lt_b) << "," << field_to_string(row.alu_op_div_std) << "," << field_to_string(row.alu_op_eq) << "," @@ -518,6 +521,7 @@ template std::ostream& operator<<(std::ostream& os, AvmFullRow << "," << field_to_string(row.main_sel_op_external_call) << "," << field_to_string(row.main_sel_op_fdiv) << "," << field_to_string(row.main_sel_op_fee_per_da_gas) << "," << field_to_string(row.main_sel_op_fee_per_l2_gas) << "," + << field_to_string(row.main_sel_op_function_selector) << "," << field_to_string(row.main_sel_op_get_contract_instance) << "," << field_to_string(row.main_sel_op_halt) << "," << field_to_string(row.main_sel_op_internal_call) << "," << field_to_string(row.main_sel_op_internal_return) << "," << field_to_string(row.main_sel_op_jump) << "," diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/avm_circuit_builder.hpp b/barretenberg/cpp/src/barretenberg/vm/generated/avm_circuit_builder.hpp index 9bbe9334c85..6508ba7d465 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/avm_circuit_builder.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/avm_circuit_builder.hpp @@ -93,6 +93,7 @@ template struct AvmFullRow { FF kernel_kernel_value_out{}; FF kernel_kernel_side_effect_out{}; FF kernel_kernel_metadata_out{}; + FF main_calldata{}; FF alu_a_hi{}; FF alu_a_lo{}; FF alu_b_hi{}; @@ -289,6 +290,7 @@ template struct AvmFullRow { FF main_sel_op_fdiv{}; FF main_sel_op_fee_per_da_gas{}; FF main_sel_op_fee_per_l2_gas{}; + FF main_sel_op_function_selector{}; FF main_sel_op_get_contract_instance{}; FF main_sel_op_halt{}; FF main_sel_op_internal_call{}; @@ -553,8 +555,8 @@ class AvmCircuitBuilder { using Polynomial = Flavor::Polynomial; using ProverPolynomials = Flavor::ProverPolynomials; - static constexpr size_t num_fixed_columns = 450; - static constexpr size_t num_polys = 385; + static constexpr size_t num_fixed_columns = 452; + static constexpr size_t num_polys = 387; std::vector rows; void set_trace(std::vector&& trace) { rows = std::move(trace); } @@ -576,6 +578,7 @@ class AvmCircuitBuilder { polys.kernel_kernel_value_out[i] = rows[i].kernel_kernel_value_out; polys.kernel_kernel_side_effect_out[i] = rows[i].kernel_kernel_side_effect_out; polys.kernel_kernel_metadata_out[i] = rows[i].kernel_kernel_metadata_out; + polys.main_calldata[i] = rows[i].main_calldata; polys.alu_a_hi[i] = rows[i].alu_a_hi; polys.alu_a_lo[i] = rows[i].alu_a_lo; polys.alu_b_hi[i] = rows[i].alu_b_hi; @@ -773,6 +776,7 @@ class AvmCircuitBuilder { polys.main_sel_op_fdiv[i] = rows[i].main_sel_op_fdiv; polys.main_sel_op_fee_per_da_gas[i] = rows[i].main_sel_op_fee_per_da_gas; polys.main_sel_op_fee_per_l2_gas[i] = rows[i].main_sel_op_fee_per_l2_gas; + polys.main_sel_op_function_selector[i] = rows[i].main_sel_op_function_selector; polys.main_sel_op_get_contract_instance[i] = rows[i].main_sel_op_get_contract_instance; polys.main_sel_op_halt[i] = rows[i].main_sel_op_halt; polys.main_sel_op_internal_call[i] = rows[i].main_sel_op_internal_call; diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/avm_flavor.hpp b/barretenberg/cpp/src/barretenberg/vm/generated/avm_flavor.hpp index e5729066c00..c29a3b0212a 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/avm_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/avm_flavor.hpp @@ -100,11 +100,11 @@ class AvmFlavor { using RelationSeparator = FF; static constexpr size_t NUM_PRECOMPUTED_ENTITIES = 2; - static constexpr size_t NUM_WITNESS_ENTITIES = 383; + static constexpr size_t NUM_WITNESS_ENTITIES = 385; static constexpr size_t NUM_WIRES = NUM_WITNESS_ENTITIES + NUM_PRECOMPUTED_ENTITIES; // We have two copies of the witness entities, so we subtract the number of fixed ones (they have no shift), one for // the unshifted and one for the shifted - static constexpr size_t NUM_ALL_ENTITIES = 450; + static constexpr size_t NUM_ALL_ENTITIES = 452; using GrandProductRelations = std::tuple, perm_main_bin_relation, @@ -264,6 +264,7 @@ class AvmFlavor { kernel_kernel_value_out, kernel_kernel_side_effect_out, kernel_kernel_metadata_out, + main_calldata, alu_a_hi, alu_a_lo, alu_b_hi, @@ -460,6 +461,7 @@ class AvmFlavor { main_sel_op_fdiv, main_sel_op_fee_per_da_gas, main_sel_op_fee_per_l2_gas, + main_sel_op_function_selector, main_sel_op_get_contract_instance, main_sel_op_halt, main_sel_op_internal_call, @@ -650,6 +652,7 @@ class AvmFlavor { kernel_kernel_value_out, kernel_kernel_side_effect_out, kernel_kernel_metadata_out, + main_calldata, alu_a_hi, alu_a_lo, alu_b_hi, @@ -846,6 +849,7 @@ class AvmFlavor { main_sel_op_fdiv, main_sel_op_fee_per_da_gas, main_sel_op_fee_per_l2_gas, + main_sel_op_function_selector, main_sel_op_get_contract_instance, main_sel_op_halt, main_sel_op_internal_call, @@ -1041,6 +1045,7 @@ class AvmFlavor { kernel_kernel_value_out, kernel_kernel_side_effect_out, kernel_kernel_metadata_out, + main_calldata, alu_a_hi, alu_a_lo, alu_b_hi, @@ -1237,6 +1242,7 @@ class AvmFlavor { main_sel_op_fdiv, main_sel_op_fee_per_da_gas, main_sel_op_fee_per_l2_gas, + main_sel_op_function_selector, main_sel_op_get_contract_instance, main_sel_op_halt, main_sel_op_internal_call, @@ -1494,6 +1500,7 @@ class AvmFlavor { kernel_kernel_value_out, kernel_kernel_side_effect_out, kernel_kernel_metadata_out, + main_calldata, alu_a_hi, alu_a_lo, alu_b_hi, @@ -1690,6 +1697,7 @@ class AvmFlavor { main_sel_op_fdiv, main_sel_op_fee_per_da_gas, main_sel_op_fee_per_l2_gas, + main_sel_op_function_selector, main_sel_op_get_contract_instance, main_sel_op_halt, main_sel_op_internal_call, @@ -1947,6 +1955,7 @@ class AvmFlavor { kernel_kernel_value_out, kernel_kernel_side_effect_out, kernel_kernel_metadata_out, + main_calldata, alu_a_hi, alu_a_lo, alu_b_hi, @@ -2143,6 +2152,7 @@ class AvmFlavor { main_sel_op_fdiv, main_sel_op_fee_per_da_gas, main_sel_op_fee_per_l2_gas, + main_sel_op_function_selector, main_sel_op_get_contract_instance, main_sel_op_halt, main_sel_op_internal_call, @@ -2756,6 +2766,7 @@ class AvmFlavor { Base::kernel_kernel_value_out = "KERNEL_KERNEL_VALUE_OUT"; Base::kernel_kernel_side_effect_out = "KERNEL_KERNEL_SIDE_EFFECT_OUT"; Base::kernel_kernel_metadata_out = "KERNEL_KERNEL_METADATA_OUT"; + Base::main_calldata = "MAIN_CALLDATA"; Base::alu_a_hi = "ALU_A_HI"; Base::alu_a_lo = "ALU_A_LO"; Base::alu_b_hi = "ALU_B_HI"; @@ -2952,6 +2963,7 @@ class AvmFlavor { Base::main_sel_op_fdiv = "MAIN_SEL_OP_FDIV"; Base::main_sel_op_fee_per_da_gas = "MAIN_SEL_OP_FEE_PER_DA_GAS"; Base::main_sel_op_fee_per_l2_gas = "MAIN_SEL_OP_FEE_PER_L2_GAS"; + Base::main_sel_op_function_selector = "MAIN_SEL_OP_FUNCTION_SELECTOR"; Base::main_sel_op_get_contract_instance = "MAIN_SEL_OP_GET_CONTRACT_INSTANCE"; Base::main_sel_op_halt = "MAIN_SEL_OP_HALT"; Base::main_sel_op_internal_call = "MAIN_SEL_OP_INTERNAL_CALL"; @@ -3158,6 +3170,7 @@ class AvmFlavor { Commitment kernel_kernel_value_out; Commitment kernel_kernel_side_effect_out; Commitment kernel_kernel_metadata_out; + Commitment main_calldata; Commitment alu_a_hi; Commitment alu_a_lo; Commitment alu_b_hi; @@ -3354,6 +3367,7 @@ class AvmFlavor { Commitment main_sel_op_fdiv; Commitment main_sel_op_fee_per_da_gas; Commitment main_sel_op_fee_per_l2_gas; + Commitment main_sel_op_function_selector; Commitment main_sel_op_get_contract_instance; Commitment main_sel_op_halt; Commitment main_sel_op_internal_call; @@ -3560,6 +3574,7 @@ class AvmFlavor { kernel_kernel_value_out = deserialize_from_buffer(Transcript::proof_data, num_frs_read); kernel_kernel_side_effect_out = deserialize_from_buffer(Transcript::proof_data, num_frs_read); kernel_kernel_metadata_out = deserialize_from_buffer(Transcript::proof_data, num_frs_read); + main_calldata = deserialize_from_buffer(Transcript::proof_data, num_frs_read); alu_a_hi = deserialize_from_buffer(Transcript::proof_data, num_frs_read); alu_a_lo = deserialize_from_buffer(Transcript::proof_data, num_frs_read); alu_b_hi = deserialize_from_buffer(Transcript::proof_data, num_frs_read); @@ -3767,6 +3782,7 @@ class AvmFlavor { main_sel_op_fdiv = deserialize_from_buffer(Transcript::proof_data, num_frs_read); main_sel_op_fee_per_da_gas = deserialize_from_buffer(Transcript::proof_data, num_frs_read); main_sel_op_fee_per_l2_gas = deserialize_from_buffer(Transcript::proof_data, num_frs_read); + main_sel_op_function_selector = deserialize_from_buffer(Transcript::proof_data, num_frs_read); main_sel_op_get_contract_instance = deserialize_from_buffer(Transcript::proof_data, num_frs_read); main_sel_op_halt = deserialize_from_buffer(Transcript::proof_data, num_frs_read); @@ -3978,6 +3994,7 @@ class AvmFlavor { serialize_to_buffer(kernel_kernel_value_out, Transcript::proof_data); serialize_to_buffer(kernel_kernel_side_effect_out, Transcript::proof_data); serialize_to_buffer(kernel_kernel_metadata_out, Transcript::proof_data); + serialize_to_buffer(main_calldata, Transcript::proof_data); serialize_to_buffer(alu_a_hi, Transcript::proof_data); serialize_to_buffer(alu_a_lo, Transcript::proof_data); serialize_to_buffer(alu_b_hi, Transcript::proof_data); @@ -4174,6 +4191,7 @@ class AvmFlavor { serialize_to_buffer(main_sel_op_fdiv, Transcript::proof_data); serialize_to_buffer(main_sel_op_fee_per_da_gas, Transcript::proof_data); serialize_to_buffer(main_sel_op_fee_per_l2_gas, Transcript::proof_data); + serialize_to_buffer(main_sel_op_function_selector, Transcript::proof_data); serialize_to_buffer(main_sel_op_get_contract_instance, Transcript::proof_data); serialize_to_buffer(main_sel_op_halt, Transcript::proof_data); serialize_to_buffer(main_sel_op_internal_call, Transcript::proof_data); diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/avm_prover.cpp b/barretenberg/cpp/src/barretenberg/vm/generated/avm_prover.cpp index a10bc668d02..93ff4ac5989 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/avm_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/avm_prover.cpp @@ -62,6 +62,7 @@ void AvmProver::execute_wire_commitments_round() witness_commitments.kernel_kernel_value_out = commitment_key->commit(key->kernel_kernel_value_out); witness_commitments.kernel_kernel_side_effect_out = commitment_key->commit(key->kernel_kernel_side_effect_out); witness_commitments.kernel_kernel_metadata_out = commitment_key->commit(key->kernel_kernel_metadata_out); + witness_commitments.main_calldata = commitment_key->commit(key->main_calldata); witness_commitments.alu_a_hi = commitment_key->commit(key->alu_a_hi); witness_commitments.alu_a_lo = commitment_key->commit(key->alu_a_lo); witness_commitments.alu_b_hi = commitment_key->commit(key->alu_b_hi); @@ -269,6 +270,7 @@ void AvmProver::execute_wire_commitments_round() witness_commitments.main_sel_op_fdiv = commitment_key->commit(key->main_sel_op_fdiv); witness_commitments.main_sel_op_fee_per_da_gas = commitment_key->commit(key->main_sel_op_fee_per_da_gas); witness_commitments.main_sel_op_fee_per_l2_gas = commitment_key->commit(key->main_sel_op_fee_per_l2_gas); + witness_commitments.main_sel_op_function_selector = commitment_key->commit(key->main_sel_op_function_selector); witness_commitments.main_sel_op_get_contract_instance = commitment_key->commit(key->main_sel_op_get_contract_instance); witness_commitments.main_sel_op_halt = commitment_key->commit(key->main_sel_op_halt); @@ -408,6 +410,7 @@ void AvmProver::execute_wire_commitments_round() witness_commitments.kernel_kernel_side_effect_out); transcript->send_to_verifier(commitment_labels.kernel_kernel_metadata_out, witness_commitments.kernel_kernel_metadata_out); + transcript->send_to_verifier(commitment_labels.main_calldata, witness_commitments.main_calldata); transcript->send_to_verifier(commitment_labels.alu_a_hi, witness_commitments.alu_a_hi); transcript->send_to_verifier(commitment_labels.alu_a_lo, witness_commitments.alu_a_lo); transcript->send_to_verifier(commitment_labels.alu_b_hi, witness_commitments.alu_b_hi); @@ -638,6 +641,8 @@ void AvmProver::execute_wire_commitments_round() witness_commitments.main_sel_op_fee_per_da_gas); transcript->send_to_verifier(commitment_labels.main_sel_op_fee_per_l2_gas, witness_commitments.main_sel_op_fee_per_l2_gas); + transcript->send_to_verifier(commitment_labels.main_sel_op_function_selector, + witness_commitments.main_sel_op_function_selector); transcript->send_to_verifier(commitment_labels.main_sel_op_get_contract_instance, witness_commitments.main_sel_op_get_contract_instance); transcript->send_to_verifier(commitment_labels.main_sel_op_halt, witness_commitments.main_sel_op_halt); @@ -963,7 +968,8 @@ void AvmProver::execute_relation_check_rounds() * */ void AvmProver::execute_pcs_rounds() { - auto prover_opening_claim = ZeroMorph::prove(prover_polynomials.get_unshifted(), + auto prover_opening_claim = ZeroMorph::prove(key->circuit_size, + prover_polynomials.get_unshifted(), prover_polynomials.get_to_be_shifted(), sumcheck_output.claimed_evaluations.get_unshifted(), sumcheck_output.claimed_evaluations.get_shifted(), diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/avm_verifier.cpp b/barretenberg/cpp/src/barretenberg/vm/generated/avm_verifier.cpp index 0a863144aad..d15ad4f2fca 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/avm_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/avm_verifier.cpp @@ -79,6 +79,7 @@ bool AvmVerifier::verify_proof(const HonkProof& proof, const std::vectortemplate receive_from_prover(commitment_labels.kernel_kernel_side_effect_out); commitments.kernel_kernel_metadata_out = transcript->template receive_from_prover(commitment_labels.kernel_kernel_metadata_out); + commitments.main_calldata = transcript->template receive_from_prover(commitment_labels.main_calldata); commitments.alu_a_hi = transcript->template receive_from_prover(commitment_labels.alu_a_hi); commitments.alu_a_lo = transcript->template receive_from_prover(commitment_labels.alu_a_lo); commitments.alu_b_hi = transcript->template receive_from_prover(commitment_labels.alu_b_hi); @@ -375,6 +376,8 @@ bool AvmVerifier::verify_proof(const HonkProof& proof, const std::vectortemplate receive_from_prover(commitment_labels.main_sel_op_fee_per_da_gas); commitments.main_sel_op_fee_per_l2_gas = transcript->template receive_from_prover(commitment_labels.main_sel_op_fee_per_l2_gas); + commitments.main_sel_op_function_selector = + transcript->template receive_from_prover(commitment_labels.main_sel_op_function_selector); commitments.main_sel_op_get_contract_instance = transcript->template receive_from_prover(commitment_labels.main_sel_op_get_contract_instance); commitments.main_sel_op_halt = @@ -712,31 +715,36 @@ bool AvmVerifier::verify_proof(const HonkProof& proof, const std::vector mle_challenge(multivariate_challenge.begin(), + multivariate_challenge.begin() + static_cast(log_circuit_size)); - FF kernel_kernel_inputs_evaluation = - evaluate_public_input_column(public_inputs[0], circuit_size, multivariate_challenge); + FF kernel_kernel_inputs_evaluation = evaluate_public_input_column(public_inputs[0], circuit_size, mle_challenge); if (kernel_kernel_inputs_evaluation != claimed_evaluations.kernel_kernel_inputs) { return false; } - FF kernel_kernel_value_out_evaluation = - evaluate_public_input_column(public_inputs[1], circuit_size, multivariate_challenge); + FF kernel_kernel_value_out_evaluation = evaluate_public_input_column(public_inputs[1], circuit_size, mle_challenge); if (kernel_kernel_value_out_evaluation != claimed_evaluations.kernel_kernel_value_out) { return false; } FF kernel_kernel_side_effect_out_evaluation = - evaluate_public_input_column(public_inputs[2], circuit_size, multivariate_challenge); + evaluate_public_input_column(public_inputs[2], circuit_size, mle_challenge); if (kernel_kernel_side_effect_out_evaluation != claimed_evaluations.kernel_kernel_side_effect_out) { return false; } FF kernel_kernel_metadata_out_evaluation = - evaluate_public_input_column(public_inputs[3], circuit_size, multivariate_challenge); + evaluate_public_input_column(public_inputs[3], circuit_size, mle_challenge); if (kernel_kernel_metadata_out_evaluation != claimed_evaluations.kernel_kernel_metadata_out) { return false; } + FF main_calldata_evaluation = evaluate_public_input_column(public_inputs[4], circuit_size, mle_challenge); + if (main_calldata_evaluation != claimed_evaluations.main_calldata) { + return false; + } + // Execute ZeroMorph rounds. See https://hackmd.io/dlf9xEwhTQyE3hiGbq4FsA?view for a complete description of the // unrolled protocol. // NOTE: temporarily disabled - facing integration issues diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/avm_arithmetic.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/avm_arithmetic.test.cpp index 314c723aca6..a320b2d7245 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/avm_arithmetic.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/avm_arithmetic.test.cpp @@ -215,6 +215,11 @@ class AvmArithmeticTests : public ::testing::Test { VmPublicInputs public_inputs; AvmTraceBuilder trace_builder; + void gen_trace_builder(std::vector const& calldata) + { + trace_builder = AvmTraceBuilder(public_inputs, {}, 0, calldata); + } + // Generate a trace with an EQ opcode operation. std::vector gen_trace_eq(uint128_t const& a, uint128_t const& b, @@ -368,9 +373,11 @@ std::vector> positive_op_div_test_values = { { // Test on basic addition over finite field type. TEST_F(AvmArithmeticTestsFF, addition) { - trace_builder.op_calldata_copy(0, 0, 3, 0, std::vector{ 37, 4, 11 }); + std::vector const calldata = { 37, 4, 11 }; + gen_trace_builder(calldata); + trace_builder.op_calldata_copy(0, 0, 3, 0); - // Memory layout: [37,4,11,0,0,0,....] + // Memory layout: [37,4,11,0,0,0,....] trace_builder.op_add(0, 0, 1, 4, AvmMemoryTag::FF); // [37,4,11,0,41,0,....] trace_builder.op_return(0, 0, 5); auto trace = trace_builder.finalize(); @@ -381,13 +388,15 @@ TEST_F(AvmArithmeticTestsFF, addition) EXPECT_EQ(alu_row.alu_cf, FF(0)); EXPECT_EQ(alu_row.alu_u8_r0, FF(0)); - validate_trace(std::move(trace), public_inputs, true); + validate_trace(std::move(trace), public_inputs, calldata, true); } // Test on basic subtraction over finite field type. TEST_F(AvmArithmeticTestsFF, subtraction) { - trace_builder.op_calldata_copy(0, 0, 3, 0, std::vector{ 8, 4, 17 }); + std::vector const calldata = { 8, 4, 17 }; + gen_trace_builder(calldata); + trace_builder.op_calldata_copy(0, 0, 3, 0); // Memory layout: [8,4,17,0,0,0,....] trace_builder.op_sub(0, 2, 0, 1, AvmMemoryTag::FF); // [8,9,17,0,0,0....] @@ -400,13 +409,15 @@ TEST_F(AvmArithmeticTestsFF, subtraction) EXPECT_EQ(alu_row.alu_cf, FF(0)); EXPECT_EQ(alu_row.alu_u8_r0, FF(0)); - validate_trace(std::move(trace), public_inputs); + validate_trace(std::move(trace), public_inputs, calldata); } // Test on basic multiplication over finite field type. TEST_F(AvmArithmeticTestsFF, multiplication) { - trace_builder.op_calldata_copy(0, 0, 3, 0, std::vector{ 5, 0, 20 }); + std::vector const calldata = { 5, 0, 20 }; + gen_trace_builder(calldata); + trace_builder.op_calldata_copy(0, 0, 3, 0); // Memory layout: [5,0,20,0,0,0,....] trace_builder.op_mul(0, 2, 0, 1, AvmMemoryTag::FF); // [5,100,20,0,0,0....] @@ -420,13 +431,15 @@ TEST_F(AvmArithmeticTestsFF, multiplication) EXPECT_EQ(alu_row.alu_cf, FF(0)); EXPECT_EQ(alu_row.alu_u8_r0, FF(0)); - validate_trace(std::move(trace), public_inputs); + validate_trace(std::move(trace), public_inputs, calldata); } // Test on multiplication by zero over finite field type. TEST_F(AvmArithmeticTestsFF, multiplicationByZero) { - trace_builder.op_calldata_copy(0, 0, 1, 0, std::vector{ 127 }); + std::vector const calldata = { 127 }; + gen_trace_builder(calldata); + trace_builder.op_calldata_copy(0, 0, 1, 0); // Memory layout: [127,0,0,0,0,0,....] trace_builder.op_mul(0, 0, 1, 2, AvmMemoryTag::FF); // [127,0,0,0,0,0....] @@ -440,13 +453,15 @@ TEST_F(AvmArithmeticTestsFF, multiplicationByZero) EXPECT_EQ(alu_row.alu_cf, FF(0)); EXPECT_EQ(alu_row.alu_u8_r0, FF(0)); - validate_trace(std::move(trace), public_inputs); + validate_trace(std::move(trace), public_inputs, calldata); } // Test on basic division over finite field type. TEST_F(AvmArithmeticTestsFF, fDivision) { - trace_builder.op_calldata_copy(0, 0, 2, 0, std::vector{ 15, 315 }); + std::vector const calldata = { 15, 315 }; + gen_trace_builder(calldata); + trace_builder.op_calldata_copy(0, 0, 2, 0); // Memory layout: [15,315,0,0,0,0,....] trace_builder.op_fdiv(0, 1, 0, 2); // [15,315,21,0,0,0....] @@ -463,13 +478,15 @@ TEST_F(AvmArithmeticTestsFF, fDivision) EXPECT_EQ(row->main_sel_mem_op_c, FF(1)); EXPECT_EQ(row->main_rwc, FF(1)); - validate_trace(std::move(trace), public_inputs); + validate_trace(std::move(trace), public_inputs, calldata); } // Test on division with zero numerator over finite field type. TEST_F(AvmArithmeticTestsFF, fDivisionNumeratorZero) { - trace_builder.op_calldata_copy(0, 0, 1, 0, std::vector{ 15 }); + std::vector const calldata = { 15 }; + gen_trace_builder(calldata); + trace_builder.op_calldata_copy(0, 0, 1, 0); // Memory layout: [15,0,0,0,0,0,....] trace_builder.op_fdiv(0, 1, 0, 0); // [0,0,0,0,0,0....] @@ -486,14 +503,16 @@ TEST_F(AvmArithmeticTestsFF, fDivisionNumeratorZero) EXPECT_EQ(row->main_sel_mem_op_c, FF(1)); EXPECT_EQ(row->main_rwc, FF(1)); - validate_trace(std::move(trace), public_inputs); + validate_trace(std::move(trace), public_inputs, calldata); } // Test on division by zero over finite field type. // We check that the operator error flag is raised. TEST_F(AvmArithmeticTestsFF, fDivisionByZeroError) { - trace_builder.op_calldata_copy(0, 0, 1, 0, std::vector{ 15 }); + std::vector const calldata = { 15 }; + gen_trace_builder(calldata); + trace_builder.op_calldata_copy(0, 0, 1, 0); // Memory layout: [15,0,0,0,0,0,....] trace_builder.op_fdiv(0, 0, 1, 2); // [15,0,0,0,0,0....] @@ -511,7 +530,7 @@ TEST_F(AvmArithmeticTestsFF, fDivisionByZeroError) EXPECT_EQ(row->main_rwc, FF(1)); EXPECT_EQ(row->main_op_err, FF(1)); - validate_trace(std::move(trace), public_inputs); + validate_trace(std::move(trace), public_inputs, calldata); } // Test on division of zero by zero over finite field type. @@ -543,7 +562,9 @@ TEST_F(AvmArithmeticTestsFF, fDivisionZeroByZeroError) // No check on the evaluation is performed here. TEST_F(AvmArithmeticTestsFF, mixedOperationsWithError) { - trace_builder.op_calldata_copy(0, 0, 3, 2, std::vector{ 45, 23, 12 }); + std::vector const calldata = { 45, 23, 12 }; + gen_trace_builder(calldata); + trace_builder.op_calldata_copy(0, 0, 3, 2); // Memory layout: [0,0,45,23,12,0,0,0,....] trace_builder.op_add(0, 2, 3, 4, AvmMemoryTag::FF); // [0,0,45,23,68,0,0,0,....] @@ -558,7 +579,7 @@ TEST_F(AvmArithmeticTestsFF, mixedOperationsWithError) trace_builder.halt(); auto trace = trace_builder.finalize(); - validate_trace(std::move(trace), public_inputs, true); + validate_trace(std::move(trace), public_inputs, calldata, true); } // Test of equality on FF elements @@ -566,7 +587,9 @@ TEST_F(AvmArithmeticTestsFF, equality) { // Pick a field-sized number FF elem = FF::modulus - FF(1); - trace_builder.op_calldata_copy(0, 0, 3, 0, std::vector{ elem, elem, 1 }); + std::vector const calldata = { elem, elem, 1 }; + gen_trace_builder(calldata); + trace_builder.op_calldata_copy(0, 0, 3, 0); trace_builder.op_eq(0, 0, 1, 2, AvmMemoryTag::FF); // Memory Layout [q - 1, q -1, 1,0..] trace_builder.op_return(0, 0, 3); auto trace = trace_builder.finalize(); @@ -576,14 +599,16 @@ TEST_F(AvmArithmeticTestsFF, equality) EXPECT_EQ(alu_row.alu_ff_tag, FF(1)); EXPECT_EQ(alu_row.alu_op_eq_diff_inv, FF(0)); // Expect 0 as inv of (q-1) - (q-1) - validate_trace(std::move(trace), public_inputs); + validate_trace(std::move(trace), public_inputs, calldata); } // Test correct non-equality of FF elements TEST_F(AvmArithmeticTestsFF, nonEquality) { FF elem = FF::modulus - FF(1); - trace_builder.op_calldata_copy(0, 0, 3, 0, std::vector{ elem, elem + FF(1), 0 }); + std::vector const calldata = { elem, elem + FF(1), 0 }; + gen_trace_builder(calldata); + trace_builder.op_calldata_copy(0, 0, 3, 0); trace_builder.op_eq(0, 0, 1, 2, AvmMemoryTag::FF); // Memory Layout [q - 1, q, 1,0..] trace_builder.op_return(0, 0, 0); auto trace = trace_builder.finalize(); @@ -593,7 +618,7 @@ TEST_F(AvmArithmeticTestsFF, nonEquality) EXPECT_EQ(alu_row.alu_ff_tag, FF(1)); EXPECT_EQ(alu_row.alu_op_eq_diff_inv, FF(-1).invert()); - validate_trace(std::move(trace), public_inputs); + validate_trace(std::move(trace), public_inputs, calldata); } TEST_P(AvmArithmeticTestsDiv, division) @@ -1758,7 +1783,9 @@ TEST_F(AvmArithmeticNegativeTestsFF, multiplication) // Test on basic incorrect division over finite field type. TEST_F(AvmArithmeticNegativeTestsFF, fDivision) { - trace_builder.op_calldata_copy(0, 0, 2, 0, std::vector{ 15, 315 }); + std::vector const calldata = { 15, 315 }; + gen_trace_builder(calldata); + trace_builder.op_calldata_copy(0, 0, 2, 0); // Memory layout: [15,315,0,0,0,0,....] trace_builder.op_fdiv(0, 1, 0, 2); // [15,315,21,0,0,0....] @@ -1775,7 +1802,9 @@ TEST_F(AvmArithmeticNegativeTestsFF, fDivision) // in the trace. TEST_F(AvmArithmeticNegativeTestsFF, fDivisionNoZeroButError) { - trace_builder.op_calldata_copy(0, 0, 2, 0, std::vector{ 15, 315 }); + std::vector const calldata = { 15, 315 }; + gen_trace_builder(calldata); + trace_builder.op_calldata_copy(0, 0, 2, 0); // Memory layout: [15,315,0,0,0,0,....] trace_builder.op_fdiv(0, 1, 0, 2); // [15,315,21,0,0,0....] @@ -1801,7 +1830,9 @@ TEST_F(AvmArithmeticNegativeTestsFF, fDivisionNoZeroButError) // Test with finite field division by zero occurs and no error is raised (remove error flag) TEST_F(AvmArithmeticNegativeTestsFF, fDivisionByZeroNoError) { - trace_builder.op_calldata_copy(0, 0, 1, 0, std::vector{ 15 }); + std::vector const calldata = { 15 }; + gen_trace_builder(calldata); + trace_builder.op_calldata_copy(0, 0, 1, 0); // Memory layout: [15,0,0,0,0,0,....] trace_builder.op_fdiv(0, 0, 1, 2); // [15,0,0,0,0,0....] @@ -1837,7 +1868,9 @@ TEST_F(AvmArithmeticNegativeTestsFF, fDivisionZeroByZeroNoError) // Test with finite field division using a wrong read instruction tag TEST_F(AvmArithmeticNegativeTestsFF, fDivisionWrongRInTag) { - trace_builder.op_calldata_copy(0, 0, 1, 0, std::vector{ 18, 6 }); + std::vector const calldata = { 18, 6 }; + gen_trace_builder(calldata); + trace_builder.op_calldata_copy(0, 0, 1, 0); // Memory layout: [18,6,0,0,0,0,....] trace_builder.op_fdiv(0, 0, 1, 2); // [18,6,3,0,0,0....] trace_builder.halt(); @@ -1855,7 +1888,9 @@ TEST_F(AvmArithmeticNegativeTestsFF, fDivisionWrongRInTag) // Test with finite field division using a wrong write instruction tag TEST_F(AvmArithmeticNegativeTestsFF, fDivisionWrongWInTag) { - trace_builder.op_calldata_copy(0, 0, 1, 0, std::vector{ 18, 6 }); + std::vector const calldata = { 18, 6 }; + gen_trace_builder(calldata); + trace_builder.op_calldata_copy(0, 0, 1, 0); // Memory layout: [18,6,0,0,0,0,....] trace_builder.op_fdiv(0, 0, 1, 2); // [18,6,3,0,0,0....] trace_builder.halt(); @@ -1874,7 +1909,9 @@ TEST_F(AvmArithmeticNegativeTestsFF, fDivisionWrongWInTag) // the addition, subtraction, multiplication. TEST_F(AvmArithmeticNegativeTestsFF, operationWithErrorFlag1) { - trace_builder.op_calldata_copy(0, 0, 3, 0, std::vector{ 37, 4, 11 }); + std::vector const calldata = { 37, 4, 11 }; + gen_trace_builder(calldata); + trace_builder.op_calldata_copy(0, 0, 3, 0); // Memory layout: [37,4,11,0,0,0,....] trace_builder.op_add(0, 0, 1, 4, AvmMemoryTag::FF); // [37,4,11,0,41,0,....] @@ -1893,7 +1930,9 @@ TEST_F(AvmArithmeticNegativeTestsFF, operationWithErrorFlag1) TEST_F(AvmArithmeticNegativeTestsFF, operationWithErrorFlag2) { - trace_builder.op_calldata_copy(0, 0, 3, 0, std::vector{ 8, 4, 17 }); + std::vector const calldata = { 8, 4, 17 }; + gen_trace_builder(calldata); + trace_builder.op_calldata_copy(0, 0, 3, 0); // Memory layout: [8,4,17,0,0,0,....] trace_builder.op_sub(0, 2, 0, 1, AvmMemoryTag::FF); // [8,9,17,0,0,0....] @@ -1911,7 +1950,9 @@ TEST_F(AvmArithmeticNegativeTestsFF, operationWithErrorFlag2) TEST_F(AvmArithmeticNegativeTestsFF, operationWithErrorFlag3) { - trace_builder.op_calldata_copy(0, 0, 3, 0, std::vector{ 5, 0, 20 }); + std::vector const calldata = { 5, 0, 20 }; + gen_trace_builder(calldata); + trace_builder.op_calldata_copy(0, 0, 3, 0); // Memory layout: [5,0,20,0,0,0,....] trace_builder.op_mul(0, 2, 0, 1, AvmMemoryTag::FF); // [5,100,20,0,0,0....] @@ -1954,7 +1995,9 @@ TEST_F(AvmArithmeticNegativeTestsFF, nonBooleanEq) TEST_F(AvmArithmeticNegativeTestsFF, eqOutputWrongTag) { FF elem = FF::modulus - FF(15); - trace_builder.op_calldata_copy(0, 0, 2, 0, std::vector{ elem, elem }); + std::vector const calldata = { elem, elem }; + gen_trace_builder(calldata); + trace_builder.op_calldata_copy(0, 0, 2, 0); trace_builder.op_eq(0, 0, 1, 2, AvmMemoryTag::FF); // Memory Layout [elem, elem, 1, 0..] trace_builder.op_return(0, 0, 0); auto trace = trace_builder.finalize(); diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/avm_bitwise.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/avm_bitwise.test.cpp index 387da11f11b..e70b50106af 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/avm_bitwise.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/avm_bitwise.test.cpp @@ -492,7 +492,7 @@ TEST_P(AvmBitwiseTestsAnd, AllAndTest) auto trace = trace_builder.finalize(); common_validate_bit_op(trace, 0, a, b, output, FF(0), FF(1), FF(2), mem_tag); - validate_trace(std::move(trace), public_inputs, true); + validate_trace(std::move(trace), public_inputs, {}, true); } INSTANTIATE_TEST_SUITE_P(AvmBitwiseTests, AvmBitwiseTestsAnd, diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/avm_cast.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/avm_cast.test.cpp index 80629cd9e57..11d9768300d 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/avm_cast.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/avm_cast.test.cpp @@ -23,6 +23,7 @@ class AvmCastTests : public ::testing::Test { VmPublicInputs public_inputs; AvmTraceBuilder trace_builder; + std::vector calldata; std::vector trace; size_t main_addr; @@ -113,9 +114,9 @@ class AvmCastTests : public ::testing::Test { // We still want the ability to enable proving through the environment variable and therefore we do not pass // the boolean variable force_proof to validate_trace second argument. if (force_proof) { - validate_trace(std::move(trace), public_inputs, true); + validate_trace(std::move(trace), public_inputs, calldata, true); } else { - validate_trace(std::move(trace), public_inputs); + validate_trace(std::move(trace), public_inputs, calldata); } } }; @@ -171,7 +172,9 @@ TEST_F(AvmCastTests, noTruncationFFToU32) TEST_F(AvmCastTests, truncationFFToU16ModMinus1) { - trace_builder.op_calldata_copy(0, 0, 1, 0, { FF(FF::modulus - 1) }); + calldata = { FF::modulus - 1 }; + trace_builder = AvmTraceBuilder(public_inputs, {}, 0, calldata); + trace_builder.op_calldata_copy(0, 0, 1, 0); trace_builder.op_cast(0, 0, 1, AvmMemoryTag::U16); trace_builder.op_return(0, 0, 0); trace = trace_builder.finalize(); @@ -182,7 +185,9 @@ TEST_F(AvmCastTests, truncationFFToU16ModMinus1) TEST_F(AvmCastTests, truncationFFToU16ModMinus2) { - trace_builder.op_calldata_copy(0, 0, 1, 0, { FF(FF::modulus_minus_two) }); + calldata = { FF::modulus_minus_two }; + trace_builder = AvmTraceBuilder(public_inputs, {}, 0, calldata); + trace_builder.op_calldata_copy(0, 0, 1, 0); trace_builder.op_cast(0, 0, 1, AvmMemoryTag::U16); trace_builder.op_return(0, 0, 0); trace = trace_builder.finalize(); @@ -291,7 +296,9 @@ TEST_F(AvmCastNegativeTests, wrongOutputAluIc) TEST_F(AvmCastNegativeTests, wrongLimbDecompositionInput) { - trace_builder.op_calldata_copy(0, 0, 1, 0, { FF(FF::modulus_minus_two) }); + calldata = { FF::modulus_minus_two }; + trace_builder = AvmTraceBuilder(public_inputs, {}, 0, calldata); + trace_builder.op_calldata_copy(0, 0, 1, 0); trace_builder.op_cast(0, 0, 1, AvmMemoryTag::U16); trace_builder.op_return(0, 0, 0); trace = trace_builder.finalize(); @@ -314,7 +321,9 @@ TEST_F(AvmCastNegativeTests, wrongPSubALo) TEST_F(AvmCastNegativeTests, wrongPSubAHi) { - trace_builder.op_calldata_copy(0, 0, 1, 0, { FF(FF::modulus_minus_two - 987) }); + calldata = { FF::modulus_minus_two - 987 }; + trace_builder = AvmTraceBuilder(public_inputs, {}, 0, calldata); + trace_builder.op_calldata_copy(0, 0, 1, 0); trace_builder.op_cast(0, 0, 1, AvmMemoryTag::U16); trace_builder.op_return(0, 0, 0); trace = trace_builder.finalize(); @@ -352,7 +361,9 @@ TEST_F(AvmCastNegativeTests, wrongRangeCheckDecompositionLo) TEST_F(AvmCastNegativeTests, wrongRangeCheckDecompositionHi) { - trace_builder.op_calldata_copy(0, 0, 1, 0, { FF(FF::modulus_minus_two - 987) }); + calldata = { FF::modulus_minus_two - 987 }; + trace_builder = AvmTraceBuilder(public_inputs, {}, 0, calldata); + trace_builder.op_calldata_copy(0, 0, 1, 0); trace_builder.op_cast(0, 0, 1, AvmMemoryTag::U16); trace_builder.op_return(0, 0, 0); trace = trace_builder.finalize(); @@ -396,7 +407,9 @@ TEST_F(AvmCastNegativeTests, wrongCopySubLoForRangeCheck) TEST_F(AvmCastNegativeTests, wrongCopySubHiForRangeCheck) { - trace_builder.op_calldata_copy(0, 0, 1, 0, { FF(FF::modulus_minus_two - 972836) }); + std::vector const calldata = { FF::modulus_minus_two - 972836 }; + trace_builder = AvmTraceBuilder(public_inputs, {}, 0, calldata); + trace_builder.op_calldata_copy(0, 0, 1, 0); trace_builder.op_cast(0, 0, 1, AvmMemoryTag::U128); trace_builder.op_return(0, 0, 0); trace = trace_builder.finalize(); diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/avm_comparison.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/avm_comparison.test.cpp index 0ed161a8afd..c3e65de1242 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/avm_comparison.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/avm_comparison.test.cpp @@ -106,8 +106,12 @@ TEST_P(AvmCmpTestsLT, ParamTest) { const auto [params, mem_tag] = GetParam(); const auto [a, b, c] = params; + std::vector calldata{}; + if (mem_tag == AvmMemoryTag::FF) { - trace_builder.op_calldata_copy(0, 0, 2, 0, std::vector{ a, b }); + calldata = { a, b }; + trace_builder = AvmTraceBuilder(public_inputs, {}, 0, calldata); + trace_builder.op_calldata_copy(0, 0, 2, 0); } else { trace_builder.op_set(0, uint128_t(a), 0, mem_tag); trace_builder.op_set(0, uint128_t(b), 1, mem_tag); @@ -128,7 +132,7 @@ TEST_P(AvmCmpTestsLT, ParamTest) ASSERT_TRUE(alu_row != trace.end()); common_validate_cmp(*row, *alu_row, a, b, c, FF(0), FF(1), FF(2), mem_tag); - validate_trace(std::move(trace), public_inputs); + validate_trace(std::move(trace), public_inputs, calldata); } INSTANTIATE_TEST_SUITE_P(AvmCmpTests, AvmCmpTestsLT, @@ -138,8 +142,12 @@ TEST_P(AvmCmpTestsLTE, ParamTest) { const auto [params, mem_tag] = GetParam(); const auto [a, b, c] = params; + std::vector calldata{}; + if (mem_tag == AvmMemoryTag::FF) { - trace_builder.op_calldata_copy(0, 0, 2, 0, std::vector{ a, b }); + calldata = { a, b }; + trace_builder = AvmTraceBuilder(public_inputs, {}, 0, calldata); + trace_builder.op_calldata_copy(0, 0, 2, 0); } else { trace_builder.op_set(0, uint128_t(a), 0, mem_tag); trace_builder.op_set(0, uint128_t(b), 1, mem_tag); @@ -157,7 +165,7 @@ TEST_P(AvmCmpTestsLTE, ParamTest) ASSERT_TRUE(row != trace.end()); ASSERT_TRUE(alu_row != trace.end()); common_validate_cmp(*row, *alu_row, a, b, c, FF(0), FF(1), FF(2), mem_tag); - validate_trace(std::move(trace), public_inputs); + validate_trace(std::move(trace), public_inputs, calldata); } INSTANTIATE_TEST_SUITE_P(AvmCmpTests, AvmCmpTestsLTE, @@ -309,7 +317,9 @@ TEST_P(AvmCmpNegativeTestsLT, ParamTest) const auto [failure, params] = GetParam(); const auto [failure_string, failure_mode] = failure; const auto [a, b, output] = params; - trace_builder.op_calldata_copy(0, 0, 3, 0, std::vector{ a, b, output }); + + trace_builder = AvmTraceBuilder(public_inputs, {}, 0, std::vector{ a, b, output }); + trace_builder.op_calldata_copy(0, 0, 3, 0); trace_builder.op_lt(0, 0, 1, 2, AvmMemoryTag::FF); trace_builder.op_return(0, 0, 0); auto trace = trace_builder.finalize(); @@ -327,7 +337,8 @@ TEST_P(AvmCmpNegativeTestsLTE, ParamTest) const auto [failure, params] = GetParam(); const auto [failure_string, failure_mode] = failure; const auto [a, b, output] = params; - trace_builder.op_calldata_copy(0, 0, 3, 0, std::vector{ a, b, output }); + trace_builder = AvmTraceBuilder(public_inputs, {}, 0, std::vector{ a, b, output }); + trace_builder.op_calldata_copy(0, 0, 3, 0); trace_builder.op_lte(0, 0, 1, 2, AvmMemoryTag::FF); trace_builder.op_return(0, 0, 0); auto trace = trace_builder.finalize(); diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/avm_control_flow.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/avm_control_flow.test.cpp index 31d4facca5e..f961e542cb4 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/avm_control_flow.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/avm_control_flow.test.cpp @@ -87,7 +87,7 @@ TEST_F(AvmControlFlowTests, simpleCall) EXPECT_EQ(halt_row->main_pc, FF(CALL_PC)); EXPECT_EQ(halt_row->main_internal_return_ptr, FF(1)); } - validate_trace(std::move(trace), public_inputs, true); + validate_trace(std::move(trace), public_inputs, {}, true); } TEST_F(AvmControlFlowTests, simpleJump) diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/avm_execution.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/avm_execution.test.cpp index c7af3789b56..21b9d2793cb 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/avm_execution.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/avm_execution.test.cpp @@ -100,7 +100,7 @@ TEST_F(AvmExecutionTests, basicAddReturn) ElementsAre(VariantWith(0), VariantWith(0), VariantWith(0))))); auto trace = gen_trace_from_instr(instructions); - validate_trace(std::move(trace), public_inputs, true); + validate_trace(std::move(trace), public_inputs, {}, true); } // Positive test for SET and SUB opcodes @@ -165,7 +165,7 @@ TEST_F(AvmExecutionTests, setAndSubOpcodes) // Find the first row enabling the subtraction selector auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_sub == 1; }); EXPECT_EQ(row->main_ic, 10000); // 47123 - 37123 = 10000 - validate_trace(std::move(trace), public_inputs, true); + validate_trace(std::move(trace), public_inputs, {}, true); } // Positive test for multiple MUL opcodes @@ -467,7 +467,7 @@ TEST_F(AvmExecutionTests, jumpAndCalldatacopy) // It must have failed as subtraction was "jumped over". EXPECT_EQ(row, trace.end()); - validate_trace(std::move(trace), public_inputs); + validate_trace(std::move(trace), public_inputs, { 13, 156 }); } // Positive test for JUMPI. @@ -561,8 +561,8 @@ TEST_F(AvmExecutionTests, jumpiAndCalldatacopy) EXPECT_EQ(row->main_ic, 1600); // 800 = (20 + 20) * (20 + 20) // traces validation - validate_trace(std::move(trace_jump), public_inputs); - validate_trace(std::move(trace_no_jump), public_inputs); + validate_trace(std::move(trace_jump), public_inputs, { 9873123 }); + validate_trace(std::move(trace_no_jump), public_inputs, { 0 }); } // Positive test with MOV. @@ -805,7 +805,7 @@ TEST_F(AvmExecutionTests, toRadixLeOpcode) } EXPECT_EQ(returndata, expected_output); - validate_trace(std::move(trace), public_inputs); + validate_trace(std::move(trace), public_inputs, { FF::modulus - FF(1) }); } // // Positive test with SHA256COMPRESSION. @@ -873,7 +873,7 @@ TEST_F(AvmExecutionTests, sha256CompressionOpcode) EXPECT_EQ(returndata, expected_output); - validate_trace(std::move(trace), public_inputs); + validate_trace(std::move(trace), public_inputs, calldata); } // Positive test with SHA256 @@ -992,7 +992,7 @@ TEST_F(AvmExecutionTests, poseidon2PermutationOpCode) EXPECT_EQ(returndata, expected_output); - validate_trace(std::move(trace), public_inputs); + validate_trace(std::move(trace), public_inputs, calldata); } // Positive test with Keccakf1600. @@ -1177,7 +1177,7 @@ TEST_F(AvmExecutionTests, pedersenHashOpCode) EXPECT_EQ(returndata[0], expected_output); - validate_trace(std::move(trace), public_inputs); + validate_trace(std::move(trace), public_inputs, calldata); } // // Positive test with EmbeddedCurveAdd @@ -1239,7 +1239,7 @@ TEST_F(AvmExecutionTests, embeddedCurveAddOpCode) EXPECT_EQ(returndata, expected_output); - validate_trace(std::move(trace), public_inputs); + validate_trace(std::move(trace), public_inputs, calldata); } // Positive test with MSM @@ -1316,139 +1316,154 @@ TEST_F(AvmExecutionTests, msmOpCode) EXPECT_EQ(returndata, expected_output); - validate_trace(std::move(trace), public_inputs); + validate_trace(std::move(trace), public_inputs, calldata); } // Positive test for Kernel Input opcodes TEST_F(AvmExecutionTests, kernelInputOpcodes) { - std::string bytecode_hex = to_hex(OpCode::SENDER) + // opcode SENDER - "00" // Indirect flag - "00000001" // dst_offset 1 - + to_hex(OpCode::ADDRESS) + // opcode ADDRESS - "00" // Indirect flag - "00000002" // dst_offset 2 - + to_hex(OpCode::STORAGEADDRESS) + // opcode STORAGEADDRESS - "00" // Indirect flag - "00000003" // dst_offset 3 - + to_hex(OpCode::FEEPERL2GAS) + // opcode FEEPERL2GAS - "00" // Indirect flag - "00000004" // dst_offset 4 - + to_hex(OpCode::FEEPERDAGAS) + // opcode FEEPERDAGAS - "00" // Indirect flag - "00000005" // dst_offset 5 - + to_hex(OpCode::TRANSACTIONFEE) + // opcode TRANSACTIONFEE - "00" // Indirect flag - "00000006" // dst_offset 6 - + to_hex(OpCode::CHAINID) + // opcode CHAINID - "00" // Indirect flag - "00000007" // dst_offset 7 - + to_hex(OpCode::VERSION) + // opcode VERSION - "00" // Indirect flag - "00000008" // dst_offset 8 - + to_hex(OpCode::BLOCKNUMBER) + // opcode BLOCKNUMBER - "00" // Indirect flag - "00000009" // dst_offset 9 - + to_hex(OpCode::TIMESTAMP) + // opcode TIMESTAMP - "00" // Indirect flag - "0000000a" // dst_offset 10 - // Not in simulator + std::string bytecode_hex = to_hex(OpCode::ADDRESS) + // opcode ADDRESS + "00" // Indirect flag + "00000001" // dst_offset + + to_hex(OpCode::STORAGEADDRESS) + // opcode STORAGEADDRESS + "00" // Indirect flag + "00000002" // dst_offset + + to_hex(OpCode::SENDER) + // opcode SENDER + "00" // Indirect flag + "00000003" // dst_offset + + to_hex(OpCode::FUNCTIONSELECTOR) + // opcode TRANSACTIONFEE + "00" // Indirect flag + "00000004" // dst_offset + + to_hex(OpCode::TRANSACTIONFEE) + // opcode TRANSACTIONFEE + "00" // Indirect flag + "00000005" // dst_offset + + to_hex(OpCode::CHAINID) + // opcode CHAINID + "00" // Indirect flag + "00000006" // dst_offset + + to_hex(OpCode::VERSION) + // opcode VERSION + "00" // Indirect flag + "00000007" // dst_offset + + to_hex(OpCode::BLOCKNUMBER) + // opcode BLOCKNUMBER + "00" // Indirect flag + "00000008" // dst_offset + + to_hex(OpCode::TIMESTAMP) + // opcode TIMESTAMP + "00" // Indirect flag + "00000009" // dst_offset + // Not in simulator // + to_hex(OpCode::COINBASE) + // opcode COINBASE // "00" // Indirect flag - // "0000000a" // dst_offset 10 - + to_hex(OpCode::RETURN) + // opcode RETURN - "00" // Indirect flag - "00000001" // ret offset 1 - "0000000a"; // ret size 10 + // "00000009" // dst_offset + + to_hex(OpCode::FEEPERL2GAS) + // opcode FEEPERL2GAS + "00" // Indirect flag + "0000000a" // dst_offset + + to_hex(OpCode::FEEPERDAGAS) + // opcode FEEPERDAGAS + "00" // Indirect flag + "0000000b" // dst_offset + + to_hex(OpCode::RETURN) + // opcode RETURN + "00" // Indirect flag + "00000001" // ret offset 1 + "0000000b"; // ret size 11 auto bytecode = hex_to_bytes(bytecode_hex); auto instructions = Deserialization::parse(bytecode); - ASSERT_THAT(instructions, SizeIs(11)); + ASSERT_THAT(instructions, SizeIs(12)); - // SENDER + // ADDRESS EXPECT_THAT(instructions.at(0), - AllOf(Field(&Instruction::op_code, OpCode::SENDER), + AllOf(Field(&Instruction::op_code, OpCode::ADDRESS), Field(&Instruction::operands, ElementsAre(VariantWith(0), VariantWith(1))))); - // ADDRESS + // STORAGEADDRESS EXPECT_THAT(instructions.at(1), - AllOf(Field(&Instruction::op_code, OpCode::ADDRESS), + AllOf(Field(&Instruction::op_code, OpCode::STORAGEADDRESS), Field(&Instruction::operands, ElementsAre(VariantWith(0), VariantWith(2))))); - // STORAGEADDRESS + // SENDER EXPECT_THAT(instructions.at(2), - AllOf(Field(&Instruction::op_code, OpCode::STORAGEADDRESS), + AllOf(Field(&Instruction::op_code, OpCode::SENDER), Field(&Instruction::operands, ElementsAre(VariantWith(0), VariantWith(3))))); - // FEEPERL2GAS + + // FUNCTIONSELECTOR EXPECT_THAT(instructions.at(3), - AllOf(Field(&Instruction::op_code, OpCode::FEEPERL2GAS), + AllOf(Field(&Instruction::op_code, OpCode::FUNCTIONSELECTOR), Field(&Instruction::operands, ElementsAre(VariantWith(0), VariantWith(4))))); - // FEEPERDAGAS - EXPECT_THAT(instructions.at(4), - AllOf(Field(&Instruction::op_code, OpCode::FEEPERDAGAS), - Field(&Instruction::operands, ElementsAre(VariantWith(0), VariantWith(5))))); - // TRANSACTIONFEE - EXPECT_THAT(instructions.at(5), + EXPECT_THAT(instructions.at(4), AllOf(Field(&Instruction::op_code, OpCode::TRANSACTIONFEE), - Field(&Instruction::operands, ElementsAre(VariantWith(0), VariantWith(6))))); + Field(&Instruction::operands, ElementsAre(VariantWith(0), VariantWith(5))))); // CHAINID - EXPECT_THAT(instructions.at(6), + EXPECT_THAT(instructions.at(5), AllOf(Field(&Instruction::op_code, OpCode::CHAINID), - Field(&Instruction::operands, ElementsAre(VariantWith(0), VariantWith(7))))); + Field(&Instruction::operands, ElementsAre(VariantWith(0), VariantWith(6))))); // VERSION - EXPECT_THAT(instructions.at(7), + EXPECT_THAT(instructions.at(6), AllOf(Field(&Instruction::op_code, OpCode::VERSION), - Field(&Instruction::operands, ElementsAre(VariantWith(0), VariantWith(8))))); + Field(&Instruction::operands, ElementsAre(VariantWith(0), VariantWith(7))))); // BLOCKNUMBER - EXPECT_THAT(instructions.at(8), + EXPECT_THAT(instructions.at(7), AllOf(Field(&Instruction::op_code, OpCode::BLOCKNUMBER), - Field(&Instruction::operands, ElementsAre(VariantWith(0), VariantWith(9))))); + Field(&Instruction::operands, ElementsAre(VariantWith(0), VariantWith(8))))); // TIMESTAMP - EXPECT_THAT(instructions.at(9), + EXPECT_THAT(instructions.at(8), AllOf(Field(&Instruction::op_code, OpCode::TIMESTAMP), - Field(&Instruction::operands, ElementsAre(VariantWith(0), VariantWith(10))))); + Field(&Instruction::operands, ElementsAre(VariantWith(0), VariantWith(9))))); // COINBASE // Not in simulator - // EXPECT_THAT(instructions.at(9), + // EXPECT_THAT(instructions.at(8), // AllOf(Field(&Instruction::op_code, OpCode::COINBASE), // Field(&Instruction::operands, ElementsAre(VariantWith(0), // VariantWith(10))))); + // FEEPERL2GAS + EXPECT_THAT(instructions.at(9), + AllOf(Field(&Instruction::op_code, OpCode::FEEPERL2GAS), + Field(&Instruction::operands, ElementsAre(VariantWith(0), VariantWith(10))))); + + // FEEPERDAGAS + EXPECT_THAT(instructions.at(10), + AllOf(Field(&Instruction::op_code, OpCode::FEEPERDAGAS), + Field(&Instruction::operands, ElementsAre(VariantWith(0), VariantWith(11))))); + // Public inputs for the circuit std::vector calldata = {}; FF sender = 1; FF address = 2; - FF storage_address = 3; - FF feeperl2gas = 4; - FF feeperdagas = 5; - FF transactionfee = 6; - FF chainid = 7; - FF version = 8; - FF blocknumber = 9; - FF timestamp = 10; - // Not in simulator - // FF coinbase = 10; + // NOTE: address doesn't actually exist in public circuit public inputs, + // so storage address is just an alias of address for now + FF storage_address = address; + FF function_selector = 4; + FF transaction_fee = 5; + FF chainid = 6; + FF version = 7; + FF blocknumber = 8; + FF timestamp = 9; + // FF coinbase = 10; // Not in simulator + FF feeperl2gas = 10; + FF feeperdagas = 11; // The return data for this test should be a the opcodes in sequence, as the opcodes dst address lines up with // this array The returndata call above will then return this array - std::vector returndata = { sender, address, storage_address, feeperl2gas, feeperdagas, - transactionfee, chainid, version, blocknumber, /*coinbase,*/ timestamp }; + std::vector returndata = { sender, address, storage_address, function_selector, transaction_fee, + chainid, version, blocknumber, /*coinbase,*/ timestamp, feeperl2gas, + feeperdagas }; // Set up public inputs to contain the above values // TODO: maybe have a javascript like object construction so that this is readable // Reduce the amount of times we have similar code to this - public_inputs_vec[SENDER_SELECTOR] = sender; + // public_inputs_vec[ADDRESS_SELECTOR] = address; public_inputs_vec[STORAGE_ADDRESS_SELECTOR] = storage_address; + public_inputs_vec[SENDER_SELECTOR] = sender; + public_inputs_vec[FUNCTION_SELECTOR_SELECTOR] = function_selector; + public_inputs_vec[TRANSACTION_FEE_OFFSET] = transaction_fee; // Global variables public_inputs_vec[CHAIN_ID_OFFSET] = chainid; @@ -1457,21 +1472,13 @@ TEST_F(AvmExecutionTests, kernelInputOpcodes) public_inputs_vec[TIMESTAMP_OFFSET] = timestamp; // Not in the simulator yet // public_inputs_vec[COINBASE_OFFSET] = coinbase; - - // Fees + // Global variables - Gas public_inputs_vec[FEE_PER_DA_GAS_OFFSET] = feeperdagas; public_inputs_vec[FEE_PER_L2_GAS_OFFSET] = feeperl2gas; - // Transaction fee - public_inputs_vec[TRANSACTION_FEE_OFFSET] = transactionfee; - auto trace = Execution::gen_trace(instructions, returndata, calldata, public_inputs_vec); // Validate that the opcode read the correct value into ia - // Check sender - auto sender_row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_sender == 1; }); - EXPECT_EQ(sender_row->main_ia, sender); - // Check address auto address_row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_address == 1; }); @@ -1482,6 +1489,20 @@ TEST_F(AvmExecutionTests, kernelInputOpcodes) std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_storage_address == 1; }); EXPECT_EQ(storage_addr_row->main_ia, storage_address); + // Check sender + auto sender_row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_sender == 1; }); + EXPECT_EQ(sender_row->main_ia, sender); + + // Check function selector + auto function_selector_row = + std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_function_selector == 1; }); + EXPECT_EQ(function_selector_row->main_ia, function_selector); + + // Check transactionfee + auto transaction_fee_row = + std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_transaction_fee == 1; }); + EXPECT_EQ(transaction_fee_row->main_ia, transaction_fee); + // Check chain id auto chainid_row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_chain_id == 1; }); @@ -1502,6 +1523,12 @@ TEST_F(AvmExecutionTests, kernelInputOpcodes) std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_timestamp == 1; }); EXPECT_EQ(timestamp_row->main_ia, timestamp); + // // Check coinbase + // Not in simulator + // auto coinbase_row = + // std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_coinbase == 1; }); + // EXPECT_EQ(coinbase_row->main_ia, coinbase); + // Check feeperdagas auto feeperdagas_row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_fee_per_da_gas == 1; }); @@ -1512,17 +1539,6 @@ TEST_F(AvmExecutionTests, kernelInputOpcodes) std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_fee_per_l2_gas == 1; }); EXPECT_EQ(feeperl2gas_row->main_ia, feeperl2gas); - // Check transactionfee - auto transactionfee_row = - std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_transaction_fee == 1; }); - EXPECT_EQ(transactionfee_row->main_ia, transactionfee); - - // // Check coinbase - // Not in simulator - // auto coinbase_row = - // std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_coinbase == 1; }); - // EXPECT_EQ(coinbase_row->main_ia, coinbase); - validate_trace(std::move(trace), Execution::convert_public_inputs(public_inputs_vec)); } @@ -1899,7 +1915,7 @@ TEST_F(AvmExecutionTests, kernelOutputStorageStoreOpcodeSimple) EXPECT_EQ(metadata_out, 9); // slot feed_output(sstore_out_offset, value_out, side_effect_out, metadata_out); - validate_trace(std::move(trace), public_inputs); + validate_trace(std::move(trace), public_inputs, calldata); } // SSTORE @@ -1961,7 +1977,7 @@ TEST_F(AvmExecutionTests, kernelOutputStorageStoreOpcodeComplex) feed_output(sstore_out_offset, 42, 0, 9); feed_output(sstore_out_offset + 1, 123, 1, 10); - validate_trace(std::move(trace), public_inputs); + validate_trace(std::move(trace), public_inputs, calldata); } // SLOAD and SSTORE @@ -2217,7 +2233,7 @@ TEST_F(AvmExecutionTests, opCallOpcodes) auto trace = Execution::gen_trace(instructions, returndata, calldata, public_inputs_vec, execution_hints); EXPECT_EQ(returndata, std::vector({ 9, 8, 1 })); // The 1 represents the success - validate_trace(std::move(trace), public_inputs); + validate_trace(std::move(trace), public_inputs, calldata); } TEST_F(AvmExecutionTests, opGetContractInstanceOpcodes) @@ -2256,7 +2272,7 @@ TEST_F(AvmExecutionTests, opGetContractInstanceOpcodes) auto trace = Execution::gen_trace(instructions, returndata, calldata, public_inputs_vec, execution_hints); EXPECT_EQ(returndata, std::vector({ 1, 2, 3, 4, 5, 6 })); // The first one represents true - validate_trace(std::move(trace), public_inputs); + validate_trace(std::move(trace), public_inputs, calldata); } // Negative test detecting an invalid opcode byte. TEST_F(AvmExecutionTests, invalidOpcode) diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/avm_indirect_mem.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/avm_indirect_mem.test.cpp index ccead55c438..47e82b75102 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/avm_indirect_mem.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/avm_indirect_mem.test.cpp @@ -68,7 +68,7 @@ TEST_F(AvmIndirectMemTests, allIndirectAdd) EXPECT_EQ(row->main_sel_mem_op_b, FF(1)); EXPECT_EQ(row->main_sel_mem_op_c, FF(1)); - validate_trace(std::move(trace), public_inputs, true); + validate_trace(std::move(trace), public_inputs, {}, true); } // Testing a subtraction operation with direct input operands a, b, and an indirect diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/avm_kernel.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/avm_kernel.test.cpp index f4076677049..0ea5ca18b30 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/avm_kernel.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/avm_kernel.test.cpp @@ -280,6 +280,42 @@ TEST_F(AvmKernelPositiveTests, kernelStorageAddress) test_kernel_lookup(true, indirect_apply_opcodes, checks); } +TEST_F(AvmKernelPositiveTests, kernelFunctionSelector) +{ + // Direct + uint32_t dst_offset = 42; + uint32_t indirect_dst_offset = 69; + // We test that the function selector opcode is included at index 0 in the public inputs + auto direct_apply_opcodes = [=](AvmTraceBuilder& trace_builder) { + trace_builder.op_function_selector(/*indirect*/ false, dst_offset); + }; + auto indirect_apply_opcodes = [=](AvmTraceBuilder& trace_builder) { + trace_builder.op_set( + /*indirect*/ false, + /*value*/ dst_offset, + /*dst_offset*/ indirect_dst_offset, + AvmMemoryTag::U32); + trace_builder.op_function_selector(/*indirect*/ true, indirect_dst_offset); + }; + + auto checks = [=](bool indirect, const std::vector& trace) { + auto row = std::ranges::find_if( + trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_function_selector == FF(1); }); + EXPECT_TRUE(row != trace.end()); + + expect_row(row, + /*kernel_in_offset=*/FUNCTION_SELECTOR_SELECTOR, + /*ia=*/FUNCTION_SELECTOR_SELECTOR + + 1, // Note the value generated above for public inputs is the same as the index read + 1 + /*ind_a*/ indirect ? indirect_dst_offset : 0, + /*mem_addr_a=*/dst_offset, + /*w_in_tag=*/AvmMemoryTag::U32); + }; + + test_kernel_lookup(false, direct_apply_opcodes, checks); + test_kernel_lookup(true, indirect_apply_opcodes, checks); +} + TEST_F(AvmKernelPositiveTests, kernelFeePerDa) { uint32_t dst_offset = 42; @@ -581,7 +617,7 @@ void negative_test_incorrect_ia_kernel_lookup(OpcodesFunc apply_opcodes, check_trace(/*indirect*/ false, trace); - EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace), public_inputs), expected_message); + EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), expected_message); } TEST_F(AvmKernelNegativeTests, incorrectIaSender) @@ -662,6 +698,32 @@ TEST_F(AvmKernelNegativeTests, incorrectIaStorageAddress) negative_test_incorrect_ia_kernel_lookup(apply_opcodes, checks, incorrect_ia, "PERM_MAIN_MEM_A"); } +TEST_F(AvmKernelNegativeTests, incorrectIaFunctionSelector) +{ + uint32_t dst_offset = 42; + FF incorrect_ia = FF(69); + + // We test that the sender opcode is inlcuded at index x in the public inputs + auto apply_opcodes = [=](AvmTraceBuilder& trace_builder) { + trace_builder.op_function_selector(/*indirect*/ false, dst_offset); + }; + auto checks = [=](bool indirect, const std::vector& trace) { + auto row = std::ranges::find_if( + trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_function_selector == FF(1); }); + EXPECT_TRUE(row != trace.end()); + + expect_row( + row, + /*kernel_in_offset=*/FUNCTION_SELECTOR_SELECTOR, + /*ia=*/incorrect_ia, // Note the value generated above for public inputs is the same as the index read + 1 + /*ind_a*/ indirect, + /*mem_addr_a=*/dst_offset, + /*w_in_tag=*/AvmMemoryTag::U32); + }; + + negative_test_incorrect_ia_kernel_lookup(apply_opcodes, checks, incorrect_ia, "PERM_MAIN_MEM_A"); +} + TEST_F(AvmKernelNegativeTests, incorrectIaDaGas) { uint32_t dst_offset = 42; diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/avm_mem_opcodes.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/avm_mem_opcodes.test.cpp index 7114919ee69..94157443a75 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/avm_mem_opcodes.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/avm_mem_opcodes.test.cpp @@ -402,7 +402,7 @@ TEST_F(AvmMemOpcodeTests, indirectMovInvalidAddressTag) MEM_ROW_FIELD_EQ(r_in_tag, static_cast(AvmMemoryTag::U32)), MEM_ROW_FIELD_EQ(sel_resolve_ind_addr_c, 1))); - validate_trace(std::move(trace), public_inputs, true); + validate_trace(std::move(trace), public_inputs, {}, true); } /****************************************************************************** diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/avm_memory.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/avm_memory.test.cpp index 4d3b6fd18a9..05a02bb3862 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/avm_memory.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/avm_memory.test.cpp @@ -36,7 +36,9 @@ class AvmMemoryTests : public ::testing::Test { // The proof must pass and we check that the AVM error is raised. TEST_F(AvmMemoryTests, mismatchedTagAddOperation) { - trace_builder.op_calldata_copy(0, 0, 2, 0, std::vector{ 98, 12 }); + std::vector const calldata = { 98, 12 }; + trace_builder = AvmTraceBuilder(public_inputs, {}, 0, calldata); + trace_builder.op_calldata_copy(0, 0, 2, 0); trace_builder.op_add(0, 0, 1, 4, AvmMemoryTag::U8); trace_builder.halt(); @@ -75,7 +77,7 @@ TEST_F(AvmMemoryTests, mismatchedTagAddOperation) EXPECT_EQ(row->mem_r_in_tag, FF(static_cast(AvmMemoryTag::U8))); EXPECT_EQ(row->mem_tag, FF(static_cast(AvmMemoryTag::FF))); - validate_trace(std::move(trace), public_inputs, true); + validate_trace(std::move(trace), public_inputs, calldata, true); } // Testing an equality operation with a mismatched memory tag. @@ -228,7 +230,8 @@ TEST_F(AvmMemoryTests, readUninitializedMemoryViolation) // must raise a VM error. TEST_F(AvmMemoryTests, mismatchedTagErrorViolation) { - trace_builder.op_calldata_copy(0, 0, 2, 0, std::vector{ 98, 12 }); + trace_builder = AvmTraceBuilder(public_inputs, {}, 0, { 98, 12 }); + trace_builder.op_calldata_copy(0, 0, 2, 0); trace_builder.op_sub(0, 0, 1, 4, AvmMemoryTag::U8); trace_builder.halt(); @@ -262,8 +265,8 @@ TEST_F(AvmMemoryTests, mismatchedTagErrorViolation) // must not set a VM error. TEST_F(AvmMemoryTests, consistentTagNoErrorViolation) { - trace_builder.op_calldata_copy(0, 0, 2, 0, std::vector{ 84, 7 }); - + trace_builder = AvmTraceBuilder(public_inputs, {}, 0, std::vector{ 84, 7 }); + trace_builder.op_calldata_copy(0, 0, 2, 0); trace_builder.op_fdiv(0, 0, 1, 4); trace_builder.halt(); auto trace = trace_builder.finalize(); @@ -288,8 +291,8 @@ TEST_F(AvmMemoryTests, consistentTagNoErrorViolation) // Testing violation that a write operation must not set a VM error. TEST_F(AvmMemoryTests, noErrorTagWriteViolation) { - trace_builder.op_calldata_copy(0, 0, 2, 0, std::vector{ 84, 7 }); - + trace_builder = AvmTraceBuilder(public_inputs, {}, 0, { 84, 7 }); + trace_builder.op_calldata_copy(0, 0, 2, 0); trace_builder.op_fdiv(0, 0, 1, 4); trace_builder.halt(); auto trace = trace_builder.finalize(); diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/helpers.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/helpers.test.cpp index 1657ba8ce0d..d84f11226de 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/helpers.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/helpers.test.cpp @@ -23,9 +23,9 @@ std::vector gen_three_op_params(std::vector opera * * @param trace The execution trace */ -void validate_trace_check_circuit(std::vector&& trace, VmPublicInputs public_inputs) +void validate_trace_check_circuit(std::vector&& trace) { - validate_trace(std::move(trace), public_inputs, false); + validate_trace(std::move(trace), {}, {}, false); }; /** @@ -34,7 +34,10 @@ void validate_trace_check_circuit(std::vector&& trace, VmPublicInputs publi * * @param trace The execution trace */ -void validate_trace(std::vector&& trace, VmPublicInputs const& public_inputs, bool with_proof) +void validate_trace(std::vector&& trace, + VmPublicInputs const& public_inputs, + std::vector const& calldata, + bool with_proof) { auto circuit_builder = AvmCircuitBuilder(); circuit_builder.set_trace(std::move(trace)); @@ -47,7 +50,8 @@ void validate_trace(std::vector&& trace, VmPublicInputs const& public_input AvmVerifier verifier = composer.create_verifier(circuit_builder); - std::vector> public_inputs_as_vec = bb::avm_trace::copy_public_inputs_columns(public_inputs); + std::vector> public_inputs_as_vec = + bb::avm_trace::copy_public_inputs_columns(public_inputs, calldata); bool verified = verifier.verify_proof(proof, { public_inputs_as_vec }); diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/helpers.test.hpp b/barretenberg/cpp/src/barretenberg/vm/tests/helpers.test.hpp index 0dcf6381502..0640121b319 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/helpers.test.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/helpers.test.hpp @@ -28,9 +28,10 @@ using VmPublicInputs = bb::avm_trace::VmPublicInputs; // If the test is expecting a relation to fail, then use validate_trace_check_circuit. // Otherwise, use validate_trace with a single argument. If the proving needs to be // enabled all the time in a given test, use validate_trace with setting with_proof = true. -void validate_trace_check_circuit(std::vector&& trace, VmPublicInputs public_inputs = {}); +void validate_trace_check_circuit(std::vector&& trace); void validate_trace(std::vector&& trace, VmPublicInputs const& public_inputs = {}, + std::vector const& calldata = {}, bool with_proof = bb::avm_trace::ENABLE_PROVING); void mutate_ic_in_trace(std::vector& trace, std::function&& selectRow, diff --git a/bb-pilcom/bb-pil-backend/src/prover_builder.rs b/bb-pilcom/bb-pil-backend/src/prover_builder.rs index ee129d6ca83..c0ea19709a5 100644 --- a/bb-pilcom/bb-pil-backend/src/prover_builder.rs +++ b/bb-pilcom/bb-pil-backend/src/prover_builder.rs @@ -192,7 +192,8 @@ impl ProverBuilder for BBFiles { * */ void {name}Prover::execute_pcs_rounds() {{ - auto prover_opening_claim = ZeroMorph::prove(prover_polynomials.get_unshifted(), + auto prover_opening_claim = ZeroMorph::prove(key->circuit_size, + prover_polynomials.get_unshifted(), prover_polynomials.get_to_be_shifted(), sumcheck_output.claimed_evaluations.get_unshifted(), sumcheck_output.claimed_evaluations.get_shifted(), diff --git a/bb-pilcom/bb-pil-backend/src/verifier_builder.rs b/bb-pilcom/bb-pil-backend/src/verifier_builder.rs index ed93731b67f..a10a7bea021 100644 --- a/bb-pilcom/bb-pil-backend/src/verifier_builder.rs +++ b/bb-pilcom/bb-pil-backend/src/verifier_builder.rs @@ -56,7 +56,7 @@ impl VerifierBuilder for BBFiles { |public_inputs_column_name: &String, idx: usize| { format!( " - FF {public_inputs_column_name}_evaluation = evaluate_public_input_column(public_inputs[{idx}], circuit_size, multivariate_challenge); + FF {public_inputs_column_name}_evaluation = evaluate_public_input_column(public_inputs[{idx}], circuit_size, mle_challenge); if ({public_inputs_column_name}_evaluation != claimed_evaluations.{public_inputs_column_name}) {{ return false; }} @@ -178,6 +178,8 @@ impl VerifierBuilder for BBFiles { }} // Public columns evaluation checks + std::vector mle_challenge(multivariate_challenge.begin(), + multivariate_challenge.begin() + static_cast(log_circuit_size)); {public_inputs_check} // Execute ZeroMorph rounds. See https://hackmd.io/dlf9xEwhTQyE3hiGbq4FsA?view for a complete description of the diff --git a/docs/docs/migration_notes.md b/docs/docs/migration_notes.md index 8dce681e600..79c62834ee3 100644 --- a/docs/docs/migration_notes.md +++ b/docs/docs/migration_notes.md @@ -1665,4 +1665,4 @@ Now, just remove the `src` folder,: ```rust easy_private_token_contract = {git = "https://github.com/AztecProtocol/aztec-packages/", tag ="v0.17.0", directory = "noir-projects/noir-contracts/contracts/easy_private_token_contract"} -``` +``` \ No newline at end of file diff --git a/docs/docs/protocol-specs/logs/index.md b/docs/docs/protocol-specs/logs/index.md index 1d442184e4f..1f98711bd1e 100644 --- a/docs/docs/protocol-specs/logs/index.md +++ b/docs/docs/protocol-specs/logs/index.md @@ -53,161 +53,27 @@ A function can emit an arbitrary number of logs, provided they don't exceed the -To minimize the on-chain verification data size, protocol circuits aggregate log hashes. The end result is a single hash within the root rollup proof, encompassing all logs of the same type. +To minimize the on-chain verification data size, protocol circuits aggregate log hashes. The end result is a single hash within the base rollup proof, encompassing all logs of the same type. Each protocol circuit outputs two values for each log type: - _`accumulated_logs_hash`_: A hash representing all logs. - _`accumulated_logs_length`_: The total length of all log preimages. +Both the `accumulated_logs_hash` and `accumulated_logs_length` for each type are included in the base rollup's `txs_effect_hash`. When rolling up to merge and root circuits, the two input proof's `txs_effect_hash`es are hashed together to form the new value of `txs_effect_hash`. + +When publishing a block on L1, the raw logs of each type and their lengths are provided (**Availability**), hashed and accumulated into each respective `accumulated_logs_hash` and `accumulated_logs_length`, then included in the on-chain recalculation of `txs_effect_hash`. If this value doesn't match the one from the rollup circuits, the block will not be valid (**Immutability**). + + For private and public kernel circuits, beyond aggregating logs from a function call, they ensure that the contract's address emitting the logs is linked to the _logs_hash_. For more details, refer to the "Hashing" sections in [Unencrypted Log](#hashing-1), [Encrypted Log](#hashing-2), and [Encrypted Note Preimage](#hashing-3). -### Encoding - -1. The encoded logs data of a transaction is a flattened array of all logs data within the transaction: - - _`tx_logs_data = [number_of_logs, ...log_data_0, ...log_data_1, ...]`_ - - The format of _log_data_ varies based on the log type. For specifics, see the "Encoding" sections in [Unencrypted Log](#encoding-1), [Encrypted Log](#encoding-2), and [Encrypted Note Preimage](#encoding-3). - -2. The encoded logs data of a block is a flatten array of a collection of the above _tx_logs_data_, with hints facilitating hashing replay in a binary tree structure: - - _`block_logs_data = [number_of_branches, number_of_transactions, ...tx_logs_data_0, ...tx_logs_data_1, ...]`_ - - - _number_of_transactions_ is the number of leaves in the left-most branch, restricted to either _1_ or _2_. - - _number_of_branches_ is the depth of the parent node of the left-most leaf. - -Here is a step-by-step example to construct the _`block_logs_data`_: - -1. A rollup, _R01_, merges two transactions: _tx0_ containing _tx_logs_data_0_, and _tx1_ containing _tx_logs_data_1_: - - ```mermaid - flowchart BT - tx0((tx0)) - tx1((tx1)) - R01((R01)) - tx0 --- R01 - tx1 --- R01 - ``` - - _block_logs_data_: _`[0, 2, ...tx_logs_data_0, ...tx_logs_data_1]`_ - - Where _0_ is the depth of the node _R01_, and _2_ is the number of aggregated _tx_logs_data_ of _R01_. - -2. Another rollup, _R23_, merges two transactions: _tx3_ containing _tx_logs_data_3_, and _tx2_ without any logs: - - ```mermaid - flowchart BT - tx2((tx2)) - tx3((tx3)) - R23((R23)) - tx2 -. no logs .- R23 - tx3 --- R23 - ``` - - _block_logs_data_: _`[0, 1, ...tx_logs_data_3]`_ - - Here, the number of aggregated _tx_logs_data_ is _1_. - -3. A rollup, _RA_, merges the two rollups _R01_ and _R23_: - - ```mermaid - flowchart BT - tx0((tx0)) - tx1((tx1)) - R01((R01)) - tx0 --- R01 - tx1 --- R01 - tx2((tx2)) - tx3((tx3)) - R23((R23)) - tx2 -.- R23 - tx3 --- R23 - RA((RA)) - R01 --- RA - R23 --- RA - ``` - - _block_logs_data_: _`[1, 2, ...tx_logs_data_0, ...tx_logs_data_1, 0, 1, ...tx_logs_data_3]`_ - - The result is the _block_logs_data_ of _R01_ concatenated with the _block_logs_data_ of _R23_, with the _number_of_branches_ of _R01_ incremented by _1_. The updated value of _number_of_branches_ (_0 + 1_) is also the depth of the node _R01_. - -4. A rollup, _RB_, merges the above rollup _RA_ and another rollup _R45_: - - ```mermaid - flowchart BT - tx0((tx0)) - tx1((tx1)) - R01((R01)) - tx0 --- R01 - tx1 --- R01 - tx2((tx2)) - tx3((tx3)) - R23((R23)) - tx2 -.- R23 - tx3 --- R23 - RA((RA)) - R01 --- RA - R23 --- RA - tx4((tx4)) - tx5((tx5)) - R45((R45)) - tx4 --- R45 - tx5 --- R45 - RB((RB)) - RA --- RB - R45 --- RB - ``` - - _block_logs_data_: _`[2, 2, ...tx_logs_data_0, ...tx_logs_data_1, 0, 1, ...tx_logs_data_3, 0, 2, ...tx_logs_data_4, ...tx_logs_data_5]`_ - - The result is the concatenation of the _block_logs_data_ from both rollups, with the _number_of_branches_ of the left-side rollup, _RA_, incremented by _1_. - -### Verification - -Upon receiving a proof and its encoded logs data, the entity can ensure the correctness of the provided _block_logs_data_ by verifying that the _accumulated_logs_hash_ in the proof can be derived from it: - -```js -const accumulated_logs_hash = compute_accumulated_logs_hash(block_logs_data); -assert(accumulated_logs_hash == proof.accumulated_logs_hash); -assert(block_logs_data.accumulated_logs_length == proof.accumulated_logs_length); - -function compute_accumulated_logs_hash(logs_data) { - const number_of_branches = logs_data.read_u32(); - - const number_of_transactions = logs_data.read_u32(); - let res = hash_tx_logs_data(logs_data); - if number_of_transactions == 2 { - res = hash(res, hash_tx_logs_data(logs_data)); - } - - for (let i = 0; i < number_of_branches; ++i) { - const res_right = compute_accumulated_logs_hash(logs_data); - res = hash(res, res_right); - } - - return res; -} - -function hash_tx_logs_data(logs_data) { - const number_of_logs = logs_data.read_u32(); - let res = hash_log_data(logs_data); - for (let i = 1; i < number_of_logs; ++i) { - const log_hash = hash_log_data(logs_data); - res = hash(res, log_hash); - } - return res; -} -``` - -The _accumulated_logs_length_ in _block_logs_data_ is computed during the processing of each _logs_data_ within _hash_log_data()_. The implementation of _hash_log_data_ varies depending on the type of the logs being processed. Refer to the "Verification" sections in [Unencrypted Log](#verification-1), [Encrypted Log](#verification-2), and [Encrypted Note Preimage](#verification-3) for details. - ## Unencrypted Log Unencrypted logs are used to communicate public information out of smart contracts. They can be emitted from both public and private functions. diff --git a/docs/docs/protocol-specs/public-vm/_nested-context.md b/docs/docs/protocol-specs/public-vm/_nested-context.md index 2b24cff09f2..c6fbd1824ab 100644 --- a/docs/docs/protocol-specs/public-vm/_nested-context.md +++ b/docs/docs/protocol-specs/public-vm/_nested-context.md @@ -14,11 +14,10 @@ nestedContext = deriveContext(context, instr.args, isStaticCall, isDelegateCall) Nested context derivation is defined as follows: ```jsx nestedExecutionEnvironment = ExecutionEnvironment { - sender: isDelegateCall ? context.sender : context.address, address: M[addrOffset], storageAddress: isDelegateCall ? context.storageAddress : M[addrOffset], - feePerL2Gas: context.environment.feePerL2Gas, - feePerDaGas: context.environment.feePerDaGas, + sender: isDelegateCall ? context.sender : context.address, + functionSelector: context.environment.functionSelector, transactionFee: context.environment.transactionFee, contractCallDepth: context.contractCallDepth + 1, contractCallPointer: context.worldStateAccessTrace.contractCalls.length + 1, @@ -49,4 +48,4 @@ nestedContext = AvmContext { } ``` -> `M[offset]` notation is shorthand for `context.machineState.memory[offset]` \ No newline at end of file +> `M[offset]` notation is shorthand for `context.machineState.memory[offset]` diff --git a/docs/docs/protocol-specs/public-vm/context.mdx b/docs/docs/protocol-specs/public-vm/context.mdx index d770462befe..6bb784ef606 100644 --- a/docs/docs/protocol-specs/public-vm/context.mdx +++ b/docs/docs/protocol-specs/public-vm/context.mdx @@ -28,9 +28,7 @@ A context's **execution environment** remains constant throughout a contract cal | address | `AztecAddress` | | | storageAddress | `AztecAddress` | | | sender | `AztecAddress` | | -| portal | `EthAddress` | | -| feePerL2Gas | `field` | | -| feePerDaGas | `field` | | +| functionSelector | `u32` | | | transactionFee | `field` | Computed transaction fee based on gas fees, inclusion fee, and gas usage. Zero in all phases but teardown. | | contractCallDepth | `field` | Depth of the current call (how many nested calls deep is it). | | contractCallPointer | `field` | Uniquely identifies each contract call processed by an AVM session. An initial call is assigned pointer value of 1 (expanded on in the AVM circuit section's ["Call Pointer"](./avm-circuit#call-pointer) subsection). | @@ -76,9 +74,7 @@ INITIAL_EXECUTION_ENVIRONMENT = ExecutionEnvironment { address: PublicCallRequest.contractAddress, storageAddress: PublicCallRequest.CallContext.storageContractAddress, sender: PublicCallRequest.CallContext.msgSender, - portal: PublicCallRequest.CallContext.portalContractAddress, - feePerL2Gas: TxRequest.feePerL2Gas, - feePerDaGas: TxRequest.feePerDaGas, + functionelector: PublicCallRequest.functionSelector, contractCallDepth: 0, contractCallPointer: 1, globals: @@ -88,8 +84,8 @@ INITIAL_EXECUTION_ENVIRONMENT = ExecutionEnvironment { } INITIAL_MACHINE_STATE = MachineState { - l2GasLeft: TxRequest.l2GasLimit, - daGasLeft: TxRequest.daGasLimit, + l2GasLeft: , + daGasLeft: , pc: 0, internalCallStack: [], // initialized as empty memory: [0, ..., 0], // all 2^32 entries are initialized to zero diff --git a/docs/docs/protocol-specs/public-vm/gen/_instruction-set.mdx b/docs/docs/protocol-specs/public-vm/gen/_instruction-set.mdx index ab744c11ed6..cf740097fc4 100644 --- a/docs/docs/protocol-specs/public-vm/gen/_instruction-set.mdx +++ b/docs/docs/protocol-specs/public-vm/gen/_instruction-set.mdx @@ -159,22 +159,14 @@ Click on an instruction name to jump to its section. 0x12 - \[\`FEEPERL2GAS\`\](#isa-section-feeperl2gas) - Get the fee to be paid per "L2 gas" - constant for entire transaction + \[\`FUNCTIONSELECTOR\`\](#isa-section-functionselector) + Get the function selector of the contract function being executed { - `M[dstOffset] = context.environment.feePerL2Gas` + `M[dstOffset] = context.environment.functionSelector` } 0x13 - \[\`FEEPERDAGAS\`\](#isa-section-feeperdagas) - Get the fee to be paid per "DA gas" - constant for entire transaction - { - `M[dstOffset] = context.environment.feePerDaGas` - } - - - 0x14 \[\`TRANSACTIONFEE\`\](#isa-section-transactionfee) Get the computed transaction fee during teardown phase, zero otherwise { @@ -182,15 +174,7 @@ Click on an instruction name to jump to its section. } - 0x15 - \[\`CONTRACTCALLDEPTH\`\](#isa-section-contractcalldepth) - Get how many contract calls deep the current call context is - { - `M[dstOffset] = context.environment.contractCallDepth` - } - - - 0x16 + 0x14 \[\`CHAINID\`\](#isa-section-chainid) Get this rollup's L1 chain ID { @@ -198,7 +182,7 @@ Click on an instruction name to jump to its section. } - 0x17 + 0x15 \[\`VERSION\`\](#isa-section-version) Get this rollup's L2 version ID { @@ -206,7 +190,7 @@ Click on an instruction name to jump to its section. } - 0x18 + 0x16 \[\`BLOCKNUMBER\`\](#isa-section-blocknumber) Get this L2 block's number { @@ -214,7 +198,7 @@ Click on an instruction name to jump to its section. } - 0x19 + 0x17 \[\`TIMESTAMP\`\](#isa-section-timestamp) Get this L2 block's timestamp { @@ -222,17 +206,33 @@ Click on an instruction name to jump to its section. } - 0x1a + 0x18 \[\`COINBASE\`\](#isa-section-coinbase) - Get the block's beneficiary address + (UNIMPLEMENTED) Get the block's beneficiary address { `M[dstOffset] = context.environment.globals.coinbase` } + + 0x19 + \[\`FEEPERL2GAS\`\](#isa-section-feeperl2gas) + Get the fee to be paid per "L2 gas" - constant for entire transaction + { + `M[dstOffset] = context.environment.globals.feePerL2Gas` + } + + + 0x1a + \[\`FEEPERDAGAS\`\](#isa-section-feeperdagas) + Get the fee to be paid per "DA gas" - constant for entire transaction + { + `M[dstOffset] = context.environment.globals.feePerDaGas` + } + 0x1b \[\`BLOCKL2GASLIMIT\`\](#isa-section-blockl2gaslimit) - Total amount of "L2 gas" that a block can consume + (UNIMPLEMENTED) Total amount of "L2 gas" that a block can consume { `M[dstOffset] = context.environment.globals.l2GasLimit` } @@ -240,7 +240,7 @@ Click on an instruction name to jump to its section. 0x1c \[\`BLOCKDAGASLIMIT\`\](#isa-section-blockdagaslimit) - Total amount of "DA gas" that a block can consume + (UNIMPLEMENTED) Total amount of "DA gas" that a block can consume { `M[dstOffset] = context.environment.globals.daGasLimit` } @@ -399,7 +399,7 @@ M[existsOffset] = exists`} 0x2e \[\`HEADERMEMBER\`\](#isa-section-headermember) - Check if a header exists in the [archive tree](../state/archive) and retrieve the specified member if so + (UNIMPLEMENTED) Check if a header exists in the [archive tree](../state/archive) and retrieve the specified member if so {`exists = context.worldState.header.has({ leafIndex: M[blockIndexOffset], leaf: M[msgKeyOffset] @@ -486,7 +486,7 @@ updateContextAfterNestedCall(context, instr.args, nestedContext)`} 0x34 \[\`DELEGATECALL\`\](#isa-section-delegatecall) - Call into another contract, but keep the caller's `sender` and `storageAddress` + (UNIMPLEMENTED) Call into another contract, but keep the caller's `sender` and `storageAddress` {`// instr.args are { gasOffset, addrOffset, argsOffset, retOffset, retSize } chargeGas(context, @@ -895,10 +895,10 @@ Get the address of the sender (caller of the current context) [![](/img/protocol-specs/public-vm/bit-formats/SENDER.png)](/img/protocol-specs/public-vm/bit-formats/SENDER.png) -### `FEEPERL2GAS` -Get the fee to be paid per "L2 gas" - constant for entire transaction +### `FUNCTIONSELECTOR` +Get the function selector of the contract function being executed -[See in table.](#isa-table-feeperl2gas) +[See in table.](#isa-table-functionselector) - **Opcode**: 0x12 - **Category**: Execution Environment @@ -906,35 +906,17 @@ Get the fee to be paid per "L2 gas" - constant for entire transaction - **indirect**: Toggles whether each memory-offset argument is an indirect offset. Rightmost bit corresponds to 0th offset arg, etc. Indirect offsets result in memory accesses like `M[M[offset]]` instead of the more standard `M[offset]`. - **Args**: - **dstOffset**: memory offset specifying where to store operation's result -- **Expression**: `M[dstOffset] = context.environment.feePerL2Gas` -- **Tag updates**: `T[dstOffset] = field` -- **Bit-size**: 56 - -[![](/img/protocol-specs/public-vm/bit-formats/FEEPERL2GAS.png)](/img/protocol-specs/public-vm/bit-formats/FEEPERL2GAS.png) - -### `FEEPERDAGAS` -Get the fee to be paid per "DA gas" - constant for entire transaction - -[See in table.](#isa-table-feeperdagas) - -- **Opcode**: 0x13 -- **Category**: Execution Environment -- **Flags**: - - **indirect**: Toggles whether each memory-offset argument is an indirect offset. Rightmost bit corresponds to 0th offset arg, etc. Indirect offsets result in memory accesses like `M[M[offset]]` instead of the more standard `M[offset]`. -- **Args**: - - **dstOffset**: memory offset specifying where to store operation's result -- **Expression**: `M[dstOffset] = context.environment.feePerDaGas` -- **Tag updates**: `T[dstOffset] = field` +- **Expression**: `M[dstOffset] = context.environment.functionSelector` +- **Tag updates**: `T[dstOffset] = u32` - **Bit-size**: 56 -[![](/img/protocol-specs/public-vm/bit-formats/FEEPERDAGAS.png)](/img/protocol-specs/public-vm/bit-formats/FEEPERDAGAS.png) ### `TRANSACTIONFEE` Get the computed transaction fee during teardown phase, zero otherwise [See in table.](#isa-table-transactionfee) -- **Opcode**: 0x14 +- **Opcode**: 0x13 - **Category**: Execution Environment - **Flags**: - **indirect**: Toggles whether each memory-offset argument is an indirect offset. Rightmost bit corresponds to 0th offset arg, etc. Indirect offsets result in memory accesses like `M[M[offset]]` instead of the more standard `M[offset]`. @@ -945,30 +927,12 @@ Get the computed transaction fee during teardown phase, zero otherwise - **Bit-size**: 56 -### `CONTRACTCALLDEPTH` -Get how many contract calls deep the current call context is - -[See in table.](#isa-table-contractcalldepth) - -- **Opcode**: 0x15 -- **Category**: Execution Environment -- **Flags**: - - **indirect**: Toggles whether each memory-offset argument is an indirect offset. Rightmost bit corresponds to 0th offset arg, etc. Indirect offsets result in memory accesses like `M[M[offset]]` instead of the more standard `M[offset]`. -- **Args**: - - **dstOffset**: memory offset specifying where to store operation's result -- **Expression**: `M[dstOffset] = context.environment.contractCallDepth` -- **Details**: Note: security issues with EVM's tx.origin can be resolved by asserting `calldepth == 0`. -- **Tag updates**: `T[dstOffset] = field` -- **Bit-size**: 56 - -[![](/img/protocol-specs/public-vm/bit-formats/CONTRACTCALLDEPTH.png)](/img/protocol-specs/public-vm/bit-formats/CONTRACTCALLDEPTH.png) - ### `CHAINID` Get this rollup's L1 chain ID [See in table.](#isa-table-chainid) -- **Opcode**: 0x16 +- **Opcode**: 0x14 - **Category**: Execution Environment - Globals - **Flags**: - **indirect**: Toggles whether each memory-offset argument is an indirect offset. Rightmost bit corresponds to 0th offset arg, etc. Indirect offsets result in memory accesses like `M[M[offset]]` instead of the more standard `M[offset]`. @@ -985,7 +949,7 @@ Get this rollup's L2 version ID [See in table.](#isa-table-version) -- **Opcode**: 0x17 +- **Opcode**: 0x15 - **Category**: Execution Environment - Globals - **Flags**: - **indirect**: Toggles whether each memory-offset argument is an indirect offset. Rightmost bit corresponds to 0th offset arg, etc. Indirect offsets result in memory accesses like `M[M[offset]]` instead of the more standard `M[offset]`. @@ -1002,7 +966,7 @@ Get this L2 block's number [See in table.](#isa-table-blocknumber) -- **Opcode**: 0x18 +- **Opcode**: 0x16 - **Category**: Execution Environment - Globals - **Flags**: - **indirect**: Toggles whether each memory-offset argument is an indirect offset. Rightmost bit corresponds to 0th offset arg, etc. Indirect offsets result in memory accesses like `M[M[offset]]` instead of the more standard `M[offset]`. @@ -1019,7 +983,7 @@ Get this L2 block's timestamp [See in table.](#isa-table-timestamp) -- **Opcode**: 0x19 +- **Opcode**: 0x17 - **Category**: Execution Environment - Globals - **Flags**: - **indirect**: Toggles whether each memory-offset argument is an indirect offset. Rightmost bit corresponds to 0th offset arg, etc. Indirect offsets result in memory accesses like `M[M[offset]]` instead of the more standard `M[offset]`. @@ -1032,11 +996,11 @@ Get this L2 block's timestamp [![](/img/protocol-specs/public-vm/bit-formats/TIMESTAMP.png)](/img/protocol-specs/public-vm/bit-formats/TIMESTAMP.png) ### `COINBASE` -Get the block's beneficiary address +(UNIMPLEMENTED) Get the block's beneficiary address [See in table.](#isa-table-coinbase) -- **Opcode**: 0x1a +- **Opcode**: 0x18 - **Category**: Execution Environment - Globals - **Flags**: - **indirect**: Toggles whether each memory-offset argument is an indirect offset. Rightmost bit corresponds to 0th offset arg, etc. Indirect offsets result in memory accesses like `M[M[offset]]` instead of the more standard `M[offset]`. @@ -1048,8 +1012,42 @@ Get the block's beneficiary address [![](/img/protocol-specs/public-vm/bit-formats/COINBASE.png)](/img/protocol-specs/public-vm/bit-formats/COINBASE.png) +### `FEEPERL2GAS` +Get the fee to be paid per "L2 gas" - constant for entire transaction + +[See in table.](#isa-table-feeperl2gas) + +- **Opcode**: 0x19 +- **Category**: Execution Environment - Globals - Gas +- **Flags**: + - **indirect**: Toggles whether each memory-offset argument is an indirect offset. Rightmost bit corresponds to 0th offset arg, etc. Indirect offsets result in memory accesses like `M[M[offset]]` instead of the more standard `M[offset]`. +- **Args**: + - **dstOffset**: memory offset specifying where to store operation's result +- **Expression**: `M[dstOffset] = context.environment.globals.feePerL2Gas` +- **Tag updates**: `T[dstOffset] = field` +- **Bit-size**: 56 + +[![](/img/protocol-specs/public-vm/bit-formats/FEEPERL2GAS.png)](/img/protocol-specs/public-vm/bit-formats/FEEPERL2GAS.png) + +### `FEEPERDAGAS` +Get the fee to be paid per "DA gas" - constant for entire transaction + +[See in table.](#isa-table-feeperdagas) + +- **Opcode**: 0x1a +- **Category**: Execution Environment - Globals - Gas +- **Flags**: + - **indirect**: Toggles whether each memory-offset argument is an indirect offset. Rightmost bit corresponds to 0th offset arg, etc. Indirect offsets result in memory accesses like `M[M[offset]]` instead of the more standard `M[offset]`. +- **Args**: + - **dstOffset**: memory offset specifying where to store operation's result +- **Expression**: `M[dstOffset] = context.environment.globals.feePerDaGas` +- **Tag updates**: `T[dstOffset] = field` +- **Bit-size**: 56 + +[![](/img/protocol-specs/public-vm/bit-formats/FEEPERDAGAS.png)](/img/protocol-specs/public-vm/bit-formats/FEEPERDAGAS.png) + ### `BLOCKL2GASLIMIT` -Total amount of "L2 gas" that a block can consume +(UNIMPLEMENTED) Total amount of "L2 gas" that a block can consume [See in table.](#isa-table-blockl2gaslimit) @@ -1066,7 +1064,7 @@ Total amount of "L2 gas" that a block can consume [![](/img/protocol-specs/public-vm/bit-formats/BLOCKL2GASLIMIT.png)](/img/protocol-specs/public-vm/bit-formats/BLOCKL2GASLIMIT.png) ### `BLOCKDAGASLIMIT` -Total amount of "DA gas" that a block can consume +(UNIMPLEMENTED) Total amount of "DA gas" that a block can consume [See in table.](#isa-table-blockdagaslimit) @@ -1522,7 +1520,7 @@ M[existsOffset] = exists`} ### `HEADERMEMBER` -Check if a header exists in the [archive tree](../state/archive) and retrieve the specified member if so +(UNIMPLEMENTED) Check if a header exists in the [archive tree](../state/archive) and retrieve the specified member if so [See in table.](#isa-table-headermember) @@ -1737,7 +1735,7 @@ T[retOffset:retOffset+retSize] = field`} [![](/img/protocol-specs/public-vm/bit-formats/STATICCALL.png)](/img/protocol-specs/public-vm/bit-formats/STATICCALL.png) ### `DELEGATECALL` -Call into another contract, but keep the caller's `sender` and `storageAddress` +(UNIMPLEMENTED) Call into another contract, but keep the caller's `sender` and `storageAddress` [See in table.](#isa-table-delegatecall) diff --git a/docs/docs/protocol-specs/public-vm/intro.md b/docs/docs/protocol-specs/public-vm/intro.md index e27ea9e1ced..a89e45fc1b2 100644 --- a/docs/docs/protocol-specs/public-vm/intro.md +++ b/docs/docs/protocol-specs/public-vm/intro.md @@ -38,4 +38,9 @@ A contract's public bytecode is a series of execution instructions for the AVM. The entirety of a contract's public code is represented as a single block of bytecode with a maximum of `MAX_PUBLIC_INSTRUCTIONS_PER_CONTRACT` ($2^{15} = 32768$) instructions. The mechanism used to distinguish between different "functions" in an AVM bytecode program is left as a higher-level abstraction (_e.g._ similar to Solidity's concept of a function selector). +::: warning +Ultimately, function selectors _may_ be removed as an enshrined protocol mechanism as described above. For now, each public function on a contract has a distinct bytecode that can be selected for execution via a function selector. +::: + + > See the [Bytecode Validation Circuit](./bytecode-validation-circuit) to see how a contract's bytecode can be validated and committed to. diff --git a/docs/docs/protocol-specs/rollup-circuits/index.md b/docs/docs/protocol-specs/rollup-circuits/index.md index 1e2523f2719..d85df805dd2 100644 --- a/docs/docs/protocol-specs/rollup-circuits/index.md +++ b/docs/docs/protocol-specs/rollup-circuits/index.md @@ -19,9 +19,9 @@ Note that we have two different types of "merger" circuits, depending on what th For transactions we have: - The `merge` rollup - - Merges two `base` rollup proofs OR two `merge` rollup proofs + - Merges two rollup proofs of either `base` or `merge` and constructs outputs for further proving - The `root` rollup - - Merges two `merge` rollup proofs + - Merges two rollup proofs of either `base` or `merge` and constructs outputs for L1 And for the message parity we have: @@ -30,7 +30,7 @@ And for the message parity we have: - The `base_parity` circuit - Merges `N` l1 to l2 messages in a subtree -In the diagram the size of the tree is limited for demonstration purposes, but a larger tree would have more layers of merge rollups proofs. +In the diagram the size of the tree is limited for demonstration purposes, but a larger tree would have more layers of merge rollups proofs. Exactly how many layers and what combination of `base` and/or `merge` circuits are consumed is based on filling a [wonky tree](../state/tree-implementations.md#wonky-merkle-trees) with N transactions. Circles mark the different types of proofs, while squares mark the different circuit types. ```mermaid @@ -465,7 +465,7 @@ Furthermore, the `OutHash` is a computed from a subset of the data in `TxsHash` Since we strive to minimize the compute requirements to prove blocks, we amortize the commitment cost across the full tree. We can do so by building merkle trees of partial "commitments", whose roots are ultimately computed in the final root rollup circuit. -Below, we outline the `TxsHash` merkle tree that is based on the `TxEffect`s and a `OutHash` which is based on the `l2_to_l1_msgs` (cross-chain messages) for each transaction. +Below, we outline the `TxsHash` merkle tree that is based on the `TxEffect`s and a `OutHash` which is based on the `l2_to_l1_msgs` (cross-chain messages) for each transaction, with four transactions in this rollup. While the `TxsHash` implicitly includes the `OutHash` we need it separately such that it can be passed to the `Outbox` for consumption by the portals with minimal work. ```mermaid @@ -588,6 +588,8 @@ graph BT While the `TxsHash` merely require the data to be published and known to L1, the `InHash` and `OutHash` needs to be computable on L1 as well. This reason require them to be efficiently computable on L1 while still being non-horrible inside a snark - leading us to rely on SHA256. + + The L2 to L1 messages from each transaction form a variable height tree. In the diagram above, transactions 0 and 3 have four messages, so require a tree with two layers, whereas the others only have two messages and so require a single layer tree. The base rollup calculates the root of this tree and passes it as the to the next layer. Merge rollups simply hash both of these roots together and pass it up as the `OutHash`. ## Next Steps diff --git a/docs/docs/protocol-specs/rollup-circuits/merge-rollup.md b/docs/docs/protocol-specs/rollup-circuits/merge-rollup.md index f1ebdce1245..5d8ce56943f 100644 --- a/docs/docs/protocol-specs/rollup-circuits/merge-rollup.md +++ b/docs/docs/protocol-specs/rollup-circuits/merge-rollup.md @@ -82,13 +82,12 @@ def MergeRollupCircuit( assert left.public_inputs.constants == right.public_inputs.constants assert left.public_inputs.end == right.public_inputs.start - assert left.public_inputs.type == right.public_inputs.type - assert left.public_inputs.height_in_block_tree == right.public_inputs.height_in_block_tree + assert left.public_inputs.num_txs >= right.public_inputs.num_txs return BaseOrMergeRollupPublicInputs( type=1, - height_in_block_tree=left.public_inputs.height_in_block_tree + 1, - txs_hash=SHA256(left.public_inputs.txs_hash | right.public_inputs.txs_hash), + num_txs=left.public_inputs.num_txs + right.public_inputs.num_txs, + txs_effect_hash=SHA256(left.public_inputs.txs_effect_hash | right.public_inputs.txs_effect_hash), out_hash=SHA256(left.public_inputs.out_hash | right.public_inputs.out_hash), start=left.public_inputs.start, end=right.public_inputs.end, diff --git a/docs/docs/protocol-specs/rollup-circuits/root-rollup.md b/docs/docs/protocol-specs/rollup-circuits/root-rollup.md index d214a01011f..0e09c4663ff 100644 --- a/docs/docs/protocol-specs/rollup-circuits/root-rollup.md +++ b/docs/docs/protocol-specs/rollup-circuits/root-rollup.md @@ -183,8 +183,7 @@ def RootRollupCircuit( assert left.public_inputs.constants == right.public_inputs.constants assert left.public_inputs.end == right.public_inputs.start - assert left.public_inputs.type == right.public_inputs.type - assert left.public_inputs.height_in_block_tree == right.public_inputs.height_in_block_tree + assert left.public_inputs.num_txs >= right.public_inputs.num_txs assert parent.state.partial == left.public_inputs.start @@ -208,8 +207,8 @@ def RootRollupCircuit( header = Header( last_archive = left.public_inputs.constants.last_archive, content_commitment: ContentCommitment( - tx_tree_height = left.public_inputs.height_in_block_tree + 1, - txs_hash = SHA256(left.public_inputs.txs_hash | right.public_inputs.txs_hash), + num_txs=left.public_inputs.num_txs + right.public_inputs.num_txs, + txs_effect_hash=SHA256(left.public_inputs.txs_effect_hash | right.public_inputs.txs_effect_hash), in_hash = l1_to_l2_roots.public_inputs.sha_root, out_hash = SHA256(left.public_inputs.out_hash | right.public_inputs.out_hash), ), diff --git a/docs/docs/protocol-specs/state/tree-implementations.md b/docs/docs/protocol-specs/state/tree-implementations.md index cf0f9cf8ccf..b40a5557d65 100644 --- a/docs/docs/protocol-specs/state/tree-implementations.md +++ b/docs/docs/protocol-specs/state/tree-implementations.md @@ -8,6 +8,12 @@ In an append-only Merkle tree, new leaves are inserted in order from left to rig Append-only trees allow for more efficient syncing than sparse trees, since clients can sync from left to right starting with their last known value. Updates to the tree root, when inserting new leaves, can be computed from the rightmost "frontier" of the tree (i.e., from the sibling path of the rightmost nonzero leaf). Batch insertions can be computed with fewer hashes than in a sparse tree. The historical snapshots of append-only trees also enable efficient membership proofs; as older roots can be computed by completing the merkle path from a past left subtree with an empty right subtree. +### Wonky Merkle Trees + +We also use a special type of append-only tree to structure the rollup circuits. Given `n` leaves, we fill from left to right and attempt to pair them to produce the next layer. If `n` is a power of 2, this tree looks exactly like a standard append-only merkle tree. Otherwise, once we reach an odd-sized row we shift the final node up until we reach another odd row to combine them. + +This results in an unbalanced tree where there are no empty leaves. For rollups, this means we don't have to pad empty transactions and process them through the rollup circuits. A full explanation is given [here](./wonky-tree.md). + ## Indexed Merkle trees Indexed Merkle trees, introduced [here](https://eprint.iacr.org/2021/1263.pdf), allow for proofs of non-inclusion more efficiently than sparse Merkle trees. Each leaf in the tree is a tuple of: the leaf value, the next-highest value in the tree, and the index of the leaf where that next-highest value is stored. New leaves are inserted from left to right, as in the append-only tree, but existing leaves can be _modified_ to update the next-highest value and next-highest index (a.k.a. the "pointer") if a new leaf with a "closer value" is added to the tree. An Indexed Merkle trees behaves as a Merkle tree over a sorted linked list. diff --git a/docs/docs/protocol-specs/state/wonky-tree.md b/docs/docs/protocol-specs/state/wonky-tree.md new file mode 100644 index 00000000000..14d1a977675 --- /dev/null +++ b/docs/docs/protocol-specs/state/wonky-tree.md @@ -0,0 +1,422 @@ +# Wonky Tree + +A 'wonky' tree is an append-only unbalanced merkle tree, filled from left to right. It is used to construct [rollup](../rollup-circuits/index.md) proofs without padding empty transactions. + +For example, using a balanced merkle tree to rollup 5 transactions requires padding of 3 empty transactions: + +```mermaid +graph BT + R_c[Root] + + M4_c[Merge] + M5_c[Merge] + M4_c --> R_c + M5_c --> R_c + + + M0_c[Merge] + M1_c[Merge] + M0_c --> M4_c + M1_c --> M4_c + + B0_c[Base] + B1_c[Base] + B2_c[Base] + B3_c[Base] + B0_c --> M0_c + B1_c --> M0_c + B2_c --> M1_c + B3_c --> M1_c + + M2_c[Merge] + M3_c[Merge*] + M2_c --> M5_c + M3_c --> M5_c + + B4_c[Base] + B5_c[Base*] + B6_c[Base*] + B7_c[Base*] + B4_c --> M2_c + B5_c --> M2_c + B6_c --> M3_c + B7_c --> M3_c + + Tx0_c((Tx 0)) + Tx1_c((Tx 1)) + Tx2_c((Tx 2)) + Tx3_c((Tx 3)) + Tx4_c((Tx 4)) + + Tx0_c --> B0_c + Tx1_c --> B1_c + Tx2_c --> B2_c + Tx3_c --> B3_c + Tx4_c --> B4_c +``` + +Where each node marked with `*` indicates a circuit proving entirely empty information. While the above structure does allow us to easily construct balanced trees later on consisting of `out_hash`es and `tx_effects_hash`es, it will lead to wasted compute and higher block processing costs unless we provide a number of transactions equal to a power of 2. + +Our wonky tree implementation instead gives the below structure for 5 transactions: + +```mermaid +graph BT + R_c[Root] + + M4_c[Merge] + M4_c --> R_c + + + M0_c[Merge] + M1_c[Merge] + M0_c --> M4_c + M1_c --> M4_c + + B0_c[Base] + B1_c[Base] + B2_c[Base] + B3_c[Base] + B0_c --> M0_c + B1_c --> M0_c + B2_c --> M1_c + B3_c --> M1_c + + + B4_c[Base] + B4_c --> R_c + + Tx0_c((Tx 0)) + Tx1_c((Tx 1)) + Tx2_c((Tx 2)) + Tx3_c((Tx 3)) + Tx4_c((Tx 4)) + + Tx0_c --> B0_c + Tx1_c --> B1_c + Tx2_c --> B2_c + Tx3_c --> B3_c + Tx4_c --> B4_c +``` + +Here, each circuit is proving useful transaction information with no wasted compute. We can construct a tree like this one for any number of transactions by greedy filling from left to right. Given the required 5 base circuits: + +```mermaid +graph + B0_c[Base 0] + B1_c[Base 1] + B2_c[Base 2] + B3_c[Base 3] + B4_c[Base 4] +``` + +...we theh pair these base circuits up to form merges: + +```mermaid +graph BT + M0_c[Merge 0] + M1_c[Merge 1] + + B0_c[Base 0] + B1_c[Base 1] + B2_c[Base 2] + B3_c[Base 3] + B0_c --> M0_c + B1_c --> M0_c + B2_c --> M1_c + B3_c --> M1_c + + B4_c[Base 4] +``` + +Since we have an odd number of transactions, we cannot pair up the final base. Instead, we continue to pair the next layers until we reach a layer with an odd number of members. In this example, that's when we reach merge 2: + +```mermaid +graph BT + M0_c[Merge 0] + M1_c[Merge 1] + M2_c[Merge 2] + + B0_c[Base 0] + B1_c[Base 1] + B2_c[Base 2] + B3_c[Base 3] + B0_c --> M0_c + B1_c --> M0_c + B2_c --> M1_c + B3_c --> M1_c + + M0_c --> M2_c + M1_c --> M2_c + + B4_c[Base 4] +``` + +Once paired, the base layer has length 4, the next merge layer has 2, and the final merge layer has 1. After reaching a layer with odd length, the orchestrator can now pair base 4: + +```mermaid +graph BT + R_c[Root] + + M0_c[Merge 0] + M1_c[Merge 1] + M2_c[Merge 2] + + B0_c[Base 0] + B1_c[Base 1] + B2_c[Base 2] + B3_c[Base 3] + B0_c --> M0_c + B1_c --> M0_c + B2_c --> M1_c + B3_c --> M1_c + + M0_c --> M2_c + M1_c --> M2_c + + B4_c[Base 4] + M2_c --> R_c + B4_c --> R_c +``` +Since we have processed all base circuits, this final pair will be input to a root circuit. + +Filling from left to right means that we can easily reconstruct the tree only from the number of transactions `n`. The above method ensures that the final tree is a combination of *balanced* subtrees of descending size. The widths of these subtrees are given by the decomposition of `n` into powers of 2. For example, 5 transactions: + +``` +Subtrees: [4, 1] -> + left_subtree_root = balanced_tree(txs[0..4]) + right_subtree_root = balanced_tree(txs[4]) = txs[4] + root = left_subtree_root | right_subtree_root +``` + +For 31 transactions: +``` +Subtrees: [16, 8, 4, 2, 1] -> + Merge D: left_subtree_root = balanced_tree(txs[0..16]) + right_subtree_root = Subtrees: [8, 4, 2, 1] --> { + Merge C: left_subtree_root = balanced_tree(txs[16..24]) + right_subtree_root = Subtrees: [4, 2, 1] --> { + Merge B: left_subtree_root = balanced_tree(txs[24..28]) + right_subtree_root = Subtrees: [2, 1] --> { + Merge A: left_subtree_root = balanced_tree(txs[28..30]) + right_subtree_root = balanced_tree(txs[30]) = txs[30] + Merge 0: root = left_subtree_root | right_subtree_root + } + Merge 1: root = left_subtree_root | right_subtree_root + } + Merge 2: root = left_subtree_root | right_subtree_root + } + root = left_subtree_root | right_subtree_root +``` +An unrolled recursive algorithm is not the easiest thing to read. This diagram represents the 31 transactions rolled up in our wonky structure, where each `Merge ` is a 'subroot' above: + +```mermaid +graph BT + M2_c[Merge 2] + M3_c[Merge D + Subtree of 16 txs] + R_c[Root] + + + B4_c[Merge C + Subtree of 8 txs] + B5_c[Merge 1] + + B4_c --> M2_c + B5_c --> M2_c + + B6_c[Merge B + Subtree of 4 txs] + B7_c[Merge 0] + + B6_c --> B5_c + B7_c --> B5_c + + B8_c[Merge A + Subtree of 2 txs] + B9_c[Base 30] + + B8_c --> B7_c + B9_c --> B7_c + + + M3_c --> R_c + M2_c --> R_c +``` +The tree is reconstructed to check the `txs_effects_hash` (= the root of a wonky tree given by leaves of each tx's `tx_effects`) on L1. We also reconstruct it to provide a membership path against the stored `out_hash` (= the root of a wonky tree given by leaves of each tx's L2 to L1 message tree root) for consuming a L2 to L1 message. + +Currently, this tree is built via the [orchestrator](../../../../yarn-project/prover-client/src/orchestrator/proving-state.ts#74) given the number of transactions to rollup (`this.totalNumTxs`). Each 'node' is assigned a level (0 at the root) and index in that level. The below function finds the parent level: + +``` + // Calculates the index and level of the parent rollup circuit + public findMergeLevel(currentLevel: bigint, currentIndex: bigint) { + const moveUpMergeLevel = (levelSize: number, index: bigint, nodeToShift: boolean) => { + levelSize /= 2; + if (levelSize & 1) { + [levelSize, nodeToShift] = nodeToShift ? [levelSize + 1, false] : [levelSize - 1, true]; + } + index >>= 1n; + return { thisLevelSize: levelSize, thisIndex: index, shiftUp: nodeToShift }; + }; + let [thisLevelSize, shiftUp] = this.totalNumTxs & 1 ? [this.totalNumTxs - 1, true] : [this.totalNumTxs, false]; + const maxLevel = this.numMergeLevels + 1n; + let placeholder = currentIndex; + for (let i = 0; i < maxLevel - currentLevel; i++) { + ({ thisLevelSize, thisIndex: placeholder, shiftUp } = moveUpMergeLevel(thisLevelSize, placeholder, shiftUp)); + } + let thisIndex = currentIndex; + let mergeLevel = currentLevel; + while (thisIndex >= thisLevelSize && mergeLevel != 0n) { + mergeLevel -= 1n; + ({ thisLevelSize, thisIndex, shiftUp } = moveUpMergeLevel(thisLevelSize, thisIndex, shiftUp)); + } + return [mergeLevel - 1n, thisIndex >> 1n, thisIndex & 1n]; + } +``` + For example, `Base 4` above starts with `level = 3` and `index = 4`. Since we have an odd number of transactions at this level, `thisLevelSize` is set to 4 with `shiftUp = true`. + + The while loop triggers and shifts up our node to `level = 2` and `index = 2`. This level (containing `Merge 0` and `Merge 1`) is of even length, so the loop continues. The next iteration shifts up to `level = 1` and `index = 1` - we now have an odd level, so the loop stops. The actual position of `Base 4` is therefore at `level = 1` and `index = 1`. This function returns the parent level of the input node, so we return `level = 0`, `index = 0`, correctly indicating that the parent of `Base 4` is the root. + + +### Flexible wonky trees + +We can also encode the structure of *any* binary merkle tree by tracking `number_of_branches` and `number_of_leaves` for each node in the tree. This encoding was originally designed for [logs](../logs/index.md) before they were included in the `txs_effects_hash`, so the below explanation references the leaves stored in relation to logs and transactions. + +The benefit of this method as opposed to the one above is allowing for any binary structure and therefore allowing for 'skipping' leaves with no information. However, the encoding grows as the tree grows, by at least 2 bytes per node. The above implementation only requires the number of leaves to be encoded, which will likely only require a single field to store. + + + +#### Encoding + +1. The encoded logs data of a transaction is a flattened array of all logs data within the transaction: + + _`tx_logs_data = [number_of_logs, ...log_data_0, ...log_data_1, ...]`_ + +2. The encoded logs data of a block is a flatten array of a collection of the above _tx_logs_data_, with hints facilitating hashing replay in a binary tree structure: + + _`block_logs_data = [number_of_branches, number_of_transactions, ...tx_logs_data_0, ...tx_logs_data_1, ...]`_ + + - _number_of_transactions_ is the number of leaves in the left-most branch, restricted to either _1_ or _2_. + - _number_of_branches_ is the depth of the parent node of the left-most leaf. + +Here is a step-by-step example to construct the _`block_logs_data`_: + +1. A rollup, _R01_, merges two transactions: _tx0_ containing _tx_logs_data_0_, and _tx1_ containing _tx_logs_data_1_: + + ```mermaid + flowchart BT + tx0((tx0)) + tx1((tx1)) + R01((R01)) + tx0 --- R01 + tx1 --- R01 + ``` + + _block_logs_data_: _`[0, 2, ...tx_logs_data_0, ...tx_logs_data_1]`_ + + Where _0_ is the depth of the node _R01_, and _2_ is the number of aggregated _tx_logs_data_ of _R01_. + +2. Another rollup, _R23_, merges two transactions: _tx3_ containing _tx_logs_data_3_, and _tx2_ without any logs: + + ```mermaid + flowchart BT + tx2((tx2)) + tx3((tx3)) + R23((R23)) + tx2 -. no logs .- R23 + tx3 --- R23 + ``` + + _block_logs_data_: _`[0, 1, ...tx_logs_data_3]`_ + + Here, the number of aggregated _tx_logs_data_ is _1_. + +3. A rollup, _RA_, merges the two rollups _R01_ and _R23_: + + ```mermaid + flowchart BT + tx0((tx0)) + tx1((tx1)) + R01((R01)) + tx0 --- R01 + tx1 --- R01 + tx2((tx2)) + tx3((tx3)) + R23((R23)) + tx2 -.- R23 + tx3 --- R23 + RA((RA)) + R01 --- RA + R23 --- RA + ``` + + _block_logs_data_: _`[1, 2, ...tx_logs_data_0, ...tx_logs_data_1, 0, 1, ...tx_logs_data_3]`_ + + The result is the _block_logs_data_ of _R01_ concatenated with the _block_logs_data_ of _R23_, with the _number_of_branches_ of _R01_ incremented by _1_. The updated value of _number_of_branches_ (_0 + 1_) is also the depth of the node _R01_. + +4. A rollup, _RB_, merges the above rollup _RA_ and another rollup _R45_: + + ```mermaid + flowchart BT + tx0((tx0)) + tx1((tx1)) + R01((R01)) + tx0 --- R01 + tx1 --- R01 + tx2((tx2)) + tx3((tx3)) + R23((R23)) + tx2 -.- R23 + tx3 --- R23 + RA((RA)) + R01 --- RA + R23 --- RA + tx4((tx4)) + tx5((tx5)) + R45((R45)) + tx4 --- R45 + tx5 --- R45 + RB((RB)) + RA --- RB + R45 --- RB + ``` + + _block_logs_data_: _`[2, 2, ...tx_logs_data_0, ...tx_logs_data_1, 0, 1, ...tx_logs_data_3, 0, 2, ...tx_logs_data_4, ...tx_logs_data_5]`_ + + The result is the concatenation of the _block_logs_data_ from both rollups, with the _number_of_branches_ of the left-side rollup, _RA_, incremented by _1_. + +#### Verification + +Upon receiving a proof and its encoded logs data, the entity can ensure the correctness of the provided _block_logs_data_ by verifying that the _accumulated_logs_hash_ in the proof can be derived from it: + +```js +const accumulated_logs_hash = compute_accumulated_logs_hash(block_logs_data); +assert(accumulated_logs_hash == proof.accumulated_logs_hash); +assert(block_logs_data.accumulated_logs_length == proof.accumulated_logs_length); + +function compute_accumulated_logs_hash(logs_data) { + const number_of_branches = logs_data.read_u32(); + + const number_of_transactions = logs_data.read_u32(); + let res = hash_tx_logs_data(logs_data); + if number_of_transactions == 2 { + res = hash(res, hash_tx_logs_data(logs_data)); + } + + for (let i = 0; i < number_of_branches; ++i) { + const res_right = compute_accumulated_logs_hash(logs_data); + res = hash(res, res_right); + } + + return res; +} + +function hash_tx_logs_data(logs_data) { + const number_of_logs = logs_data.read_u32(); + let res = hash_log_data(logs_data); + for (let i = 1; i < number_of_logs; ++i) { + const log_hash = hash_log_data(logs_data); + res = hash(res, log_hash); + } + return res; +} +``` \ No newline at end of file diff --git a/docs/docs/reference/smart_contract_reference/history_lib_reference.md b/docs/docs/reference/smart_contract_reference/history_lib_reference.md index 825d2ddb8cc..a717c3fb9e6 100644 --- a/docs/docs/reference/smart_contract_reference/history_lib_reference.md +++ b/docs/docs/reference/smart_contract_reference/history_lib_reference.md @@ -7,43 +7,26 @@ sidebar_position: 3 ## Note inclusion -Note inclusion proves that a note existed (its hash was included in a note hash tree) at a specific block number. There exists a version that tests for note inclusion at current block number. It is recommended to use this version whenever possible to reduce cost. +Note inclusion proves that a note existed (its hash was included in a note hash tree) in a block header. ### prove_note_inclusion -`prove_note_inclusion_at` takes 3 parameters: +`prove_note_inclusion` takes 1 parameter: -| Name | Type | Description | -| ---------------- | -------------- | ----------------------------------------- | -| note_with_header | Note | The note you are proving inclusion for | -| block_number | u32 | Block number for proving note's existence | -| context | PrivateContext | Private context | +| Name | Type | Description | +| ---- | ---- | -------------------------------------- | +| note | Note | The note you are proving inclusion for | -## prove_note_commitment_inclusion +#### Example -A **commitment**, also referred to as a **note hash** is a public acknowledgment of the existence of a note without revealing the content of the note. You can learn more about how to compress a note to a note hash [here](../../aztec/concepts/storage/trees/index.md#example-note). - -`prove_note_commitment_inclusion` takes 2 parameters: - -| Name | Type | Description | -| ---------------- | -------------- | -------------------------------------- | -| note_with_header | Note | The note you are proving inclusion for | -| context | PrivateContext | Private context | +#include_code prove_note_inclusion noir-projects/noir-contracts/contracts/inclusion_proofs_contract/src/main.nr rust ## Note validity -This proves that a note exists and has not been nullified at a specified block. Again as above, there exists a version that tests for validity at current block. It is recommended to use this version whenever possible to reduce cost. +This proves that a note exists and has not been nullified in a specific block header. ### prove_note_validity -`prove_note_validity_at` takes 3 parameters: - -| Name | Type | Description | -| ---------------- | -------------- | ----------------------------------------- | -| note_with_header | Note | The note you are proving inclusion for | -| block_number | u32 | Block number for proving note's existence | -| context | PrivateContext | Private context | - `prove_note_validity` takes 2 parameters: | Name | Type | Description | @@ -51,56 +34,58 @@ This proves that a note exists and has not been nullified at a specified block. | note_with_header | Note | The note you are proving inclusion for | | context | PrivateContext | Private context | +#### Example + +#include_code prove_note_validity noir-projects/noir-contracts/contracts/inclusion_proofs_contract/src/main.nr rust + ## Nullifier inclusion -This proves that a nullifier was included in a certain block (can be used to prove that a note had been nullified). The same disclaimer above holds true for this, and subsequent functions that specify another version without a block_number argument. +This proves that a nullifier exists in a given block header (can be used to prove that a note had been nullified). ### prove_nullifier_inclusion -`prove_nullifier_inclusion_at` takes 3 parameters: +`prove_nullifier_inclusion` takes 1 parameter: -| Name | Type | Description | -| ------------ | -------------- | ------------------------------------------- | -| nullifier | Field | The nullifier you are proving inclusion for | -| block_number | u32 | Block number for proving note's existence | -| context | PrivateContext | Private context | +| Name | Type | Description | +| --------- | ----- | ------------------------------------------- | +| nullifier | Field | The nullifier you are proving inclusion for | -`prove_nullifier_inclusion` takes 2 parameters: +#### Example -| Name | Type | Description | -| --------- | -------------- | ------------------------------------------- | -| nullifier | Field | The nullifier you are proving inclusion for | -| context | PrivateContext | Private context | +#include_code prove_nullifier_inclusion noir-projects/noir-contracts/contracts/inclusion_proofs_contract/src/main.nr rust -### prove_note_is_nullified_at / prove_note_is_nullified +### prove_note_is_nullified Instead of passing the nullifier, you can check that a note has been nullified by passing the note. +#### Implementation + +#include_code prove_note_is_nullified noir-projects/aztec-nr/aztec/src/history/nullifier_inclusion.nr rust + ## Nullifier non inclusion -This proves that a nullifier was not included in a certain block (can be used to prove that a note had not yet been nullified in a given block). +This proves that a nullifier was not included in a certain block, given the block header (can be used to prove that a note had not yet been nullified in a given block). -### prove_nullifier_not_included +### prove_nullifier_non_inclusion -`prove_nullifier_not_included_at` takes 3 parameters: +`prove_nullifier_non_inclusion` takes 1 parameters: -| Name | Type | Description | -| ------------ | -------------- | ------------------------------------------- | -| nullifier | Field | The nullifier you are proving inclusion for | -| block_number | u32 | Block number for proving note's existence | -| context | PrivateContext | Private context | +| Name | Type | Description | +| --------- | ----- | ------------------------------------------- | +| nullifier | Field | The nullifier you are proving inclusion for | -`prove_nullifier_not_included` takes 2 parameters: +#### Example -| Name | Type | Description | -| --------- | -------------- | ------------------------------------------- | -| nullifier | Field | The nullifier you are proving inclusion for | -| context | PrivateContext | Private context | +#include_code prove_nullifier_non_inclusion noir-projects/aztec-nr/aztec/src/history/contract_inclusion.nr rust -### prove_note_not_nullified_at / prove_note_not_nullified +### prove_note_not_nullified Instead of passing the nullifier, you can check that a note has not been nullified by passing the note. +#### Implementation + +#include_code prove_note_not_nullified noir-projects/aztec-nr/aztec/src/history/nullifier_non_inclusion.nr rust + ## Public storage historical reads These return the value stored in a public storage slot of a given contract at the end of the execution of a certain block (the latest one if using `public_storage_historical_read`). @@ -109,36 +94,65 @@ Note that it is never possible to read the _current_ value in a public storage s ### public_storage_historical_read -`public_storage_historical_read_at` takes 4 parameters: +`public_storage_historical_read` takes 2 parameters: -| Name | Type | Description | -| ---------------- | -------------- | ---------------------------------------- | -| context | PrivateContext | Private context | -| storage_slot | Field | Storage slot | -| contract_address | AztecAddress | The contract that owns the storage slot | -| block_number | u32 | Historical block number in which to read | +| Name | Type | Description | +| ---------------- | ------------ | --------------------------------------- | +| storage_slot | Field | Storage slot | +| contract_address | AztecAddress | The contract that owns the storage slot | -`public_storage_historical_read` takes 3 parameters. `block_number` is implicitly the historical block number from the context: +#### Example -| Name | Type | Description | -| ---------------- | -------------- | --------------------------------------- | -| context | PrivateContext | Private context | -| storage_slot | Field | Storage slot | -| contract_address | AztecAddress | The contract that owns the storage slot | +#include_code public_storage_historical_read noir-projects/noir-contracts/contracts/inclusion_proofs_contract/src/main.nr rust ## Contract inclusion This proves that a contract exists in, ie had been deployed before or in, a certain block. -### prove_contract_inclusion +### prove_contract_deployment + +`prove_contract_deployment` takes 1 parameter: + +| Name | Type | Description | +| ---------------- | ------------ | ------------------------------------------- | +| contract_address | AztecAddress | The contract address to prove deployment of | + +#### Example + +#include_code prove_contract_deployment noir-projects/noir-contracts/contracts/inclusion_proofs_contract/src/main.nr rust + +### prove_contract_non_deployment + +`prove_contract_non_deployment` takes 1 parameter: + +| Name | Type | Description | +| ---------------- | ------------ | ----------------------------------------------- | +| contract_address | AztecAddress | The contract address to prove non-deployment of | + +#### Example + +#include_code prove_contract_non_deployment noir-projects/noir-contracts/contracts/inclusion_proofs_contract/src/main.nr rust + +### prove_contract_initialization + +`prove_contract_initialization` takes 1 parameter: + +| Name | Type | Description | +| ---------------- | ------------ | ----------------------------------------------- | +| contract_address | AztecAddress | The contract address to prove initialization of | + +#### Example + +#include_code prove_contract_initialization noir-projects/noir-contracts/contracts/inclusion_proofs_contract/src/main.nr rust + +### prove_contract_non_initialization + +`prove_contract_non_initialization` takes 1 parameter: + +| Name | Type | Description | +| ---------------- | ------------ | --------------------------------------------------- | +| contract_address | AztecAddress | The contract address to prove non-initialization of | -`prove_contract_inclusion_at` takes 7 parameters: +#### Example -| Name | Type | Description | -| --------------------- | -------------- | -------------------------------------------- | -| deployer_public_key | GrumpkinPoint | Public key of the contract deployer | -| contract_address_salt | Field | Unique identifier for the contract's address | -| function_tree_root | Field | Root of the contract's function tree | -| constructor_hash | Field | Hash of the contract's constructor | -| block_number | u32 | Block number for proof verification | -| context | PrivateContext | Private context | +#include_code prove_contract_non_initialization noir-projects/noir-contracts/contracts/inclusion_proofs_contract/src/main.nr rust diff --git a/docs/sidebars.js b/docs/sidebars.js index 9e9383590d8..0093b1ab1b0 100644 --- a/docs/sidebars.js +++ b/docs/sidebars.js @@ -109,6 +109,7 @@ export default { "protocol-specs/state/note-hash-tree", "protocol-specs/state/nullifier-tree", "protocol-specs/state/public-data-tree", + "protocol-specs/state/wonky-tree", ], }, { diff --git a/docs/src/preprocess/InstructionSet/InstructionSet.js b/docs/src/preprocess/InstructionSet/InstructionSet.js index daead5a8c39..5fd93fc92e3 100644 --- a/docs/src/preprocess/InstructionSet/InstructionSet.js +++ b/docs/src/preprocess/InstructionSet/InstructionSet.js @@ -550,27 +550,8 @@ const INSTRUCTION_SET_RAW = [ "Tag updates": "`T[dstOffset] = field`", }, { - id: "feeperl2gas", - Name: "`FEEPERL2GAS`", - Category: "Execution Environment", - Flags: [{ name: "indirect", description: INDIRECT_FLAG_DESCRIPTION }], - Args: [ - { - name: "dstOffset", - description: - "memory offset specifying where to store operation's result", - }, - ], - Expression: "`M[dstOffset] = context.environment.feePerL2Gas`", - Summary: - 'Get the fee to be paid per "L2 gas" - constant for entire transaction', - Details: "", - "Tag checks": "", - "Tag updates": "`T[dstOffset] = field`", - }, - { - id: "feeperdagas", - Name: "`FEEPERDAGAS`", + id: "functionselector", + Name: "`FUNCTIONSELECTOR`", Category: "Execution Environment", Flags: [{ name: "indirect", description: INDIRECT_FLAG_DESCRIPTION }], Args: [ @@ -580,12 +561,11 @@ const INSTRUCTION_SET_RAW = [ "memory offset specifying where to store operation's result", }, ], - Expression: "`M[dstOffset] = context.environment.feePerDaGas`", - Summary: - 'Get the fee to be paid per "DA gas" - constant for entire transaction', + Expression: "`M[dstOffset] = context.environment.functionSelector`", + Summary: "Get the function selector of the contract function being executed", Details: "", "Tag checks": "", - "Tag updates": "`T[dstOffset] = field`", + "Tag updates": "`T[dstOffset] = u32`", }, { id: "transactionfee", @@ -606,25 +586,6 @@ const INSTRUCTION_SET_RAW = [ "Tag checks": "", "Tag updates": "`T[dstOffset] = field`", }, - { - id: "contractcalldepth", - Name: "`CONTRACTCALLDEPTH`", - Category: "Execution Environment", - Flags: [{ name: "indirect", description: INDIRECT_FLAG_DESCRIPTION }], - Args: [ - { - name: "dstOffset", - description: - "memory offset specifying where to store operation's result", - }, - ], - Expression: "`M[dstOffset] = context.environment.contractCallDepth`", - Summary: "Get how many contract calls deep the current call context is", - Details: - "Note: security issues with EVM's tx.origin can be resolved by asserting `calldepth == 0`.", - "Tag checks": "", - "Tag updates": "`T[dstOffset] = field`", - }, { id: "chainid", Name: "`CHAINID`", @@ -710,7 +671,45 @@ const INSTRUCTION_SET_RAW = [ }, ], Expression: "`M[dstOffset] = context.environment.globals.coinbase`", - Summary: "Get the block's beneficiary address", + Summary: "(UNIMPLEMENTED) Get the block's beneficiary address", + Details: "", + "Tag checks": "", + "Tag updates": "`T[dstOffset] = field`", + }, + { + id: "feeperl2gas", + Name: "`FEEPERL2GAS`", + Category: "Execution Environment - Globals - Gas", + Flags: [{ name: "indirect", description: INDIRECT_FLAG_DESCRIPTION }], + Args: [ + { + name: "dstOffset", + description: + "memory offset specifying where to store operation's result", + }, + ], + Expression: "`M[dstOffset] = context.environment.globals.feePerL2Gas`", + Summary: + 'Get the fee to be paid per "L2 gas" - constant for entire transaction', + Details: "", + "Tag checks": "", + "Tag updates": "`T[dstOffset] = field`", + }, + { + id: "feeperdagas", + Name: "`FEEPERDAGAS`", + Category: "Execution Environment - Globals - Gas", + Flags: [{ name: "indirect", description: INDIRECT_FLAG_DESCRIPTION }], + Args: [ + { + name: "dstOffset", + description: + "memory offset specifying where to store operation's result", + }, + ], + Expression: "`M[dstOffset] = context.environment.globals.feePerDaGas`", + Summary: + 'Get the fee to be paid per "DA gas" - constant for entire transaction', Details: "", "Tag checks": "", "Tag updates": "`T[dstOffset] = field`", @@ -728,7 +727,7 @@ const INSTRUCTION_SET_RAW = [ }, ], Expression: "`M[dstOffset] = context.environment.globals.l2GasLimit`", - Summary: 'Total amount of "L2 gas" that a block can consume', + Summary: '(UNIMPLEMENTED) Total amount of "L2 gas" that a block can consume', Details: "", "Tag checks": "", "Tag updates": "`T[dstOffset] = field`", @@ -746,7 +745,7 @@ const INSTRUCTION_SET_RAW = [ }, ], Expression: "`M[dstOffset] = context.environment.globals.daGasLimit`", - Summary: 'Total amount of "DA gas" that a block can consume', + Summary: '(UNIMPLEMENTED) Total amount of "DA gas" that a block can consume', Details: "", "Tag checks": "", "Tag updates": "`T[dstOffset] = field`", @@ -1287,7 +1286,7 @@ if exists: M[dstOffset] = header[M[memberIndexOffset]] // member `, Summary: - "Check if a header exists in the [archive tree](../state/archive) and retrieve the specified member if so", + "(UNIMPLEMENTED) Check if a header exists in the [archive tree](../state/archive) and retrieve the specified member if so", "World State access tracing": ` context.worldStateAccessTrace.archiveChecks.append( TracedArchiveLeafCheck { @@ -1462,7 +1461,7 @@ execute(nestedContext) updateContextAfterNestedCall(context, instr.args, nestedContext) `, Summary: - "Call into another contract, but keep the caller's `sender` and `storageAddress`", + "(UNIMPLEMENTED) Call into another contract, but keep the caller's `sender` and `storageAddress`", Details: `Same as \`CALL\`, but \`sender\` and \`storageAddress\` remains the same in the nested call as they were in the caller. ` + diff --git a/l1-contracts/src/core/Rollup.sol b/l1-contracts/src/core/Rollup.sol index 2ac9123a82f..13046308571 100644 --- a/l1-contracts/src/core/Rollup.sol +++ b/l1-contracts/src/core/Rollup.sol @@ -16,6 +16,7 @@ import {HeaderLib} from "./libraries/HeaderLib.sol"; import {Hash} from "./libraries/Hash.sol"; import {Errors} from "./libraries/Errors.sol"; import {Constants} from "./libraries/ConstantsGen.sol"; +import {MerkleLib} from "./libraries/MerkleLib.sol"; import {EnumerableSet} from "@oz/utils/structs/EnumerableSet.sol"; // Contracts @@ -149,10 +150,10 @@ contract Rollup is IRollup { revert Errors.Rollup__InvalidInHash(inHash, header.contentCommitment.inHash); } - // Currently trying out storing each tx's L2 to L1 messages in variable height trees (smallest tree required) - // => path lengths will differ and we cannot provide one here - // We can provide a minimum which is the height of the rollup layers (txTreeHeight) and the smallest 'tree' (1 layer) - uint256 l2ToL1TreeMinHeight = header.contentCommitment.txTreeHeight + 1; + // TODO(#7218): Revert to fixed height tree for outbox, currently just providing min as interim + // Min size = smallest path of the rollup tree + 1 + (uint256 min,) = MerkleLib.computeMinMaxPathLength(header.contentCommitment.numTxs); + uint256 l2ToL1TreeMinHeight = min + 1; OUTBOX.insert( header.globalVariables.blockNumber, header.contentCommitment.outHash, l2ToL1TreeMinHeight ); diff --git a/l1-contracts/src/core/interfaces/messagebridge/IOutbox.sol b/l1-contracts/src/core/interfaces/messagebridge/IOutbox.sol index c01b2f378f1..6eba97fca43 100644 --- a/l1-contracts/src/core/interfaces/messagebridge/IOutbox.sol +++ b/l1-contracts/src/core/interfaces/messagebridge/IOutbox.sol @@ -11,7 +11,7 @@ import {DataStructures} from "../../libraries/DataStructures.sol"; * and will be consumed by the portal contracts. */ interface IOutbox { - event RootAdded(uint256 indexed l2BlockNumber, bytes32 indexed root, uint256 height); + event RootAdded(uint256 indexed l2BlockNumber, bytes32 indexed root, uint256 minHeight); event MessageConsumed( uint256 indexed l2BlockNumber, bytes32 indexed root, diff --git a/l1-contracts/src/core/libraries/Errors.sol b/l1-contracts/src/core/libraries/Errors.sol index 7481445954d..e2c82cf5496 100644 --- a/l1-contracts/src/core/libraries/Errors.sol +++ b/l1-contracts/src/core/libraries/Errors.sol @@ -46,7 +46,7 @@ library Errors { error Rollup__TimestampInFuture(); // 0xbc1ce916 error Rollup__TimestampTooOld(); // 0x72ed9c81 error Rollup__UnavailableTxs(bytes32 txsHash); // 0x414906c3 - error Rollup__InvalidSequencer(address sequencer); + error Rollup__InvalidSequencer(address sequencer); // 0xa127a106 // Registry error Registry__RollupNotRegistered(address rollup); // 0xa1fee4cf @@ -54,6 +54,7 @@ library Errors { //TxsDecoder error TxsDecoder__InvalidLogsLength(uint256 expected, uint256 actual); // 0x829ca981 + error TxsDecoder__TxsTooLarge(uint256 expected, uint256 actual); // 0xc7d44a62 // HeaderLib error HeaderLib__InvalidHeaderSize(uint256 expected, uint256 actual); // 0xf3ccb247 diff --git a/l1-contracts/src/core/libraries/HeaderLib.sol b/l1-contracts/src/core/libraries/HeaderLib.sol index 877c617d7fa..e461b1381f1 100644 --- a/l1-contracts/src/core/libraries/HeaderLib.sol +++ b/l1-contracts/src/core/libraries/HeaderLib.sol @@ -25,7 +25,7 @@ import {Hash} from "./Hash.sol"; * | 0x0000 | 0x20 | lastArchive.root * | 0x0020 | 0x04 | lastArchive.nextAvailableLeafIndex * | | | ContentCommitment { - * | 0x0024 | 0x20 | txTreeHeight + * | 0x0024 | 0x20 | numTxs * | 0x0044 | 0x20 | txsEffectsHash * | 0x0064 | 0x20 | inHash * | 0x0084 | 0x20 | outHash @@ -90,7 +90,7 @@ library HeaderLib { } struct ContentCommitment { - uint256 txTreeHeight; + uint256 numTxs; bytes32 txsEffectsHash; bytes32 inHash; bytes32 outHash; @@ -163,7 +163,7 @@ library HeaderLib { ); // Reading ContentCommitment - header.contentCommitment.txTreeHeight = uint256(bytes32(_header[0x0024:0x0044])); + header.contentCommitment.numTxs = uint256(bytes32(_header[0x0024:0x0044])); header.contentCommitment.txsEffectsHash = bytes32(_header[0x0044:0x0064]); header.contentCommitment.inHash = bytes32(_header[0x0064:0x0084]); header.contentCommitment.outHash = bytes32(_header[0x0084:0x00a4]); @@ -204,7 +204,7 @@ library HeaderLib { // must match the order in the Header.getFields fields[0] = _header.lastArchive.root; fields[1] = bytes32(uint256(_header.lastArchive.nextAvailableLeafIndex)); - fields[2] = bytes32(_header.contentCommitment.txTreeHeight); + fields[2] = bytes32(_header.contentCommitment.numTxs); fields[3] = _header.contentCommitment.txsEffectsHash; fields[4] = _header.contentCommitment.inHash; fields[5] = _header.contentCommitment.outHash; diff --git a/l1-contracts/src/core/libraries/MerkleLib.sol b/l1-contracts/src/core/libraries/MerkleLib.sol index c7ab82502b0..89dc020a5a2 100644 --- a/l1-contracts/src/core/libraries/MerkleLib.sol +++ b/l1-contracts/src/core/libraries/MerkleLib.sol @@ -51,4 +51,64 @@ library MerkleLib { revert Errors.MerkleLib__InvalidRoot(_expectedRoot, subtreeRoot, _leaf, _index); } } + + /** + * @notice Computes the minimum and maximum path size of an unbalanced tree. + * @dev Follows structure of rollup circuits by greedy filling subtrees. + * @param _numTxs - The number of txs to form into subtrees. + * @return (min, max) - The min and max path sizes. + */ + function computeMinMaxPathLength(uint256 _numTxs) internal pure returns (uint256, uint256) { + uint256 numTxs = _numTxs < 2 ? 2 : _numTxs; + uint256 numSubtrees = 0; + uint256 currentSubtreeSize = 1; + uint256 currentSubtreeHeight = 0; + uint256 firstSubtreeHeight; + uint256 finalSubtreeHeight; + while (numTxs != 0) { + // If size & txs == 0, the subtree doesn't exist for this number of txs + if (currentSubtreeSize & numTxs == 0) { + currentSubtreeSize <<= 1; + currentSubtreeHeight++; + continue; + } + // Assign the smallest rightmost subtree height + if (numSubtrees == 0) finalSubtreeHeight = currentSubtreeHeight; + // Assign the largest leftmost subtree height + if (numTxs - currentSubtreeSize == 0) firstSubtreeHeight = currentSubtreeHeight; + numTxs -= currentSubtreeSize; + currentSubtreeSize <<= 1; + currentSubtreeHeight++; + numSubtrees++; + } + if (numSubtrees == 1) { + // We have a balanced tree + return (firstSubtreeHeight, firstSubtreeHeight); + } + uint256 min = finalSubtreeHeight + numSubtrees - 1; + uint256 max = firstSubtreeHeight + 1; + return (min, max); + } + + /** + * @notice Calculates a tree height from the amount of elements in the tree + * @dev - This mirrors the function in TestUtil, but assumes _size is an exact power of 2 or = 1 + * @param _size - The number of elements in the tree + */ + function calculateTreeHeightFromSize(uint256 _size) internal pure returns (uint256) { + /// We need the height of the tree that will contain all of our leaves, + /// hence the next highest power of two from the amount of leaves - Math.ceil(Math.log2(x)) + uint256 height = 0; + + if (_size == 1) { + return 0; + } + + /// While size > 1, we divide by two, and count how many times we do this; producing a rudimentary way of calculating Math.Floor(Math.log2(x)) + while (_size > 1) { + _size >>= 1; + height++; + } + return height; + } } diff --git a/l1-contracts/src/core/libraries/decoders/TxsDecoder.sol b/l1-contracts/src/core/libraries/decoders/TxsDecoder.sol index 43f00cc5b8e..e3ecc6ecb2c 100644 --- a/l1-contracts/src/core/libraries/decoders/TxsDecoder.sol +++ b/l1-contracts/src/core/libraries/decoders/TxsDecoder.sol @@ -261,7 +261,7 @@ library TxsDecoder { } } - return computeRoot(vars.baseLeaves); + return computeUnbalancedRoot(vars.baseLeaves); } /** @@ -516,6 +516,40 @@ library TxsDecoder { return _leafs[0]; } + /** + * @notice Computes the root for a binary unbalanced Merkle-tree given the leaves. + * @dev Filled in greedily with subtrees. Useful for txsEffectHash and outHash tree. + * @param _leaves - The 32 bytes leafs to build the tree of. + * @return The root of the Merkle tree. + */ + function computeUnbalancedRoot(bytes32[] memory _leaves) internal pure returns (bytes32) { + // e.g. an unbalanced tree of 7 txs will contain subtrees of 4, 2, and 1 tx(s) = 111 + // e.g. an unbalanced tree of 9 txs will contain subtrees of 8 and 1 tx(s) = 1001 + // We collect the roots of each subtree + bytes32 root; + uint256 currentSubtreeSize = 1; + uint256 numTxs = _leaves.length; + // We must calculate the smaller rightmost subtrees first, hence starting at 1 + while (numTxs != 0) { + // If size & txs == 0, the subtree doesn't exist for this number of txs + if (currentSubtreeSize & numTxs == 0) { + currentSubtreeSize <<= 1; + continue; + } + bytes32[] memory leavesInSubtree = new bytes32[](currentSubtreeSize); + uint256 start = numTxs - currentSubtreeSize; + for (uint256 i = start; i < numTxs; i++) { + leavesInSubtree[i - start] = _leaves[i]; + } + bytes32 subtreeRoot = computeRoot(leavesInSubtree); + root = + numTxs == _leaves.length ? subtreeRoot : Hash.sha256ToField(bytes.concat(subtreeRoot, root)); + numTxs -= currentSubtreeSize; + currentSubtreeSize <<= 1; + } + return root; + } + /** * @notice Wrapper around the slicing to avoid some stack too deep * @param _data - The data to slice @@ -592,18 +626,6 @@ library TxsDecoder { } else if (_numTxEffects == 1) { return 1; } - - uint32 v = _numTxEffects; - - // the following rounds _numTxEffects up to the next power of 2 (works only for 4 bytes value!) - v--; - v |= v >> 1; - v |= v >> 2; - v |= v >> 4; - v |= v >> 8; - v |= v >> 16; - v++; - - return v - _numTxEffects; + return 0; } } diff --git a/l1-contracts/src/core/messagebridge/Outbox.sol b/l1-contracts/src/core/messagebridge/Outbox.sol index b62665d8a87..db1ccb76447 100644 --- a/l1-contracts/src/core/messagebridge/Outbox.sol +++ b/l1-contracts/src/core/messagebridge/Outbox.sol @@ -100,19 +100,14 @@ contract Outbox is IOutbox { if (rootData.nullified[_leafIndex]) { revert Errors.Outbox__AlreadyNullified(_l2BlockNumber, _leafIndex); } + // TODO(#7218): We will eventually move back to a balanced tree and constrain the path length + // to be equal to height - for now we just check the min // Min height = height of rollup layers // The smallest num of messages will require a subtree of height 1 - uint256 treeHeight = rootData.minHeight; - if (treeHeight > _path.length) { - revert Errors.Outbox__InvalidPathLength(treeHeight, _path.length); - } - - // Max height = height of rollup layers + max possible subtree height - // The max num of messages N will require a subtree of height log2(N) - uint256 maxSubtreeHeight = calculateTreeHeightFromSize(Constants.MAX_NEW_L2_TO_L1_MSGS_PER_TX); - if (treeHeight + maxSubtreeHeight < _path.length) { - revert Errors.Outbox__InvalidPathLength(treeHeight + maxSubtreeHeight, _path.length); + uint256 minHeight = rootData.minHeight; + if (minHeight > _path.length) { + revert Errors.Outbox__InvalidPathLength(minHeight, _path.length); } bytes32 messageHash = _message.sha256ToField(); @@ -138,22 +133,4 @@ contract Outbox is IOutbox { { return roots[_l2BlockNumber].nullified[_leafIndex]; } - - /** - * @notice Calculates a tree height from the amount of elements in the tree - * @dev - This mirrors the function in TestUtil, but assumes _size is an exact power of 2 - * @param _size - The number of elements in the tree - */ - function calculateTreeHeightFromSize(uint256 _size) internal pure returns (uint256) { - /// We need the height of the tree that will contain all of our leaves, - /// hence the next highest power of two from the amount of leaves - Math.ceil(Math.log2(x)) - uint256 height = 0; - - /// While size > 1, we divide by two, and count how many times we do this; producing a rudimentary way of calculating Math.Floor(Math.log2(x)) - while (_size > 1) { - _size >>= 1; - height++; - } - return height; - } } diff --git a/l1-contracts/test/Rollup.t.sol b/l1-contracts/test/Rollup.t.sol index 4d8613db027..3523412dd81 100644 --- a/l1-contracts/test/Rollup.t.sol +++ b/l1-contracts/test/Rollup.t.sol @@ -162,15 +162,15 @@ contract RollupTest is DecoderBase { // NB: The below works with full blocks because we require the largest possible subtrees // for L2 to L1 messages - usually we make variable height subtrees, the roots of which // form a balanced tree - uint256 numTxsWithPadding = txsHelper.computeNumTxEffectsToPad(numTxs) + numTxs; + // The below is a little janky - we know that this test deals with full txs with equal numbers // of msgs or txs with no messages, so the division works // TODO edit full.messages to include information about msgs per tx? uint256 subTreeHeight = merkleTestUtil.calculateTreeHeightFromSize( full.messages.l2ToL1Messages.length == 0 ? 0 : full.messages.l2ToL1Messages.length / numTxs ); - uint256 outHashTreeHeight = merkleTestUtil.calculateTreeHeightFromSize(numTxsWithPadding); - uint256 numMessagesWithPadding = numTxsWithPadding * Constants.MAX_NEW_L2_TO_L1_MSGS_PER_TX; + uint256 outHashTreeHeight = merkleTestUtil.calculateTreeHeightFromSize(numTxs); + uint256 numMessagesWithPadding = numTxs * Constants.MAX_NEW_L2_TO_L1_MSGS_PER_TX; uint256 treeHeight = subTreeHeight + outHashTreeHeight; NaiveMerkle tree = new NaiveMerkle(treeHeight); diff --git a/l1-contracts/test/decoders/Base.sol b/l1-contracts/test/decoders/Base.sol index 8301379c8f2..d962bbac376 100644 --- a/l1-contracts/test/decoders/Base.sol +++ b/l1-contracts/test/decoders/Base.sol @@ -73,8 +73,8 @@ contract DecoderBase is Test { struct ContentCommitment { bytes32 inHash; + uint256 numTxs; bytes32 outHash; - uint256 txTreeHeight; bytes32 txsEffectsHash; } diff --git a/l1-contracts/test/decoders/Decoders.t.sol b/l1-contracts/test/decoders/Decoders.t.sol index bd7eef2bf4b..a3f6c3958ca 100644 --- a/l1-contracts/test/decoders/Decoders.t.sol +++ b/l1-contracts/test/decoders/Decoders.t.sol @@ -72,11 +72,7 @@ contract DecodersTest is DecoderBase { { DecoderBase.ContentCommitment memory contentCommitment = referenceHeader.contentCommitment; - assertEq( - header.contentCommitment.txTreeHeight, - contentCommitment.txTreeHeight, - "Invalid txTreeSize" - ); + assertEq(header.contentCommitment.numTxs, contentCommitment.numTxs, "Invalid txTreeSize"); assertEq( header.contentCommitment.txsEffectsHash, contentCommitment.txsEffectsHash, @@ -332,26 +328,10 @@ contract DecodersTest is DecoderBase { numTxEffects = 3; paddedNumTxEffects = txsHelper.computeNumTxEffectsToPad(numTxEffects); - assertEq(paddedNumTxEffects, 2 ** 2 - numTxEffects, "Incorrect number of tx effects to pad"); - - numTxEffects = 5; - paddedNumTxEffects = txsHelper.computeNumTxEffectsToPad(numTxEffects); - assertEq(paddedNumTxEffects, 2 ** 3 - numTxEffects, "Incorrect number of tx effects to pad"); - - numTxEffects = 8; - paddedNumTxEffects = txsHelper.computeNumTxEffectsToPad(numTxEffects); - assertEq(paddedNumTxEffects, 2 ** 3 - numTxEffects, "Incorrect number of tx effects to pad"); - - numTxEffects = 10; - paddedNumTxEffects = txsHelper.computeNumTxEffectsToPad(numTxEffects); - assertEq(paddedNumTxEffects, 2 ** 4 - numTxEffects, "Incorrect number of tx effects to pad"); - - numTxEffects = 16; - paddedNumTxEffects = txsHelper.computeNumTxEffectsToPad(numTxEffects); - assertEq(paddedNumTxEffects, 2 ** 4 - numTxEffects, "Incorrect number of tx effects to pad"); + assertEq(paddedNumTxEffects, 0, "Incorrect number of tx effects to pad"); numTxEffects = 17; paddedNumTxEffects = txsHelper.computeNumTxEffectsToPad(numTxEffects); - assertEq(paddedNumTxEffects, 2 ** 5 - numTxEffects, "Incorrect number of tx effects to pad"); + assertEq(paddedNumTxEffects, 0, "Incorrect number of tx effects to pad"); } } diff --git a/l1-contracts/test/decoders/helpers/TxsDecoderHelper.sol b/l1-contracts/test/decoders/helpers/TxsDecoderHelper.sol index 41b5352b270..f34fd9c3437 100644 --- a/l1-contracts/test/decoders/helpers/TxsDecoderHelper.sol +++ b/l1-contracts/test/decoders/helpers/TxsDecoderHelper.sol @@ -3,6 +3,7 @@ pragma solidity >=0.8.18; import {TxsDecoder} from "../../../src/core/libraries/decoders/TxsDecoder.sol"; +import {MerkleLib} from "../../../src/core/libraries/MerkleLib.sol"; contract TxsDecoderHelper { // A wrapper used such that we get "calldata" and not memory @@ -21,4 +22,12 @@ contract TxsDecoderHelper { function computeNumTxEffectsToPad(uint32 _numTxEffects) external pure returns (uint32) { return TxsDecoder.computeNumTxEffectsToPad(_numTxEffects); } + + function computeUnbalancedRoot(bytes32[] memory _leaves) external pure returns (bytes32) { + return TxsDecoder.computeUnbalancedRoot(_leaves); + } + + function computeMinMaxPathLength(uint32 _numTxEffects) external pure returns (uint256, uint256) { + return MerkleLib.computeMinMaxPathLength(_numTxEffects); + } } diff --git a/l1-contracts/test/fixtures/empty_block_0.json b/l1-contracts/test/fixtures/empty_block_0.json index 3f6e46d2c1f..8698dda56e8 100644 --- a/l1-contracts/test/fixtures/empty_block_0.json +++ b/l1-contracts/test/fixtures/empty_block_0.json @@ -8,14 +8,14 @@ "l2ToL1Messages": [] }, "block": { - "archive": "0x1cf715c65eecea3dda1833ca8e9f7b23ca588a7ece864b957f919bb7f0890523", + "archive": "0x062d0b928c3e1fa5529032c8c663c4b3b1a359d03943f20667b02d87bf71a7ad", "body": "0x00000000", "txsEffectsHash": "0x00d09e7feff5a1049661763ded52742f02aac5d9793b27a40d6b9c60a668bdf2", "decodedHeader": { "contentCommitment": { "inHash": "0x00089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c", "outHash": "0x0007638bb56b6dda2b64b8f76841114ac3a87a1820030e2e16772c4d294879c3", - "txTreeHeight": 1, + "numTxs": 2, "txsEffectsHash": "0x00d09e7feff5a1049661763ded52742f02aac5d9793b27a40d6b9c60a668bdf2" }, "globalVariables": { @@ -23,8 +23,8 @@ "chainId": 31337, "timestamp": 0, "version": 1, - "coinbase": "0x154e0eb6154e0eb6154e0eb6154e0eb6154e0eb6", - "feeRecipient": "0x301bf845ed245d172febeaa6c1a11d59b6041b79531a00694f9042df161e2626", + "coinbase": "0x6adca08f06cc255a12c609d284c5861c1cad740c", + "feeRecipient": "0x09d7dc61a2ee0c764bc8f5954500c7b43d5422958e67d20144b3e738b04dfc07", "gasFees": { "feePerDaGas": 0, "feePerL2Gas": 0 @@ -55,8 +55,8 @@ } } }, - "header": "0x0afb332dff10b3b4221c5c26ead8202d94bb977f644c91b06dec3ee098acc2b600000001000000000000000000000000000000000000000000000000000000000000000100d09e7feff5a1049661763ded52742f02aac5d9793b27a40d6b9c60a668bdf200089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c0007638bb56b6dda2b64b8f76841114ac3a87a1820030e2e16772c4d294879c31864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f800000001016642d9ccd8346c403aa4c3fa451178b22534a27035cdaa6ec34ae53b29c50cb000000800bcfa3e9f1a8922ee92c6dc964d6595907c1804a86753774322b468f69d4f27800000100021a6cc64c830b4914600d0296c3968c5d28c1b00c5c4b0b33d1f39d948edbd4000001000000000000000000000000000000000000000000000000000000000000007a69000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000154e0eb6154e0eb6154e0eb6154e0eb6154e0eb6301bf845ed245d172febeaa6c1a11d59b6041b79531a00694f9042df161e2626000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "publicInputsHash": "0x00e1b985afe7ad2360a25bc829b614b5ef63e5cae914a38d99f59d5b2a5522fe", + "header": "0x0afb332dff10b3b4221c5c26ead8202d94bb977f644c91b06dec3ee098acc2b600000001000000000000000000000000000000000000000000000000000000000000000200d09e7feff5a1049661763ded52742f02aac5d9793b27a40d6b9c60a668bdf200089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c0007638bb56b6dda2b64b8f76841114ac3a87a1820030e2e16772c4d294879c31864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f800000001016642d9ccd8346c403aa4c3fa451178b22534a27035cdaa6ec34ae53b29c50cb000000800bcfa3e9f1a8922ee92c6dc964d6595907c1804a86753774322b468f69d4f27800000100021a6cc64c830b4914600d0296c3968c5d28c1b00c5c4b0b33d1f39d948edbd4000001000000000000000000000000000000000000000000000000000000000000007a690000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000006adca08f06cc255a12c609d284c5861c1cad740c09d7dc61a2ee0c764bc8f5954500c7b43d5422958e67d20144b3e738b04dfc07000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "publicInputsHash": "0x002aa4bb5409ae75e705b167d45ba569055b2ae62c67c1608f4cf17ac5129ad6", "numTxs": 0 } } \ No newline at end of file diff --git a/l1-contracts/test/fixtures/empty_block_1.json b/l1-contracts/test/fixtures/empty_block_1.json index 018b043a71a..a0706e4b24f 100644 --- a/l1-contracts/test/fixtures/empty_block_1.json +++ b/l1-contracts/test/fixtures/empty_block_1.json @@ -8,23 +8,23 @@ "l2ToL1Messages": [] }, "block": { - "archive": "0x2074c6a0cc1f2dd305c8614df3a7426eb3b20dac06850c5d6cb64910a5a1caef", + "archive": "0x0f049707f5cee10d833aea2adf93e1e3462eaa5b328576342fbea7837195c91a", "body": "0x00000000", "txsEffectsHash": "0x00d09e7feff5a1049661763ded52742f02aac5d9793b27a40d6b9c60a668bdf2", "decodedHeader": { "contentCommitment": { "inHash": "0x00089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c", "outHash": "0x0007638bb56b6dda2b64b8f76841114ac3a87a1820030e2e16772c4d294879c3", - "txTreeHeight": 1, + "numTxs": 2, "txsEffectsHash": "0x00d09e7feff5a1049661763ded52742f02aac5d9793b27a40d6b9c60a668bdf2" }, "globalVariables": { "blockNumber": 2, "chainId": 31337, - "timestamp": 1718108388, + "timestamp": 1719332523, "version": 1, - "coinbase": "0x154e0eb6154e0eb6154e0eb6154e0eb6154e0eb6", - "feeRecipient": "0x301bf845ed245d172febeaa6c1a11d59b6041b79531a00694f9042df161e2626", + "coinbase": "0x6adca08f06cc255a12c609d284c5861c1cad740c", + "feeRecipient": "0x09d7dc61a2ee0c764bc8f5954500c7b43d5422958e67d20144b3e738b04dfc07", "gasFees": { "feePerDaGas": 0, "feePerL2Gas": 0 @@ -32,7 +32,7 @@ }, "lastArchive": { "nextAvailableLeafIndex": 2, - "root": "0x1cf715c65eecea3dda1833ca8e9f7b23ca588a7ece864b957f919bb7f0890523" + "root": "0x062d0b928c3e1fa5529032c8c663c4b3b1a359d03943f20667b02d87bf71a7ad" }, "stateReference": { "l1ToL2MessageTree": { @@ -55,8 +55,8 @@ } } }, - "header": "0x1cf715c65eecea3dda1833ca8e9f7b23ca588a7ece864b957f919bb7f089052300000002000000000000000000000000000000000000000000000000000000000000000100d09e7feff5a1049661763ded52742f02aac5d9793b27a40d6b9c60a668bdf200089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c0007638bb56b6dda2b64b8f76841114ac3a87a1820030e2e16772c4d294879c31864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f800000002016642d9ccd8346c403aa4c3fa451178b22534a27035cdaa6ec34ae53b29c50cb000001000bcfa3e9f1a8922ee92c6dc964d6595907c1804a86753774322b468f69d4f27800000180021a6cc64c830b4914600d0296c3968c5d28c1b00c5c4b0b33d1f39d948edbd4000001800000000000000000000000000000000000000000000000000000000000007a690000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000666840e4154e0eb6154e0eb6154e0eb6154e0eb6154e0eb6301bf845ed245d172febeaa6c1a11d59b6041b79531a00694f9042df161e2626000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "publicInputsHash": "0x002d5e3fa366ee431f598f8bc6060165320453e2ad908c3ad80b1e7d3c1a8006", + "header": "0x062d0b928c3e1fa5529032c8c663c4b3b1a359d03943f20667b02d87bf71a7ad00000002000000000000000000000000000000000000000000000000000000000000000200d09e7feff5a1049661763ded52742f02aac5d9793b27a40d6b9c60a668bdf200089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c0007638bb56b6dda2b64b8f76841114ac3a87a1820030e2e16772c4d294879c31864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f800000002016642d9ccd8346c403aa4c3fa451178b22534a27035cdaa6ec34ae53b29c50cb000001000bcfa3e9f1a8922ee92c6dc964d6595907c1804a86753774322b468f69d4f27800000180021a6cc64c830b4914600d0296c3968c5d28c1b00c5c4b0b33d1f39d948edbd4000001800000000000000000000000000000000000000000000000000000000000007a690000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000667aeeab6adca08f06cc255a12c609d284c5861c1cad740c09d7dc61a2ee0c764bc8f5954500c7b43d5422958e67d20144b3e738b04dfc07000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "publicInputsHash": "0x00d8e0d4aa3b09294fa37c11ca7f356dc35c160e2ec9a95363a07dca826e1397", "numTxs": 0 } } \ No newline at end of file diff --git a/l1-contracts/test/fixtures/mixed_block_0.json b/l1-contracts/test/fixtures/mixed_block_0.json index c0bc6a5c453..f9b76ee0dec 100644 --- a/l1-contracts/test/fixtures/mixed_block_0.json +++ b/l1-contracts/test/fixtures/mixed_block_0.json @@ -58,14 +58,14 @@ ] }, "block": { - "archive": "0x20fbe5614957ca8c09d74fd86ebbab70e3c95d6996b4e0086f7809f9d03a302d", + "archive": "0x1caafe747155b2a72a6f44744dc68fa9d6c3b605e5dc661383c5a202dd7ee7c8", "body": "0x00000004000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000014100000000000000000000000000000000000000000000000000000000000001420000000000000000000000000000000000000000000000000000000000000143000000000000000000000000000000000000000000000000000000000000014400000000000000000000000000000000000000000000000000000000000001450000000000000000000000000000000000000000000000000000000000000146000000000000000000000000000000000000000000000000000000000000014700000000000000000000000000000000000000000000000000000000000001480000000000000000000000000000000000000000000000000000000000000149000000000000000000000000000000000000000000000000000000000000014a000000000000000000000000000000000000000000000000000000000000014b000000000000000000000000000000000000000000000000000000000000014c000000000000000000000000000000000000000000000000000000000000014d000000000000000000000000000000000000000000000000000000000000014e000000000000000000000000000000000000000000000000000000000000014f0000000000000000000000000000000000000000000000000000000000000150000000000000000000000000000000000000000000000000000000000000015100000000000000000000000000000000000000000000000000000000000001520000000000000000000000000000000000000000000000000000000000000153000000000000000000000000000000000000000000000000000000000000015400000000000000000000000000000000000000000000000000000000000001550000000000000000000000000000000000000000000000000000000000000156000000000000000000000000000000000000000000000000000000000000015700000000000000000000000000000000000000000000000000000000000001580000000000000000000000000000000000000000000000000000000000000159000000000000000000000000000000000000000000000000000000000000015a000000000000000000000000000000000000000000000000000000000000015b000000000000000000000000000000000000000000000000000000000000015c000000000000000000000000000000000000000000000000000000000000015d000000000000000000000000000000000000000000000000000000000000015e000000000000000000000000000000000000000000000000000000000000015f0000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000016100000000000000000000000000000000000000000000000000000000000001620000000000000000000000000000000000000000000000000000000000000163000000000000000000000000000000000000000000000000000000000000016400000000000000000000000000000000000000000000000000000000000001650000000000000000000000000000000000000000000000000000000000000166000000000000000000000000000000000000000000000000000000000000016700000000000000000000000000000000000000000000000000000000000001680000000000000000000000000000000000000000000000000000000000000169000000000000000000000000000000000000000000000000000000000000016a000000000000000000000000000000000000000000000000000000000000016b000000000000000000000000000000000000000000000000000000000000016c000000000000000000000000000000000000000000000000000000000000016d000000000000000000000000000000000000000000000000000000000000016e000000000000000000000000000000000000000000000000000000000000016f0000000000000000000000000000000000000000000000000000000000000170000000000000000000000000000000000000000000000000000000000000017100000000000000000000000000000000000000000000000000000000000001720000000000000000000000000000000000000000000000000000000000000173000000000000000000000000000000000000000000000000000000000000017400000000000000000000000000000000000000000000000000000000000001750000000000000000000000000000000000000000000000000000000000000176000000000000000000000000000000000000000000000000000000000000017700000000000000000000000000000000000000000000000000000000000001780000000000000000000000000000000000000000000000000000000000000179000000000000000000000000000000000000000000000000000000000000017a000000000000000000000000000000000000000000000000000000000000017b000000000000000000000000000000000000000000000000000000000000017c000000000000000000000000000000000000000000000000000000000000017d000000000000000000000000000000000000000000000000000000000000017e000000000000000000000000000000000000000000000000000000000000017f3f0000000000000000000000000000000000000000000000000000000000000240000000000000000000000000000000000000000000000000000000000000024100000000000000000000000000000000000000000000000000000000000002420000000000000000000000000000000000000000000000000000000000000243000000000000000000000000000000000000000000000000000000000000024400000000000000000000000000000000000000000000000000000000000002450000000000000000000000000000000000000000000000000000000000000246000000000000000000000000000000000000000000000000000000000000024700000000000000000000000000000000000000000000000000000000000002480000000000000000000000000000000000000000000000000000000000000249000000000000000000000000000000000000000000000000000000000000024a000000000000000000000000000000000000000000000000000000000000024b000000000000000000000000000000000000000000000000000000000000024c000000000000000000000000000000000000000000000000000000000000024d000000000000000000000000000000000000000000000000000000000000024e000000000000000000000000000000000000000000000000000000000000024f0000000000000000000000000000000000000000000000000000000000000250000000000000000000000000000000000000000000000000000000000000025100000000000000000000000000000000000000000000000000000000000002520000000000000000000000000000000000000000000000000000000000000253000000000000000000000000000000000000000000000000000000000000025400000000000000000000000000000000000000000000000000000000000002550000000000000000000000000000000000000000000000000000000000000256000000000000000000000000000000000000000000000000000000000000025700000000000000000000000000000000000000000000000000000000000002580000000000000000000000000000000000000000000000000000000000000259000000000000000000000000000000000000000000000000000000000000025a000000000000000000000000000000000000000000000000000000000000025b000000000000000000000000000000000000000000000000000000000000025c000000000000000000000000000000000000000000000000000000000000025d000000000000000000000000000000000000000000000000000000000000025e000000000000000000000000000000000000000000000000000000000000025f0000000000000000000000000000000000000000000000000000000000000260000000000000000000000000000000000000000000000000000000000000026100000000000000000000000000000000000000000000000000000000000002620000000000000000000000000000000000000000000000000000000000000263000000000000000000000000000000000000000000000000000000000000026400000000000000000000000000000000000000000000000000000000000002650000000000000000000000000000000000000000000000000000000000000266000000000000000000000000000000000000000000000000000000000000026700000000000000000000000000000000000000000000000000000000000002680000000000000000000000000000000000000000000000000000000000000269000000000000000000000000000000000000000000000000000000000000026a000000000000000000000000000000000000000000000000000000000000026b000000000000000000000000000000000000000000000000000000000000026c000000000000000000000000000000000000000000000000000000000000026d000000000000000000000000000000000000000000000000000000000000026e000000000000000000000000000000000000000000000000000000000000026f0000000000000000000000000000000000000000000000000000000000000270000000000000000000000000000000000000000000000000000000000000027100000000000000000000000000000000000000000000000000000000000002720000000000000000000000000000000000000000000000000000000000000273000000000000000000000000000000000000000000000000000000000000027400000000000000000000000000000000000000000000000000000000000002750000000000000000000000000000000000000000000000000000000000000276000000000000000000000000000000000000000000000000000000000000027700000000000000000000000000000000000000000000000000000000000002780000000000000000000000000000000000000000000000000000000000000279000000000000000000000000000000000000000000000000000000000000027a000000000000000000000000000000000000000000000000000000000000027b000000000000000000000000000000000000000000000000000000000000027c000000000000000000000000000000000000000000000000000000000000027d000000000000000000000000000000000000000000000000000000000000027e08000000000000000000000000000000000000000000000000000000000000034000000000000000000000000000000000000000000000000000000000000003410000000000000000000000000000000000000000000000000000000000000342000000000000000000000000000000000000000000000000000000000000034300000000000000000000000000000000000000000000000000000000000003440000000000000000000000000000000000000000000000000000000000000345000000000000000000000000000000000000000000000000000000000000034600000000000000000000000000000000000000000000000000000000000003473f0000000000000000000000000000000000000000000000000000000000000540000000000000000000000000000000000000000000000000000000000000054a0000000000000000000000000000000000000000000000000000000000000541000000000000000000000000000000000000000000000000000000000000054b0000000000000000000000000000000000000000000000000000000000000542000000000000000000000000000000000000000000000000000000000000054c0000000000000000000000000000000000000000000000000000000000000543000000000000000000000000000000000000000000000000000000000000054d0000000000000000000000000000000000000000000000000000000000000544000000000000000000000000000000000000000000000000000000000000054e0000000000000000000000000000000000000000000000000000000000000545000000000000000000000000000000000000000000000000000000000000054f00000000000000000000000000000000000000000000000000000000000005460000000000000000000000000000000000000000000000000000000000000550000000000000000000000000000000000000000000000000000000000000054700000000000000000000000000000000000000000000000000000000000005510000000000000000000000000000000000000000000000000000000000000548000000000000000000000000000000000000000000000000000000000000055200000000000000000000000000000000000000000000000000000000000005490000000000000000000000000000000000000000000000000000000000000553000000000000000000000000000000000000000000000000000000000000054a0000000000000000000000000000000000000000000000000000000000000554000000000000000000000000000000000000000000000000000000000000054b0000000000000000000000000000000000000000000000000000000000000555000000000000000000000000000000000000000000000000000000000000054c0000000000000000000000000000000000000000000000000000000000000556000000000000000000000000000000000000000000000000000000000000054d0000000000000000000000000000000000000000000000000000000000000557000000000000000000000000000000000000000000000000000000000000054e0000000000000000000000000000000000000000000000000000000000000558000000000000000000000000000000000000000000000000000000000000054f00000000000000000000000000000000000000000000000000000000000005590000000000000000000000000000000000000000000000000000000000000550000000000000000000000000000000000000000000000000000000000000055a0000000000000000000000000000000000000000000000000000000000000551000000000000000000000000000000000000000000000000000000000000055b0000000000000000000000000000000000000000000000000000000000000552000000000000000000000000000000000000000000000000000000000000055c0000000000000000000000000000000000000000000000000000000000000553000000000000000000000000000000000000000000000000000000000000055d0000000000000000000000000000000000000000000000000000000000000554000000000000000000000000000000000000000000000000000000000000055e0000000000000000000000000000000000000000000000000000000000000555000000000000000000000000000000000000000000000000000000000000055f00000000000000000000000000000000000000000000000000000000000005560000000000000000000000000000000000000000000000000000000000000560000000000000000000000000000000000000000000000000000000000000055700000000000000000000000000000000000000000000000000000000000005610000000000000000000000000000000000000000000000000000000000000558000000000000000000000000000000000000000000000000000000000000056200000000000000000000000000000000000000000000000000000000000005590000000000000000000000000000000000000000000000000000000000000563000000000000000000000000000000000000000000000000000000000000055a0000000000000000000000000000000000000000000000000000000000000564000000000000000000000000000000000000000000000000000000000000055b0000000000000000000000000000000000000000000000000000000000000565000000000000000000000000000000000000000000000000000000000000055c0000000000000000000000000000000000000000000000000000000000000566000000000000000000000000000000000000000000000000000000000000055d0000000000000000000000000000000000000000000000000000000000000567000000000000000000000000000000000000000000000000000000000000055e0000000000000000000000000000000000000000000000000000000000000568000000000000000000000000000000000000000000000000000000000000055f00000000000000000000000000000000000000000000000000000000000005690000000000000000000000000000000000000000000000000000000000000560000000000000000000000000000000000000000000000000000000000000056a0000000000000000000000000000000000000000000000000000000000000561000000000000000000000000000000000000000000000000000000000000056b0000000000000000000000000000000000000000000000000000000000000562000000000000000000000000000000000000000000000000000000000000056c0000000000000000000000000000000000000000000000000000000000000563000000000000000000000000000000000000000000000000000000000000056d0000000000000000000000000000000000000000000000000000000000000564000000000000000000000000000000000000000000000000000000000000056e0000000000000000000000000000000000000000000000000000000000000565000000000000000000000000000000000000000000000000000000000000056f00000000000000000000000000000000000000000000000000000000000005660000000000000000000000000000000000000000000000000000000000000570000000000000000000000000000000000000000000000000000000000000056700000000000000000000000000000000000000000000000000000000000005710000000000000000000000000000000000000000000000000000000000000568000000000000000000000000000000000000000000000000000000000000057200000000000000000000000000000000000000000000000000000000000005690000000000000000000000000000000000000000000000000000000000000573000000000000000000000000000000000000000000000000000000000000056a0000000000000000000000000000000000000000000000000000000000000574000000000000000000000000000000000000000000000000000000000000056b0000000000000000000000000000000000000000000000000000000000000575000000000000000000000000000000000000000000000000000000000000056c0000000000000000000000000000000000000000000000000000000000000576000000000000000000000000000000000000000000000000000000000000056d0000000000000000000000000000000000000000000000000000000000000577000000000000000000000000000000000000000000000000000000000000056e0000000000000000000000000000000000000000000000000000000000000578000000000000000000000000000000000000000000000000000000000000056f00000000000000000000000000000000000000000000000000000000000005790000000000000000000000000000000000000000000000000000000000000570000000000000000000000000000000000000000000000000000000000000057a0000000000000000000000000000000000000000000000000000000000000571000000000000000000000000000000000000000000000000000000000000057b0000000000000000000000000000000000000000000000000000000000000572000000000000000000000000000000000000000000000000000000000000057c0000000000000000000000000000000000000000000000000000000000000573000000000000000000000000000000000000000000000000000000000000057d0000000000000000000000000000000000000000000000000000000000000574000000000000000000000000000000000000000000000000000000000000057e0000000000000000000000000000000000000000000000000000000000000575000000000000000000000000000000000000000000000000000000000000057f00000000000000000000000000000000000000000000000000000000000005760000000000000000000000000000000000000000000000000000000000000580000000000000000000000000000000000000000000000000000000000000057700000000000000000000000000000000000000000000000000000000000005810000000000000000000000000000000000000000000000000000000000000578000000000000000000000000000000000000000000000000000000000000058200000000000000000000000000000000000000000000000000000000000005790000000000000000000000000000000000000000000000000000000000000583000000000000000000000000000000000000000000000000000000000000057a0000000000000000000000000000000000000000000000000000000000000584000000000000000000000000000000000000000000000000000000000000057b0000000000000000000000000000000000000000000000000000000000000585000000000000000000000000000000000000000000000000000000000000057c0000000000000000000000000000000000000000000000000000000000000586000000000000000000000000000000000000000000000000000000000000057d0000000000000000000000000000000000000000000000000000000000000587000000000000000000000000000000000000000000000000000000000000057e0000000000000000000000000000000000000000000000000000000000000588000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000180000000000000000000000000000000000000000000000000000000000000018100000000000000000000000000000000000000000000000000000000000001820000000000000000000000000000000000000000000000000000000000000183000000000000000000000000000000000000000000000000000000000000018400000000000000000000000000000000000000000000000000000000000001850000000000000000000000000000000000000000000000000000000000000186000000000000000000000000000000000000000000000000000000000000018700000000000000000000000000000000000000000000000000000000000001880000000000000000000000000000000000000000000000000000000000000189000000000000000000000000000000000000000000000000000000000000018a000000000000000000000000000000000000000000000000000000000000018b000000000000000000000000000000000000000000000000000000000000018c000000000000000000000000000000000000000000000000000000000000018d000000000000000000000000000000000000000000000000000000000000018e000000000000000000000000000000000000000000000000000000000000018f0000000000000000000000000000000000000000000000000000000000000190000000000000000000000000000000000000000000000000000000000000019100000000000000000000000000000000000000000000000000000000000001920000000000000000000000000000000000000000000000000000000000000193000000000000000000000000000000000000000000000000000000000000019400000000000000000000000000000000000000000000000000000000000001950000000000000000000000000000000000000000000000000000000000000196000000000000000000000000000000000000000000000000000000000000019700000000000000000000000000000000000000000000000000000000000001980000000000000000000000000000000000000000000000000000000000000199000000000000000000000000000000000000000000000000000000000000019a000000000000000000000000000000000000000000000000000000000000019b000000000000000000000000000000000000000000000000000000000000019c000000000000000000000000000000000000000000000000000000000000019d000000000000000000000000000000000000000000000000000000000000019e000000000000000000000000000000000000000000000000000000000000019f00000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001a100000000000000000000000000000000000000000000000000000000000001a200000000000000000000000000000000000000000000000000000000000001a300000000000000000000000000000000000000000000000000000000000001a400000000000000000000000000000000000000000000000000000000000001a500000000000000000000000000000000000000000000000000000000000001a600000000000000000000000000000000000000000000000000000000000001a700000000000000000000000000000000000000000000000000000000000001a800000000000000000000000000000000000000000000000000000000000001a900000000000000000000000000000000000000000000000000000000000001aa00000000000000000000000000000000000000000000000000000000000001ab00000000000000000000000000000000000000000000000000000000000001ac00000000000000000000000000000000000000000000000000000000000001ad00000000000000000000000000000000000000000000000000000000000001ae00000000000000000000000000000000000000000000000000000000000001af00000000000000000000000000000000000000000000000000000000000001b000000000000000000000000000000000000000000000000000000000000001b100000000000000000000000000000000000000000000000000000000000001b200000000000000000000000000000000000000000000000000000000000001b300000000000000000000000000000000000000000000000000000000000001b400000000000000000000000000000000000000000000000000000000000001b500000000000000000000000000000000000000000000000000000000000001b600000000000000000000000000000000000000000000000000000000000001b700000000000000000000000000000000000000000000000000000000000001b800000000000000000000000000000000000000000000000000000000000001b900000000000000000000000000000000000000000000000000000000000001ba00000000000000000000000000000000000000000000000000000000000001bb00000000000000000000000000000000000000000000000000000000000001bc00000000000000000000000000000000000000000000000000000000000001bd00000000000000000000000000000000000000000000000000000000000001be00000000000000000000000000000000000000000000000000000000000001bf3f0000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000028100000000000000000000000000000000000000000000000000000000000002820000000000000000000000000000000000000000000000000000000000000283000000000000000000000000000000000000000000000000000000000000028400000000000000000000000000000000000000000000000000000000000002850000000000000000000000000000000000000000000000000000000000000286000000000000000000000000000000000000000000000000000000000000028700000000000000000000000000000000000000000000000000000000000002880000000000000000000000000000000000000000000000000000000000000289000000000000000000000000000000000000000000000000000000000000028a000000000000000000000000000000000000000000000000000000000000028b000000000000000000000000000000000000000000000000000000000000028c000000000000000000000000000000000000000000000000000000000000028d000000000000000000000000000000000000000000000000000000000000028e000000000000000000000000000000000000000000000000000000000000028f0000000000000000000000000000000000000000000000000000000000000290000000000000000000000000000000000000000000000000000000000000029100000000000000000000000000000000000000000000000000000000000002920000000000000000000000000000000000000000000000000000000000000293000000000000000000000000000000000000000000000000000000000000029400000000000000000000000000000000000000000000000000000000000002950000000000000000000000000000000000000000000000000000000000000296000000000000000000000000000000000000000000000000000000000000029700000000000000000000000000000000000000000000000000000000000002980000000000000000000000000000000000000000000000000000000000000299000000000000000000000000000000000000000000000000000000000000029a000000000000000000000000000000000000000000000000000000000000029b000000000000000000000000000000000000000000000000000000000000029c000000000000000000000000000000000000000000000000000000000000029d000000000000000000000000000000000000000000000000000000000000029e000000000000000000000000000000000000000000000000000000000000029f00000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000002a100000000000000000000000000000000000000000000000000000000000002a200000000000000000000000000000000000000000000000000000000000002a300000000000000000000000000000000000000000000000000000000000002a400000000000000000000000000000000000000000000000000000000000002a500000000000000000000000000000000000000000000000000000000000002a600000000000000000000000000000000000000000000000000000000000002a700000000000000000000000000000000000000000000000000000000000002a800000000000000000000000000000000000000000000000000000000000002a900000000000000000000000000000000000000000000000000000000000002aa00000000000000000000000000000000000000000000000000000000000002ab00000000000000000000000000000000000000000000000000000000000002ac00000000000000000000000000000000000000000000000000000000000002ad00000000000000000000000000000000000000000000000000000000000002ae00000000000000000000000000000000000000000000000000000000000002af00000000000000000000000000000000000000000000000000000000000002b000000000000000000000000000000000000000000000000000000000000002b100000000000000000000000000000000000000000000000000000000000002b200000000000000000000000000000000000000000000000000000000000002b300000000000000000000000000000000000000000000000000000000000002b400000000000000000000000000000000000000000000000000000000000002b500000000000000000000000000000000000000000000000000000000000002b600000000000000000000000000000000000000000000000000000000000002b700000000000000000000000000000000000000000000000000000000000002b800000000000000000000000000000000000000000000000000000000000002b900000000000000000000000000000000000000000000000000000000000002ba00000000000000000000000000000000000000000000000000000000000002bb00000000000000000000000000000000000000000000000000000000000002bc00000000000000000000000000000000000000000000000000000000000002bd00000000000000000000000000000000000000000000000000000000000002be08000000000000000000000000000000000000000000000000000000000000038000000000000000000000000000000000000000000000000000000000000003810000000000000000000000000000000000000000000000000000000000000382000000000000000000000000000000000000000000000000000000000000038300000000000000000000000000000000000000000000000000000000000003840000000000000000000000000000000000000000000000000000000000000385000000000000000000000000000000000000000000000000000000000000038600000000000000000000000000000000000000000000000000000000000003873f0000000000000000000000000000000000000000000000000000000000000580000000000000000000000000000000000000000000000000000000000000058a0000000000000000000000000000000000000000000000000000000000000581000000000000000000000000000000000000000000000000000000000000058b0000000000000000000000000000000000000000000000000000000000000582000000000000000000000000000000000000000000000000000000000000058c0000000000000000000000000000000000000000000000000000000000000583000000000000000000000000000000000000000000000000000000000000058d0000000000000000000000000000000000000000000000000000000000000584000000000000000000000000000000000000000000000000000000000000058e0000000000000000000000000000000000000000000000000000000000000585000000000000000000000000000000000000000000000000000000000000058f00000000000000000000000000000000000000000000000000000000000005860000000000000000000000000000000000000000000000000000000000000590000000000000000000000000000000000000000000000000000000000000058700000000000000000000000000000000000000000000000000000000000005910000000000000000000000000000000000000000000000000000000000000588000000000000000000000000000000000000000000000000000000000000059200000000000000000000000000000000000000000000000000000000000005890000000000000000000000000000000000000000000000000000000000000593000000000000000000000000000000000000000000000000000000000000058a0000000000000000000000000000000000000000000000000000000000000594000000000000000000000000000000000000000000000000000000000000058b0000000000000000000000000000000000000000000000000000000000000595000000000000000000000000000000000000000000000000000000000000058c0000000000000000000000000000000000000000000000000000000000000596000000000000000000000000000000000000000000000000000000000000058d0000000000000000000000000000000000000000000000000000000000000597000000000000000000000000000000000000000000000000000000000000058e0000000000000000000000000000000000000000000000000000000000000598000000000000000000000000000000000000000000000000000000000000058f00000000000000000000000000000000000000000000000000000000000005990000000000000000000000000000000000000000000000000000000000000590000000000000000000000000000000000000000000000000000000000000059a0000000000000000000000000000000000000000000000000000000000000591000000000000000000000000000000000000000000000000000000000000059b0000000000000000000000000000000000000000000000000000000000000592000000000000000000000000000000000000000000000000000000000000059c0000000000000000000000000000000000000000000000000000000000000593000000000000000000000000000000000000000000000000000000000000059d0000000000000000000000000000000000000000000000000000000000000594000000000000000000000000000000000000000000000000000000000000059e0000000000000000000000000000000000000000000000000000000000000595000000000000000000000000000000000000000000000000000000000000059f000000000000000000000000000000000000000000000000000000000000059600000000000000000000000000000000000000000000000000000000000005a0000000000000000000000000000000000000000000000000000000000000059700000000000000000000000000000000000000000000000000000000000005a1000000000000000000000000000000000000000000000000000000000000059800000000000000000000000000000000000000000000000000000000000005a2000000000000000000000000000000000000000000000000000000000000059900000000000000000000000000000000000000000000000000000000000005a3000000000000000000000000000000000000000000000000000000000000059a00000000000000000000000000000000000000000000000000000000000005a4000000000000000000000000000000000000000000000000000000000000059b00000000000000000000000000000000000000000000000000000000000005a5000000000000000000000000000000000000000000000000000000000000059c00000000000000000000000000000000000000000000000000000000000005a6000000000000000000000000000000000000000000000000000000000000059d00000000000000000000000000000000000000000000000000000000000005a7000000000000000000000000000000000000000000000000000000000000059e00000000000000000000000000000000000000000000000000000000000005a8000000000000000000000000000000000000000000000000000000000000059f00000000000000000000000000000000000000000000000000000000000005a900000000000000000000000000000000000000000000000000000000000005a000000000000000000000000000000000000000000000000000000000000005aa00000000000000000000000000000000000000000000000000000000000005a100000000000000000000000000000000000000000000000000000000000005ab00000000000000000000000000000000000000000000000000000000000005a200000000000000000000000000000000000000000000000000000000000005ac00000000000000000000000000000000000000000000000000000000000005a300000000000000000000000000000000000000000000000000000000000005ad00000000000000000000000000000000000000000000000000000000000005a400000000000000000000000000000000000000000000000000000000000005ae00000000000000000000000000000000000000000000000000000000000005a500000000000000000000000000000000000000000000000000000000000005af00000000000000000000000000000000000000000000000000000000000005a600000000000000000000000000000000000000000000000000000000000005b000000000000000000000000000000000000000000000000000000000000005a700000000000000000000000000000000000000000000000000000000000005b100000000000000000000000000000000000000000000000000000000000005a800000000000000000000000000000000000000000000000000000000000005b200000000000000000000000000000000000000000000000000000000000005a900000000000000000000000000000000000000000000000000000000000005b300000000000000000000000000000000000000000000000000000000000005aa00000000000000000000000000000000000000000000000000000000000005b400000000000000000000000000000000000000000000000000000000000005ab00000000000000000000000000000000000000000000000000000000000005b500000000000000000000000000000000000000000000000000000000000005ac00000000000000000000000000000000000000000000000000000000000005b600000000000000000000000000000000000000000000000000000000000005ad00000000000000000000000000000000000000000000000000000000000005b700000000000000000000000000000000000000000000000000000000000005ae00000000000000000000000000000000000000000000000000000000000005b800000000000000000000000000000000000000000000000000000000000005af00000000000000000000000000000000000000000000000000000000000005b900000000000000000000000000000000000000000000000000000000000005b000000000000000000000000000000000000000000000000000000000000005ba00000000000000000000000000000000000000000000000000000000000005b100000000000000000000000000000000000000000000000000000000000005bb00000000000000000000000000000000000000000000000000000000000005b200000000000000000000000000000000000000000000000000000000000005bc00000000000000000000000000000000000000000000000000000000000005b300000000000000000000000000000000000000000000000000000000000005bd00000000000000000000000000000000000000000000000000000000000005b400000000000000000000000000000000000000000000000000000000000005be00000000000000000000000000000000000000000000000000000000000005b500000000000000000000000000000000000000000000000000000000000005bf00000000000000000000000000000000000000000000000000000000000005b600000000000000000000000000000000000000000000000000000000000005c000000000000000000000000000000000000000000000000000000000000005b700000000000000000000000000000000000000000000000000000000000005c100000000000000000000000000000000000000000000000000000000000005b800000000000000000000000000000000000000000000000000000000000005c200000000000000000000000000000000000000000000000000000000000005b900000000000000000000000000000000000000000000000000000000000005c300000000000000000000000000000000000000000000000000000000000005ba00000000000000000000000000000000000000000000000000000000000005c400000000000000000000000000000000000000000000000000000000000005bb00000000000000000000000000000000000000000000000000000000000005c500000000000000000000000000000000000000000000000000000000000005bc00000000000000000000000000000000000000000000000000000000000005c600000000000000000000000000000000000000000000000000000000000005bd00000000000000000000000000000000000000000000000000000000000005c700000000000000000000000000000000000000000000000000000000000005be00000000000000000000000000000000000000000000000000000000000005c80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000001c100000000000000000000000000000000000000000000000000000000000001c200000000000000000000000000000000000000000000000000000000000001c300000000000000000000000000000000000000000000000000000000000001c400000000000000000000000000000000000000000000000000000000000001c500000000000000000000000000000000000000000000000000000000000001c600000000000000000000000000000000000000000000000000000000000001c700000000000000000000000000000000000000000000000000000000000001c800000000000000000000000000000000000000000000000000000000000001c900000000000000000000000000000000000000000000000000000000000001ca00000000000000000000000000000000000000000000000000000000000001cb00000000000000000000000000000000000000000000000000000000000001cc00000000000000000000000000000000000000000000000000000000000001cd00000000000000000000000000000000000000000000000000000000000001ce00000000000000000000000000000000000000000000000000000000000001cf00000000000000000000000000000000000000000000000000000000000001d000000000000000000000000000000000000000000000000000000000000001d100000000000000000000000000000000000000000000000000000000000001d200000000000000000000000000000000000000000000000000000000000001d300000000000000000000000000000000000000000000000000000000000001d400000000000000000000000000000000000000000000000000000000000001d500000000000000000000000000000000000000000000000000000000000001d600000000000000000000000000000000000000000000000000000000000001d700000000000000000000000000000000000000000000000000000000000001d800000000000000000000000000000000000000000000000000000000000001d900000000000000000000000000000000000000000000000000000000000001da00000000000000000000000000000000000000000000000000000000000001db00000000000000000000000000000000000000000000000000000000000001dc00000000000000000000000000000000000000000000000000000000000001dd00000000000000000000000000000000000000000000000000000000000001de00000000000000000000000000000000000000000000000000000000000001df00000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000001e100000000000000000000000000000000000000000000000000000000000001e200000000000000000000000000000000000000000000000000000000000001e300000000000000000000000000000000000000000000000000000000000001e400000000000000000000000000000000000000000000000000000000000001e500000000000000000000000000000000000000000000000000000000000001e600000000000000000000000000000000000000000000000000000000000001e700000000000000000000000000000000000000000000000000000000000001e800000000000000000000000000000000000000000000000000000000000001e900000000000000000000000000000000000000000000000000000000000001ea00000000000000000000000000000000000000000000000000000000000001eb00000000000000000000000000000000000000000000000000000000000001ec00000000000000000000000000000000000000000000000000000000000001ed00000000000000000000000000000000000000000000000000000000000001ee00000000000000000000000000000000000000000000000000000000000001ef00000000000000000000000000000000000000000000000000000000000001f000000000000000000000000000000000000000000000000000000000000001f100000000000000000000000000000000000000000000000000000000000001f200000000000000000000000000000000000000000000000000000000000001f300000000000000000000000000000000000000000000000000000000000001f400000000000000000000000000000000000000000000000000000000000001f500000000000000000000000000000000000000000000000000000000000001f600000000000000000000000000000000000000000000000000000000000001f700000000000000000000000000000000000000000000000000000000000001f800000000000000000000000000000000000000000000000000000000000001f900000000000000000000000000000000000000000000000000000000000001fa00000000000000000000000000000000000000000000000000000000000001fb00000000000000000000000000000000000000000000000000000000000001fc00000000000000000000000000000000000000000000000000000000000001fd00000000000000000000000000000000000000000000000000000000000001fe00000000000000000000000000000000000000000000000000000000000001ff3f00000000000000000000000000000000000000000000000000000000000002c000000000000000000000000000000000000000000000000000000000000002c100000000000000000000000000000000000000000000000000000000000002c200000000000000000000000000000000000000000000000000000000000002c300000000000000000000000000000000000000000000000000000000000002c400000000000000000000000000000000000000000000000000000000000002c500000000000000000000000000000000000000000000000000000000000002c600000000000000000000000000000000000000000000000000000000000002c700000000000000000000000000000000000000000000000000000000000002c800000000000000000000000000000000000000000000000000000000000002c900000000000000000000000000000000000000000000000000000000000002ca00000000000000000000000000000000000000000000000000000000000002cb00000000000000000000000000000000000000000000000000000000000002cc00000000000000000000000000000000000000000000000000000000000002cd00000000000000000000000000000000000000000000000000000000000002ce00000000000000000000000000000000000000000000000000000000000002cf00000000000000000000000000000000000000000000000000000000000002d000000000000000000000000000000000000000000000000000000000000002d100000000000000000000000000000000000000000000000000000000000002d200000000000000000000000000000000000000000000000000000000000002d300000000000000000000000000000000000000000000000000000000000002d400000000000000000000000000000000000000000000000000000000000002d500000000000000000000000000000000000000000000000000000000000002d600000000000000000000000000000000000000000000000000000000000002d700000000000000000000000000000000000000000000000000000000000002d800000000000000000000000000000000000000000000000000000000000002d900000000000000000000000000000000000000000000000000000000000002da00000000000000000000000000000000000000000000000000000000000002db00000000000000000000000000000000000000000000000000000000000002dc00000000000000000000000000000000000000000000000000000000000002dd00000000000000000000000000000000000000000000000000000000000002de00000000000000000000000000000000000000000000000000000000000002df00000000000000000000000000000000000000000000000000000000000002e000000000000000000000000000000000000000000000000000000000000002e100000000000000000000000000000000000000000000000000000000000002e200000000000000000000000000000000000000000000000000000000000002e300000000000000000000000000000000000000000000000000000000000002e400000000000000000000000000000000000000000000000000000000000002e500000000000000000000000000000000000000000000000000000000000002e600000000000000000000000000000000000000000000000000000000000002e700000000000000000000000000000000000000000000000000000000000002e800000000000000000000000000000000000000000000000000000000000002e900000000000000000000000000000000000000000000000000000000000002ea00000000000000000000000000000000000000000000000000000000000002eb00000000000000000000000000000000000000000000000000000000000002ec00000000000000000000000000000000000000000000000000000000000002ed00000000000000000000000000000000000000000000000000000000000002ee00000000000000000000000000000000000000000000000000000000000002ef00000000000000000000000000000000000000000000000000000000000002f000000000000000000000000000000000000000000000000000000000000002f100000000000000000000000000000000000000000000000000000000000002f200000000000000000000000000000000000000000000000000000000000002f300000000000000000000000000000000000000000000000000000000000002f400000000000000000000000000000000000000000000000000000000000002f500000000000000000000000000000000000000000000000000000000000002f600000000000000000000000000000000000000000000000000000000000002f700000000000000000000000000000000000000000000000000000000000002f800000000000000000000000000000000000000000000000000000000000002f900000000000000000000000000000000000000000000000000000000000002fa00000000000000000000000000000000000000000000000000000000000002fb00000000000000000000000000000000000000000000000000000000000002fc00000000000000000000000000000000000000000000000000000000000002fd00000000000000000000000000000000000000000000000000000000000002fe0800000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000003c100000000000000000000000000000000000000000000000000000000000003c200000000000000000000000000000000000000000000000000000000000003c300000000000000000000000000000000000000000000000000000000000003c400000000000000000000000000000000000000000000000000000000000003c500000000000000000000000000000000000000000000000000000000000003c600000000000000000000000000000000000000000000000000000000000003c73f00000000000000000000000000000000000000000000000000000000000005c000000000000000000000000000000000000000000000000000000000000005ca00000000000000000000000000000000000000000000000000000000000005c100000000000000000000000000000000000000000000000000000000000005cb00000000000000000000000000000000000000000000000000000000000005c200000000000000000000000000000000000000000000000000000000000005cc00000000000000000000000000000000000000000000000000000000000005c300000000000000000000000000000000000000000000000000000000000005cd00000000000000000000000000000000000000000000000000000000000005c400000000000000000000000000000000000000000000000000000000000005ce00000000000000000000000000000000000000000000000000000000000005c500000000000000000000000000000000000000000000000000000000000005cf00000000000000000000000000000000000000000000000000000000000005c600000000000000000000000000000000000000000000000000000000000005d000000000000000000000000000000000000000000000000000000000000005c700000000000000000000000000000000000000000000000000000000000005d100000000000000000000000000000000000000000000000000000000000005c800000000000000000000000000000000000000000000000000000000000005d200000000000000000000000000000000000000000000000000000000000005c900000000000000000000000000000000000000000000000000000000000005d300000000000000000000000000000000000000000000000000000000000005ca00000000000000000000000000000000000000000000000000000000000005d400000000000000000000000000000000000000000000000000000000000005cb00000000000000000000000000000000000000000000000000000000000005d500000000000000000000000000000000000000000000000000000000000005cc00000000000000000000000000000000000000000000000000000000000005d600000000000000000000000000000000000000000000000000000000000005cd00000000000000000000000000000000000000000000000000000000000005d700000000000000000000000000000000000000000000000000000000000005ce00000000000000000000000000000000000000000000000000000000000005d800000000000000000000000000000000000000000000000000000000000005cf00000000000000000000000000000000000000000000000000000000000005d900000000000000000000000000000000000000000000000000000000000005d000000000000000000000000000000000000000000000000000000000000005da00000000000000000000000000000000000000000000000000000000000005d100000000000000000000000000000000000000000000000000000000000005db00000000000000000000000000000000000000000000000000000000000005d200000000000000000000000000000000000000000000000000000000000005dc00000000000000000000000000000000000000000000000000000000000005d300000000000000000000000000000000000000000000000000000000000005dd00000000000000000000000000000000000000000000000000000000000005d400000000000000000000000000000000000000000000000000000000000005de00000000000000000000000000000000000000000000000000000000000005d500000000000000000000000000000000000000000000000000000000000005df00000000000000000000000000000000000000000000000000000000000005d600000000000000000000000000000000000000000000000000000000000005e000000000000000000000000000000000000000000000000000000000000005d700000000000000000000000000000000000000000000000000000000000005e100000000000000000000000000000000000000000000000000000000000005d800000000000000000000000000000000000000000000000000000000000005e200000000000000000000000000000000000000000000000000000000000005d900000000000000000000000000000000000000000000000000000000000005e300000000000000000000000000000000000000000000000000000000000005da00000000000000000000000000000000000000000000000000000000000005e400000000000000000000000000000000000000000000000000000000000005db00000000000000000000000000000000000000000000000000000000000005e500000000000000000000000000000000000000000000000000000000000005dc00000000000000000000000000000000000000000000000000000000000005e600000000000000000000000000000000000000000000000000000000000005dd00000000000000000000000000000000000000000000000000000000000005e700000000000000000000000000000000000000000000000000000000000005de00000000000000000000000000000000000000000000000000000000000005e800000000000000000000000000000000000000000000000000000000000005df00000000000000000000000000000000000000000000000000000000000005e900000000000000000000000000000000000000000000000000000000000005e000000000000000000000000000000000000000000000000000000000000005ea00000000000000000000000000000000000000000000000000000000000005e100000000000000000000000000000000000000000000000000000000000005eb00000000000000000000000000000000000000000000000000000000000005e200000000000000000000000000000000000000000000000000000000000005ec00000000000000000000000000000000000000000000000000000000000005e300000000000000000000000000000000000000000000000000000000000005ed00000000000000000000000000000000000000000000000000000000000005e400000000000000000000000000000000000000000000000000000000000005ee00000000000000000000000000000000000000000000000000000000000005e500000000000000000000000000000000000000000000000000000000000005ef00000000000000000000000000000000000000000000000000000000000005e600000000000000000000000000000000000000000000000000000000000005f000000000000000000000000000000000000000000000000000000000000005e700000000000000000000000000000000000000000000000000000000000005f100000000000000000000000000000000000000000000000000000000000005e800000000000000000000000000000000000000000000000000000000000005f200000000000000000000000000000000000000000000000000000000000005e900000000000000000000000000000000000000000000000000000000000005f300000000000000000000000000000000000000000000000000000000000005ea00000000000000000000000000000000000000000000000000000000000005f400000000000000000000000000000000000000000000000000000000000005eb00000000000000000000000000000000000000000000000000000000000005f500000000000000000000000000000000000000000000000000000000000005ec00000000000000000000000000000000000000000000000000000000000005f600000000000000000000000000000000000000000000000000000000000005ed00000000000000000000000000000000000000000000000000000000000005f700000000000000000000000000000000000000000000000000000000000005ee00000000000000000000000000000000000000000000000000000000000005f800000000000000000000000000000000000000000000000000000000000005ef00000000000000000000000000000000000000000000000000000000000005f900000000000000000000000000000000000000000000000000000000000005f000000000000000000000000000000000000000000000000000000000000005fa00000000000000000000000000000000000000000000000000000000000005f100000000000000000000000000000000000000000000000000000000000005fb00000000000000000000000000000000000000000000000000000000000005f200000000000000000000000000000000000000000000000000000000000005fc00000000000000000000000000000000000000000000000000000000000005f300000000000000000000000000000000000000000000000000000000000005fd00000000000000000000000000000000000000000000000000000000000005f400000000000000000000000000000000000000000000000000000000000005fe00000000000000000000000000000000000000000000000000000000000005f500000000000000000000000000000000000000000000000000000000000005ff00000000000000000000000000000000000000000000000000000000000005f6000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000005f7000000000000000000000000000000000000000000000000000000000000060100000000000000000000000000000000000000000000000000000000000005f8000000000000000000000000000000000000000000000000000000000000060200000000000000000000000000000000000000000000000000000000000005f9000000000000000000000000000000000000000000000000000000000000060300000000000000000000000000000000000000000000000000000000000005fa000000000000000000000000000000000000000000000000000000000000060400000000000000000000000000000000000000000000000000000000000005fb000000000000000000000000000000000000000000000000000000000000060500000000000000000000000000000000000000000000000000000000000005fc000000000000000000000000000000000000000000000000000000000000060600000000000000000000000000000000000000000000000000000000000005fd000000000000000000000000000000000000000000000000000000000000060700000000000000000000000000000000000000000000000000000000000005fe0000000000000000000000000000000000000000000000000000000000000608000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020100000000000000000000000000000000000000000000000000000000000002020000000000000000000000000000000000000000000000000000000000000203000000000000000000000000000000000000000000000000000000000000020400000000000000000000000000000000000000000000000000000000000002050000000000000000000000000000000000000000000000000000000000000206000000000000000000000000000000000000000000000000000000000000020700000000000000000000000000000000000000000000000000000000000002080000000000000000000000000000000000000000000000000000000000000209000000000000000000000000000000000000000000000000000000000000020a000000000000000000000000000000000000000000000000000000000000020b000000000000000000000000000000000000000000000000000000000000020c000000000000000000000000000000000000000000000000000000000000020d000000000000000000000000000000000000000000000000000000000000020e000000000000000000000000000000000000000000000000000000000000020f0000000000000000000000000000000000000000000000000000000000000210000000000000000000000000000000000000000000000000000000000000021100000000000000000000000000000000000000000000000000000000000002120000000000000000000000000000000000000000000000000000000000000213000000000000000000000000000000000000000000000000000000000000021400000000000000000000000000000000000000000000000000000000000002150000000000000000000000000000000000000000000000000000000000000216000000000000000000000000000000000000000000000000000000000000021700000000000000000000000000000000000000000000000000000000000002180000000000000000000000000000000000000000000000000000000000000219000000000000000000000000000000000000000000000000000000000000021a000000000000000000000000000000000000000000000000000000000000021b000000000000000000000000000000000000000000000000000000000000021c000000000000000000000000000000000000000000000000000000000000021d000000000000000000000000000000000000000000000000000000000000021e000000000000000000000000000000000000000000000000000000000000021f0000000000000000000000000000000000000000000000000000000000000220000000000000000000000000000000000000000000000000000000000000022100000000000000000000000000000000000000000000000000000000000002220000000000000000000000000000000000000000000000000000000000000223000000000000000000000000000000000000000000000000000000000000022400000000000000000000000000000000000000000000000000000000000002250000000000000000000000000000000000000000000000000000000000000226000000000000000000000000000000000000000000000000000000000000022700000000000000000000000000000000000000000000000000000000000002280000000000000000000000000000000000000000000000000000000000000229000000000000000000000000000000000000000000000000000000000000022a000000000000000000000000000000000000000000000000000000000000022b000000000000000000000000000000000000000000000000000000000000022c000000000000000000000000000000000000000000000000000000000000022d000000000000000000000000000000000000000000000000000000000000022e000000000000000000000000000000000000000000000000000000000000022f0000000000000000000000000000000000000000000000000000000000000230000000000000000000000000000000000000000000000000000000000000023100000000000000000000000000000000000000000000000000000000000002320000000000000000000000000000000000000000000000000000000000000233000000000000000000000000000000000000000000000000000000000000023400000000000000000000000000000000000000000000000000000000000002350000000000000000000000000000000000000000000000000000000000000236000000000000000000000000000000000000000000000000000000000000023700000000000000000000000000000000000000000000000000000000000002380000000000000000000000000000000000000000000000000000000000000239000000000000000000000000000000000000000000000000000000000000023a000000000000000000000000000000000000000000000000000000000000023b000000000000000000000000000000000000000000000000000000000000023c000000000000000000000000000000000000000000000000000000000000023d000000000000000000000000000000000000000000000000000000000000023e000000000000000000000000000000000000000000000000000000000000023f3f0000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000030100000000000000000000000000000000000000000000000000000000000003020000000000000000000000000000000000000000000000000000000000000303000000000000000000000000000000000000000000000000000000000000030400000000000000000000000000000000000000000000000000000000000003050000000000000000000000000000000000000000000000000000000000000306000000000000000000000000000000000000000000000000000000000000030700000000000000000000000000000000000000000000000000000000000003080000000000000000000000000000000000000000000000000000000000000309000000000000000000000000000000000000000000000000000000000000030a000000000000000000000000000000000000000000000000000000000000030b000000000000000000000000000000000000000000000000000000000000030c000000000000000000000000000000000000000000000000000000000000030d000000000000000000000000000000000000000000000000000000000000030e000000000000000000000000000000000000000000000000000000000000030f0000000000000000000000000000000000000000000000000000000000000310000000000000000000000000000000000000000000000000000000000000031100000000000000000000000000000000000000000000000000000000000003120000000000000000000000000000000000000000000000000000000000000313000000000000000000000000000000000000000000000000000000000000031400000000000000000000000000000000000000000000000000000000000003150000000000000000000000000000000000000000000000000000000000000316000000000000000000000000000000000000000000000000000000000000031700000000000000000000000000000000000000000000000000000000000003180000000000000000000000000000000000000000000000000000000000000319000000000000000000000000000000000000000000000000000000000000031a000000000000000000000000000000000000000000000000000000000000031b000000000000000000000000000000000000000000000000000000000000031c000000000000000000000000000000000000000000000000000000000000031d000000000000000000000000000000000000000000000000000000000000031e000000000000000000000000000000000000000000000000000000000000031f0000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000032100000000000000000000000000000000000000000000000000000000000003220000000000000000000000000000000000000000000000000000000000000323000000000000000000000000000000000000000000000000000000000000032400000000000000000000000000000000000000000000000000000000000003250000000000000000000000000000000000000000000000000000000000000326000000000000000000000000000000000000000000000000000000000000032700000000000000000000000000000000000000000000000000000000000003280000000000000000000000000000000000000000000000000000000000000329000000000000000000000000000000000000000000000000000000000000032a000000000000000000000000000000000000000000000000000000000000032b000000000000000000000000000000000000000000000000000000000000032c000000000000000000000000000000000000000000000000000000000000032d000000000000000000000000000000000000000000000000000000000000032e000000000000000000000000000000000000000000000000000000000000032f0000000000000000000000000000000000000000000000000000000000000330000000000000000000000000000000000000000000000000000000000000033100000000000000000000000000000000000000000000000000000000000003320000000000000000000000000000000000000000000000000000000000000333000000000000000000000000000000000000000000000000000000000000033400000000000000000000000000000000000000000000000000000000000003350000000000000000000000000000000000000000000000000000000000000336000000000000000000000000000000000000000000000000000000000000033700000000000000000000000000000000000000000000000000000000000003380000000000000000000000000000000000000000000000000000000000000339000000000000000000000000000000000000000000000000000000000000033a000000000000000000000000000000000000000000000000000000000000033b000000000000000000000000000000000000000000000000000000000000033c000000000000000000000000000000000000000000000000000000000000033d000000000000000000000000000000000000000000000000000000000000033e08000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000004010000000000000000000000000000000000000000000000000000000000000402000000000000000000000000000000000000000000000000000000000000040300000000000000000000000000000000000000000000000000000000000004040000000000000000000000000000000000000000000000000000000000000405000000000000000000000000000000000000000000000000000000000000040600000000000000000000000000000000000000000000000000000000000004073f0000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000060a0000000000000000000000000000000000000000000000000000000000000601000000000000000000000000000000000000000000000000000000000000060b0000000000000000000000000000000000000000000000000000000000000602000000000000000000000000000000000000000000000000000000000000060c0000000000000000000000000000000000000000000000000000000000000603000000000000000000000000000000000000000000000000000000000000060d0000000000000000000000000000000000000000000000000000000000000604000000000000000000000000000000000000000000000000000000000000060e0000000000000000000000000000000000000000000000000000000000000605000000000000000000000000000000000000000000000000000000000000060f00000000000000000000000000000000000000000000000000000000000006060000000000000000000000000000000000000000000000000000000000000610000000000000000000000000000000000000000000000000000000000000060700000000000000000000000000000000000000000000000000000000000006110000000000000000000000000000000000000000000000000000000000000608000000000000000000000000000000000000000000000000000000000000061200000000000000000000000000000000000000000000000000000000000006090000000000000000000000000000000000000000000000000000000000000613000000000000000000000000000000000000000000000000000000000000060a0000000000000000000000000000000000000000000000000000000000000614000000000000000000000000000000000000000000000000000000000000060b0000000000000000000000000000000000000000000000000000000000000615000000000000000000000000000000000000000000000000000000000000060c0000000000000000000000000000000000000000000000000000000000000616000000000000000000000000000000000000000000000000000000000000060d0000000000000000000000000000000000000000000000000000000000000617000000000000000000000000000000000000000000000000000000000000060e0000000000000000000000000000000000000000000000000000000000000618000000000000000000000000000000000000000000000000000000000000060f00000000000000000000000000000000000000000000000000000000000006190000000000000000000000000000000000000000000000000000000000000610000000000000000000000000000000000000000000000000000000000000061a0000000000000000000000000000000000000000000000000000000000000611000000000000000000000000000000000000000000000000000000000000061b0000000000000000000000000000000000000000000000000000000000000612000000000000000000000000000000000000000000000000000000000000061c0000000000000000000000000000000000000000000000000000000000000613000000000000000000000000000000000000000000000000000000000000061d0000000000000000000000000000000000000000000000000000000000000614000000000000000000000000000000000000000000000000000000000000061e0000000000000000000000000000000000000000000000000000000000000615000000000000000000000000000000000000000000000000000000000000061f00000000000000000000000000000000000000000000000000000000000006160000000000000000000000000000000000000000000000000000000000000620000000000000000000000000000000000000000000000000000000000000061700000000000000000000000000000000000000000000000000000000000006210000000000000000000000000000000000000000000000000000000000000618000000000000000000000000000000000000000000000000000000000000062200000000000000000000000000000000000000000000000000000000000006190000000000000000000000000000000000000000000000000000000000000623000000000000000000000000000000000000000000000000000000000000061a0000000000000000000000000000000000000000000000000000000000000624000000000000000000000000000000000000000000000000000000000000061b0000000000000000000000000000000000000000000000000000000000000625000000000000000000000000000000000000000000000000000000000000061c0000000000000000000000000000000000000000000000000000000000000626000000000000000000000000000000000000000000000000000000000000061d0000000000000000000000000000000000000000000000000000000000000627000000000000000000000000000000000000000000000000000000000000061e0000000000000000000000000000000000000000000000000000000000000628000000000000000000000000000000000000000000000000000000000000061f00000000000000000000000000000000000000000000000000000000000006290000000000000000000000000000000000000000000000000000000000000620000000000000000000000000000000000000000000000000000000000000062a0000000000000000000000000000000000000000000000000000000000000621000000000000000000000000000000000000000000000000000000000000062b0000000000000000000000000000000000000000000000000000000000000622000000000000000000000000000000000000000000000000000000000000062c0000000000000000000000000000000000000000000000000000000000000623000000000000000000000000000000000000000000000000000000000000062d0000000000000000000000000000000000000000000000000000000000000624000000000000000000000000000000000000000000000000000000000000062e0000000000000000000000000000000000000000000000000000000000000625000000000000000000000000000000000000000000000000000000000000062f00000000000000000000000000000000000000000000000000000000000006260000000000000000000000000000000000000000000000000000000000000630000000000000000000000000000000000000000000000000000000000000062700000000000000000000000000000000000000000000000000000000000006310000000000000000000000000000000000000000000000000000000000000628000000000000000000000000000000000000000000000000000000000000063200000000000000000000000000000000000000000000000000000000000006290000000000000000000000000000000000000000000000000000000000000633000000000000000000000000000000000000000000000000000000000000062a0000000000000000000000000000000000000000000000000000000000000634000000000000000000000000000000000000000000000000000000000000062b0000000000000000000000000000000000000000000000000000000000000635000000000000000000000000000000000000000000000000000000000000062c0000000000000000000000000000000000000000000000000000000000000636000000000000000000000000000000000000000000000000000000000000062d0000000000000000000000000000000000000000000000000000000000000637000000000000000000000000000000000000000000000000000000000000062e0000000000000000000000000000000000000000000000000000000000000638000000000000000000000000000000000000000000000000000000000000062f00000000000000000000000000000000000000000000000000000000000006390000000000000000000000000000000000000000000000000000000000000630000000000000000000000000000000000000000000000000000000000000063a0000000000000000000000000000000000000000000000000000000000000631000000000000000000000000000000000000000000000000000000000000063b0000000000000000000000000000000000000000000000000000000000000632000000000000000000000000000000000000000000000000000000000000063c0000000000000000000000000000000000000000000000000000000000000633000000000000000000000000000000000000000000000000000000000000063d0000000000000000000000000000000000000000000000000000000000000634000000000000000000000000000000000000000000000000000000000000063e0000000000000000000000000000000000000000000000000000000000000635000000000000000000000000000000000000000000000000000000000000063f00000000000000000000000000000000000000000000000000000000000006360000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000000000063700000000000000000000000000000000000000000000000000000000000006410000000000000000000000000000000000000000000000000000000000000638000000000000000000000000000000000000000000000000000000000000064200000000000000000000000000000000000000000000000000000000000006390000000000000000000000000000000000000000000000000000000000000643000000000000000000000000000000000000000000000000000000000000063a0000000000000000000000000000000000000000000000000000000000000644000000000000000000000000000000000000000000000000000000000000063b0000000000000000000000000000000000000000000000000000000000000645000000000000000000000000000000000000000000000000000000000000063c0000000000000000000000000000000000000000000000000000000000000646000000000000000000000000000000000000000000000000000000000000063d0000000000000000000000000000000000000000000000000000000000000647000000000000000000000000000000000000000000000000000000000000063e0000000000000000000000000000000000000000000000000000000000000648000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "txsEffectsHash": "0x006e4c1d10533ea35e67118a58a08e56c1c799d33ae60046b88aeb76bc5974a3", "decodedHeader": { "contentCommitment": { "inHash": "0x00089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c", "outHash": "0x0071556a0e9f403540d572c98a081d21b325e7c802b8b3baf54f3d56fecb2230", - "txTreeHeight": 2, + "numTxs": 4, "txsEffectsHash": "0x006e4c1d10533ea35e67118a58a08e56c1c799d33ae60046b88aeb76bc5974a3" }, "globalVariables": { @@ -73,8 +73,8 @@ "chainId": 31337, "timestamp": 0, "version": 1, - "coinbase": "0xcb460eb6cb460eb6cb460eb6cb460eb6cb460eb6", - "feeRecipient": "0x0cacc1f59212369f15989d55449e2460f787453f9a729749d363f4eee29d4c8c", + "coinbase": "0x38e74ed15dd5ab05fff041b5037372cce88aa7e9", + "feeRecipient": "0x1bf48a8c128750df4186da470571948ac0d14d79b3de69978f5a779fbdf547be", "gasFees": { "feePerDaGas": 0, "feePerL2Gas": 0 @@ -105,8 +105,8 @@ } } }, - "header": "0x0afb332dff10b3b4221c5c26ead8202d94bb977f644c91b06dec3ee098acc2b6000000010000000000000000000000000000000000000000000000000000000000000002006e4c1d10533ea35e67118a58a08e56c1c799d33ae60046b88aeb76bc5974a300089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c0071556a0e9f403540d572c98a081d21b325e7c802b8b3baf54f3d56fecb22301864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f80000000100d944282e11bdcfa5e8f2b55fe80db4c586087bfc10e0bbba5724d30b8c15e2e0000010001c16141039343d4d403501e66deecff1b024bd76794820a43dc3424087813a2000001802f72d4fe80aa0b43708532e4fb05cdf574bfd36c8c6bba1ff4ec3c6e0ffc9b3a000001800000000000000000000000000000000000000000000000000000000000007a69000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000cb460eb6cb460eb6cb460eb6cb460eb6cb460eb60cacc1f59212369f15989d55449e2460f787453f9a729749d363f4eee29d4c8c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "publicInputsHash": "0x00c13e59e7ffaa51e87daa6e5e2983fa353c47ff1883bfef731b9e784ade8399", + "header": "0x0afb332dff10b3b4221c5c26ead8202d94bb977f644c91b06dec3ee098acc2b6000000010000000000000000000000000000000000000000000000000000000000000004006e4c1d10533ea35e67118a58a08e56c1c799d33ae60046b88aeb76bc5974a300089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c0071556a0e9f403540d572c98a081d21b325e7c802b8b3baf54f3d56fecb22301864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f80000000100d944282e11bdcfa5e8f2b55fe80db4c586087bfc10e0bbba5724d30b8c15e2e0000010001c16141039343d4d403501e66deecff1b024bd76794820a43dc3424087813a2000001802f72d4fe80aa0b43708532e4fb05cdf574bfd36c8c6bba1ff4ec3c6e0ffc9b3a000001800000000000000000000000000000000000000000000000000000000000007a6900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000038e74ed15dd5ab05fff041b5037372cce88aa7e91bf48a8c128750df4186da470571948ac0d14d79b3de69978f5a779fbdf547be000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "publicInputsHash": "0x0086d49b8b947a0b784ea6e86697292895d7f54a547fa954ab820140274340d4", "numTxs": 4 } } \ No newline at end of file diff --git a/l1-contracts/test/fixtures/mixed_block_1.json b/l1-contracts/test/fixtures/mixed_block_1.json index 62963048eb1..b3d023bdcda 100644 --- a/l1-contracts/test/fixtures/mixed_block_1.json +++ b/l1-contracts/test/fixtures/mixed_block_1.json @@ -58,23 +58,23 @@ ] }, "block": { - "archive": "0x1782e665d3991213a60e4add07b2bdf3c49bd81f93ca6ca1d79da91b937cebb2", + "archive": "0x0796e4e2dcd2e9d783732a42084fd8fd79acd7bbc7e9d511f5d0c59d4de6aa80", "body": "0x00000004000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000240000000000000000000000000000000000000000000000000000000000000024100000000000000000000000000000000000000000000000000000000000002420000000000000000000000000000000000000000000000000000000000000243000000000000000000000000000000000000000000000000000000000000024400000000000000000000000000000000000000000000000000000000000002450000000000000000000000000000000000000000000000000000000000000246000000000000000000000000000000000000000000000000000000000000024700000000000000000000000000000000000000000000000000000000000002480000000000000000000000000000000000000000000000000000000000000249000000000000000000000000000000000000000000000000000000000000024a000000000000000000000000000000000000000000000000000000000000024b000000000000000000000000000000000000000000000000000000000000024c000000000000000000000000000000000000000000000000000000000000024d000000000000000000000000000000000000000000000000000000000000024e000000000000000000000000000000000000000000000000000000000000024f0000000000000000000000000000000000000000000000000000000000000250000000000000000000000000000000000000000000000000000000000000025100000000000000000000000000000000000000000000000000000000000002520000000000000000000000000000000000000000000000000000000000000253000000000000000000000000000000000000000000000000000000000000025400000000000000000000000000000000000000000000000000000000000002550000000000000000000000000000000000000000000000000000000000000256000000000000000000000000000000000000000000000000000000000000025700000000000000000000000000000000000000000000000000000000000002580000000000000000000000000000000000000000000000000000000000000259000000000000000000000000000000000000000000000000000000000000025a000000000000000000000000000000000000000000000000000000000000025b000000000000000000000000000000000000000000000000000000000000025c000000000000000000000000000000000000000000000000000000000000025d000000000000000000000000000000000000000000000000000000000000025e000000000000000000000000000000000000000000000000000000000000025f0000000000000000000000000000000000000000000000000000000000000260000000000000000000000000000000000000000000000000000000000000026100000000000000000000000000000000000000000000000000000000000002620000000000000000000000000000000000000000000000000000000000000263000000000000000000000000000000000000000000000000000000000000026400000000000000000000000000000000000000000000000000000000000002650000000000000000000000000000000000000000000000000000000000000266000000000000000000000000000000000000000000000000000000000000026700000000000000000000000000000000000000000000000000000000000002680000000000000000000000000000000000000000000000000000000000000269000000000000000000000000000000000000000000000000000000000000026a000000000000000000000000000000000000000000000000000000000000026b000000000000000000000000000000000000000000000000000000000000026c000000000000000000000000000000000000000000000000000000000000026d000000000000000000000000000000000000000000000000000000000000026e000000000000000000000000000000000000000000000000000000000000026f0000000000000000000000000000000000000000000000000000000000000270000000000000000000000000000000000000000000000000000000000000027100000000000000000000000000000000000000000000000000000000000002720000000000000000000000000000000000000000000000000000000000000273000000000000000000000000000000000000000000000000000000000000027400000000000000000000000000000000000000000000000000000000000002750000000000000000000000000000000000000000000000000000000000000276000000000000000000000000000000000000000000000000000000000000027700000000000000000000000000000000000000000000000000000000000002780000000000000000000000000000000000000000000000000000000000000279000000000000000000000000000000000000000000000000000000000000027a000000000000000000000000000000000000000000000000000000000000027b000000000000000000000000000000000000000000000000000000000000027c000000000000000000000000000000000000000000000000000000000000027d000000000000000000000000000000000000000000000000000000000000027e000000000000000000000000000000000000000000000000000000000000027f3f0000000000000000000000000000000000000000000000000000000000000340000000000000000000000000000000000000000000000000000000000000034100000000000000000000000000000000000000000000000000000000000003420000000000000000000000000000000000000000000000000000000000000343000000000000000000000000000000000000000000000000000000000000034400000000000000000000000000000000000000000000000000000000000003450000000000000000000000000000000000000000000000000000000000000346000000000000000000000000000000000000000000000000000000000000034700000000000000000000000000000000000000000000000000000000000003480000000000000000000000000000000000000000000000000000000000000349000000000000000000000000000000000000000000000000000000000000034a000000000000000000000000000000000000000000000000000000000000034b000000000000000000000000000000000000000000000000000000000000034c000000000000000000000000000000000000000000000000000000000000034d000000000000000000000000000000000000000000000000000000000000034e000000000000000000000000000000000000000000000000000000000000034f0000000000000000000000000000000000000000000000000000000000000350000000000000000000000000000000000000000000000000000000000000035100000000000000000000000000000000000000000000000000000000000003520000000000000000000000000000000000000000000000000000000000000353000000000000000000000000000000000000000000000000000000000000035400000000000000000000000000000000000000000000000000000000000003550000000000000000000000000000000000000000000000000000000000000356000000000000000000000000000000000000000000000000000000000000035700000000000000000000000000000000000000000000000000000000000003580000000000000000000000000000000000000000000000000000000000000359000000000000000000000000000000000000000000000000000000000000035a000000000000000000000000000000000000000000000000000000000000035b000000000000000000000000000000000000000000000000000000000000035c000000000000000000000000000000000000000000000000000000000000035d000000000000000000000000000000000000000000000000000000000000035e000000000000000000000000000000000000000000000000000000000000035f0000000000000000000000000000000000000000000000000000000000000360000000000000000000000000000000000000000000000000000000000000036100000000000000000000000000000000000000000000000000000000000003620000000000000000000000000000000000000000000000000000000000000363000000000000000000000000000000000000000000000000000000000000036400000000000000000000000000000000000000000000000000000000000003650000000000000000000000000000000000000000000000000000000000000366000000000000000000000000000000000000000000000000000000000000036700000000000000000000000000000000000000000000000000000000000003680000000000000000000000000000000000000000000000000000000000000369000000000000000000000000000000000000000000000000000000000000036a000000000000000000000000000000000000000000000000000000000000036b000000000000000000000000000000000000000000000000000000000000036c000000000000000000000000000000000000000000000000000000000000036d000000000000000000000000000000000000000000000000000000000000036e000000000000000000000000000000000000000000000000000000000000036f0000000000000000000000000000000000000000000000000000000000000370000000000000000000000000000000000000000000000000000000000000037100000000000000000000000000000000000000000000000000000000000003720000000000000000000000000000000000000000000000000000000000000373000000000000000000000000000000000000000000000000000000000000037400000000000000000000000000000000000000000000000000000000000003750000000000000000000000000000000000000000000000000000000000000376000000000000000000000000000000000000000000000000000000000000037700000000000000000000000000000000000000000000000000000000000003780000000000000000000000000000000000000000000000000000000000000379000000000000000000000000000000000000000000000000000000000000037a000000000000000000000000000000000000000000000000000000000000037b000000000000000000000000000000000000000000000000000000000000037c000000000000000000000000000000000000000000000000000000000000037d000000000000000000000000000000000000000000000000000000000000037e08000000000000000000000000000000000000000000000000000000000000044000000000000000000000000000000000000000000000000000000000000004410000000000000000000000000000000000000000000000000000000000000442000000000000000000000000000000000000000000000000000000000000044300000000000000000000000000000000000000000000000000000000000004440000000000000000000000000000000000000000000000000000000000000445000000000000000000000000000000000000000000000000000000000000044600000000000000000000000000000000000000000000000000000000000004473f0000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000000000064a0000000000000000000000000000000000000000000000000000000000000641000000000000000000000000000000000000000000000000000000000000064b0000000000000000000000000000000000000000000000000000000000000642000000000000000000000000000000000000000000000000000000000000064c0000000000000000000000000000000000000000000000000000000000000643000000000000000000000000000000000000000000000000000000000000064d0000000000000000000000000000000000000000000000000000000000000644000000000000000000000000000000000000000000000000000000000000064e0000000000000000000000000000000000000000000000000000000000000645000000000000000000000000000000000000000000000000000000000000064f00000000000000000000000000000000000000000000000000000000000006460000000000000000000000000000000000000000000000000000000000000650000000000000000000000000000000000000000000000000000000000000064700000000000000000000000000000000000000000000000000000000000006510000000000000000000000000000000000000000000000000000000000000648000000000000000000000000000000000000000000000000000000000000065200000000000000000000000000000000000000000000000000000000000006490000000000000000000000000000000000000000000000000000000000000653000000000000000000000000000000000000000000000000000000000000064a0000000000000000000000000000000000000000000000000000000000000654000000000000000000000000000000000000000000000000000000000000064b0000000000000000000000000000000000000000000000000000000000000655000000000000000000000000000000000000000000000000000000000000064c0000000000000000000000000000000000000000000000000000000000000656000000000000000000000000000000000000000000000000000000000000064d0000000000000000000000000000000000000000000000000000000000000657000000000000000000000000000000000000000000000000000000000000064e0000000000000000000000000000000000000000000000000000000000000658000000000000000000000000000000000000000000000000000000000000064f00000000000000000000000000000000000000000000000000000000000006590000000000000000000000000000000000000000000000000000000000000650000000000000000000000000000000000000000000000000000000000000065a0000000000000000000000000000000000000000000000000000000000000651000000000000000000000000000000000000000000000000000000000000065b0000000000000000000000000000000000000000000000000000000000000652000000000000000000000000000000000000000000000000000000000000065c0000000000000000000000000000000000000000000000000000000000000653000000000000000000000000000000000000000000000000000000000000065d0000000000000000000000000000000000000000000000000000000000000654000000000000000000000000000000000000000000000000000000000000065e0000000000000000000000000000000000000000000000000000000000000655000000000000000000000000000000000000000000000000000000000000065f00000000000000000000000000000000000000000000000000000000000006560000000000000000000000000000000000000000000000000000000000000660000000000000000000000000000000000000000000000000000000000000065700000000000000000000000000000000000000000000000000000000000006610000000000000000000000000000000000000000000000000000000000000658000000000000000000000000000000000000000000000000000000000000066200000000000000000000000000000000000000000000000000000000000006590000000000000000000000000000000000000000000000000000000000000663000000000000000000000000000000000000000000000000000000000000065a0000000000000000000000000000000000000000000000000000000000000664000000000000000000000000000000000000000000000000000000000000065b0000000000000000000000000000000000000000000000000000000000000665000000000000000000000000000000000000000000000000000000000000065c0000000000000000000000000000000000000000000000000000000000000666000000000000000000000000000000000000000000000000000000000000065d0000000000000000000000000000000000000000000000000000000000000667000000000000000000000000000000000000000000000000000000000000065e0000000000000000000000000000000000000000000000000000000000000668000000000000000000000000000000000000000000000000000000000000065f00000000000000000000000000000000000000000000000000000000000006690000000000000000000000000000000000000000000000000000000000000660000000000000000000000000000000000000000000000000000000000000066a0000000000000000000000000000000000000000000000000000000000000661000000000000000000000000000000000000000000000000000000000000066b0000000000000000000000000000000000000000000000000000000000000662000000000000000000000000000000000000000000000000000000000000066c0000000000000000000000000000000000000000000000000000000000000663000000000000000000000000000000000000000000000000000000000000066d0000000000000000000000000000000000000000000000000000000000000664000000000000000000000000000000000000000000000000000000000000066e0000000000000000000000000000000000000000000000000000000000000665000000000000000000000000000000000000000000000000000000000000066f00000000000000000000000000000000000000000000000000000000000006660000000000000000000000000000000000000000000000000000000000000670000000000000000000000000000000000000000000000000000000000000066700000000000000000000000000000000000000000000000000000000000006710000000000000000000000000000000000000000000000000000000000000668000000000000000000000000000000000000000000000000000000000000067200000000000000000000000000000000000000000000000000000000000006690000000000000000000000000000000000000000000000000000000000000673000000000000000000000000000000000000000000000000000000000000066a0000000000000000000000000000000000000000000000000000000000000674000000000000000000000000000000000000000000000000000000000000066b0000000000000000000000000000000000000000000000000000000000000675000000000000000000000000000000000000000000000000000000000000066c0000000000000000000000000000000000000000000000000000000000000676000000000000000000000000000000000000000000000000000000000000066d0000000000000000000000000000000000000000000000000000000000000677000000000000000000000000000000000000000000000000000000000000066e0000000000000000000000000000000000000000000000000000000000000678000000000000000000000000000000000000000000000000000000000000066f00000000000000000000000000000000000000000000000000000000000006790000000000000000000000000000000000000000000000000000000000000670000000000000000000000000000000000000000000000000000000000000067a0000000000000000000000000000000000000000000000000000000000000671000000000000000000000000000000000000000000000000000000000000067b0000000000000000000000000000000000000000000000000000000000000672000000000000000000000000000000000000000000000000000000000000067c0000000000000000000000000000000000000000000000000000000000000673000000000000000000000000000000000000000000000000000000000000067d0000000000000000000000000000000000000000000000000000000000000674000000000000000000000000000000000000000000000000000000000000067e0000000000000000000000000000000000000000000000000000000000000675000000000000000000000000000000000000000000000000000000000000067f00000000000000000000000000000000000000000000000000000000000006760000000000000000000000000000000000000000000000000000000000000680000000000000000000000000000000000000000000000000000000000000067700000000000000000000000000000000000000000000000000000000000006810000000000000000000000000000000000000000000000000000000000000678000000000000000000000000000000000000000000000000000000000000068200000000000000000000000000000000000000000000000000000000000006790000000000000000000000000000000000000000000000000000000000000683000000000000000000000000000000000000000000000000000000000000067a0000000000000000000000000000000000000000000000000000000000000684000000000000000000000000000000000000000000000000000000000000067b0000000000000000000000000000000000000000000000000000000000000685000000000000000000000000000000000000000000000000000000000000067c0000000000000000000000000000000000000000000000000000000000000686000000000000000000000000000000000000000000000000000000000000067d0000000000000000000000000000000000000000000000000000000000000687000000000000000000000000000000000000000000000000000000000000067e0000000000000000000000000000000000000000000000000000000000000688000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000028100000000000000000000000000000000000000000000000000000000000002820000000000000000000000000000000000000000000000000000000000000283000000000000000000000000000000000000000000000000000000000000028400000000000000000000000000000000000000000000000000000000000002850000000000000000000000000000000000000000000000000000000000000286000000000000000000000000000000000000000000000000000000000000028700000000000000000000000000000000000000000000000000000000000002880000000000000000000000000000000000000000000000000000000000000289000000000000000000000000000000000000000000000000000000000000028a000000000000000000000000000000000000000000000000000000000000028b000000000000000000000000000000000000000000000000000000000000028c000000000000000000000000000000000000000000000000000000000000028d000000000000000000000000000000000000000000000000000000000000028e000000000000000000000000000000000000000000000000000000000000028f0000000000000000000000000000000000000000000000000000000000000290000000000000000000000000000000000000000000000000000000000000029100000000000000000000000000000000000000000000000000000000000002920000000000000000000000000000000000000000000000000000000000000293000000000000000000000000000000000000000000000000000000000000029400000000000000000000000000000000000000000000000000000000000002950000000000000000000000000000000000000000000000000000000000000296000000000000000000000000000000000000000000000000000000000000029700000000000000000000000000000000000000000000000000000000000002980000000000000000000000000000000000000000000000000000000000000299000000000000000000000000000000000000000000000000000000000000029a000000000000000000000000000000000000000000000000000000000000029b000000000000000000000000000000000000000000000000000000000000029c000000000000000000000000000000000000000000000000000000000000029d000000000000000000000000000000000000000000000000000000000000029e000000000000000000000000000000000000000000000000000000000000029f00000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000002a100000000000000000000000000000000000000000000000000000000000002a200000000000000000000000000000000000000000000000000000000000002a300000000000000000000000000000000000000000000000000000000000002a400000000000000000000000000000000000000000000000000000000000002a500000000000000000000000000000000000000000000000000000000000002a600000000000000000000000000000000000000000000000000000000000002a700000000000000000000000000000000000000000000000000000000000002a800000000000000000000000000000000000000000000000000000000000002a900000000000000000000000000000000000000000000000000000000000002aa00000000000000000000000000000000000000000000000000000000000002ab00000000000000000000000000000000000000000000000000000000000002ac00000000000000000000000000000000000000000000000000000000000002ad00000000000000000000000000000000000000000000000000000000000002ae00000000000000000000000000000000000000000000000000000000000002af00000000000000000000000000000000000000000000000000000000000002b000000000000000000000000000000000000000000000000000000000000002b100000000000000000000000000000000000000000000000000000000000002b200000000000000000000000000000000000000000000000000000000000002b300000000000000000000000000000000000000000000000000000000000002b400000000000000000000000000000000000000000000000000000000000002b500000000000000000000000000000000000000000000000000000000000002b600000000000000000000000000000000000000000000000000000000000002b700000000000000000000000000000000000000000000000000000000000002b800000000000000000000000000000000000000000000000000000000000002b900000000000000000000000000000000000000000000000000000000000002ba00000000000000000000000000000000000000000000000000000000000002bb00000000000000000000000000000000000000000000000000000000000002bc00000000000000000000000000000000000000000000000000000000000002bd00000000000000000000000000000000000000000000000000000000000002be00000000000000000000000000000000000000000000000000000000000002bf3f0000000000000000000000000000000000000000000000000000000000000380000000000000000000000000000000000000000000000000000000000000038100000000000000000000000000000000000000000000000000000000000003820000000000000000000000000000000000000000000000000000000000000383000000000000000000000000000000000000000000000000000000000000038400000000000000000000000000000000000000000000000000000000000003850000000000000000000000000000000000000000000000000000000000000386000000000000000000000000000000000000000000000000000000000000038700000000000000000000000000000000000000000000000000000000000003880000000000000000000000000000000000000000000000000000000000000389000000000000000000000000000000000000000000000000000000000000038a000000000000000000000000000000000000000000000000000000000000038b000000000000000000000000000000000000000000000000000000000000038c000000000000000000000000000000000000000000000000000000000000038d000000000000000000000000000000000000000000000000000000000000038e000000000000000000000000000000000000000000000000000000000000038f0000000000000000000000000000000000000000000000000000000000000390000000000000000000000000000000000000000000000000000000000000039100000000000000000000000000000000000000000000000000000000000003920000000000000000000000000000000000000000000000000000000000000393000000000000000000000000000000000000000000000000000000000000039400000000000000000000000000000000000000000000000000000000000003950000000000000000000000000000000000000000000000000000000000000396000000000000000000000000000000000000000000000000000000000000039700000000000000000000000000000000000000000000000000000000000003980000000000000000000000000000000000000000000000000000000000000399000000000000000000000000000000000000000000000000000000000000039a000000000000000000000000000000000000000000000000000000000000039b000000000000000000000000000000000000000000000000000000000000039c000000000000000000000000000000000000000000000000000000000000039d000000000000000000000000000000000000000000000000000000000000039e000000000000000000000000000000000000000000000000000000000000039f00000000000000000000000000000000000000000000000000000000000003a000000000000000000000000000000000000000000000000000000000000003a100000000000000000000000000000000000000000000000000000000000003a200000000000000000000000000000000000000000000000000000000000003a300000000000000000000000000000000000000000000000000000000000003a400000000000000000000000000000000000000000000000000000000000003a500000000000000000000000000000000000000000000000000000000000003a600000000000000000000000000000000000000000000000000000000000003a700000000000000000000000000000000000000000000000000000000000003a800000000000000000000000000000000000000000000000000000000000003a900000000000000000000000000000000000000000000000000000000000003aa00000000000000000000000000000000000000000000000000000000000003ab00000000000000000000000000000000000000000000000000000000000003ac00000000000000000000000000000000000000000000000000000000000003ad00000000000000000000000000000000000000000000000000000000000003ae00000000000000000000000000000000000000000000000000000000000003af00000000000000000000000000000000000000000000000000000000000003b000000000000000000000000000000000000000000000000000000000000003b100000000000000000000000000000000000000000000000000000000000003b200000000000000000000000000000000000000000000000000000000000003b300000000000000000000000000000000000000000000000000000000000003b400000000000000000000000000000000000000000000000000000000000003b500000000000000000000000000000000000000000000000000000000000003b600000000000000000000000000000000000000000000000000000000000003b700000000000000000000000000000000000000000000000000000000000003b800000000000000000000000000000000000000000000000000000000000003b900000000000000000000000000000000000000000000000000000000000003ba00000000000000000000000000000000000000000000000000000000000003bb00000000000000000000000000000000000000000000000000000000000003bc00000000000000000000000000000000000000000000000000000000000003bd00000000000000000000000000000000000000000000000000000000000003be08000000000000000000000000000000000000000000000000000000000000048000000000000000000000000000000000000000000000000000000000000004810000000000000000000000000000000000000000000000000000000000000482000000000000000000000000000000000000000000000000000000000000048300000000000000000000000000000000000000000000000000000000000004840000000000000000000000000000000000000000000000000000000000000485000000000000000000000000000000000000000000000000000000000000048600000000000000000000000000000000000000000000000000000000000004873f0000000000000000000000000000000000000000000000000000000000000680000000000000000000000000000000000000000000000000000000000000068a0000000000000000000000000000000000000000000000000000000000000681000000000000000000000000000000000000000000000000000000000000068b0000000000000000000000000000000000000000000000000000000000000682000000000000000000000000000000000000000000000000000000000000068c0000000000000000000000000000000000000000000000000000000000000683000000000000000000000000000000000000000000000000000000000000068d0000000000000000000000000000000000000000000000000000000000000684000000000000000000000000000000000000000000000000000000000000068e0000000000000000000000000000000000000000000000000000000000000685000000000000000000000000000000000000000000000000000000000000068f00000000000000000000000000000000000000000000000000000000000006860000000000000000000000000000000000000000000000000000000000000690000000000000000000000000000000000000000000000000000000000000068700000000000000000000000000000000000000000000000000000000000006910000000000000000000000000000000000000000000000000000000000000688000000000000000000000000000000000000000000000000000000000000069200000000000000000000000000000000000000000000000000000000000006890000000000000000000000000000000000000000000000000000000000000693000000000000000000000000000000000000000000000000000000000000068a0000000000000000000000000000000000000000000000000000000000000694000000000000000000000000000000000000000000000000000000000000068b0000000000000000000000000000000000000000000000000000000000000695000000000000000000000000000000000000000000000000000000000000068c0000000000000000000000000000000000000000000000000000000000000696000000000000000000000000000000000000000000000000000000000000068d0000000000000000000000000000000000000000000000000000000000000697000000000000000000000000000000000000000000000000000000000000068e0000000000000000000000000000000000000000000000000000000000000698000000000000000000000000000000000000000000000000000000000000068f00000000000000000000000000000000000000000000000000000000000006990000000000000000000000000000000000000000000000000000000000000690000000000000000000000000000000000000000000000000000000000000069a0000000000000000000000000000000000000000000000000000000000000691000000000000000000000000000000000000000000000000000000000000069b0000000000000000000000000000000000000000000000000000000000000692000000000000000000000000000000000000000000000000000000000000069c0000000000000000000000000000000000000000000000000000000000000693000000000000000000000000000000000000000000000000000000000000069d0000000000000000000000000000000000000000000000000000000000000694000000000000000000000000000000000000000000000000000000000000069e0000000000000000000000000000000000000000000000000000000000000695000000000000000000000000000000000000000000000000000000000000069f000000000000000000000000000000000000000000000000000000000000069600000000000000000000000000000000000000000000000000000000000006a0000000000000000000000000000000000000000000000000000000000000069700000000000000000000000000000000000000000000000000000000000006a1000000000000000000000000000000000000000000000000000000000000069800000000000000000000000000000000000000000000000000000000000006a2000000000000000000000000000000000000000000000000000000000000069900000000000000000000000000000000000000000000000000000000000006a3000000000000000000000000000000000000000000000000000000000000069a00000000000000000000000000000000000000000000000000000000000006a4000000000000000000000000000000000000000000000000000000000000069b00000000000000000000000000000000000000000000000000000000000006a5000000000000000000000000000000000000000000000000000000000000069c00000000000000000000000000000000000000000000000000000000000006a6000000000000000000000000000000000000000000000000000000000000069d00000000000000000000000000000000000000000000000000000000000006a7000000000000000000000000000000000000000000000000000000000000069e00000000000000000000000000000000000000000000000000000000000006a8000000000000000000000000000000000000000000000000000000000000069f00000000000000000000000000000000000000000000000000000000000006a900000000000000000000000000000000000000000000000000000000000006a000000000000000000000000000000000000000000000000000000000000006aa00000000000000000000000000000000000000000000000000000000000006a100000000000000000000000000000000000000000000000000000000000006ab00000000000000000000000000000000000000000000000000000000000006a200000000000000000000000000000000000000000000000000000000000006ac00000000000000000000000000000000000000000000000000000000000006a300000000000000000000000000000000000000000000000000000000000006ad00000000000000000000000000000000000000000000000000000000000006a400000000000000000000000000000000000000000000000000000000000006ae00000000000000000000000000000000000000000000000000000000000006a500000000000000000000000000000000000000000000000000000000000006af00000000000000000000000000000000000000000000000000000000000006a600000000000000000000000000000000000000000000000000000000000006b000000000000000000000000000000000000000000000000000000000000006a700000000000000000000000000000000000000000000000000000000000006b100000000000000000000000000000000000000000000000000000000000006a800000000000000000000000000000000000000000000000000000000000006b200000000000000000000000000000000000000000000000000000000000006a900000000000000000000000000000000000000000000000000000000000006b300000000000000000000000000000000000000000000000000000000000006aa00000000000000000000000000000000000000000000000000000000000006b400000000000000000000000000000000000000000000000000000000000006ab00000000000000000000000000000000000000000000000000000000000006b500000000000000000000000000000000000000000000000000000000000006ac00000000000000000000000000000000000000000000000000000000000006b600000000000000000000000000000000000000000000000000000000000006ad00000000000000000000000000000000000000000000000000000000000006b700000000000000000000000000000000000000000000000000000000000006ae00000000000000000000000000000000000000000000000000000000000006b800000000000000000000000000000000000000000000000000000000000006af00000000000000000000000000000000000000000000000000000000000006b900000000000000000000000000000000000000000000000000000000000006b000000000000000000000000000000000000000000000000000000000000006ba00000000000000000000000000000000000000000000000000000000000006b100000000000000000000000000000000000000000000000000000000000006bb00000000000000000000000000000000000000000000000000000000000006b200000000000000000000000000000000000000000000000000000000000006bc00000000000000000000000000000000000000000000000000000000000006b300000000000000000000000000000000000000000000000000000000000006bd00000000000000000000000000000000000000000000000000000000000006b400000000000000000000000000000000000000000000000000000000000006be00000000000000000000000000000000000000000000000000000000000006b500000000000000000000000000000000000000000000000000000000000006bf00000000000000000000000000000000000000000000000000000000000006b600000000000000000000000000000000000000000000000000000000000006c000000000000000000000000000000000000000000000000000000000000006b700000000000000000000000000000000000000000000000000000000000006c100000000000000000000000000000000000000000000000000000000000006b800000000000000000000000000000000000000000000000000000000000006c200000000000000000000000000000000000000000000000000000000000006b900000000000000000000000000000000000000000000000000000000000006c300000000000000000000000000000000000000000000000000000000000006ba00000000000000000000000000000000000000000000000000000000000006c400000000000000000000000000000000000000000000000000000000000006bb00000000000000000000000000000000000000000000000000000000000006c500000000000000000000000000000000000000000000000000000000000006bc00000000000000000000000000000000000000000000000000000000000006c600000000000000000000000000000000000000000000000000000000000006bd00000000000000000000000000000000000000000000000000000000000006c700000000000000000000000000000000000000000000000000000000000006be00000000000000000000000000000000000000000000000000000000000006c80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000002c000000000000000000000000000000000000000000000000000000000000002c100000000000000000000000000000000000000000000000000000000000002c200000000000000000000000000000000000000000000000000000000000002c300000000000000000000000000000000000000000000000000000000000002c400000000000000000000000000000000000000000000000000000000000002c500000000000000000000000000000000000000000000000000000000000002c600000000000000000000000000000000000000000000000000000000000002c700000000000000000000000000000000000000000000000000000000000002c800000000000000000000000000000000000000000000000000000000000002c900000000000000000000000000000000000000000000000000000000000002ca00000000000000000000000000000000000000000000000000000000000002cb00000000000000000000000000000000000000000000000000000000000002cc00000000000000000000000000000000000000000000000000000000000002cd00000000000000000000000000000000000000000000000000000000000002ce00000000000000000000000000000000000000000000000000000000000002cf00000000000000000000000000000000000000000000000000000000000002d000000000000000000000000000000000000000000000000000000000000002d100000000000000000000000000000000000000000000000000000000000002d200000000000000000000000000000000000000000000000000000000000002d300000000000000000000000000000000000000000000000000000000000002d400000000000000000000000000000000000000000000000000000000000002d500000000000000000000000000000000000000000000000000000000000002d600000000000000000000000000000000000000000000000000000000000002d700000000000000000000000000000000000000000000000000000000000002d800000000000000000000000000000000000000000000000000000000000002d900000000000000000000000000000000000000000000000000000000000002da00000000000000000000000000000000000000000000000000000000000002db00000000000000000000000000000000000000000000000000000000000002dc00000000000000000000000000000000000000000000000000000000000002dd00000000000000000000000000000000000000000000000000000000000002de00000000000000000000000000000000000000000000000000000000000002df00000000000000000000000000000000000000000000000000000000000002e000000000000000000000000000000000000000000000000000000000000002e100000000000000000000000000000000000000000000000000000000000002e200000000000000000000000000000000000000000000000000000000000002e300000000000000000000000000000000000000000000000000000000000002e400000000000000000000000000000000000000000000000000000000000002e500000000000000000000000000000000000000000000000000000000000002e600000000000000000000000000000000000000000000000000000000000002e700000000000000000000000000000000000000000000000000000000000002e800000000000000000000000000000000000000000000000000000000000002e900000000000000000000000000000000000000000000000000000000000002ea00000000000000000000000000000000000000000000000000000000000002eb00000000000000000000000000000000000000000000000000000000000002ec00000000000000000000000000000000000000000000000000000000000002ed00000000000000000000000000000000000000000000000000000000000002ee00000000000000000000000000000000000000000000000000000000000002ef00000000000000000000000000000000000000000000000000000000000002f000000000000000000000000000000000000000000000000000000000000002f100000000000000000000000000000000000000000000000000000000000002f200000000000000000000000000000000000000000000000000000000000002f300000000000000000000000000000000000000000000000000000000000002f400000000000000000000000000000000000000000000000000000000000002f500000000000000000000000000000000000000000000000000000000000002f600000000000000000000000000000000000000000000000000000000000002f700000000000000000000000000000000000000000000000000000000000002f800000000000000000000000000000000000000000000000000000000000002f900000000000000000000000000000000000000000000000000000000000002fa00000000000000000000000000000000000000000000000000000000000002fb00000000000000000000000000000000000000000000000000000000000002fc00000000000000000000000000000000000000000000000000000000000002fd00000000000000000000000000000000000000000000000000000000000002fe00000000000000000000000000000000000000000000000000000000000002ff3f00000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000003c100000000000000000000000000000000000000000000000000000000000003c200000000000000000000000000000000000000000000000000000000000003c300000000000000000000000000000000000000000000000000000000000003c400000000000000000000000000000000000000000000000000000000000003c500000000000000000000000000000000000000000000000000000000000003c600000000000000000000000000000000000000000000000000000000000003c700000000000000000000000000000000000000000000000000000000000003c800000000000000000000000000000000000000000000000000000000000003c900000000000000000000000000000000000000000000000000000000000003ca00000000000000000000000000000000000000000000000000000000000003cb00000000000000000000000000000000000000000000000000000000000003cc00000000000000000000000000000000000000000000000000000000000003cd00000000000000000000000000000000000000000000000000000000000003ce00000000000000000000000000000000000000000000000000000000000003cf00000000000000000000000000000000000000000000000000000000000003d000000000000000000000000000000000000000000000000000000000000003d100000000000000000000000000000000000000000000000000000000000003d200000000000000000000000000000000000000000000000000000000000003d300000000000000000000000000000000000000000000000000000000000003d400000000000000000000000000000000000000000000000000000000000003d500000000000000000000000000000000000000000000000000000000000003d600000000000000000000000000000000000000000000000000000000000003d700000000000000000000000000000000000000000000000000000000000003d800000000000000000000000000000000000000000000000000000000000003d900000000000000000000000000000000000000000000000000000000000003da00000000000000000000000000000000000000000000000000000000000003db00000000000000000000000000000000000000000000000000000000000003dc00000000000000000000000000000000000000000000000000000000000003dd00000000000000000000000000000000000000000000000000000000000003de00000000000000000000000000000000000000000000000000000000000003df00000000000000000000000000000000000000000000000000000000000003e000000000000000000000000000000000000000000000000000000000000003e100000000000000000000000000000000000000000000000000000000000003e200000000000000000000000000000000000000000000000000000000000003e300000000000000000000000000000000000000000000000000000000000003e400000000000000000000000000000000000000000000000000000000000003e500000000000000000000000000000000000000000000000000000000000003e600000000000000000000000000000000000000000000000000000000000003e700000000000000000000000000000000000000000000000000000000000003e800000000000000000000000000000000000000000000000000000000000003e900000000000000000000000000000000000000000000000000000000000003ea00000000000000000000000000000000000000000000000000000000000003eb00000000000000000000000000000000000000000000000000000000000003ec00000000000000000000000000000000000000000000000000000000000003ed00000000000000000000000000000000000000000000000000000000000003ee00000000000000000000000000000000000000000000000000000000000003ef00000000000000000000000000000000000000000000000000000000000003f000000000000000000000000000000000000000000000000000000000000003f100000000000000000000000000000000000000000000000000000000000003f200000000000000000000000000000000000000000000000000000000000003f300000000000000000000000000000000000000000000000000000000000003f400000000000000000000000000000000000000000000000000000000000003f500000000000000000000000000000000000000000000000000000000000003f600000000000000000000000000000000000000000000000000000000000003f700000000000000000000000000000000000000000000000000000000000003f800000000000000000000000000000000000000000000000000000000000003f900000000000000000000000000000000000000000000000000000000000003fa00000000000000000000000000000000000000000000000000000000000003fb00000000000000000000000000000000000000000000000000000000000003fc00000000000000000000000000000000000000000000000000000000000003fd00000000000000000000000000000000000000000000000000000000000003fe0800000000000000000000000000000000000000000000000000000000000004c000000000000000000000000000000000000000000000000000000000000004c100000000000000000000000000000000000000000000000000000000000004c200000000000000000000000000000000000000000000000000000000000004c300000000000000000000000000000000000000000000000000000000000004c400000000000000000000000000000000000000000000000000000000000004c500000000000000000000000000000000000000000000000000000000000004c600000000000000000000000000000000000000000000000000000000000004c73f00000000000000000000000000000000000000000000000000000000000006c000000000000000000000000000000000000000000000000000000000000006ca00000000000000000000000000000000000000000000000000000000000006c100000000000000000000000000000000000000000000000000000000000006cb00000000000000000000000000000000000000000000000000000000000006c200000000000000000000000000000000000000000000000000000000000006cc00000000000000000000000000000000000000000000000000000000000006c300000000000000000000000000000000000000000000000000000000000006cd00000000000000000000000000000000000000000000000000000000000006c400000000000000000000000000000000000000000000000000000000000006ce00000000000000000000000000000000000000000000000000000000000006c500000000000000000000000000000000000000000000000000000000000006cf00000000000000000000000000000000000000000000000000000000000006c600000000000000000000000000000000000000000000000000000000000006d000000000000000000000000000000000000000000000000000000000000006c700000000000000000000000000000000000000000000000000000000000006d100000000000000000000000000000000000000000000000000000000000006c800000000000000000000000000000000000000000000000000000000000006d200000000000000000000000000000000000000000000000000000000000006c900000000000000000000000000000000000000000000000000000000000006d300000000000000000000000000000000000000000000000000000000000006ca00000000000000000000000000000000000000000000000000000000000006d400000000000000000000000000000000000000000000000000000000000006cb00000000000000000000000000000000000000000000000000000000000006d500000000000000000000000000000000000000000000000000000000000006cc00000000000000000000000000000000000000000000000000000000000006d600000000000000000000000000000000000000000000000000000000000006cd00000000000000000000000000000000000000000000000000000000000006d700000000000000000000000000000000000000000000000000000000000006ce00000000000000000000000000000000000000000000000000000000000006d800000000000000000000000000000000000000000000000000000000000006cf00000000000000000000000000000000000000000000000000000000000006d900000000000000000000000000000000000000000000000000000000000006d000000000000000000000000000000000000000000000000000000000000006da00000000000000000000000000000000000000000000000000000000000006d100000000000000000000000000000000000000000000000000000000000006db00000000000000000000000000000000000000000000000000000000000006d200000000000000000000000000000000000000000000000000000000000006dc00000000000000000000000000000000000000000000000000000000000006d300000000000000000000000000000000000000000000000000000000000006dd00000000000000000000000000000000000000000000000000000000000006d400000000000000000000000000000000000000000000000000000000000006de00000000000000000000000000000000000000000000000000000000000006d500000000000000000000000000000000000000000000000000000000000006df00000000000000000000000000000000000000000000000000000000000006d600000000000000000000000000000000000000000000000000000000000006e000000000000000000000000000000000000000000000000000000000000006d700000000000000000000000000000000000000000000000000000000000006e100000000000000000000000000000000000000000000000000000000000006d800000000000000000000000000000000000000000000000000000000000006e200000000000000000000000000000000000000000000000000000000000006d900000000000000000000000000000000000000000000000000000000000006e300000000000000000000000000000000000000000000000000000000000006da00000000000000000000000000000000000000000000000000000000000006e400000000000000000000000000000000000000000000000000000000000006db00000000000000000000000000000000000000000000000000000000000006e500000000000000000000000000000000000000000000000000000000000006dc00000000000000000000000000000000000000000000000000000000000006e600000000000000000000000000000000000000000000000000000000000006dd00000000000000000000000000000000000000000000000000000000000006e700000000000000000000000000000000000000000000000000000000000006de00000000000000000000000000000000000000000000000000000000000006e800000000000000000000000000000000000000000000000000000000000006df00000000000000000000000000000000000000000000000000000000000006e900000000000000000000000000000000000000000000000000000000000006e000000000000000000000000000000000000000000000000000000000000006ea00000000000000000000000000000000000000000000000000000000000006e100000000000000000000000000000000000000000000000000000000000006eb00000000000000000000000000000000000000000000000000000000000006e200000000000000000000000000000000000000000000000000000000000006ec00000000000000000000000000000000000000000000000000000000000006e300000000000000000000000000000000000000000000000000000000000006ed00000000000000000000000000000000000000000000000000000000000006e400000000000000000000000000000000000000000000000000000000000006ee00000000000000000000000000000000000000000000000000000000000006e500000000000000000000000000000000000000000000000000000000000006ef00000000000000000000000000000000000000000000000000000000000006e600000000000000000000000000000000000000000000000000000000000006f000000000000000000000000000000000000000000000000000000000000006e700000000000000000000000000000000000000000000000000000000000006f100000000000000000000000000000000000000000000000000000000000006e800000000000000000000000000000000000000000000000000000000000006f200000000000000000000000000000000000000000000000000000000000006e900000000000000000000000000000000000000000000000000000000000006f300000000000000000000000000000000000000000000000000000000000006ea00000000000000000000000000000000000000000000000000000000000006f400000000000000000000000000000000000000000000000000000000000006eb00000000000000000000000000000000000000000000000000000000000006f500000000000000000000000000000000000000000000000000000000000006ec00000000000000000000000000000000000000000000000000000000000006f600000000000000000000000000000000000000000000000000000000000006ed00000000000000000000000000000000000000000000000000000000000006f700000000000000000000000000000000000000000000000000000000000006ee00000000000000000000000000000000000000000000000000000000000006f800000000000000000000000000000000000000000000000000000000000006ef00000000000000000000000000000000000000000000000000000000000006f900000000000000000000000000000000000000000000000000000000000006f000000000000000000000000000000000000000000000000000000000000006fa00000000000000000000000000000000000000000000000000000000000006f100000000000000000000000000000000000000000000000000000000000006fb00000000000000000000000000000000000000000000000000000000000006f200000000000000000000000000000000000000000000000000000000000006fc00000000000000000000000000000000000000000000000000000000000006f300000000000000000000000000000000000000000000000000000000000006fd00000000000000000000000000000000000000000000000000000000000006f400000000000000000000000000000000000000000000000000000000000006fe00000000000000000000000000000000000000000000000000000000000006f500000000000000000000000000000000000000000000000000000000000006ff00000000000000000000000000000000000000000000000000000000000006f6000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000006f7000000000000000000000000000000000000000000000000000000000000070100000000000000000000000000000000000000000000000000000000000006f8000000000000000000000000000000000000000000000000000000000000070200000000000000000000000000000000000000000000000000000000000006f9000000000000000000000000000000000000000000000000000000000000070300000000000000000000000000000000000000000000000000000000000006fa000000000000000000000000000000000000000000000000000000000000070400000000000000000000000000000000000000000000000000000000000006fb000000000000000000000000000000000000000000000000000000000000070500000000000000000000000000000000000000000000000000000000000006fc000000000000000000000000000000000000000000000000000000000000070600000000000000000000000000000000000000000000000000000000000006fd000000000000000000000000000000000000000000000000000000000000070700000000000000000000000000000000000000000000000000000000000006fe0000000000000000000000000000000000000000000000000000000000000708000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000030100000000000000000000000000000000000000000000000000000000000003020000000000000000000000000000000000000000000000000000000000000303000000000000000000000000000000000000000000000000000000000000030400000000000000000000000000000000000000000000000000000000000003050000000000000000000000000000000000000000000000000000000000000306000000000000000000000000000000000000000000000000000000000000030700000000000000000000000000000000000000000000000000000000000003080000000000000000000000000000000000000000000000000000000000000309000000000000000000000000000000000000000000000000000000000000030a000000000000000000000000000000000000000000000000000000000000030b000000000000000000000000000000000000000000000000000000000000030c000000000000000000000000000000000000000000000000000000000000030d000000000000000000000000000000000000000000000000000000000000030e000000000000000000000000000000000000000000000000000000000000030f0000000000000000000000000000000000000000000000000000000000000310000000000000000000000000000000000000000000000000000000000000031100000000000000000000000000000000000000000000000000000000000003120000000000000000000000000000000000000000000000000000000000000313000000000000000000000000000000000000000000000000000000000000031400000000000000000000000000000000000000000000000000000000000003150000000000000000000000000000000000000000000000000000000000000316000000000000000000000000000000000000000000000000000000000000031700000000000000000000000000000000000000000000000000000000000003180000000000000000000000000000000000000000000000000000000000000319000000000000000000000000000000000000000000000000000000000000031a000000000000000000000000000000000000000000000000000000000000031b000000000000000000000000000000000000000000000000000000000000031c000000000000000000000000000000000000000000000000000000000000031d000000000000000000000000000000000000000000000000000000000000031e000000000000000000000000000000000000000000000000000000000000031f0000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000032100000000000000000000000000000000000000000000000000000000000003220000000000000000000000000000000000000000000000000000000000000323000000000000000000000000000000000000000000000000000000000000032400000000000000000000000000000000000000000000000000000000000003250000000000000000000000000000000000000000000000000000000000000326000000000000000000000000000000000000000000000000000000000000032700000000000000000000000000000000000000000000000000000000000003280000000000000000000000000000000000000000000000000000000000000329000000000000000000000000000000000000000000000000000000000000032a000000000000000000000000000000000000000000000000000000000000032b000000000000000000000000000000000000000000000000000000000000032c000000000000000000000000000000000000000000000000000000000000032d000000000000000000000000000000000000000000000000000000000000032e000000000000000000000000000000000000000000000000000000000000032f0000000000000000000000000000000000000000000000000000000000000330000000000000000000000000000000000000000000000000000000000000033100000000000000000000000000000000000000000000000000000000000003320000000000000000000000000000000000000000000000000000000000000333000000000000000000000000000000000000000000000000000000000000033400000000000000000000000000000000000000000000000000000000000003350000000000000000000000000000000000000000000000000000000000000336000000000000000000000000000000000000000000000000000000000000033700000000000000000000000000000000000000000000000000000000000003380000000000000000000000000000000000000000000000000000000000000339000000000000000000000000000000000000000000000000000000000000033a000000000000000000000000000000000000000000000000000000000000033b000000000000000000000000000000000000000000000000000000000000033c000000000000000000000000000000000000000000000000000000000000033d000000000000000000000000000000000000000000000000000000000000033e000000000000000000000000000000000000000000000000000000000000033f3f0000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000040100000000000000000000000000000000000000000000000000000000000004020000000000000000000000000000000000000000000000000000000000000403000000000000000000000000000000000000000000000000000000000000040400000000000000000000000000000000000000000000000000000000000004050000000000000000000000000000000000000000000000000000000000000406000000000000000000000000000000000000000000000000000000000000040700000000000000000000000000000000000000000000000000000000000004080000000000000000000000000000000000000000000000000000000000000409000000000000000000000000000000000000000000000000000000000000040a000000000000000000000000000000000000000000000000000000000000040b000000000000000000000000000000000000000000000000000000000000040c000000000000000000000000000000000000000000000000000000000000040d000000000000000000000000000000000000000000000000000000000000040e000000000000000000000000000000000000000000000000000000000000040f0000000000000000000000000000000000000000000000000000000000000410000000000000000000000000000000000000000000000000000000000000041100000000000000000000000000000000000000000000000000000000000004120000000000000000000000000000000000000000000000000000000000000413000000000000000000000000000000000000000000000000000000000000041400000000000000000000000000000000000000000000000000000000000004150000000000000000000000000000000000000000000000000000000000000416000000000000000000000000000000000000000000000000000000000000041700000000000000000000000000000000000000000000000000000000000004180000000000000000000000000000000000000000000000000000000000000419000000000000000000000000000000000000000000000000000000000000041a000000000000000000000000000000000000000000000000000000000000041b000000000000000000000000000000000000000000000000000000000000041c000000000000000000000000000000000000000000000000000000000000041d000000000000000000000000000000000000000000000000000000000000041e000000000000000000000000000000000000000000000000000000000000041f0000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000042100000000000000000000000000000000000000000000000000000000000004220000000000000000000000000000000000000000000000000000000000000423000000000000000000000000000000000000000000000000000000000000042400000000000000000000000000000000000000000000000000000000000004250000000000000000000000000000000000000000000000000000000000000426000000000000000000000000000000000000000000000000000000000000042700000000000000000000000000000000000000000000000000000000000004280000000000000000000000000000000000000000000000000000000000000429000000000000000000000000000000000000000000000000000000000000042a000000000000000000000000000000000000000000000000000000000000042b000000000000000000000000000000000000000000000000000000000000042c000000000000000000000000000000000000000000000000000000000000042d000000000000000000000000000000000000000000000000000000000000042e000000000000000000000000000000000000000000000000000000000000042f0000000000000000000000000000000000000000000000000000000000000430000000000000000000000000000000000000000000000000000000000000043100000000000000000000000000000000000000000000000000000000000004320000000000000000000000000000000000000000000000000000000000000433000000000000000000000000000000000000000000000000000000000000043400000000000000000000000000000000000000000000000000000000000004350000000000000000000000000000000000000000000000000000000000000436000000000000000000000000000000000000000000000000000000000000043700000000000000000000000000000000000000000000000000000000000004380000000000000000000000000000000000000000000000000000000000000439000000000000000000000000000000000000000000000000000000000000043a000000000000000000000000000000000000000000000000000000000000043b000000000000000000000000000000000000000000000000000000000000043c000000000000000000000000000000000000000000000000000000000000043d000000000000000000000000000000000000000000000000000000000000043e08000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000005010000000000000000000000000000000000000000000000000000000000000502000000000000000000000000000000000000000000000000000000000000050300000000000000000000000000000000000000000000000000000000000005040000000000000000000000000000000000000000000000000000000000000505000000000000000000000000000000000000000000000000000000000000050600000000000000000000000000000000000000000000000000000000000005073f0000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000070a0000000000000000000000000000000000000000000000000000000000000701000000000000000000000000000000000000000000000000000000000000070b0000000000000000000000000000000000000000000000000000000000000702000000000000000000000000000000000000000000000000000000000000070c0000000000000000000000000000000000000000000000000000000000000703000000000000000000000000000000000000000000000000000000000000070d0000000000000000000000000000000000000000000000000000000000000704000000000000000000000000000000000000000000000000000000000000070e0000000000000000000000000000000000000000000000000000000000000705000000000000000000000000000000000000000000000000000000000000070f00000000000000000000000000000000000000000000000000000000000007060000000000000000000000000000000000000000000000000000000000000710000000000000000000000000000000000000000000000000000000000000070700000000000000000000000000000000000000000000000000000000000007110000000000000000000000000000000000000000000000000000000000000708000000000000000000000000000000000000000000000000000000000000071200000000000000000000000000000000000000000000000000000000000007090000000000000000000000000000000000000000000000000000000000000713000000000000000000000000000000000000000000000000000000000000070a0000000000000000000000000000000000000000000000000000000000000714000000000000000000000000000000000000000000000000000000000000070b0000000000000000000000000000000000000000000000000000000000000715000000000000000000000000000000000000000000000000000000000000070c0000000000000000000000000000000000000000000000000000000000000716000000000000000000000000000000000000000000000000000000000000070d0000000000000000000000000000000000000000000000000000000000000717000000000000000000000000000000000000000000000000000000000000070e0000000000000000000000000000000000000000000000000000000000000718000000000000000000000000000000000000000000000000000000000000070f00000000000000000000000000000000000000000000000000000000000007190000000000000000000000000000000000000000000000000000000000000710000000000000000000000000000000000000000000000000000000000000071a0000000000000000000000000000000000000000000000000000000000000711000000000000000000000000000000000000000000000000000000000000071b0000000000000000000000000000000000000000000000000000000000000712000000000000000000000000000000000000000000000000000000000000071c0000000000000000000000000000000000000000000000000000000000000713000000000000000000000000000000000000000000000000000000000000071d0000000000000000000000000000000000000000000000000000000000000714000000000000000000000000000000000000000000000000000000000000071e0000000000000000000000000000000000000000000000000000000000000715000000000000000000000000000000000000000000000000000000000000071f00000000000000000000000000000000000000000000000000000000000007160000000000000000000000000000000000000000000000000000000000000720000000000000000000000000000000000000000000000000000000000000071700000000000000000000000000000000000000000000000000000000000007210000000000000000000000000000000000000000000000000000000000000718000000000000000000000000000000000000000000000000000000000000072200000000000000000000000000000000000000000000000000000000000007190000000000000000000000000000000000000000000000000000000000000723000000000000000000000000000000000000000000000000000000000000071a0000000000000000000000000000000000000000000000000000000000000724000000000000000000000000000000000000000000000000000000000000071b0000000000000000000000000000000000000000000000000000000000000725000000000000000000000000000000000000000000000000000000000000071c0000000000000000000000000000000000000000000000000000000000000726000000000000000000000000000000000000000000000000000000000000071d0000000000000000000000000000000000000000000000000000000000000727000000000000000000000000000000000000000000000000000000000000071e0000000000000000000000000000000000000000000000000000000000000728000000000000000000000000000000000000000000000000000000000000071f00000000000000000000000000000000000000000000000000000000000007290000000000000000000000000000000000000000000000000000000000000720000000000000000000000000000000000000000000000000000000000000072a0000000000000000000000000000000000000000000000000000000000000721000000000000000000000000000000000000000000000000000000000000072b0000000000000000000000000000000000000000000000000000000000000722000000000000000000000000000000000000000000000000000000000000072c0000000000000000000000000000000000000000000000000000000000000723000000000000000000000000000000000000000000000000000000000000072d0000000000000000000000000000000000000000000000000000000000000724000000000000000000000000000000000000000000000000000000000000072e0000000000000000000000000000000000000000000000000000000000000725000000000000000000000000000000000000000000000000000000000000072f00000000000000000000000000000000000000000000000000000000000007260000000000000000000000000000000000000000000000000000000000000730000000000000000000000000000000000000000000000000000000000000072700000000000000000000000000000000000000000000000000000000000007310000000000000000000000000000000000000000000000000000000000000728000000000000000000000000000000000000000000000000000000000000073200000000000000000000000000000000000000000000000000000000000007290000000000000000000000000000000000000000000000000000000000000733000000000000000000000000000000000000000000000000000000000000072a0000000000000000000000000000000000000000000000000000000000000734000000000000000000000000000000000000000000000000000000000000072b0000000000000000000000000000000000000000000000000000000000000735000000000000000000000000000000000000000000000000000000000000072c0000000000000000000000000000000000000000000000000000000000000736000000000000000000000000000000000000000000000000000000000000072d0000000000000000000000000000000000000000000000000000000000000737000000000000000000000000000000000000000000000000000000000000072e0000000000000000000000000000000000000000000000000000000000000738000000000000000000000000000000000000000000000000000000000000072f00000000000000000000000000000000000000000000000000000000000007390000000000000000000000000000000000000000000000000000000000000730000000000000000000000000000000000000000000000000000000000000073a0000000000000000000000000000000000000000000000000000000000000731000000000000000000000000000000000000000000000000000000000000073b0000000000000000000000000000000000000000000000000000000000000732000000000000000000000000000000000000000000000000000000000000073c0000000000000000000000000000000000000000000000000000000000000733000000000000000000000000000000000000000000000000000000000000073d0000000000000000000000000000000000000000000000000000000000000734000000000000000000000000000000000000000000000000000000000000073e0000000000000000000000000000000000000000000000000000000000000735000000000000000000000000000000000000000000000000000000000000073f00000000000000000000000000000000000000000000000000000000000007360000000000000000000000000000000000000000000000000000000000000740000000000000000000000000000000000000000000000000000000000000073700000000000000000000000000000000000000000000000000000000000007410000000000000000000000000000000000000000000000000000000000000738000000000000000000000000000000000000000000000000000000000000074200000000000000000000000000000000000000000000000000000000000007390000000000000000000000000000000000000000000000000000000000000743000000000000000000000000000000000000000000000000000000000000073a0000000000000000000000000000000000000000000000000000000000000744000000000000000000000000000000000000000000000000000000000000073b0000000000000000000000000000000000000000000000000000000000000745000000000000000000000000000000000000000000000000000000000000073c0000000000000000000000000000000000000000000000000000000000000746000000000000000000000000000000000000000000000000000000000000073d0000000000000000000000000000000000000000000000000000000000000747000000000000000000000000000000000000000000000000000000000000073e0000000000000000000000000000000000000000000000000000000000000748000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "txsEffectsHash": "0x00c6c40beb1ea89a3546d3527c7f1e86eb3866a40ce5f9854afaefd49f51cd5b", "decodedHeader": { "contentCommitment": { "inHash": "0x00212ff46db74e06c26240f9a92fb6fea84709380935d657361bbd5bcb891937", "outHash": "0x008bb57ba402f4917a5169c695e37af3fa10ae64220de709573dbf127d9955e8", - "txTreeHeight": 2, + "numTxs": 4, "txsEffectsHash": "0x00c6c40beb1ea89a3546d3527c7f1e86eb3866a40ce5f9854afaefd49f51cd5b" }, "globalVariables": { "blockNumber": 2, "chainId": 31337, - "timestamp": 1718108261, + "timestamp": 1719332461, "version": 1, - "coinbase": "0xcb460eb6cb460eb6cb460eb6cb460eb6cb460eb6", - "feeRecipient": "0x0cacc1f59212369f15989d55449e2460f787453f9a729749d363f4eee29d4c8c", + "coinbase": "0x38e74ed15dd5ab05fff041b5037372cce88aa7e9", + "feeRecipient": "0x1bf48a8c128750df4186da470571948ac0d14d79b3de69978f5a779fbdf547be", "gasFees": { "feePerDaGas": 0, "feePerL2Gas": 0 @@ -82,7 +82,7 @@ }, "lastArchive": { "nextAvailableLeafIndex": 2, - "root": "0x20fbe5614957ca8c09d74fd86ebbab70e3c95d6996b4e0086f7809f9d03a302d" + "root": "0x1caafe747155b2a72a6f44744dc68fa9d6c3b605e5dc661383c5a202dd7ee7c8" }, "stateReference": { "l1ToL2MessageTree": { @@ -105,8 +105,8 @@ } } }, - "header": "0x20fbe5614957ca8c09d74fd86ebbab70e3c95d6996b4e0086f7809f9d03a302d00000002000000000000000000000000000000000000000000000000000000000000000200c6c40beb1ea89a3546d3527c7f1e86eb3866a40ce5f9854afaefd49f51cd5b00212ff46db74e06c26240f9a92fb6fea84709380935d657361bbd5bcb891937008bb57ba402f4917a5169c695e37af3fa10ae64220de709573dbf127d9955e82e0232573b292e99cb24c082c3ef340d619341ab76aa1e9dff1ab1914963452d0000002024c6dc6d357aad01e10fe1adb877bb28b1df97375b874116e488086ca76e5f9600000200268020a622156e2beac47431b0cd70e1c81fef9a6aa3c365bfcbed9aa7301c5e000002802f1b0fefdce35aa5d17156a75b5df1128daa19c74dd56455e4545054d6a48eff000002800000000000000000000000000000000000000000000000000000000000007a69000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000066684065cb460eb6cb460eb6cb460eb6cb460eb6cb460eb60cacc1f59212369f15989d55449e2460f787453f9a729749d363f4eee29d4c8c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "publicInputsHash": "0x008ce3a989d35090e9f9539ddecbc7b3f9f11b7c58321cf5c3b02ade618d3f67", + "header": "0x1caafe747155b2a72a6f44744dc68fa9d6c3b605e5dc661383c5a202dd7ee7c800000002000000000000000000000000000000000000000000000000000000000000000400c6c40beb1ea89a3546d3527c7f1e86eb3866a40ce5f9854afaefd49f51cd5b00212ff46db74e06c26240f9a92fb6fea84709380935d657361bbd5bcb891937008bb57ba402f4917a5169c695e37af3fa10ae64220de709573dbf127d9955e82e0232573b292e99cb24c082c3ef340d619341ab76aa1e9dff1ab1914963452d0000002024c6dc6d357aad01e10fe1adb877bb28b1df97375b874116e488086ca76e5f9600000200268020a622156e2beac47431b0cd70e1c81fef9a6aa3c365bfcbed9aa7301c5e000002802f1b0fefdce35aa5d17156a75b5df1128daa19c74dd56455e4545054d6a48eff000002800000000000000000000000000000000000000000000000000000000000007a690000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000667aee6d38e74ed15dd5ab05fff041b5037372cce88aa7e91bf48a8c128750df4186da470571948ac0d14d79b3de69978f5a779fbdf547be000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "publicInputsHash": "0x006abc0437c6efc01d8f9e20d9bc15d8181ffcbf03c5869276d004c087bc117a", "numTxs": 4 } } \ No newline at end of file diff --git a/l1-contracts/test/merkle/UnbalancedMerkle.t.sol b/l1-contracts/test/merkle/UnbalancedMerkle.t.sol new file mode 100644 index 00000000000..ce3604351ab --- /dev/null +++ b/l1-contracts/test/merkle/UnbalancedMerkle.t.sol @@ -0,0 +1,199 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2024 Aztec Labs. +pragma solidity >=0.8.18; + +import {Test} from "forge-std/Test.sol"; +import {Hash} from "../../src/core/libraries/Hash.sol"; + +import {TxsDecoderHelper} from "../decoders/helpers/TxsDecoderHelper.sol"; +/** + * Tests the tree construction for unbalanced rollups. + * Used for calculating txsEffectsHash over non balanced rollups - each leaf is one baseLeaf + * calculated in TxsDecoder.sol. + */ + +contract UnbalancedMerkleTest is Test { + /** + * Rollups are constructed greedily, with a set of N transactions split into subtrees of decreasing + * powers of 2. + * We list them in reverse order as we compute subtree roots from R to L + */ + TxsDecoderHelper internal txsHelper; + + function setUp() public { + txsHelper = new TxsDecoderHelper(); + } + + function testDecomp() public { + // Worst case - max num txs + uint32 numTxs = 65535; + (uint256 min, uint256 max) = txsHelper.computeMinMaxPathLength(numTxs); + assertEq(min, 15); + assertEq(max, 16); + // Single tree of 2**15 + numTxs = 32768; + (min, max) = txsHelper.computeMinMaxPathLength(numTxs); + assertEq(min, 15); + assertEq(max, 15); + // Single tree of 2**13 + numTxs = 8192; + (min, max) = txsHelper.computeMinMaxPathLength(numTxs); + assertEq(min, 13); + assertEq(max, 13); + // Trees of 2**12, 2**11, ... 2**0 + numTxs = 8191; + (min, max) = txsHelper.computeMinMaxPathLength(numTxs); + assertEq(min, 12); + assertEq(max, 13); + // Single tree of 2**8 + numTxs = 256; + (min, max) = txsHelper.computeMinMaxPathLength(numTxs); + assertEq(min, 8); + assertEq(max, 8); + // Left subtree of 2**8, right subtree of single leaf + numTxs = 257; + (min, max) = txsHelper.computeMinMaxPathLength(numTxs); + assertEq(min, 1); + assertEq(max, 9); + } + + // Example - 2 txs: + // + // root + // / \ + // base base + function testComputeTxsEffectsHash2() public { + // Generate some base leaves + bytes32[] memory baseLeaves = new bytes32[](2); + for (uint256 i = 0; i < 2; i++) { + baseLeaves[i] = Hash.sha256ToField(abi.encodePacked(i)); + } + // We have just one 'balanced' branch, so depth is 0 with 2 elements + (uint256 min, uint256 max) = txsHelper.computeMinMaxPathLength(2); + assertEq(min, 1); + assertEq(max, 1); + bytes32 rootTxsEffectsHash = Hash.sha256ToField(bytes.concat(baseLeaves[0], baseLeaves[1])); + bytes32 calculatedTxsEffectsHash = txsHelper.computeUnbalancedRoot(baseLeaves); + assertEq(calculatedTxsEffectsHash, rootTxsEffectsHash); + } + // Example - 3 txs: + // + // root + // / \ + // merge base + // / \ + // base base + + function testComputeTxsEffectsHash3() public { + // Generate some base leaves + bytes32[] memory baseLeaves = new bytes32[](3); + for (uint256 i = 0; i < 3; i++) { + baseLeaves[i] = Hash.sha256ToField(abi.encodePacked(i)); + } + (uint256 min, uint256 max) = txsHelper.computeMinMaxPathLength(3); + assertEq(min, 1); + assertEq(max, 2); + bytes32 mergeTxsEffectsHash = Hash.sha256ToField(bytes.concat(baseLeaves[0], baseLeaves[1])); + bytes32 rootTxsEffectsHash = + Hash.sha256ToField(bytes.concat(mergeTxsEffectsHash, baseLeaves[2])); + bytes32 calculatedTxsEffectsHash = txsHelper.computeUnbalancedRoot(baseLeaves); + assertEq(calculatedTxsEffectsHash, rootTxsEffectsHash); + } + + // Example - 5 txs: + // + // root + // / \ + // merge base + // / \ + // merge merge + // / \ / \ + // base base base base + function testComputeTxsEffectsHash5() public { + // Generate some base leaves + bytes32[] memory baseLeaves = new bytes32[](5); + for (uint256 i = 0; i < 5; i++) { + baseLeaves[i] = Hash.sha256ToField(abi.encodePacked(i)); + } + (uint256 min, uint256 max) = txsHelper.computeMinMaxPathLength(5); + assertEq(min, 1); + assertEq(max, 3); + bytes32 firstMergeTxsEffectsHash = + Hash.sha256ToField(bytes.concat(baseLeaves[0], baseLeaves[1])); + bytes32 secondMergeTxsEffectsHash = + Hash.sha256ToField(bytes.concat(baseLeaves[2], baseLeaves[3])); + bytes32 thirdMergeTxsEffectsHash = + Hash.sha256ToField(bytes.concat(firstMergeTxsEffectsHash, secondMergeTxsEffectsHash)); + bytes32 rootTxsEffectsHash = + Hash.sha256ToField(bytes.concat(thirdMergeTxsEffectsHash, baseLeaves[4])); + bytes32 calculatedTxsEffectsHash = txsHelper.computeUnbalancedRoot(baseLeaves); + assertEq(calculatedTxsEffectsHash, rootTxsEffectsHash); + } + + // Example - 6 txs: + // + // root + // / \ + // merge4 merge3 + // / \ / \ + // merge1 merge2 base base + // / \ / \ + // base base base base + function testComputeTxsEffectsHash6() public { + // Generate some base leaves + bytes32[] memory baseLeaves = new bytes32[](6); + for (uint256 i = 0; i < 6; i++) { + baseLeaves[i] = Hash.sha256ToField(abi.encodePacked(i)); + } + (uint256 min, uint256 max) = txsHelper.computeMinMaxPathLength(6); + assertEq(min, 2); + assertEq(max, 3); + bytes32 firstMergeTxsEffectsHash = + Hash.sha256ToField(bytes.concat(baseLeaves[0], baseLeaves[1])); + bytes32 secondMergeTxsEffectsHash = + Hash.sha256ToField(bytes.concat(baseLeaves[2], baseLeaves[3])); + bytes32 thirdMergeTxsEffectsHash = + Hash.sha256ToField(bytes.concat(baseLeaves[4], baseLeaves[5])); + bytes32 fourthMergeTxsEffectsHash = + Hash.sha256ToField(bytes.concat(firstMergeTxsEffectsHash, secondMergeTxsEffectsHash)); + bytes32 rootTxsEffectsHash = + Hash.sha256ToField(bytes.concat(fourthMergeTxsEffectsHash, thirdMergeTxsEffectsHash)); + bytes32 calculatedTxsEffectsHash = txsHelper.computeUnbalancedRoot(baseLeaves); + assertEq(calculatedTxsEffectsHash, rootTxsEffectsHash); + } + + // Example - 7 txs: + // + // root + // / \ + // merge3 merge5 + // / \ / \ + // merge1 merge2 merge4 base + // / \ / \ / \ + // base base base base base base + function testComputeTxsEffectsHash7() public { + // Generate some base leaves + bytes32[] memory baseLeaves = new bytes32[](7); + for (uint256 i = 0; i < 6; i++) { + baseLeaves[i] = Hash.sha256ToField(abi.encodePacked(i)); + } + (uint256 min, uint256 max) = txsHelper.computeMinMaxPathLength(7); + assertEq(min, 2); + assertEq(max, 3); + bytes32 firstMergeTxsEffectsHash = + Hash.sha256ToField(bytes.concat(baseLeaves[0], baseLeaves[1])); + bytes32 secondMergeTxsEffectsHash = + Hash.sha256ToField(bytes.concat(baseLeaves[2], baseLeaves[3])); + bytes32 thirdMergeTxsEffectsHash = + Hash.sha256ToField(bytes.concat(firstMergeTxsEffectsHash, secondMergeTxsEffectsHash)); + bytes32 fourthMergeTxsEffectsHash = + Hash.sha256ToField(bytes.concat(baseLeaves[4], baseLeaves[5])); + bytes32 fifthMergeTxsEffectsHash = + Hash.sha256ToField(bytes.concat(fourthMergeTxsEffectsHash, baseLeaves[6])); + + bytes32 rootTxsEffectsHash = + Hash.sha256ToField(bytes.concat(thirdMergeTxsEffectsHash, fifthMergeTxsEffectsHash)); + bytes32 calculatedTxsEffectsHash = txsHelper.computeUnbalancedRoot(baseLeaves); + assertEq(calculatedTxsEffectsHash, rootTxsEffectsHash); + } +} diff --git a/noir-projects/Earthfile b/noir-projects/Earthfile index 13f21ffed8d..50267fa3084 100644 --- a/noir-projects/Earthfile +++ b/noir-projects/Earthfile @@ -77,7 +77,7 @@ format: RUN nargo fmt --check gates-report: - FROM +build + FROM +build-protocol-circuits WORKDIR /usr/src/noir-projects COPY ./gates_report.sh ./gates_report.sh diff --git a/noir-projects/aztec-nr/.gitrepo b/noir-projects/aztec-nr/.gitrepo index 62e0a6d03de..c7d2bb77284 100644 --- a/noir-projects/aztec-nr/.gitrepo +++ b/noir-projects/aztec-nr/.gitrepo @@ -6,7 +6,7 @@ [subrepo] remote = https://github.com/AztecProtocol/aztec-nr branch = master - commit = 03b6171663564ad6313ad8ae466a2707b06eb05c + commit = 78cf0ff0aa88841df0e344b2f6253313dde889af method = merge cmdver = 0.4.6 - parent = aeb5908a8ff4631a7c0985272fbd8b0d16b0d472 + parent = 8c45343ad837b0e273bc9a946e37644a76b219ec diff --git a/noir-projects/aztec-nr/aztec/src/context/inputs/public_context_inputs.nr b/noir-projects/aztec-nr/aztec/src/context/inputs/public_context_inputs.nr index 9075e5a207d..aa7bb176c0f 100644 --- a/noir-projects/aztec-nr/aztec/src/context/inputs/public_context_inputs.nr +++ b/noir-projects/aztec-nr/aztec/src/context/inputs/public_context_inputs.nr @@ -2,7 +2,6 @@ use dep::protocol_types::traits::Empty; // These inputs will likely go away once the AVM processes 1 public kernel per enqueued call. struct PublicContextInputs { - selector: Field, args_hash: Field, is_static_call: bool } @@ -10,7 +9,6 @@ struct PublicContextInputs { impl Empty for PublicContextInputs { fn empty() -> Self { PublicContextInputs { - selector: 0, args_hash: 0, is_static_call: false } diff --git a/noir-projects/aztec-nr/aztec/src/context/private_context.nr b/noir-projects/aztec-nr/aztec/src/context/private_context.nr index 25bb33ba663..48899a15876 100644 --- a/noir-projects/aztec-nr/aztec/src/context/private_context.nr +++ b/noir-projects/aztec-nr/aztec/src/context/private_context.nr @@ -1,17 +1,11 @@ use crate::{ context::{inputs::PrivateContextInputs, packed_returns::PackedReturns}, - messaging::process_l1_to_l2_message, - hash::{hash_args_array, ArgsHasher, compute_unencrypted_log_hash}, + messaging::process_l1_to_l2_message, hash::{hash_args_array, ArgsHasher}, keys::constants::{NULLIFIER_INDEX, OUTGOING_INDEX, NUM_KEY_TYPES, sk_generators}, - note::note_interface::NoteInterface, oracle::{ key_validation_request::get_key_validation_request, arguments, returns::pack_returns, call_private_function::call_private_function_internal, header::get_header_at, - logs::{ - emit_encrypted_note_log, emit_encrypted_event_log, - emit_contract_class_unencrypted_log_private_internal, emit_unencrypted_log_private_internal -}, - logs_traits::{LensForEncryptedLog, ToBytesForUnencryptedLog}, + logs::{emit_encrypted_note_log, emit_encrypted_event_log}, enqueue_public_function_call::{ enqueue_public_function_call_internal, set_public_teardown_function_call_internal, parse_public_call_stack_item_from_oracle @@ -19,7 +13,6 @@ use crate::{ } }; use dep::protocol_types::{ - hash::sha256_to_field, abis::{ caller_context::CallerContext, function_selector::FunctionSelector, max_block_number::MaxBlockNumber, @@ -36,10 +29,7 @@ use dep::protocol_types::{ MAX_KEY_VALIDATION_REQUESTS_PER_CALL, MAX_ENCRYPTED_LOGS_PER_CALL, MAX_UNENCRYPTED_LOGS_PER_CALL, MAX_NOTE_ENCRYPTED_LOGS_PER_CALL }, - contrakt::{storage_read::StorageRead, storage_update_request::StorageUpdateRequest}, - grumpkin_private_key::GrumpkinPrivateKey, grumpkin_point::GrumpkinPoint, header::Header, - messaging::l2_to_l1_message::L2ToL1Message, utils::reader::Reader, traits::{is_empty, Empty}, - utils::arrays::find_index + header::Header, messaging::l2_to_l1_message::L2ToL1Message, utils::reader::Reader, traits::Empty }; // When finished, one can call .finish() to convert back to the abi @@ -270,63 +260,25 @@ impl PrivateContext { } // docs:end:consume_l1_to_l2_message - // TODO: We might want to remove this since emitting unencrypted logs from private functions is violating privacy. - // --> might be a better approach to force devs to make a public function call that emits the log if needed then - // it would be less easy to accidentally leak information. - // If we decide to keep this function around would make sense to wait for traits and then merge it with emit_unencrypted_log. - pub fn emit_unencrypted_log(&mut self, log: T) where T: ToBytesForUnencryptedLog { - let event_selector = 5; // TODO: compute actual event selector. - let contract_address = self.this_address(); - let counter = self.next_counter(); - let log_slice = log.to_be_bytes_arr(); - let log_hash = compute_unencrypted_log_hash(contract_address, event_selector, log); - // 44 = addr (32) + selector (4) + raw log len (4) + processed log len (4) - let len = 44 + log_slice.len().to_field(); - let side_effect = LogHash { value: log_hash, counter, length: len }; - self.unencrypted_logs_hashes.push(side_effect); - // call oracle - let _void = emit_unencrypted_log_private_internal(contract_address, event_selector, log, counter); - } - - // This fn exists separately from emit_unencrypted_log because sha hashing the preimage - // is too large to compile (16,200 fields, 518,400 bytes) => the oracle hashes it - // It is ONLY used with contract_class_registerer_contract since we already assert correctness: - // - Contract class -> we will commit to the packed bytecode (currently a TODO) - // - Private function -> we provide a membership proof - // - Unconstrained function -> we provide a membership proof - // Ordinary logs are not protected by the above so this fn shouldn't be called by anything else - pub fn emit_contract_class_unencrypted_log(&mut self, log: [Field; N]) { - let event_selector = 5; // TODO: compute actual event selector. - let contract_address = self.this_address(); - let counter = self.next_counter(); - let log_hash = emit_contract_class_unencrypted_log_private_internal(contract_address, event_selector, log, counter); - // 44 = addr (32) + selector (4) + raw log len (4) + processed log len (4) - let len = 44 + N * 32; - let side_effect = LogHash { value: log_hash, counter, length: len }; - self.unencrypted_logs_hashes.push(side_effect); - } - // NB: A randomness value of 0 signals that the kernels should not mask the contract address // used in siloing later on e.g. 'handshaking' contract w/ known address. - pub fn emit_raw_event_log_with_masked_address(&mut self, randomness: Field, encrypted_log: [u8; M]) { + pub fn emit_raw_event_log_with_masked_address(&mut self, randomness: Field, log: [u8; M], log_hash: Field) { let counter = self.next_counter(); let contract_address = self.this_address(); - let len = encrypted_log.len() as Field + 4; - let log_hash = sha256_to_field(encrypted_log); + let len = log.len() as Field + 4; let side_effect = EncryptedLogHash { value: log_hash, counter, length: len, randomness }; self.encrypted_logs_hashes.push(side_effect); - emit_encrypted_event_log(contract_address, randomness, encrypted_log, counter); + emit_encrypted_event_log(contract_address, randomness, log, counter); } - pub fn emit_raw_note_log(&mut self, note_hash_counter: u32, encrypted_log: [u8; M]) { + pub fn emit_raw_note_log(&mut self, note_hash_counter: u32, log: [u8; M], log_hash: Field) { let counter = self.next_counter(); - let len = encrypted_log.len() as Field + 4; - let log_hash = sha256_to_field(encrypted_log); + let len = log.len() as Field + 4; let side_effect = NoteLogHash { value: log_hash, counter, length: len, note_hash_counter }; self.note_encrypted_logs_hashes.push(side_effect); - emit_encrypted_note_log(note_hash_counter, encrypted_log, counter); + emit_encrypted_note_log(note_hash_counter, log, counter); } pub fn call_private_function( diff --git a/noir-projects/aztec-nr/aztec/src/context/public_context.nr b/noir-projects/aztec-nr/aztec/src/context/public_context.nr index 87b17aa92d2..53e213abb8f 100644 --- a/noir-projects/aztec-nr/aztec/src/context/public_context.nr +++ b/noir-projects/aztec-nr/aztec/src/context/public_context.nr @@ -14,20 +14,6 @@ impl PublicContext { PublicContext { inputs } } - pub fn storage_address(self) -> AztecAddress { - storage_address() - } - pub fn fee_per_l2_gas(self) -> Field { - fee_per_l2_gas() - } - pub fn fee_per_da_gas(self) -> Field { - fee_per_da_gas() - } - /** - * Emit a log with the given event selector and message. - * @param event_selector The event selector for the log. - * @param message The message to emit in the log. - */ pub fn emit_unencrypted_log(&mut self, log: T) where T: Serialize { emit_unencrypted_log(Serialize::serialize(log).as_slice()); } @@ -35,22 +21,11 @@ impl PublicContext { pub fn note_hash_exists(self, note_hash: Field, leaf_index: Field) -> bool { note_hash_exists(note_hash, leaf_index) == 1 } + pub fn l1_to_l2_msg_exists(self, msg_hash: Field, msg_leaf_index: Field) -> bool { l1_to_l2_msg_exists(msg_hash, msg_leaf_index) == 1 } - fn block_number(self) -> Field { - block_number() - } - - fn timestamp(self) -> u64 { - timestamp() - } - - fn transaction_fee(self) -> Field { - transaction_fee() - } - fn nullifier_exists(self, unsiloed_nullifier: Field, address: AztecAddress) -> bool { nullifier_exists(unsiloed_nullifier, address.to_field()) == 1 } @@ -91,7 +66,7 @@ impl PublicContext { fn call_public_function( self: &mut Self, contract_address: AztecAddress, - temporary_function_selector: FunctionSelector, + function_selector: FunctionSelector, args: [Field], gas_opts: GasOpts ) -> FunctionReturns { @@ -99,7 +74,7 @@ impl PublicContext { gas_for_call(gas_opts), contract_address, args, - temporary_function_selector.to_field() + function_selector.to_field() ); let data_to_return: [Field; RETURNS_COUNT] = results.0; let success: u8 = results.1; @@ -111,7 +86,7 @@ impl PublicContext { fn static_call_public_function( self: &mut Self, contract_address: AztecAddress, - temporary_function_selector: FunctionSelector, + function_selector: FunctionSelector, args: [Field], gas_opts: GasOpts ) -> FunctionReturns { @@ -119,7 +94,7 @@ impl PublicContext { gas_for_call(gas_opts), contract_address, args, - temporary_function_selector.to_field() + function_selector.to_field() ); assert(success == 1, "Nested static call failed!"); @@ -143,30 +118,67 @@ impl PublicContext { // Cannot nullify pending commitments in AVM, so `nullified_commitment` is not used emit_nullifier(nullifier); } + + fn this_address(self) -> AztecAddress { + address() + } + pub fn storage_address(self) -> AztecAddress { + storage_address() + } fn msg_sender(self) -> AztecAddress { sender() } - fn this_address(self) -> AztecAddress { - address() + fn selector(self) -> FunctionSelector { + FunctionSelector::from_u32(function_selector()) } + fn get_args_hash(self) -> Field { + self.inputs.args_hash + } + fn transaction_fee(self) -> Field { + transaction_fee() + } + fn chain_id(self) -> Field { chain_id() } fn version(self) -> Field { version() } - fn selector(self) -> FunctionSelector { - FunctionSelector::from_field(self.inputs.selector) + fn block_number(self) -> Field { + block_number() } - fn get_args_hash(self) -> Field { - self.inputs.args_hash + fn timestamp(self) -> u64 { + timestamp() + } + pub fn fee_per_l2_gas(self) -> Field { + fee_per_l2_gas() + } + pub fn fee_per_da_gas(self) -> Field { + fee_per_da_gas() } + fn l2_gas_left(self) -> Field { l2_gas_left() } fn da_gas_left(self) -> Field { da_gas_left() } + + fn raw_storage_read(_self: Self, storage_slot: Field) -> [Field; N] { + storage_read(storage_slot) + } + + fn storage_read(self, storage_slot: Field) -> T where T: Deserialize { + T::deserialize(self.raw_storage_read(storage_slot)) + } + + fn raw_storage_write(_self: Self, storage_slot: Field, values: [Field; N]) { + storage_write(storage_slot, values); + } + + fn storage_write(self, storage_slot: Field, value: T) where T: Serialize { + self.raw_storage_write(storage_slot, value.serialize()); + } } // Helper functions @@ -194,11 +206,8 @@ unconstrained fn sender() -> AztecAddress { unconstrained fn portal() -> EthAddress { portal_opcode() } -unconstrained fn fee_per_l2_gas() -> Field { - fee_per_l2_gas_opcode() -} -unconstrained fn fee_per_da_gas() -> Field { - fee_per_da_gas_opcode() +unconstrained fn function_selector() -> u32 { + function_selector_opcode() } unconstrained fn transaction_fee() -> Field { transaction_fee_opcode() @@ -215,6 +224,12 @@ unconstrained fn block_number() -> Field { unconstrained fn timestamp() -> u64 { timestamp_opcode() } +unconstrained fn fee_per_l2_gas() -> Field { + fee_per_l2_gas_opcode() +} +unconstrained fn fee_per_da_gas() -> Field { + fee_per_da_gas_opcode() +} unconstrained fn l2_gas_left() -> Field { l2_gas_left_opcode() } @@ -259,6 +274,14 @@ unconstrained fn call_static( call_static_opcode(gas, address, args, function_selector) } +unconstrained fn storage_read(storage_slot: Field) -> [Field; N] { + storage_read_opcode(storage_slot) +} + +unconstrained fn storage_write(storage_slot: Field, values: [Field; N]) { + storage_write_opcode(storage_slot, values); +} + impl Empty for PublicContext { fn empty() -> Self { PublicContext::new(PublicContextInputs::empty()) @@ -278,11 +301,8 @@ unconstrained fn sender_opcode() -> AztecAddress {} #[oracle(avmOpcodePortal)] unconstrained fn portal_opcode() -> EthAddress {} -#[oracle(avmOpcodeFeePerL2Gas)] -unconstrained fn fee_per_l2_gas_opcode() -> Field {} - -#[oracle(avmOpcodeFeePerDaGas)] -unconstrained fn fee_per_da_gas_opcode() -> Field {} +#[oracle(avmOpcodeFunctionSelector)] +unconstrained fn function_selector_opcode() -> u32 {} #[oracle(avmOpcodeTransactionFee)] unconstrained fn transaction_fee_opcode() -> Field {} @@ -299,6 +319,12 @@ unconstrained fn block_number_opcode() -> Field {} #[oracle(avmOpcodeTimestamp)] unconstrained fn timestamp_opcode() -> u64 {} +#[oracle(avmOpcodeFeePerL2Gas)] +unconstrained fn fee_per_l2_gas_opcode() -> Field {} + +#[oracle(avmOpcodeFeePerDaGas)] +unconstrained fn fee_per_da_gas_opcode() -> Field {} + #[oracle(avmOpcodeL2GasLeft)] unconstrained fn l2_gas_left_opcode() -> Field {} @@ -346,6 +372,12 @@ unconstrained fn call_static_opcode( ) -> ([Field; RET_SIZE], u8) {} // ^ return data ^ success +#[oracle(avmOpcodeStorageRead)] +unconstrained fn storage_read_opcode(storage_slot: Field) -> [Field; N] {} + +#[oracle(avmOpcodeStorageWrite)] +unconstrained fn storage_write_opcode(storage_slot: Field, values: [Field; N]) {} + struct FunctionReturns { values: [Field; N] } diff --git a/noir-projects/aztec-nr/aztec/src/context/unconstrained_context.nr b/noir-projects/aztec-nr/aztec/src/context/unconstrained_context.nr index b36691616e0..eedd97aa8d6 100644 --- a/noir-projects/aztec-nr/aztec/src/context/unconstrained_context.nr +++ b/noir-projects/aztec-nr/aztec/src/context/unconstrained_context.nr @@ -1,4 +1,5 @@ -use dep::protocol_types::address::AztecAddress; +use dep::protocol_types::{address::AztecAddress, traits::Deserialize}; +use crate::oracle::storage::{raw_storage_read, storage_read}; struct UnconstrainedContext { block_number: u32, @@ -35,6 +36,14 @@ impl UnconstrainedContext { fn chain_id(self) -> Field { self.chain_id } + + unconstrained fn raw_storage_read(self: Self, storage_slot: Field) -> [Field; N] { + storage_read(self.this_address(), storage_slot, self.block_number()) + } + + unconstrained fn storage_read(self, storage_slot: Field) -> T where T: Deserialize { + T::deserialize(self.raw_storage_read(storage_slot)) + } } #[oracle(getContractAddress)] diff --git a/noir-projects/aztec-nr/aztec/src/encrypted_logs/encrypted_event_emission.nr b/noir-projects/aztec-nr/aztec/src/encrypted_logs/encrypted_event_emission.nr index a027c168515..f5366a16174 100644 --- a/noir-projects/aztec-nr/aztec/src/encrypted_logs/encrypted_event_emission.nr +++ b/noir-projects/aztec-nr/aztec/src/encrypted_logs/encrypted_event_emission.nr @@ -1,25 +1,91 @@ use crate::{ context::PrivateContext, event::event_interface::EventInterface, - encrypted_logs::payload::compute_encrypted_event_log, oracle::logs_traits::LensForEncryptedEvent + encrypted_logs::payload::compute_encrypted_event_log, oracle::logs_traits::LensForEncryptedEvent, + oracle::unsafe_rand::unsafe_rand }; -use dep::protocol_types::{address::AztecAddress, grumpkin_point::GrumpkinPoint}; +use dep::protocol_types::{address::AztecAddress, grumpkin_point::GrumpkinPoint, hash::sha256_to_field}; + +unconstrained fn compute_unconstrained( + contract_address: AztecAddress, + randomness: Field, + ovsk_app: Field, + ovpk: GrumpkinPoint, + ivpk: GrumpkinPoint, + event: Event +) -> ([u8; OB], Field) where Event: EventInterface, [u8; NB]: LensForEncryptedEvent { + compute(contract_address, randomness, ovsk_app, ovpk, ivpk, event) +} + +fn compute( + contract_address: AztecAddress, + randomness: Field, + ovsk_app: Field, + ovpk: GrumpkinPoint, + ivpk: GrumpkinPoint, + event: Event +) -> ([u8; OB], Field) where Event: EventInterface, [u8; NB]: LensForEncryptedEvent { + let encrypted_log: [u8; OB] = compute_encrypted_event_log(contract_address, randomness, ovsk_app, ovpk, ivpk, event); + let log_hash = sha256_to_field(encrypted_log); + (encrypted_log, log_hash) +} fn emit_with_keys( context: &mut PrivateContext, randomness: Field, event: Event, ovpk: GrumpkinPoint, - ivpk: GrumpkinPoint + ivpk: GrumpkinPoint, + inner_compute: fn(AztecAddress, Field, Field, GrumpkinPoint, GrumpkinPoint, Event) -> ([u8; OB], Field) ) where Event: EventInterface, [u8; NB]: LensForEncryptedEvent { let contract_address: AztecAddress = context.this_address(); let ovsk_app: Field = context.request_ovsk_app(ovpk.hash()); + let (encrypted_log, log_hash) = inner_compute(contract_address, randomness, ovsk_app, ovpk, ivpk, event); + context.emit_raw_event_log_with_masked_address(randomness, encrypted_log, log_hash); +} - let encrypted_log: [u8; OB] = compute_encrypted_event_log(contract_address, randomness, ovsk_app, ovpk, ivpk, event); +pub fn encode_and_encrypt_event( + context: &mut PrivateContext, + ov: AztecAddress, + iv: AztecAddress +) -> fn[(&mut PrivateContext, AztecAddress, AztecAddress)](Event) -> () where Event: EventInterface, [u8; NB]: LensForEncryptedEvent { + | e: Event | { + let header = context.get_header(); + let ovpk = header.get_ovpk_m(context, ov); + let ivpk = header.get_ivpk_m(context, iv); + let randomness = unsafe_rand(); + emit_with_keys(context, randomness, e, ovpk, ivpk, compute); + } +} - context.emit_raw_event_log_with_masked_address(randomness, encrypted_log); +pub fn encode_and_encrypt_event_unconstrained( + context: &mut PrivateContext, + ov: AztecAddress, + iv: AztecAddress +) -> fn[(&mut PrivateContext, AztecAddress, AztecAddress)](Event) -> () where Event: EventInterface, [u8; NB]: LensForEncryptedEvent { + | e: Event | { + let header = context.get_header(); + let ovpk = header.get_ovpk_m(context, ov); + let ivpk = header.get_ivpk_m(context, iv); + let randomness = unsafe_rand(); + emit_with_keys(context, randomness, e, ovpk, ivpk, compute_unconstrained); + } } -pub fn encode_and_encrypt_event( +pub fn encode_and_encrypt_event_with_randomness( + context: &mut PrivateContext, + randomness: Field, + ov: AztecAddress, + iv: AztecAddress +) -> fn[(&mut PrivateContext, AztecAddress, AztecAddress, Field)](Event) -> () where Event: EventInterface, [u8; NB]: LensForEncryptedEvent { + | e: Event | { + let header = context.get_header(); + let ovpk = header.get_ovpk_m(context, ov); + let ivpk = header.get_ivpk_m(context, iv); + emit_with_keys(context, randomness, e, ovpk, ivpk, compute); + } +} + +pub fn encode_and_encrypt_event_with_randomness_unconstrained( context: &mut PrivateContext, randomness: Field, ov: AztecAddress, @@ -29,17 +95,50 @@ pub fn encode_and_encrypt_event( let header = context.get_header(); let ovpk = header.get_ovpk_m(context, ov); let ivpk = header.get_ivpk_m(context, iv); - emit_with_keys(context, randomness, e, ovpk, ivpk); + emit_with_keys(context, randomness, e, ovpk, ivpk, compute_unconstrained); } } pub fn encode_and_encrypt_event_with_keys( + context: &mut PrivateContext, + ovpk: GrumpkinPoint, + ivpk: GrumpkinPoint +) -> fn[(&mut PrivateContext, GrumpkinPoint, GrumpkinPoint)](Event) -> () where Event: EventInterface, [u8; NB]: LensForEncryptedEvent { + | e: Event | { + let randomness = unsafe_rand(); + emit_with_keys(context, randomness, e, ovpk, ivpk, compute); + } +} + +pub fn encode_and_encrypt_event_with_keys_unconstrained( + context: &mut PrivateContext, + ovpk: GrumpkinPoint, + ivpk: GrumpkinPoint +) -> fn[(&mut PrivateContext, GrumpkinPoint, GrumpkinPoint)](Event) -> () where Event: EventInterface, [u8; NB]: LensForEncryptedEvent { + | e: Event | { + let randomness = unsafe_rand(); + emit_with_keys(context, randomness, e, ovpk, ivpk, compute_unconstrained); + } +} + +pub fn encode_and_encrypt_event_with_keys_with_randomness( + context: &mut PrivateContext, + randomness: Field, + ovpk: GrumpkinPoint, + ivpk: GrumpkinPoint +) -> fn[(&mut PrivateContext, Field, GrumpkinPoint, GrumpkinPoint)](Event) -> () where Event: EventInterface, [u8; NB]: LensForEncryptedEvent { + | e: Event | { + emit_with_keys(context, randomness, e, ovpk, ivpk, compute); + } +} + +pub fn encode_and_encrypt_event_with_keys_with_randomness_unconstrained( context: &mut PrivateContext, randomness: Field, ovpk: GrumpkinPoint, ivpk: GrumpkinPoint ) -> fn[(&mut PrivateContext, Field, GrumpkinPoint, GrumpkinPoint)](Event) -> () where Event: EventInterface, [u8; NB]: LensForEncryptedEvent { | e: Event | { - emit_with_keys(context, randomness, e, ovpk, ivpk); + emit_with_keys(context, randomness, e, ovpk, ivpk, compute_unconstrained); } } diff --git a/noir-projects/aztec-nr/aztec/src/encrypted_logs/encrypted_note_emission.nr b/noir-projects/aztec-nr/aztec/src/encrypted_logs/encrypted_note_emission.nr index 5b66e2e8027..8a82eccdfc4 100644 --- a/noir-projects/aztec-nr/aztec/src/encrypted_logs/encrypted_note_emission.nr +++ b/noir-projects/aztec-nr/aztec/src/encrypted_logs/encrypted_note_emission.nr @@ -3,15 +3,40 @@ use crate::{ encrypted_logs::payload::compute_encrypted_note_log, oracle::logs_traits::LensForEncryptedLog }; use dep::protocol_types::{ - address::AztecAddress, grumpkin_point::GrumpkinPoint, abis::note_hash::NoteHash, - constants::MAX_NEW_NOTE_HASHES_PER_CALL, utils::arrays::find_index + hash::sha256_to_field, address::AztecAddress, grumpkin_point::GrumpkinPoint, + abis::note_hash::NoteHash, constants::MAX_NEW_NOTE_HASHES_PER_CALL, utils::arrays::find_index }; +unconstrained fn compute_unconstrained( + contract_address: AztecAddress, + storage_slot: Field, + ovsk_app: Field, + ovpk: GrumpkinPoint, + ivpk: GrumpkinPoint, + note: Note +) -> ([u8; M], Field) where Note: NoteInterface, [Field; N]: LensForEncryptedLog { + compute(contract_address, storage_slot, ovsk_app, ovpk, ivpk, note) +} + +fn compute( + contract_address: AztecAddress, + storage_slot: Field, + ovsk_app: Field, + ovpk: GrumpkinPoint, + ivpk: GrumpkinPoint, + note: Note +) -> ([u8; M], Field) where Note: NoteInterface, [Field; N]: LensForEncryptedLog { + let encrypted_log: [u8; M] = compute_encrypted_note_log(contract_address, storage_slot, ovsk_app, ovpk, ivpk, note); + let log_hash = sha256_to_field(encrypted_log); + (encrypted_log, log_hash) +} + fn emit_with_keys( context: &mut PrivateContext, note: Note, ovpk: GrumpkinPoint, - ivpk: GrumpkinPoint + ivpk: GrumpkinPoint, + inner_compute: fn(AztecAddress, Field, Field, GrumpkinPoint, GrumpkinPoint, Note) -> ([u8; M], Field) ) where Note: NoteInterface, [Field; N]: LensForEncryptedLog { let note_header = note.get_header(); let note_hash_counter = note_header.note_hash_counter; @@ -28,9 +53,9 @@ fn emit_with_keys( let contract_address: AztecAddress = context.this_address(); let ovsk_app: Field = context.request_ovsk_app(ovpk.hash()); - let encrypted_log: [u8; M] = compute_encrypted_note_log(contract_address, storage_slot, ovsk_app, ovpk, ivpk, note); + let (encrypted_log, log_hash) = inner_compute(contract_address, storage_slot, ovsk_app, ovpk, ivpk, note); - context.emit_raw_note_log(note_hash_counter, encrypted_log); + context.emit_raw_note_log(note_hash_counter, encrypted_log, log_hash); } pub fn encode_and_encrypt_note( @@ -42,7 +67,20 @@ pub fn encode_and_encrypt_note( let header = context.get_header(); let ovpk = header.get_ovpk_m(context, ov); let ivpk = header.get_ivpk_m(context, iv); - emit_with_keys(context, e.note, ovpk, ivpk); + emit_with_keys(context, e.note, ovpk, ivpk, compute); + } +} + +pub fn encode_and_encrypt_note_unconstrained( + context: &mut PrivateContext, + ov: AztecAddress, + iv: AztecAddress +) -> fn[(&mut PrivateContext, AztecAddress, AztecAddress)](NoteEmission) -> () where Note: NoteInterface, [Field; N]: LensForEncryptedLog { + | e: NoteEmission | { + let header = context.get_header(); + let ovpk = header.get_ovpk_m(context, ov); + let ivpk = header.get_ivpk_m(context, iv); + emit_with_keys(context, e.note, ovpk, ivpk, compute_unconstrained); } } @@ -52,6 +90,16 @@ pub fn encode_and_encrypt_note_with_keys( ivpk: GrumpkinPoint ) -> fn[(&mut PrivateContext, GrumpkinPoint, GrumpkinPoint)](NoteEmission) -> () where Note: NoteInterface, [Field; N]: LensForEncryptedLog { | e: NoteEmission | { - emit_with_keys(context, e.note, ovpk, ivpk); + emit_with_keys(context, e.note, ovpk, ivpk, compute); + } +} + +pub fn encode_and_encrypt_note_with_keys_unconstrained( + context: &mut PrivateContext, + ovpk: GrumpkinPoint, + ivpk: GrumpkinPoint +) -> fn[(&mut PrivateContext, GrumpkinPoint, GrumpkinPoint)](NoteEmission) -> () where Note: NoteInterface, [Field; N]: LensForEncryptedLog { + | e: NoteEmission | { + emit_with_keys(context, e.note, ovpk, ivpk, compute_unconstrained); } } diff --git a/noir-projects/aztec-nr/aztec/src/history/contract_inclusion.nr b/noir-projects/aztec-nr/aztec/src/history/contract_inclusion.nr index 986ccc39e2f..78ce23575e4 100644 --- a/noir-projects/aztec-nr/aztec/src/history/contract_inclusion.nr +++ b/noir-projects/aztec-nr/aztec/src/history/contract_inclusion.nr @@ -31,7 +31,9 @@ impl ProveContractNonDeployment for Header { contract_address.to_field() ); + // docs:start:prove_nullifier_non_inclusion self.prove_nullifier_non_inclusion(nullifier); + // docs:end:prove_nullifier_non_inclusion } } diff --git a/noir-projects/aztec-nr/aztec/src/history/nullifier_inclusion.nr b/noir-projects/aztec-nr/aztec/src/history/nullifier_inclusion.nr index 69d571e9623..ea2a199d75c 100644 --- a/noir-projects/aztec-nr/aztec/src/history/nullifier_inclusion.nr +++ b/noir-projects/aztec-nr/aztec/src/history/nullifier_inclusion.nr @@ -36,9 +36,11 @@ trait ProveNoteIsNullified { } impl ProveNoteIsNullified for Header { + // docs:start:prove_note_is_nullified fn prove_note_is_nullified(self, note: Note, context: &mut PrivateContext) where Note: NoteInterface { let nullifier = compute_siloed_nullifier(note, context); self.prove_nullifier_inclusion(nullifier); } + // docs:end:prove_note_is_nullified } diff --git a/noir-projects/aztec-nr/aztec/src/history/nullifier_non_inclusion.nr b/noir-projects/aztec-nr/aztec/src/history/nullifier_non_inclusion.nr index eb67b1bb23d..d43b7c3e1cd 100644 --- a/noir-projects/aztec-nr/aztec/src/history/nullifier_non_inclusion.nr +++ b/noir-projects/aztec-nr/aztec/src/history/nullifier_non_inclusion.nr @@ -44,9 +44,11 @@ trait ProveNoteNotNullified { } impl ProveNoteNotNullified for Header { + // docs:start:prove_note_not_nullified fn prove_note_not_nullified(self, note: Note, context: &mut PrivateContext) where Note: NoteInterface { let nullifier = compute_siloed_nullifier(note, context); self.prove_nullifier_non_inclusion(nullifier); } + // docs:end:prove_note_not_nullified } diff --git a/noir-projects/aztec-nr/aztec/src/lib.nr b/noir-projects/aztec-nr/aztec/src/lib.nr index 7e7b1af2a8a..d4b1abf35e7 100644 --- a/noir-projects/aztec-nr/aztec/src/lib.nr +++ b/noir-projects/aztec-nr/aztec/src/lib.nr @@ -10,8 +10,8 @@ mod event; mod oracle; mod state_vars; mod prelude; -mod public_storage; mod encrypted_logs; +mod unencrypted_logs; use dep::protocol_types; mod utils; diff --git a/noir-projects/aztec-nr/aztec/src/note/note_getter.nr b/noir-projects/aztec-nr/aztec/src/note/note_getter.nr index 53648875124..b5df4dd7ce7 100644 --- a/noir-projects/aztec-nr/aztec/src/note/note_getter.nr +++ b/noir-projects/aztec-nr/aztec/src/note/note_getter.nr @@ -127,7 +127,7 @@ fn constrain_get_notes_internal( let filtered_notes = filter_fn(opt_notes, filter_args); let mut prev_fields = [0; N]; - for i in 0..filtered_notes.len() { + for i in 0..options.limit { let opt_note = filtered_notes[i]; if opt_note.is_some() { let note = opt_note.unwrap_unchecked(); @@ -154,7 +154,13 @@ fn constrain_get_notes_internal( }; } + // As long as we only loop till `options.limit` the array will be guaranteed to be at most of length `options.limit`. assert(returned_notes.len() <= options.limit, "Got more notes than limit."); + // We will however check that nothing else was returned after the limit. + for i in options.limit..filtered_notes.len() { + assert(filtered_notes[i].is_none(), "Got more notes than limit."); + } + assert(returned_notes.len() != 0, "Cannot return zero notes"); returned_notes diff --git a/noir-projects/aztec-nr/aztec/src/oracle/logs_traits.nr b/noir-projects/aztec-nr/aztec/src/oracle/logs_traits.nr index 899f7f0d0d1..c3d2cfb83c7 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/logs_traits.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/logs_traits.nr @@ -40,6 +40,30 @@ impl LensForEncryptedLog<6, 672> for [Field; 6] { fn output_fields(self) -> [Field; 6] {[self[0]; 6]} fn output_bytes(self) -> [u8; 672] {[self[0] as u8; 672]} } +impl LensForEncryptedLog<7, 704> for [Field; 7] { + fn output_fields(self) -> [Field; 7] {[self[0]; 7]} + fn output_bytes(self) -> [u8; 704] {[self[0] as u8; 704]} +} +impl LensForEncryptedLog<8, 736> for [Field; 8] { + fn output_fields(self) -> [Field; 8] {[self[0]; 8]} + fn output_bytes(self) -> [u8; 736] {[self[0] as u8; 736]} +} +impl LensForEncryptedLog<9, 768> for [Field; 9] { + fn output_fields(self) -> [Field; 9] {[self[0]; 9]} + fn output_bytes(self) -> [u8; 768] {[self[0] as u8; 768]} +} +impl LensForEncryptedLog<10, 800> for [Field; 10] { + fn output_fields(self) -> [Field; 10] {[self[0]; 10]} + fn output_bytes(self) -> [u8; 800] {[self[0] as u8; 800]} +} +impl LensForEncryptedLog<11, 832> for [Field; 11] { + fn output_fields(self) -> [Field; 11] {[self[0]; 11]} + fn output_bytes(self) -> [u8; 832] {[self[0] as u8; 832]} +} +impl LensForEncryptedLog<12, 864> for [Field; 12] { + fn output_fields(self) -> [Field; 12] {[self[0]; 12]} + fn output_bytes(self) -> [u8; 864] {[self[0] as u8; 864]} +} trait LensForEncryptedEvent { // N = event preimage input in bytes diff --git a/noir-projects/aztec-nr/aztec/src/oracle/storage.nr b/noir-projects/aztec-nr/aztec/src/oracle/storage.nr index b25e4a3b55c..b4a6b1f9102 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/storage.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/storage.nr @@ -1,19 +1,59 @@ -use dep::protocol_types::traits::{Deserialize, Serialize}; +use dep::protocol_types::{address::AztecAddress, traits::Deserialize}; #[oracle(storageRead)] -unconstrained fn storage_read_oracle(_storage_slot: Field, _number_of_elements: Field) -> [Field; N] {} +unconstrained fn storage_read_oracle( + address: Field, + storage_slot: Field, + block_number: Field, + length: Field +) -> [Field; N] {} -unconstrained fn storage_read_oracle_wrapper(_storage_slot: Field) -> [Field; N] { - storage_read_oracle(_storage_slot, N) +unconstrained pub fn raw_storage_read( + address: AztecAddress, + storage_slot: Field, + block_number: u32 +) -> [Field; N] { + storage_read_oracle(address.to_field(), storage_slot, block_number as Field, N) } -pub fn storage_read(storage_slot: Field) -> [Field; N] { - storage_read_oracle_wrapper(storage_slot) +unconstrained pub fn storage_read( + address: AztecAddress, + storage_slot: Field, + block_number: u32 +) -> T where T: Deserialize { + T::deserialize(raw_storage_read(address, storage_slot, block_number)) } -#[oracle(storageWrite)] -unconstrained fn storage_write_oracle(_storage_slot: Field, _values: [Field; N]) -> [Field; N] {} +mod tests { + use crate::oracle::storage::{raw_storage_read, storage_read}; + use dep::protocol_types::address::AztecAddress; -unconstrained pub fn storage_write(storage_slot: Field, fields: [Field; N]) { - let _hash = storage_write_oracle(storage_slot, fields); + use std::test::OracleMock; + use crate::test::mocks::mock_struct::MockStruct; + + global address = AztecAddress::from_field(29); + global slot = 7; + global block_number = 17; + + #[test] + fn test_raw_storage_read() { + let written = MockStruct { a: 13, b: 42 }; + + let _ = OracleMock::mock("storageRead").returns(written.serialize()); + + let read: [Field; 2] = raw_storage_read(address, slot, block_number); + assert_eq(read[0], 13); + assert_eq(read[1], 42); + } + + #[test] + fn test_storage_read() { + let written = MockStruct { a: 13, b: 42 }; + + let _ = OracleMock::mock("storageRead").returns(written.serialize()); + + let read: MockStruct = storage_read(address, slot, block_number); + assert_eq(read.a, 13); + assert_eq(read.b, 42); + } } diff --git a/noir-projects/aztec-nr/aztec/src/public_storage.nr b/noir-projects/aztec-nr/aztec/src/public_storage.nr deleted file mode 100644 index 59bc25b5197..00000000000 --- a/noir-projects/aztec-nr/aztec/src/public_storage.nr +++ /dev/null @@ -1,72 +0,0 @@ -use dep::protocol_types::traits::{Deserialize, Serialize}; -use crate::oracle::storage::{storage_read, storage_write}; - -pub fn read(storage_slot: Field) -> T where T: Deserialize { - T::deserialize(storage_read(storage_slot)) -} - -pub fn write(storage_slot: Field, value: T) where T: Serialize { - storage_write(storage_slot, value.serialize()); -} - -// Ideally we'd do the following, but we cannot because of https://github.com/noir-lang/noir/issues/4633 -// pub fn read_historical( -// storage_slot: Field, -// context: PrivateContext -// ) -> T where T: Deserialize { -// let mut fields = [0; N]; -// for i in 0..N { -// fields[i] = public_storage_historical_read( -// context, -// storage_slot + i as Field, -// context.this_address() -// ); -// } -// T::deserialize(fields) -// } - -mod tests { - use std::test::OracleMock; - use dep::protocol_types::traits::{Deserialize, Serialize}; - use crate::public_storage; - - struct TestStruct { - a: Field, - b: Field, - } - - impl Deserialize<2> for TestStruct { - fn deserialize(fields: [Field; 2]) -> TestStruct { - TestStruct { a: fields[0], b: fields[1] } - } - } - - impl Serialize<2> for TestStruct { - fn serialize(self) -> [Field; 2] { - [self.a, self.b] - } - } - - #[test] - fn test_read() { - let slot = 7; - let written = TestStruct { a: 13, b: 42 }; - - OracleMock::mock("storageRead").with_params((slot, 2)).returns(written.serialize()); - - let read: TestStruct = public_storage::read(slot); - assert_eq(read.a, 13); - assert_eq(read.b, 42); - } - - #[test] - fn test_write() { - let slot = 7; - let to_write = TestStruct { a: 13, b: 42 }; - - let mock = OracleMock::mock("storageWrite").returns([0; 2]); // The return value is unused - - public_storage::write(slot, to_write); - assert_eq(mock.get_last_params(), (slot, to_write.serialize())); - } -} diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/public_immutable.nr b/noir-projects/aztec-nr/aztec/src/state_vars/public_immutable.nr index b8f2c1d2dde..1206916cf79 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/public_immutable.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/public_immutable.nr @@ -1,5 +1,5 @@ use crate::{ - context::{PublicContext, UnconstrainedContext}, oracle::{storage::{storage_read, storage_write}}, + context::{PublicContext, UnconstrainedContext}, oracle::storage::storage_read, state_vars::storage::Storage }; use dep::protocol_types::{constants::INITIALIZATION_SLOT_SEPARATOR, traits::{Deserialize, Serialize}}; @@ -30,39 +30,27 @@ impl PublicImmutable { impl PublicImmutable { // docs:start:public_immutable_struct_write pub fn initialize(self, value: T) where T: Serialize { - // TODO(#4738): Uncomment the following assert - // assert( - // self.context.public.unwrap_unchecked().is_deployment(), "PublicImmutable can only be initialized during contract deployment" - // ); - // We check that the struct is not yet initialized by checking if the initialization slot is 0 let initialization_slot = INITIALIZATION_SLOT_SEPARATOR + self.storage_slot; - let fields_read: [Field; 1] = storage_read(initialization_slot); - assert(fields_read[0] == 0, "PublicImmutable already initialized"); + let init_field: Field = self.context.storage_read(initialization_slot); + assert(init_field == 0, "PublicImmutable already initialized"); // We populate the initialization slot with a non-zero value to indicate that the struct is initialized - storage_write(initialization_slot, [0xdead]); - - let fields_write = T::serialize(value); - storage_write(self.storage_slot, fields_write); + self.context.storage_write(initialization_slot, 0xdead); + self.context.storage_write(self.storage_slot, value); } // docs:end:public_immutable_struct_write // Note that we don't access the context, but we do call oracles that are only available in public // docs:start:public_immutable_struct_read pub fn read(self) -> T where T: Deserialize { - let fields = storage_read(self.storage_slot); - T::deserialize(fields) + self.context.storage_read(self.storage_slot) } // docs:end:public_immutable_struct_read } impl PublicImmutable { - pub fn read(self) -> T where T: Deserialize { - // This looks the same as the &mut PublicContext impl, but is actually very different. In public execution the - // storage read oracle gets transpiled to SLOAD opcodes, whereas in unconstrained execution the PXE returns - // historical data. - let fields = storage_read(self.storage_slot); - T::deserialize(fields) + unconstrained pub fn read(self) -> T where T: Deserialize { + self.context.storage_read(self.storage_slot) } } diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/public_mutable.nr b/noir-projects/aztec-nr/aztec/src/state_vars/public_mutable.nr index 69a6a0f8a48..07038e14984 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/public_mutable.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/public_mutable.nr @@ -1,6 +1,5 @@ use crate::context::{PublicContext, UnconstrainedContext}; use crate::oracle::storage::storage_read; -use crate::oracle::storage::storage_write; use dep::protocol_types::traits::{Deserialize, Serialize}; use crate::state_vars::storage::Storage; @@ -29,25 +28,19 @@ impl PublicMutable { impl PublicMutable { // docs:start:public_mutable_struct_read pub fn read(self) -> T where T: Deserialize { - let fields = storage_read(self.storage_slot); - T::deserialize(fields) + self.context.storage_read(self.storage_slot) } // docs:end:public_mutable_struct_read // docs:start:public_mutable_struct_write pub fn write(self, value: T) where T: Serialize { - let fields = T::serialize(value); - storage_write(self.storage_slot, fields); + self.context.storage_write(self.storage_slot, value); } // docs:end:public_mutable_struct_write } impl PublicMutable { - pub fn read(self) -> T where T: Deserialize { - // This looks the same as the &mut PublicContext impl, but is actually very different. In public execution the - // storage read oracle gets transpiled to SLOAD opcodes, whereas in unconstrained execution the PXE returns - // historical data. - let fields = storage_read(self.storage_slot); - T::deserialize(fields) + unconstrained pub fn read(self) -> T where T: Deserialize { + self.context.storage_read(self.storage_slot) } } diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/shared_immutable.nr b/noir-projects/aztec-nr/aztec/src/state_vars/shared_immutable.nr index 086c47aca56..c366a38cfd1 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/shared_immutable.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/shared_immutable.nr @@ -1,6 +1,6 @@ use crate::{ - context::{PrivateContext, PublicContext, UnconstrainedContext}, - oracle::{storage::{storage_read, storage_write}}, state_vars::storage::Storage + context::{PrivateContext, PublicContext, UnconstrainedContext}, oracle::storage::storage_read, + state_vars::storage::Storage }; use dep::protocol_types::{constants::INITIALIZATION_SLOT_SEPARATOR, traits::{Deserialize, Serialize}}; @@ -26,33 +26,24 @@ impl SharedImmutable { impl SharedImmutable { // Intended to be only called once. pub fn initialize(self, value: T) where T: Serialize { - // TODO(#4738): Uncomment the following assert - // assert( - // self.context.public.unwrap_unchecked().is_deployment(), "SharedImmutable can only be initialized during contract deployment" - // ); - // We check that the struct is not yet initialized by checking if the initialization slot is 0 let initialization_slot = INITIALIZATION_SLOT_SEPARATOR + self.storage_slot; - let fields_read: [Field; 1] = storage_read(initialization_slot); - assert(fields_read[0] == 0, "SharedImmutable already initialized"); + let init_field: Field = self.context.storage_read(initialization_slot); + assert(init_field == 0, "SharedImmutable already initialized"); // We populate the initialization slot with a non-zero value to indicate that the struct is initialized - storage_write(initialization_slot, [0xdead]); - - let fields_write = T::serialize(value); - storage_write(self.storage_slot, fields_write); + self.context.storage_write(initialization_slot, 0xdead); + self.context.storage_write(self.storage_slot, value); } pub fn read_public(self) -> T where T: Deserialize { - let fields = storage_read(self.storage_slot); - T::deserialize(fields) + self.context.storage_read(self.storage_slot) } } impl SharedImmutable { - pub fn read_public(self) -> T where T: Deserialize { - let fields = storage_read(self.storage_slot); - T::deserialize(fields) + unconstrained pub fn read_public(self) -> T where T: Deserialize { + self.context.storage_read(self.storage_slot) } } diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/scheduled_delay_change.nr b/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/scheduled_delay_change.nr index 66f1400917e..7710c73f6a3 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/scheduled_delay_change.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/scheduled_delay_change.nr @@ -171,3 +171,9 @@ impl Deserialize<1> for ScheduledDelayChange { } } } + +impl Eq for ScheduledDelayChange { + fn eq(self, other: Self) -> bool { + (self.pre == other.pre) & (self.post == other.post) & (self.block_of_change == other.block_of_change) + } +} diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/scheduled_delay_change/test.nr b/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/scheduled_delay_change/test.nr index 5e4a6d9bcf9..c569510e2cd 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/scheduled_delay_change/test.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/scheduled_delay_change/test.nr @@ -7,6 +7,7 @@ fn assert_equal_after_conversion(original: ScheduledDelayChange = ScheduledDelayChange::deserialize((original).serialize()); + assert_eq(original, converted); // This also tests the Eq impl assert_eq(original.pre, converted.pre); assert_eq(original.post, converted.post); assert_eq(original.block_of_change, converted.block_of_change); diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/scheduled_value_change.nr b/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/scheduled_value_change.nr index 8ca92f61693..d0d84ad94c0 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/scheduled_value_change.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/scheduled_value_change.nr @@ -152,3 +152,9 @@ impl Deserialize<3> for ScheduledValueChange { } } } + +impl Eq for ScheduledValueChange { + fn eq(self, other: Self) -> bool where T: Eq { + (self.pre == other.pre) & (self.post == other.post) & (self.block_of_change == other.block_of_change) + } +} diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/scheduled_value_change/test.nr b/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/scheduled_value_change/test.nr index 8a48ee013be..5dab89c9701 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/scheduled_value_change/test.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/scheduled_value_change/test.nr @@ -11,6 +11,7 @@ fn test_serde() { let original = ScheduledValueChange::new(pre, post, block_of_change); let converted = ScheduledValueChange::deserialize((original).serialize()); + assert_eq(original, converted); // This also tests the Eq impl assert_eq(original.pre, converted.pre); assert_eq(original.post, converted.post); assert_eq(original.block_of_change, converted.block_of_change); diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/shared_mutable.nr b/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/shared_mutable.nr index 91c864a03b2..9823b25d8c9 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/shared_mutable.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/shared_mutable.nr @@ -1,11 +1,15 @@ -use dep::protocol_types::{hash::pedersen_hash, traits::FromField}; +use dep::protocol_types::{ + hash::{pedersen_hash, poseidon2_hash}, header::Header, address::AztecAddress, + traits::{FromField, ToField} +}; use crate::context::{PrivateContext, PublicContext}; -use crate::public_storage; use crate::state_vars::{ storage::Storage, shared_mutable::{scheduled_value_change::ScheduledValueChange, scheduled_delay_change::ScheduledDelayChange} }; +use crate::oracle::storage::storage_read; +use dep::std::unsafe::zeroed; mod test; @@ -19,10 +23,23 @@ struct SharedMutable { // - a ScheduledValueChange, which requires 1 + 2 * M storage slots, where M is the serialization length of T // - a ScheduledDelayChange, which requires another storage slot // -// TODO https://github.com/AztecProtocol/aztec-packages/issues/5736: change the storage allocation scheme so that we +// TODO https://github.com/AztecProtocol/aztec-packages/issues/5736: change the storage allocation scheme so that we // can actually use it here impl Storage for SharedMutable {} +// TODO: extract into a utils module once we can do arithmetic on generics, i.e. https://github.com/noir-lang/noir/issues/4784 +fn concat_arrays(arr_n: [Field; N], arr_m: [Field; M]) -> [Field; O] { + assert_eq(N + M, O); + let mut out: [Field; O] = [0; O]; + for i in 0..N { + out[i] = arr_n[i]; + } + for i in 0..M { + out[N+i] = arr_m[i]; + } + out +} + // SharedMutable stores a value of type T that is: // - publicly known (i.e. unencrypted) // - mutable in public @@ -30,9 +47,9 @@ impl Storage for SharedMutable SharedMutable { pub fn new(context: Context, storage_slot: Field) -> Self { @@ -40,10 +57,24 @@ impl SharedMutable { Self { context, storage_slot } } + fn hash_scheduled_data( + value_change: ScheduledValueChange, + delay_change: ScheduledDelayChange + ) -> Field where T: ToField { + // TODO(#5491 and https://github.com/noir-lang/noir/issues/4784): update this so that we don't need to rely on + // ScheduledValueChange serializing to 3 and ScheduledDelayChange serializing to 1 + let concatenated: [Field; 4] = concat_arrays(value_change.serialize(), delay_change.serialize()); + poseidon2_hash(concatenated) + } + // Since we can't rely on the native storage allocation scheme, we hash the storage slot to get a unique location in - // which we can safely store as much data as we need. - // See https://github.com/AztecProtocol/aztec-packages/issues/5492 and + // which we can safely store as much data as we need. + // See https://github.com/AztecProtocol/aztec-packages/issues/5492 and // https://github.com/AztecProtocol/aztec-packages/issues/5736 + // We store three things in public storage: + // - a ScheduledValueChange + // - a ScheduledDelaChange + // - the hash of both of these (via `hash_scheduled_data`) fn get_value_change_storage_slot(self) -> Field { pedersen_hash([self.storage_slot, 0], 0) } @@ -51,10 +82,53 @@ impl SharedMutable { fn get_delay_change_storage_slot(self) -> Field { pedersen_hash([self.storage_slot, 1], 0) } + + fn get_hash_storage_slot(self) -> Field { + pedersen_hash([self.storage_slot, 2], 0) + } + + // It may seem odd that we take a header and address instead of reading from e.g. a PrivateContext, but this lets us + // reuse this function in SharedMutablePrivateGetter. + fn historical_read_from_public_storage( + self, + header: Header, + address: AztecAddress + ) -> (ScheduledValueChange, ScheduledDelayChange, u32) where T: FromField + ToField + Eq { + let historical_block_number = header.global_variables.block_number as u32; + + // We could simply produce historical inclusion proofs for both the ScheduledValueChange and + // ScheduledDelayChange, but that'd require one full sibling path per storage slot (since due to kernel siloing + // the storage is not contiguous), and in the best case in which T is a single field that'd be 4 slots. + // Instead, we get an oracle to provide us the correct values for both the value and delay changes, and instead + // prove inclusion of their hash, which is both a much smaller proof (a single slot), and also independent of + // the size of T. + let (value_change_hint, delay_change_hint) = get_public_storage_hints(address, self.storage_slot, historical_block_number); + + // Ideally the following would be simply public_storage::read_historical, but we can't implement that yet. + let hash = header.public_storage_historical_read(self.get_hash_storage_slot(), address); + + // @todo This is written strangely to bypass a formatting issue with the if that is breaking ci. + let (a, b, c) = if hash != 0 { + let a = SharedMutable::hash_scheduled_data(value_change_hint, delay_change_hint); + (a, value_change_hint, delay_change_hint) + } else { + // The hash slot can only hold a zero if it is uninitialized, meaning no value or delay change was ever + // scheduled. Therefore, the hints must then correspond to uninitialized scheduled changes. + let b = ScheduledValueChange::deserialize(zeroed()); + let c = ScheduledDelayChange::deserialize(zeroed()); + (hash, b, c) + }; + + assert_eq(hash, a, "Hint values do not match hash"); + assert_eq(value_change_hint, b, "Non-zero value change for zero hash"); + assert_eq(delay_change_hint, c, "Non-zero delay change for zero hash"); + + (value_change_hint, delay_change_hint, historical_block_number) + } } impl SharedMutable { - pub fn schedule_value_change(self, new_value: T) { + pub fn schedule_value_change(self, new_value: T) where T: ToField { let mut value_change = self.read_value_change(); let delay_change = self.read_delay_change(); @@ -66,17 +140,17 @@ impl SharedMutable { let block_of_change = block_number + current_delay; value_change.schedule_change(new_value, block_number, current_delay, block_of_change); - self.write_value_change(value_change); + self.write(value_change, delay_change); } - pub fn schedule_delay_change(self, new_delay: u32) { + pub fn schedule_delay_change(self, new_delay: u32) where T: ToField { let mut delay_change = self.read_delay_change(); let block_number = self.context.block_number() as u32; delay_change.schedule_change(new_delay, block_number); - self.write_delay_change(delay_change); + self.write(self.read_value_change(), delay_change); } pub fn get_current_value_in_public(self) -> T { @@ -98,71 +172,71 @@ impl SharedMutable { } fn read_value_change(self) -> ScheduledValueChange { - public_storage::read(self.get_value_change_storage_slot()) + self.context.storage_read(self.get_value_change_storage_slot()) } fn read_delay_change(self) -> ScheduledDelayChange { - public_storage::read(self.get_delay_change_storage_slot()) + self.context.storage_read(self.get_delay_change_storage_slot()) } - fn write_value_change(self, value_change: ScheduledValueChange) { - public_storage::write(self.get_value_change_storage_slot(), value_change); - } - - fn write_delay_change(self, delay_change: ScheduledDelayChange) { - public_storage::write(self.get_delay_change_storage_slot(), delay_change); + fn write( + self, + value_change: ScheduledValueChange, + delay_change: ScheduledDelayChange + ) where T: ToField { + // Whenever we write to public storage, we write both the value change and delay change as well as the hash of + // them both. This guarantees that the hash is always kept up to date. + // While this makes for more costly writes, it also makes private proofs much simpler because they only need to + // produce a historical proof for the hash, which results in a single inclusion proof (as opposed to 4 in the + // best case scenario in which T is a single field). Private shared mutable reads are assumed to be much more + // frequent than public writes, so this tradeoff makes sense. + self.context.storage_write(self.get_value_change_storage_slot(), value_change); + self.context.storage_write(self.get_delay_change_storage_slot(), delay_change); + self.context.storage_write( + self.get_hash_storage_slot(), + SharedMutable::hash_scheduled_data(value_change, delay_change) + ); } } impl SharedMutable { - pub fn get_current_value_in_private(self) -> T where T: FromField { + pub fn get_current_value_in_private(self) -> T where T: FromField + ToField + Eq { // When reading the current value in private we construct a historical state proof for the public value. // However, since this value might change, we must constrain the maximum transaction block number as this proof // will only be valid for however many blocks we can ensure the value will not change, which will depend on the // current delay and any scheduled delay changes. - let (value_change, delay_change, historical_block_number) = self.historical_read_from_public_storage(*self.context); + let (value_change, delay_change, historical_block_number) = self.historical_read_from_public_storage(self.context.get_header(), self.context.this_address()); // We use the effective minimum delay as opposed to the current delay at the historical block as this one also - // takes into consideration any scheduled delay changes. + // takes into consideration any scheduled delay changes. // For example, consider a scenario in which at block 200 the current delay was 50. We may naively think that // the earliest we could change the value would be at block 251 by scheduling immediately after the historical - // block, i.e. at block 201. But if there was a delay change scheduled for block 210 to reduce the delay to 20 - // blocks, then if a value change was scheduled at block 210 it would go into effect at block 230, which is + // block, i.e. at block 201. But if there was a delay change scheduled for block 210 to reduce the delay to 20 + // blocks, then if a value change was scheduled at block 210 it would go into effect at block 230, which is // earlier than what we'd expect if we only considered the current delay. let effective_minimum_delay = delay_change.get_effective_minimum_delay_at(historical_block_number); let block_horizon = value_change.get_block_horizon(historical_block_number, effective_minimum_delay); - // We prevent this transaction from being included in any block after the block horizon, ensuring that the + // We prevent this transaction from being included in any block after the block horizon, ensuring that the // historical public value matches the current one, since it can only change after the horizon. self.context.set_tx_max_block_number(block_horizon); value_change.get_current_at(historical_block_number) } +} - fn historical_read_from_public_storage( - self, - context: PrivateContext - ) -> (ScheduledValueChange, ScheduledDelayChange, u32) where T: FromField { - let header = context.get_header(); - // Ideally the following would be simply public_storage::read_historical, but we can't implement that yet. - let value_change_slot = self.get_value_change_storage_slot(); - let mut raw_value_change_fields = [0; 3]; - for i in 0..3 { - raw_value_change_fields[i] = header.public_storage_historical_read( - value_change_slot + i as Field, - context.this_address() - ); - } - - // Ideally the following would be simply public_storage::read_historical, but we can't implement that yet. - let delay_change_slot = self.get_delay_change_storage_slot(); - let raw_delay_change_fields = [header.public_storage_historical_read(delay_change_slot, context.this_address())]; - - let value_change = ScheduledValueChange::deserialize(raw_value_change_fields); - let delay_change = ScheduledDelayChange::deserialize(raw_delay_change_fields); - - let historical_block_number = context.historical_header.global_variables.block_number as u32; - - (value_change, delay_change, historical_block_number) - } +unconstrained fn get_public_storage_hints( + address: AztecAddress, + storage_slot: Field, + block_number: u32 +) -> (ScheduledValueChange, ScheduledDelayChange) { + // This function cannot be part of the &mut PrivateContext impl because that'd mean that by passing `self` we'd also + // be passing a mutable reference to an unconstrained function, which is not allowed. We therefore create a dummy + // state variable here so that we can access the methods to compute storage slots. This will all be removed in the + // future once we do proper storage slot allocation (#5492). + let dummy = SharedMutable::new((), storage_slot); + + ( + storage_read(address, dummy.get_value_change_storage_slot(), block_number), storage_read(address, dummy.get_delay_change_storage_slot(), block_number) + ) } diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/shared_mutable_private_getter.nr b/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/shared_mutable_private_getter.nr index 5a6ad9ad6fd..78c7cc66bb3 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/shared_mutable_private_getter.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/shared_mutable_private_getter.nr @@ -1,10 +1,15 @@ -use dep::protocol_types::{hash::pedersen_hash, traits::FromField, address::AztecAddress, header::Header}; +use dep::protocol_types::{ + hash::{pedersen_hash, poseidon2_hash}, traits::{FromField, ToField}, address::AztecAddress, + header::Header +}; use crate::context::PrivateContext; -use crate::public_storage; use crate::state_vars::{ storage::Storage, - shared_mutable::{scheduled_delay_change::ScheduledDelayChange, scheduled_value_change::ScheduledValueChange} + shared_mutable::{ + shared_mutable::SharedMutable, scheduled_delay_change::ScheduledDelayChange, + scheduled_value_change::ScheduledValueChange +} }; struct SharedMutablePrivateGetter { @@ -31,8 +36,12 @@ impl SharedMutablePrivateGetter { Self { context, other_contract_address, storage_slot, _dummy: [0; INITIAL_DELAY] } } - pub fn get_value_in_private(self, header: Header) -> T where T: FromField { - let (value_change, delay_change, historical_block_number) = self.historical_read_from_public_storage(header); + pub fn get_value_in_private(self, header: Header) -> T where T: FromField + ToField + Eq { + // We create a dummy SharedMutable state variable so that we can reuse its historical_read_from_public_storage + // method, greatly reducing code duplication. + let dummy: SharedMutable = SharedMutable::new((), self.storage_slot); + let (value_change, delay_change, historical_block_number) = dummy.historical_read_from_public_storage(header, self.other_contract_address); + let effective_minimum_delay = delay_change.get_effective_minimum_delay_at(historical_block_number); let block_horizon = value_change.get_block_horizon(historical_block_number, effective_minimum_delay); @@ -45,36 +54,4 @@ impl SharedMutablePrivateGetter { value_change.get_current_at(historical_block_number) } - - fn historical_read_from_public_storage( - self, - header: Header - ) -> (ScheduledValueChange, ScheduledDelayChange, u32) where T: FromField { - let value_change_slot = self.get_value_change_storage_slot(); - let mut raw_value_change_fields = [0; 3]; - for i in 0..3 { - raw_value_change_fields[i] = header.public_storage_historical_read( - value_change_slot + i as Field, - self.other_contract_address - ); - } - - let delay_change_slot = self.get_delay_change_storage_slot(); - let raw_delay_change_fields = [header.public_storage_historical_read(delay_change_slot, self.other_contract_address)]; - - let value_change = ScheduledValueChange::deserialize(raw_value_change_fields); - let delay_change = ScheduledDelayChange::deserialize(raw_delay_change_fields); - - let historical_block_number = header.global_variables.block_number as u32; - - (value_change, delay_change, historical_block_number) - } - - fn get_value_change_storage_slot(self) -> Field { - pedersen_hash([self.storage_slot, 0], 0) - } - - fn get_delay_change_storage_slot(self) -> Field { - pedersen_hash([self.storage_slot, 1], 0) - } } diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/test.nr b/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/test.nr index b193640a54b..abf0e28940b 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/test.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/test.nr @@ -1,18 +1,22 @@ use crate::{ - context::{PublicContext, PrivateContext}, state_vars::shared_mutable::shared_mutable::SharedMutable, + context::{PublicContext, PrivateContext}, + state_vars::shared_mutable::{ + shared_mutable::SharedMutable, scheduled_value_change::ScheduledValueChange, + scheduled_delay_change::ScheduledDelayChange +}, test::helpers::test_environment::TestEnvironment }; use dep::protocol_types::address::AztecAddress; +use dep::std::{test::OracleMock, unsafe::zeroed}; -global new_value = 57; +global new_value = 17; -global pre_delay = 20; -global post_delay = 15; +global new_delay = 20; -global storage_slot = 57; +global storage_slot = 47; -global TEST_INITIAL_DELAY: u32 = 30; +global TEST_INITIAL_DELAY: u32 = 32; fn setup() -> TestEnvironment { TestEnvironment::new() @@ -29,335 +33,291 @@ fn in_private( SharedMutable::new(&mut env.private_at(historical_block_number), storage_slot) } -// #[test] -// fn test_get_current_value_in_public_initial() { -// let env = setup(); -// let state_var = in_public(env); +#[test] +fn test_get_current_value_in_public_initial() { + let env = setup(); + let state_var = in_public(env); -// // 0 is the default empty value for a Field -// assert_eq(state_var.get_current_value_in_public(), 0); -// } + assert_eq(state_var.get_current_value_in_public(), zeroed()); +} + +#[test] +fn test_get_scheduled_value_in_public() { + let mut env = setup(); + let state_var = in_public(env); + + state_var.schedule_value_change(new_value); + + let (scheduled, block_of_change) = state_var.get_scheduled_value_in_public(); + assert_eq(scheduled, new_value); + assert_eq(block_of_change, env.block_number() + TEST_INITIAL_DELAY); +} + +#[test] +fn test_get_current_value_in_public_before_scheduled_change() { + let mut env = setup(); + let state_var = in_public(env); + + state_var.schedule_value_change(new_value); + + let (_, block_of_change) = state_var.get_scheduled_value_in_public(); + + let original_value = zeroed(); + + // The current value has not changed + assert_eq(state_var.get_current_value_in_public(), original_value); + + // The current value still does not change right before the block of change + env.advance_block_to(block_of_change - 1); + assert_eq(state_var.get_current_value_in_public(), original_value); +} + +#[test] +fn test_get_current_value_in_public_at_scheduled_change() { + let mut env = setup(); + let state_var = in_public(env); + + state_var.schedule_value_change(new_value); -// #[test] -// fn test_get_current_value_in_public_before_scheduled_change() { -// let mut env = setup(); -// let state_var = in_public(env); + let (_, block_of_change) = state_var.get_scheduled_value_in_public(); -// state_var.schedule_value_change(new_value); + env.advance_block_to(block_of_change); + assert_eq(state_var.get_current_value_in_public(), new_value); +} -// let (_, block_of_change) = state_var.get_scheduled_value_in_public(); +#[test] +fn test_get_current_value_in_public_after_scheduled_change() { + let mut env = setup(); + let state_var = in_public(env); -// let original_value = 0; + state_var.schedule_value_change(new_value); -// // The current value has not changed -// assert_eq(state_var.get_current_value_in_public(), original_value); + let (_, block_of_change) = state_var.get_scheduled_value_in_public(); -// // The current value still does not change right before the block of change -// env.advance_block_to(block_of_change - 1); -// assert_eq(state_var.get_current_value_in_public(), original_value); -// } + env.advance_block_to(block_of_change + 10); + assert_eq(state_var.get_current_value_in_public(), new_value); +} -// #[test] -// fn test_get_current_value_in_public_at_scheduled_change() { -// let mut env = setup(); -// let state_var = in_public(env); +#[test] +fn test_get_current_delay_in_public_initial() { + let env = setup(); + let state_var = in_public(env); -// state_var.schedule_value_change(new_value); + assert_eq(state_var.get_current_delay_in_public(), TEST_INITIAL_DELAY); +} -// let (_, block_of_change) = state_var.get_scheduled_value_in_public(); +#[test] +fn test_get_scheduled_delay_in_public() { + let mut env = setup(); + let state_var = in_public(env); -// env.advance_block_to(block_of_change); -// assert_eq(state_var.get_current_value_in_public(), new_value); -// } + state_var.schedule_delay_change(new_delay); -// #[test] -// fn test_get_current_value_in_public_after_scheduled_change() { -// let mut env = setup(); -// let state_var = in_public(env); + let (scheduled, block_of_change) = state_var.get_scheduled_delay_in_public(); + assert_eq(scheduled, new_delay); + // The new delay is smaller, therefore we need to wait for the difference between current and new + assert_eq(block_of_change, env.block_number() + TEST_INITIAL_DELAY - new_delay); +} -// state_var.schedule_value_change(new_value); +#[test] +fn test_get_current_delay_in_public_before_scheduled_change() { + let mut env = setup(); + let state_var = in_public(env); -// let (_, block_of_change) = state_var.get_scheduled_value_in_public(); + state_var.schedule_delay_change(new_delay); -// env.advance_block_to(block_of_change + 10); -// assert_eq(state_var.get_current_value_in_public(), new_value); -// } + let (_, block_of_change) = state_var.get_scheduled_delay_in_public(); -// #[test] -// fn test_get_current_value_in_private_before_change() { -// let mut env = setup(); + let original_delay = TEST_INITIAL_DELAY; + + // The current delay has not changed + assert_eq(state_var.get_current_delay_in_public(), original_delay); + + // The current delay still does not change right before the block of change + env.advance_block_to(block_of_change - 1); + assert_eq(state_var.get_current_delay_in_public(), original_delay); +} -// let public_state_var = in_public(env); -// public_state_var.schedule_value_change(new_value); +#[test] +fn test_get_current_delay_in_public_at_scheduled_change() { + let mut env = setup(); + let state_var = in_public(env); -// let (_, block_of_change) = public_state_var.get_scheduled_value_in_public(); + state_var.schedule_delay_change(new_delay); -// let schedule_block_number = env.block_number(); + let (_, block_of_change) = state_var.get_scheduled_delay_in_public(); -// let private_state_var = in_private(&mut env, schedule_block_number); -// assert_eq(private_state_var.get_current_value_in_private(), 0); -// assert_eq(private_state_var.context.max_block_number.unwrap(), block_of_change - 1); -// } + env.advance_block_to(block_of_change); + assert_eq(state_var.get_current_delay_in_public(), new_delay); +} -// #[test] -// fn test_get_current_value_in_private_immediately_before_change() { -// let mut env = setup(); +#[test] +fn test_get_current_delay_in_public_after_scheduled_change() { + let mut env = setup(); + let state_var = in_public(env); -// let public_state_var = in_public(env); -// public_state_var.schedule_value_change(new_value); + state_var.schedule_delay_change(new_delay); -// let (_, block_of_change) = public_state_var.get_scheduled_value_in_public(); + let (_, block_of_change) = state_var.get_scheduled_delay_in_public(); -// let private_state_var = in_private(&mut env, block_of_change - 1); + env.advance_block_to(block_of_change + 10); + assert_eq(state_var.get_current_delay_in_public(), new_delay); +} -// assert_eq(private_state_var.get_current_value_in_private(), 0); -// assert_eq(private_state_var.context.max_block_number.unwrap(), block_of_change - 1); -// } +#[test] +fn test_get_current_value_in_private_initial() { + let mut env = setup(); -// #[test] -// fn test_get_current_value_in_private_at_change() { -// let mut env = setup(); + let historical_block_number = env.block_number(); + let state_var = in_private(&mut env, historical_block_number); -// let public_state_var = in_public(env); -// public_state_var.schedule_value_change(new_value); + assert_eq(state_var.get_current_value_in_private(), zeroed()); + assert_eq(state_var.context.max_block_number.unwrap(), historical_block_number + TEST_INITIAL_DELAY); +} -// let (_, block_of_change) = public_state_var.get_scheduled_value_in_public(); +#[test] +fn test_get_current_value_in_private_before_change() { + let mut env = setup(); -// let historical_block_number = block_of_change; -// let private_state_var = in_private(&mut env, historical_block_number); -// assert_eq(private_state_var.get_current_value_in_private(), new_value); -// assert_eq( -// private_state_var.context.max_block_number.unwrap(), historical_block_number + TEST_INITIAL_DELAY -// ); -// } + let public_state_var = in_public(env); + public_state_var.schedule_value_change(new_value); -// #[test] -// fn test_get_current_value_in_private_after_change() { -// let mut env = setup(); + let (_, block_of_change) = public_state_var.get_scheduled_value_in_public(); -// let public_state_var = in_public(env); -// public_state_var.schedule_value_change(new_value); + let schedule_block_number = env.block_number(); -// let (_, block_of_change) = public_state_var.get_scheduled_value_in_public(); + let private_state_var = in_private(&mut env, schedule_block_number); + assert_eq(private_state_var.get_current_value_in_private(), 0); + assert_eq(private_state_var.context.max_block_number.unwrap(), block_of_change - 1); +} -// let historical_block_number = block_of_change + 10; -// let private_state_var = in_private(&mut env, historical_block_number); -// assert_eq(private_state_var.get_current_value_in_private(), new_value); -// assert_eq( -// private_state_var.context.max_block_number.unwrap(), historical_block_number + TEST_INITIAL_DELAY -// ); -// } +#[test] +fn test_get_current_value_in_private_immediately_before_change() { + let mut env = setup(); -// #[test] -// fn test_get_current_delay_in_public() { -// let (state_var, block_number) = setup(); + let public_state_var = in_public(env); + public_state_var.schedule_value_change(new_value); -// // Uninitialized -// mock_delay_change_read_uninitialized(state_var); -// assert_eq(state_var.get_current_delay_in_public(), TEST_INITIAL_DELAY as u32); + let (_, block_of_change) = public_state_var.get_scheduled_value_in_public(); -// // Change in the future, current value is pre -// mock_delay_change_read(state_var, pre_delay, post_delay, block_number + 1); -// assert_eq(state_var.get_current_delay_in_public(), pre_delay as u32); + let private_state_var = in_private(&mut env, block_of_change - 1); -// // Change in the current block, current value is post -// mock_delay_change_read(state_var, pre_delay, post_delay, block_number); -// assert_eq(state_var.get_current_delay_in_public(), post_delay as u32); + // Note that this transaction would never be valid since the max block number is the same as the historical block + // used to built the proof, i.e. in the past. + assert_eq(private_state_var.get_current_value_in_private(), 0); + assert_eq(private_state_var.context.max_block_number.unwrap(), block_of_change - 1); +} -// // Change in the past, current value is post -// mock_delay_change_read(state_var, pre_delay, post_delay, block_number - 1); -// assert_eq(state_var.get_current_delay_in_public(), post_delay as u32); -// } +#[test] +fn test_get_current_value_in_private_at_change() { + let mut env = setup(); -// #[test] -// fn test_get_scheduled_delay_in_public_before_change() { -// let (state_var, block_number) = setup(); + let public_state_var = in_public(env); + public_state_var.schedule_value_change(new_value); -// // Uninitialized -// mock_delay_change_read_uninitialized(state_var); -// assert_eq(state_var.get_scheduled_delay_in_public(), (TEST_INITIAL_DELAY as u32, 0)); + let (_, block_of_change) = public_state_var.get_scheduled_value_in_public(); -// // Change in the future, scheduled is post (always is) -// mock_delay_change_read(state_var, pre_delay, post_delay, block_number + 1); -// assert_eq(state_var.get_scheduled_delay_in_public(), (post_delay as u32, (block_number + 1) as u32)); + let historical_block_number = block_of_change; + let private_state_var = in_private(&mut env, historical_block_number); + assert_eq(private_state_var.get_current_value_in_private(), new_value); + assert_eq( + private_state_var.context.max_block_number.unwrap(), historical_block_number + TEST_INITIAL_DELAY + ); +} -// // Change in the current block, scheduled is post (always is) -// mock_delay_change_read(state_var, pre_delay, post_delay, block_number); -// assert_eq(state_var.get_scheduled_delay_in_public(), (post_delay as u32, block_number as u32)); +#[test] +fn test_get_current_value_in_private_after_change() { + let mut env = setup(); -// // Change in the past, scheduled is post (always is) -// mock_delay_change_read(state_var, pre_delay, post_delay, block_number - 1); -// assert_eq(state_var.get_scheduled_delay_in_public(), (post_delay as u32, (block_number - 1) as u32)); -// } + let public_state_var = in_public(env); + public_state_var.schedule_value_change(new_value); -// #[test] -// fn test_schedule_value_change_no_delay() { -// let (state_var, block_number) = setup(); + let (_, block_of_change) = public_state_var.get_scheduled_value_in_public(); -// // Last value change was in the past -// mock_value_change_read(state_var, pre_value, post_value, 0); - -// // Current delay is 0 -// mock_delay_change_read(state_var, 0, 0, block_number); - -// let write_mock = mock_value_change_write(); + let historical_block_number = block_of_change + 10; + let private_state_var = in_private(&mut env, historical_block_number); + assert_eq(private_state_var.get_current_value_in_private(), new_value); + assert_eq( + private_state_var.context.max_block_number.unwrap(), historical_block_number + TEST_INITIAL_DELAY + ); +} -// state_var.schedule_value_change(new_value); - -// // The new value has a block of change equal to the current block, i.e. it is the current value -// assert_value_change_write(state_var, write_mock, post_value, new_value, block_number); -// } - -// #[test] -// fn test_schedule_value_change_before_change_no_scheduled_delay() { -// let (state_var, block_number) = setup(); - -// // Value change in the future, delay change in the past -// mock_value_and_delay_read(state_var, block_number + 1, block_number - 1); -// let write_mock = mock_value_change_write(); - -// state_var.schedule_value_change(new_value); - -// // The new scheduled value change replaces the old one, post delay (current) is used -// assert_value_change_write( -// state_var, -// write_mock, -// pre_value, -// new_value, -// block_number + post_delay -// ); -// } - -// #[test] -// fn test_schedule_value_change_before_change_scheduled_delay() { -// let (state_var, block_number) = setup(); - -// // Value change in the future, delay change in the future -// mock_value_and_delay_read(state_var, block_number + 1, block_number + 1); - -// let write_mock = mock_value_change_write(); - -// state_var.schedule_value_change(new_value); - -// // The new scheduled value change replaces the old one, pre delay (current, not scheduled) is used -// assert_value_change_write( -// state_var, -// write_mock, -// pre_value, -// new_value, -// block_number + pre_delay -// ); -// } - -// #[test] -// fn test_schedule_value_change_after_change_no_scheduled_delay() { -// let (state_var, block_number) = setup(); - -// // Value change in the past, delay change in the past -// mock_value_and_delay_read(state_var, block_number - 1, block_number - 1); -// let write_mock = mock_value_change_write(); - -// state_var.schedule_value_change(new_value); - -// // The previous post value becomes the pre value, post delay (current) is used -// assert_value_change_write( -// state_var, -// write_mock, -// post_value, -// new_value, -// block_number + post_delay -// ); -// } - -// #[test] -// fn test_schedule_value_change_after_change_scheduled_delay() { -// let (state_var, block_number) = setup(); - -// // Value change in the past, delay change in the future -// mock_value_and_delay_read(state_var, block_number - 1, block_number + 1); - -// let write_mock = mock_value_change_write(); - -// state_var.schedule_value_change(new_value); - -// // The previous post value becomes the pre value, pre delay (current, not scheduled) is used -// assert_value_change_write( -// state_var, -// write_mock, -// post_value, -// new_value, -// block_number + pre_delay -// ); -// } - -// #[test] -// fn test_schedule_delay_increase_before_change() { -// let (state_var, block_number) = setup(); - -// // Delay change in future, current delay is pre -// mock_delay_change_read(state_var, pre_delay, post_delay, block_number + 1); -// let write_mock = mock_delay_change_write(); - -// let new_delay = pre_delay + 1; -// state_var.schedule_delay_change(new_delay as u32); - -// // The previous scheduled change is lost, change is immediate (due to increase) -// assert_delay_change_write(state_var, write_mock, pre_delay, new_delay, block_number); -// } - -// #[test] -// fn test_schedule_delay_reduction_before_change() { -// let (state_var, block_number) = setup(); - -// // Delay change in future, current delay is pre -// mock_delay_change_read(state_var, pre_delay, post_delay, block_number + 1); -// let write_mock = mock_delay_change_write(); - -// let new_delay = pre_delay - 1; -// state_var.schedule_delay_change(new_delay as u32); - -// // The previous scheduled change is lost, change delay equals difference (due to reduction) -// assert_delay_change_write( -// state_var, -// write_mock, -// pre_delay, -// new_delay, -// block_number + pre_delay - new_delay -// ); -// } - -// #[test] -// fn test_schedule_delay_increase_after_change() { -// let (state_var, block_number) = setup(); - -// // Delay change in the past, current delay is post -// mock_delay_change_read(state_var, pre_delay, post_delay, block_number - 1); -// let write_mock = mock_delay_change_write(); - -// let new_delay = post_delay + 1; -// state_var.schedule_delay_change(new_delay as u32); - -// // The current value becomes pre, change is immediate (due to increase) -// assert_delay_change_write(state_var, write_mock, post_delay, new_delay, block_number); -// } - -// #[test] -// fn test_schedule_delay_reduction_after_change() { -// let (state_var, block_number) = setup(); - -// // Delay change in the past, current delay is post -// mock_delay_change_read(state_var, pre_delay, post_delay, block_number - 1); -// let write_mock = mock_delay_change_write(); - -// let new_delay = post_delay - 1; -// state_var.schedule_delay_change(new_delay as u32); - -// // The current value becomes pre, change delay equals difference (due to reduction) -// assert_delay_change_write( -// state_var, -// write_mock, -// post_delay, -// new_delay, -// block_number + post_delay - new_delay -// ); -// } \ No newline at end of file +#[test] +fn test_get_current_value_in_private_with_non_initial_delay() { + let mut env = setup(); + + let public_state_var = in_public(env); + public_state_var.schedule_value_change(new_value); + public_state_var.schedule_delay_change(new_delay); + + let (_, value_block_of_change) = public_state_var.get_scheduled_value_in_public(); + let (_, delay_block_of_change) = public_state_var.get_scheduled_delay_in_public(); + + let historical_block_number = if value_block_of_change > delay_block_of_change { + value_block_of_change + } else { + delay_block_of_change + }; + + let private_state_var = in_private(&mut env, historical_block_number); + assert_eq(private_state_var.get_current_value_in_private(), new_value); + assert_eq(private_state_var.context.max_block_number.unwrap(), historical_block_number + new_delay); +} + +#[test(should_fail_with="Hint values do not match hash")] +fn test_get_current_value_in_private_bad_value_hints() { + let mut env = setup(); + + let public_state_var = in_public(env); + public_state_var.schedule_value_change(new_value); + + let schedule_block_number = env.block_number(); + let private_state_var = in_private(&mut env, schedule_block_number); + + let mocked: ScheduledValueChange = ScheduledValueChange::new(0, new_value + 1, schedule_block_number); + let _ = OracleMock::mock("storageRead").with_params((private_state_var.get_value_change_storage_slot(), 3)).returns(mocked.serialize()).times(1); + + let _ = private_state_var.get_current_value_in_private(); +} + +#[test(should_fail_with="Hint values do not match hash")] +fn test_get_current_value_in_private_bad_delay_hints() { + let mut env = setup(); + + let public_state_var = in_public(env); + public_state_var.schedule_value_change(new_value); + + let schedule_block_number = env.block_number(); + let private_state_var = in_private(&mut env, schedule_block_number); + + let mocked: ScheduledDelayChange = ScheduledDelayChange::new(Option::none(), Option::some(42), schedule_block_number); + let _ = OracleMock::mock("storageRead").with_params((private_state_var.get_delay_change_storage_slot(), 1)).returns(mocked.serialize()).times(1); + + let _ = private_state_var.get_current_value_in_private(); +} + +#[test(should_fail_with="Non-zero value change for zero hash")] +fn test_get_current_value_in_private_bad_zero_hash_value_hints() { + let mut env = setup(); + + let historical_block_number = env.block_number(); + let state_var = in_private(&mut env, historical_block_number); + + let mocked: ScheduledValueChange = ScheduledValueChange::new(0, new_value, 0); + let _ = OracleMock::mock("storageRead").with_params((state_var.get_value_change_storage_slot(), 3)).returns(mocked.serialize()).times(1); + + let _ = state_var.get_current_value_in_private(); +} + +#[test(should_fail_with="Non-zero delay change for zero hash")] +fn test_get_current_value_in_private_bad_zero_hash_delay_hints() { + let mut env = setup(); + + let historical_block_number = env.block_number(); + let state_var = in_private(&mut env, historical_block_number); + + let mocked: ScheduledDelayChange = ScheduledDelayChange::new(Option::none(), Option::some(new_delay), 0); + let _ = OracleMock::mock("storageRead").with_params((state_var.get_delay_change_storage_slot(), 1)).returns(mocked.serialize()).times(1); + + let _ = state_var.get_current_value_in_private(); +} diff --git a/noir-projects/aztec-nr/aztec/src/test/helpers/test_environment.nr b/noir-projects/aztec-nr/aztec/src/test/helpers/test_environment.nr index 9b66e64264b..e07b411e012 100644 --- a/noir-projects/aztec-nr/aztec/src/test/helpers/test_environment.nr +++ b/noir-projects/aztec-nr/aztec/src/test/helpers/test_environment.nr @@ -164,7 +164,6 @@ impl TestEnvironment { cheatcodes::set_contract_address(target_address); cheatcodes::set_msg_sender(original_contract_address); let mut inputs = cheatcodes::get_public_context_inputs(); - inputs.selector = call_interface.get_selector().to_field(); inputs.args_hash = hash_args(call_interface.get_args()); inputs.is_static_call = call_interface.get_is_static(); let result = original_fn(inputs); diff --git a/noir-projects/aztec-nr/aztec/src/test/helpers/utils.nr b/noir-projects/aztec-nr/aztec/src/test/helpers/utils.nr index 808b5ad37f5..87639e0fb73 100644 --- a/noir-projects/aztec-nr/aztec/src/test/helpers/utils.nr +++ b/noir-projects/aztec-nr/aztec/src/test/helpers/utils.nr @@ -82,7 +82,6 @@ impl Deployer { cheatcodes::set_contract_address(instance.to_address()); cheatcodes::set_msg_sender(original_contract_address); let mut inputs = cheatcodes::get_public_context_inputs(); - inputs.selector = call_interface.get_selector().to_field(); inputs.args_hash = hash_args(call_interface.get_args()); let _result: T = original_fn(inputs); diff --git a/noir-projects/aztec-nr/aztec/src/unencrypted_logs.nr b/noir-projects/aztec-nr/aztec/src/unencrypted_logs.nr new file mode 100644 index 00000000000..3eae1f8dc8e --- /dev/null +++ b/noir-projects/aztec-nr/aztec/src/unencrypted_logs.nr @@ -0,0 +1 @@ +mod unencrypted_event_emission; diff --git a/noir-projects/aztec-nr/aztec/src/unencrypted_logs/unencrypted_event_emission.nr b/noir-projects/aztec-nr/aztec/src/unencrypted_logs/unencrypted_event_emission.nr new file mode 100644 index 00000000000..f374a2a1195 --- /dev/null +++ b/noir-projects/aztec-nr/aztec/src/unencrypted_logs/unencrypted_event_emission.nr @@ -0,0 +1,58 @@ +use crate::{ + context::{PrivateContext, PublicContext}, event::event_interface::EventInterface, + encrypted_logs::payload::compute_encrypted_event_log, oracle::logs_traits::LensForEncryptedEvent +}; +use dep::protocol_types::{address::AztecAddress, grumpkin_point::GrumpkinPoint, traits::Serialize}; + +fn emit( + context: &mut PublicContext, + event: Event +) where Event: EventInterface, Event: Serialize, [Field; N]: LensForEventSelector { + let selector = Event::get_event_type_id(); + + let serialized_event = event.serialize(); + let mut emitted_log = [0; M]; + + // We put the selector in the "last" place, to avoid reading or assigning to an expression in an index + for i in 0..serialized_event.len() { + emitted_log[i] = serialized_event[i]; + } + + emitted_log[serialized_event.len()] = selector.to_field(); + + context.emit_unencrypted_log(emitted_log); +} + +pub fn encode_event(context: &mut PublicContext) -> fn[(&mut PublicContext,)](Event) -> () where Event: EventInterface, Event: Serialize, [Field; N]: LensForEventSelector { + | e: Event | { + emit( + context, + e, + ); + } +} + +trait LensForEventSelector { + // N = event preimage input in fields + // M = event preimage input in fields + event selector as field + fn output(self: [Field; N]) -> [Field; M]; +} + +impl LensForEventSelector<1, 2> for [Field; 1] { + fn output(self) -> [Field; 2] {[self[0] as Field; 2]} +} +impl LensForEventSelector<2, 3> for [Field; 2] { + fn output(self) -> [Field; 3] {[self[0] as Field; 3]} +} +impl LensForEventSelector<3, 4> for [Field; 3] { + fn output(self) -> [Field; 4] {[self[0] as Field; 4]} +} +impl LensForEventSelector<4, 5> for [Field; 4] { + fn output(self) -> [Field; 5] {[self[0] as Field; 5]} +} +impl LensForEventSelector<5, 6> for [Field; 5] { + fn output(self) -> [Field; 6] {[self[0] as Field; 6]} +} +impl LensForEventSelector<6, 7> for [Field; 6] { + fn output(self) -> [Field; 7] {[self[0] as Field; 7]} +} 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 16274f1db46..6132c880cb3 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 @@ -273,13 +273,8 @@ contract AvmTest { } #[aztec(public)] - fn get_fee_per_l2_gas() -> Field { - context.fee_per_l2_gas() - } - - #[aztec(public)] - fn get_fee_per_da_gas() -> Field { - context.fee_per_da_gas() + fn get_function_selector() -> FunctionSelector { + context.selector() } #[aztec(public)] @@ -307,6 +302,16 @@ contract AvmTest { context.timestamp() } + #[aztec(public)] + fn get_fee_per_l2_gas() -> Field { + context.fee_per_l2_gas() + } + + #[aztec(public)] + fn get_fee_per_da_gas() -> Field { + context.fee_per_da_gas() + } + #[aztec(public)] fn get_l2_gas_left() -> Field { context.l2_gas_left() diff --git a/noir-projects/noir-contracts/contracts/contract_class_registerer_contract/src/main.nr b/noir-projects/noir-contracts/contracts/contract_class_registerer_contract/src/main.nr index aa5e3bf242d..16d6f1ceaf6 100644 --- a/noir-projects/noir-contracts/contracts/contract_class_registerer_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/contract_class_registerer_contract/src/main.nr @@ -9,9 +9,11 @@ contract ContractClassRegisterer { ARTIFACT_FUNCTION_TREE_MAX_HEIGHT, FUNCTION_TREE_HEIGHT, MAX_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS, REGISTERER_CONTRACT_CLASS_REGISTERED_MAGIC_VALUE }, - traits::Serialize + traits::Serialize, abis::log_hash::LogHash }; + use dep::aztec::{context::PrivateContext, oracle::logs::emit_contract_class_unencrypted_log_private_internal}; + use crate::events::{ class_registered::ContractClassRegistered, private_function_broadcasted::{ClassPrivateFunctionBroadcasted, PrivateFunction}, @@ -52,7 +54,7 @@ contract ContractClassRegisterer { public_bytecode_commitment ] ); - context.emit_contract_class_unencrypted_log(event.serialize()); + emit_contract_class_unencrypted_log(&mut context, event.serialize()); } #[aztec(private)] @@ -87,7 +89,7 @@ contract ContractClassRegisterer { function_data.metadata_hash ] ); - context.emit_contract_class_unencrypted_log(event.serialize()); + emit_contract_class_unencrypted_log(&mut context, event.serialize()); } #[aztec(private)] @@ -117,6 +119,25 @@ contract ContractClassRegisterer { function_data.metadata_hash ] ); - context.emit_contract_class_unencrypted_log(event.serialize()); + emit_contract_class_unencrypted_log(&mut context, event.serialize()); + } + + // This fn exists separately from emit_unencrypted_log because sha hashing the preimage + // is too large to compile (16,200 fields, 518,400 bytes) => the oracle hashes it + // It is ONLY used with contract_class_registerer_contract since we already assert correctness: + // - Contract class -> we will commit to the packed bytecode (currently a TODO) + // - Private function -> we provide a membership proof + // - Unconstrained function -> we provide a membership proof + // Ordinary logs are not protected by the above so this fn shouldn't be called by anything else + #[contract_library_method] + pub fn emit_contract_class_unencrypted_log(context: &mut PrivateContext, log: [Field; N]) { + let event_selector = 5; // TODO: compute actual event selector. + let contract_address = context.this_address(); + let counter = context.next_counter(); + let log_hash = emit_contract_class_unencrypted_log_private_internal(contract_address, event_selector, log, counter); + // 44 = addr (32) + selector (4) + raw log len (4) + processed log len (4) + let len = 44 + N * 32; + let side_effect = LogHash { value: log_hash, counter, length: len }; + context.unencrypted_logs_hashes.push(side_effect); } } diff --git a/noir-projects/noir-contracts/contracts/contract_instance_deployer_contract/src/events.nr b/noir-projects/noir-contracts/contracts/contract_instance_deployer_contract/src/events.nr deleted file mode 100644 index d2b6ed6033f..00000000000 --- a/noir-projects/noir-contracts/contracts/contract_instance_deployer_contract/src/events.nr +++ /dev/null @@ -1 +0,0 @@ -mod instance_deployed; diff --git a/noir-projects/noir-contracts/contracts/contract_instance_deployer_contract/src/events/instance_deployed.nr b/noir-projects/noir-contracts/contracts/contract_instance_deployer_contract/src/events/instance_deployed.nr deleted file mode 100644 index 638a08db001..00000000000 --- a/noir-projects/noir-contracts/contracts/contract_instance_deployer_contract/src/events/instance_deployed.nr +++ /dev/null @@ -1,33 +0,0 @@ -use dep::aztec::protocol_types::{ - contract_class_id::ContractClassId, - address::{AztecAddress, EthAddress, PublicKeysHash, PartialAddress}, - constants::DEPLOYER_CONTRACT_INSTANCE_DEPLOYED_MAGIC_VALUE, traits::Serialize -}; - -// #[aztec(event)] -struct ContractInstanceDeployed { - address: AztecAddress, - version: u8, - salt: Field, - contract_class_id: ContractClassId, - initialization_hash: Field, - public_keys_hash: PublicKeysHash, - deployer: AztecAddress, -} - -global CONTRACT_INSTANCE_DEPLOYED_SERIALIZED_SIZE: Field = 8; - -impl Serialize for ContractInstanceDeployed { - fn serialize(self: Self) -> [Field; CONTRACT_INSTANCE_DEPLOYED_SERIALIZED_SIZE] { - [ - DEPLOYER_CONTRACT_INSTANCE_DEPLOYED_MAGIC_VALUE, - self.address.to_field(), - self.version as Field, - self.salt, - self.contract_class_id.to_field(), - self.initialization_hash, - self.public_keys_hash.to_field(), - self.deployer.to_field(), - ] - } -} diff --git a/noir-projects/noir-contracts/contracts/contract_instance_deployer_contract/src/main.nr b/noir-projects/noir-contracts/contracts/contract_instance_deployer_contract/src/main.nr index 43e7d45c655..56f5e4827f5 100644 --- a/noir-projects/noir-contracts/contracts/contract_instance_deployer_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/contract_instance_deployer_contract/src/main.nr @@ -1,13 +1,42 @@ -mod events; - contract ContractInstanceDeployer { use dep::aztec::protocol_types::{ address::{AztecAddress, EthAddress, PublicKeysHash, PartialAddress}, contract_class_id::ContractClassId, constants::DEPLOYER_CONTRACT_INSTANCE_DEPLOYED_MAGIC_VALUE, - traits::Serialize + traits::Serialize, abis::log_hash::LogHash + }; + use dep::aztec::{ + context::PrivateContext, hash::compute_unencrypted_log_hash, + oracle::logs::emit_unencrypted_log_private_internal }; - use crate::events::{instance_deployed::ContractInstanceDeployed}; + // @todo This should be using an event, but currently we only support fields in the struct. + // #[aztec(event)] + struct ContractInstanceDeployed { + address: AztecAddress, + version: u8, + salt: Field, + contract_class_id: ContractClassId, + initialization_hash: Field, + public_keys_hash: PublicKeysHash, + deployer: AztecAddress, + } + + global CONTRACT_INSTANCE_DEPLOYED_SERIALIZED_SIZE: Field = 8; + + impl Serialize for ContractInstanceDeployed { + fn serialize(self: Self) -> [Field; CONTRACT_INSTANCE_DEPLOYED_SERIALIZED_SIZE] { + [ + DEPLOYER_CONTRACT_INSTANCE_DEPLOYED_MAGIC_VALUE, + self.address.to_field(), + self.version as Field, + self.salt, + self.contract_class_id.to_field(), + self.initialization_hash, + self.public_keys_hash.to_field(), + self.deployer.to_field(), + ] + } + } #[aztec(private)] fn deploy( @@ -34,8 +63,25 @@ contract ContractInstanceDeployer { // Broadcast the event let event = ContractInstanceDeployed { contract_class_id, address, public_keys_hash, initialization_hash, salt, deployer, version: 1 }; - let event_payload = event.serialize(); - dep::aztec::oracle::debug_log::debug_log_format("ContractInstanceDeployed: {}", event_payload); - context.emit_unencrypted_log(event_payload); + + let payload = event.serialize(); + dep::aztec::oracle::debug_log::debug_log_format("ContractInstanceDeployed: {}", payload); + + let contract_address = context.this_address(); + let counter = context.next_counter(); + + // The event_type_id is not strictly needed. So i'm setting it to 0 here, and we can then purge it + // later on. + let event_type_id = 0; + + // @todo This is very inefficient, we are doing a lot of back and forth conversions. + let log_slice = payload.to_be_bytes_arr(); + let log_hash = compute_unencrypted_log_hash(contract_address, event_type_id, payload); + // 44 = addr (32) + selector (4) + raw log len (4) + processed log len (4) + let len = 44 + log_slice.len().to_field(); + let side_effect = LogHash { value: log_hash, counter, length: len }; + context.unencrypted_logs_hashes.push(side_effect); + + let _void = emit_unencrypted_log_private_internal(contract_address, event_type_id, payload, counter); } } 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 9e43661a329..4eb7657462e 100644 --- a/noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr @@ -4,13 +4,11 @@ contract Crowdfunding { // docs:start:all-deps use dep::aztec::{ - protocol_types::{ - abis::function_selector::FunctionSelector, address::AztecAddress, traits::Serialize, - grumpkin_point::GrumpkinPoint - }, + protocol_types::address::AztecAddress, encrypted_logs::encrypted_note_emission::encode_and_encrypt_note, state_vars::{PrivateSet, PublicImmutable, SharedImmutable} }; + use dep::aztec::unencrypted_logs::unencrypted_event_emission::encode_event; use dep::value_note::value_note::ValueNote; use dep::token::Token; // docs:end:all-deps @@ -95,10 +93,14 @@ contract Crowdfunding { // 2) Transfer the donation tokens from this contract to the operator Token::at(storage.donation_token.read_private()).transfer(operator_address, amount as Field).call(&mut context); - // 3) Emit an unencrypted event so that anyone can audit how much the operator has withdrawn - let event = WithdrawalProcessed { amount: amount as Field, who: operator_address.to_field() }; - context.emit_unencrypted_log(event.serialize()); + Crowdfunding::at(context.this_address())._publish_donation_receipts(amount, operator_address).enqueue(&mut context); } // docs:end:operator-withdrawals + + #[aztec(public)] + #[aztec(internal)] + fn _publish_donation_receipts(amount: u64, to: AztecAddress) { + WithdrawalProcessed { amount: amount as Field, who: to.to_field() }.emit(encode_event(&mut context)); + } } 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 71cc8d803f7..875686868c4 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 @@ -194,9 +194,11 @@ contract InclusionProofs { let header = context.get_header_at(block_number); assert_eq( + // docs:start:public_storage_historical_read header.public_storage_historical_read( storage.public_unused_value.storage_slot, context.this_address() + // docs:end:public_storage_historical_read ), 0 ); } @@ -229,10 +231,14 @@ contract InclusionProofs { let header = context.get_header_at(block_number); if test_deployment { + // docs:start:prove_contract_deployment header.prove_contract_deployment(contract_address); + // docs:end:prove_contract_deployment } if test_initialization { + // docs:start:prove_contract_initialization header.prove_contract_initialization(contract_address); + // docs:end:prove_contract_initialization } } @@ -247,10 +253,14 @@ contract InclusionProofs { let header = context.get_header_at(block_number); if test_deployment { + // docs:start:prove_contract_non_deployment header.prove_contract_non_deployment(contract_address); + // docs:end:prove_contract_non_deployment } if test_initialization { + // docs:start:prove_contract_non_initialization header.prove_contract_non_initialization(contract_address); + // docs:end:prove_contract_non_initialization } } } diff --git a/noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr b/noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr index aef32ca6133..f51631c1f1c 100644 --- a/noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr @@ -41,8 +41,15 @@ contract KeyRegistry { npk_m_y_registry.schedule_value_change(new_npk_m.y); } + // We need to have two separate register functions because a single one would produce too many storage writes, since + // each SharedMutable.schedule_value_change call results in 5 writes (pre, post, block_of_change, delay and hash), + // totaling 40 writes, while the kernels only accept up to 32 writes. + // Once SharedMutable accepts multi-field values, we can have a single state variable hold all keys, and that way + // also have a single block of change, hash, and delay. + // TODO (#5491): make this be a single function with a single schedule call. + #[aztec(public)] - fn register(address: AztecAddress, partial_address: PartialAddress, keys: PublicKeys) { + fn register_npk_and_ivpk(address: AztecAddress, partial_address: PartialAddress, keys: PublicKeys) { let computed_address = AztecAddress::compute(keys.hash(), partial_address); assert(computed_address.eq(address), "Computed address does not match supplied address"); @@ -51,15 +58,24 @@ contract KeyRegistry { let npk_m_y_registry = storage.npk_m_y_registry.at(address); let ivpk_m_x_registry = storage.ivpk_m_x_registry.at(address); let ivpk_m_y_registry = storage.ivpk_m_y_registry.at(address); - let ovpk_m_x_registry = storage.ovpk_m_x_registry.at(address); - let ovpk_m_y_registry = storage.ovpk_m_y_registry.at(address); - let tpk_m_x_registry = storage.tpk_m_x_registry.at(address); - let tpk_m_y_registry = storage.tpk_m_y_registry.at(address); npk_m_x_registry.schedule_value_change(keys.npk_m.x); npk_m_y_registry.schedule_value_change(keys.npk_m.y); ivpk_m_x_registry.schedule_value_change(keys.ivpk_m.x); ivpk_m_y_registry.schedule_value_change(keys.ivpk_m.y); + } + + #[aztec(public)] + fn register_ovpk_and_tpk(address: AztecAddress, partial_address: PartialAddress, keys: PublicKeys) { + let computed_address = AztecAddress::compute(keys.hash(), partial_address); + + assert(computed_address.eq(address), "Computed address does not match supplied address"); + + let ovpk_m_x_registry = storage.ovpk_m_x_registry.at(address); + let ovpk_m_y_registry = storage.ovpk_m_y_registry.at(address); + let tpk_m_x_registry = storage.tpk_m_x_registry.at(address); + let tpk_m_y_registry = storage.tpk_m_y_registry.at(address); + ovpk_m_x_registry.schedule_value_change(keys.ovpk_m.x); ovpk_m_y_registry.schedule_value_change(keys.ovpk_m.y); tpk_m_x_registry.schedule_value_change(keys.tpk_m.x); 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 eb34674b095..2f8e598aa64 100644 --- a/noir-projects/noir-contracts/contracts/test_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/test_contract/src/main.nr @@ -8,7 +8,7 @@ contract Test { PrivateContext, PrivateImmutable, PrivateSet, SharedImmutable }; use dep::aztec::encrypted_logs::encrypted_note_emission::encode_and_encrypt_note; - use dep::aztec::encrypted_logs::encrypted_event_emission::encode_and_encrypt_event_with_keys; + use dep::aztec::encrypted_logs::encrypted_event_emission::encode_and_encrypt_event_with_keys_with_randomness; use dep::aztec::protocol_types::{ abis::private_circuit_public_inputs::PrivateCircuitPublicInputs, @@ -271,7 +271,7 @@ contract Test { let event = ExampleEvent { value0: fields[0], value1: fields[1], value2: fields[2], value3: fields[3], value4: fields[4] }; event.emit( - encode_and_encrypt_event_with_keys( + encode_and_encrypt_event_with_keys_with_randomness( &mut context, // testing only - a secret random value is passed in here to salt / mask the address 5, @@ -288,7 +288,7 @@ contract Test { let otherEvent = ExampleEvent { value0: 1, value1: 2, value2: 3, value3: 4, value4: 5 }; otherEvent.emit( - encode_and_encrypt_event_with_keys( + encode_and_encrypt_event_with_keys_with_randomness( &mut context, // testing only - a randomness of 0 signals the kerels to not mask the address 0, @@ -299,25 +299,6 @@ contract Test { } } - #[aztec(private)] - fn emit_msg_sender() { - context.emit_unencrypted_log(context.msg_sender()); - } - - #[aztec(private)] - fn emit_unencrypted_logs(fields: [Field; 5], nest: bool) { - // Merged two fns to avoid hitting max #functions limit: - // nest -> emit_unencrypted_logs_nested - // else -> emit_array_as_unencrypted_log - if nest { - Test::at(context.this_address()).emit_msg_sender().call(&mut context); - Test::at(context.this_address()).emit_unencrypted_logs(fields, false).call(&mut context); - context.emit_unencrypted_log("test"); - } else { - context.emit_unencrypted_log(fields); - } - } - #[aztec(private)] fn emit_encrypted_logs_nested(value: Field, owner: AztecAddress, outgoing_viewer: AztecAddress) { let mut storage_slot = storage.example_constant.get_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 f42cb2ffd7a..0d1d06b731d 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 @@ -1,10 +1,14 @@ contract TestLog { use dep::aztec::prelude::PrivateSet; - use dep::aztec::protocol_types::{traits::Serialize, grumpkin_point::GrumpkinPoint, grumpkin_private_key::GrumpkinPrivateKey}; + use dep::aztec::protocol_types::{ + traits::Serialize, grumpkin_point::GrumpkinPoint, grumpkin_private_key::GrumpkinPrivateKey, + address::AztecAddress + }; use dep::value_note::value_note::ValueNote; use dep::aztec::encrypted_logs::incoming_body::EncryptedLogIncomingBody; use dep::aztec::event::event_interface::EventInterface; - use dep::aztec::encrypted_logs::encrypted_event_emission::{encode_and_encrypt_event, encode_and_encrypt_event_with_keys}; + use dep::aztec::encrypted_logs::encrypted_event_emission::encode_and_encrypt_event_with_randomness; + use dep::aztec::unencrypted_logs::unencrypted_event_emission::encode_event; #[aztec(event)] struct ExampleEvent0 { @@ -41,27 +45,51 @@ contract TestLog { } #[aztec(private)] - fn emit_encrypted_events(randomness: [Field; 2], preimages: [Field; 4]) { + fn emit_encrypted_events(other: AztecAddress, randomness: [Field; 2], preimages: [Field; 4]) { let event0 = ExampleEvent0 { value0: preimages[0], value1: preimages[1] }; event0.emit( - encode_and_encrypt_event( + encode_and_encrypt_event_with_randomness( &mut context, randomness[0], - context.msg_sender(), + // outgoing is set to other, incoming is set to msg sender + other, context.msg_sender() ) ); + // We duplicate the emission, but specifying different incoming and outgoing parties + event0.emit( + encode_and_encrypt_event_with_randomness( + &mut context, + randomness[0], + // outgoing is set to msg sender, incoming is set to other + context.msg_sender(), + other + ) + ); + let event1 = ExampleEvent1 { value2: preimages[2], value3: preimages[3] }; event1.emit( - encode_and_encrypt_event( + encode_and_encrypt_event_with_randomness( &mut context, randomness[1], - context.msg_sender(), + // outgoing is set to other, incoming is set to msg sender + other, context.msg_sender() ) ); } + + #[aztec(public)] + fn emit_unencrypted_events(preimages: [Field; 4]) { + let event0 = ExampleEvent0 { value0: preimages[0], value1: preimages[1] }; + + event0.emit(encode_event(&mut context)); + + let event1 = ExampleEvent1 { value2: preimages[2], value3: preimages[3] }; + + event1.emit(encode_event(&mut context)); + } } diff --git a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/roles.nr b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/roles.nr index 4321a2a7f28..bbb93b0efa4 100644 --- a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/roles.nr +++ b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/roles.nr @@ -41,6 +41,12 @@ impl ToField for UserFlags { } } +impl Eq for UserFlags { + fn eq(self, other: Self) -> bool { + (self.is_admin == other.is_admin) & (self.is_minter == other.is_minter) & (self.is_blacklisted == other.is_blacklisted) + } +} + // We implement this as it is used when serializing the state variable into return values // This is very inefficient if used to store the state variable. // We are currently "abusing" that the `to_field` is called in the `scheduled_value_change` 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 d13145c89e2..d1695732c06 100644 --- a/noir-projects/noir-contracts/contracts/token_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/token_contract/src/main.nr @@ -18,7 +18,13 @@ contract Token { use dep::aztec::{ hash::compute_secret_hash, prelude::{NoteGetterOptions, Map, PublicMutable, SharedImmutable, PrivateSet, AztecAddress}, - encrypted_logs::encrypted_note_emission::{encode_and_encrypt_note, encode_and_encrypt_note_with_keys} + encrypted_logs::{ + encrypted_note_emission::{ + encode_and_encrypt_note, encode_and_encrypt_note_with_keys, + encode_and_encrypt_note_with_keys_unconstrained + }, + encrypted_event_emission::{encode_and_encrypt_event, encode_and_encrypt_event_with_keys_unconstrained} + } }; // docs:start:import_authwit @@ -28,6 +34,13 @@ contract Token { use crate::types::{transparent_note::TransparentNote, token_note::{TokenNote, TOKEN_NOTE_LEN}, balances_map::BalancesMap}; // docs:end::imports + #[aztec(event)] + struct Transfer { + from: Field, + to: Field, + amount: Field, + } + // docs:start:storage_struct #[aztec(storage)] struct Storage { @@ -322,8 +335,10 @@ contract Token { let to_ivpk = header.get_ivpk_m(&mut context, to); let amount = U128::from_integer(amount); - storage.balances.sub(from, amount).emit(encode_and_encrypt_note_with_keys(&mut context, from_ovpk, from_ivpk)); - storage.balances.add(to, amount).emit(encode_and_encrypt_note_with_keys(&mut context, from_ovpk, to_ivpk)); + storage.balances.sub(from, amount).emit(encode_and_encrypt_note_with_keys_unconstrained(&mut context, from_ovpk, from_ivpk)); + storage.balances.add(to, amount).emit(encode_and_encrypt_note_with_keys_unconstrained(&mut context, from_ovpk, to_ivpk)); + + Transfer { from: from.to_field(), to: to.to_field(), amount: amount.to_field() }.emit(encode_and_encrypt_event_with_keys_unconstrained(&mut context, from_ovpk, to_ivpk)); } // docs:end:transfer 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 1801ddd7213..5431b94bc10 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 @@ -72,11 +72,12 @@ pub fn setup_and_mint(with_account_contracts: bool) -> (&mut TestEnvironment, Az pub fn check_public_balance(token_contract_address: AztecAddress, address: AztecAddress, address_amount: Field) { let current_contract_address = cheatcodes::get_contract_address(); cheatcodes::set_contract_address(token_contract_address); + let block_number = cheatcodes::get_block_number(); let balances_slot = Token::storage().public_balances.slot; let address_slot = derive_storage_slot_in_map(balances_slot, address); - let fields = storage_read(address_slot); - assert(U128::deserialize(fields).to_field() == address_amount, "Public balance is not correct"); + let amount: U128 = storage_read(token_contract_address, address_slot, block_number); + assert(amount.to_field() == address_amount, "Public balance is not correct"); cheatcodes::set_contract_address(current_contract_address); } diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/base_or_merge_rollup_public_inputs.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/base_or_merge_rollup_public_inputs.nr index 0b643692f67..cbe1a5cb28b 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/base_or_merge_rollup_public_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/base_or_merge_rollup_public_inputs.nr @@ -12,9 +12,7 @@ struct BaseOrMergeRollupPublicInputs { // rollup_type is either 0 (base) or 1 (merge) // TODO(Kev): Why is this a u32 instead of a u8/u16? rollup_type : u32, - // subtree height is always 0 for base. - // so that we always pass-in two base/merge circuits of the same height into the next level of recursion - height_in_block_tree : Field, + num_txs : u32, constants : ConstantRollupData, start: PartialStateReference, @@ -35,7 +33,7 @@ impl Empty for BaseOrMergeRollupPublicInputs { fn empty() -> Self { BaseOrMergeRollupPublicInputs { rollup_type : 0 as u32, - height_in_block_tree : 0, + num_txs : 0 as u32, constants : ConstantRollupData::empty(), start: PartialStateReference::empty(), end: PartialStateReference::empty(), @@ -49,7 +47,7 @@ impl Empty for BaseOrMergeRollupPublicInputs { impl Eq for BaseOrMergeRollupPublicInputs { fn eq(self, other: Self) -> bool { (self.rollup_type == other.rollup_type) & - (self.height_in_block_tree == other.height_in_block_tree) & + (self.num_txs == other.num_txs) & (self.constants.eq(other.constants)) & (self.start.eq(other.start)) & (self.end.eq(other.end)) & @@ -64,7 +62,7 @@ impl Serialize for BaseOrMergeRollupPublicIn let mut fields: BoundedVec = BoundedVec::new(); fields.push(self.rollup_type as Field); - fields.push(self.height_in_block_tree as Field); + fields.push(self.num_txs as Field); fields.extend_from_array(self.constants.serialize()); fields.extend_from_array(self.start.serialize()); fields.extend_from_array(self.end.serialize()); @@ -83,7 +81,7 @@ impl Deserialize for BaseOrMergeRollupPublic let mut reader = Reader::new(fields); let item = Self { rollup_type: reader.read() as u32, - height_in_block_tree: reader.read(), + num_txs: reader.read() as u32, constants: reader.read_struct(ConstantRollupData::deserialize), start: reader.read_struct(PartialStateReference::deserialize), end: reader.read_struct(PartialStateReference::deserialize), diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/base_rollup_inputs.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/base_rollup_inputs.nr index c68f2215780..e9317e56105 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/base_rollup_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/base_rollup_inputs.nr @@ -128,7 +128,7 @@ impl BaseRollupInputs { BaseOrMergeRollupPublicInputs { rollup_type: BASE_ROLLUP_TYPE, - height_in_block_tree: 0, + num_txs: 1, constants: self.constants, start: self.start, end: PartialStateReference { @@ -1147,10 +1147,10 @@ mod tests { } #[test] - unconstrained fn subtree_height_is_0() { + unconstrained fn num_txs_is_1() { let outputs = BaseRollupInputsBuilder::new().execute(); - assert_eq(outputs.height_in_block_tree, 0); + assert_eq(outputs.num_txs, 1); } #[test] diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/components.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/components.nr index e74c8398eaf..4653d57bae0 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/components.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/components.nr @@ -15,28 +15,29 @@ use dep::types::{ }; /** - * Asserts that the rollup types are the same. - * Either both merge or both base + * Asserts that the tree formed by rollup circuits is filled greedily from L to R + * */ -pub fn assert_both_input_proofs_of_same_rollup_type( +pub fn assert_txs_filled_from_left( left: BaseOrMergeRollupPublicInputs, right: BaseOrMergeRollupPublicInputs ) { - assert(left.rollup_type == right.rollup_type, "input proofs are of different rollup types"); -} - -/** - * Asserts that the rollup subtree heights are the same and returns the height - * Returns the height of the rollup subtrees - */ -pub fn assert_both_input_proofs_of_same_height_and_return( - left: BaseOrMergeRollupPublicInputs, - right: BaseOrMergeRollupPublicInputs -) -> Field { - assert( - left.height_in_block_tree == right.height_in_block_tree, "input proofs are of different rollup heights" - ); - left.height_in_block_tree + // assert that the left rollup is either a base (1 tx) or a balanced tree (num txs = power of 2) + if (left.rollup_type == 1) { + let left_txs = left.num_txs; + let right_txs = right.num_txs; + // See https://graphics.stanford.edu/~seander/bithacks.html#DetermineIfPowerOf2 + assert( + (left_txs) & (left_txs - 1) == 0, "The rollup should be filled greedily from L to R, but received an unbalanced left subtree" + ); + assert( + right_txs <= left_txs, "The rollup should be filled greedily from L to R, but received a L txs < R txs" + ); + } else { + assert( + right.rollup_type == 0, "The rollup should be filled greedily from L to R, but received a L base and R merge" + ); + } } /** diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/merge/merge_rollup_inputs.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/merge/merge_rollup_inputs.nr index daa66bfff13..0fbdc3d22d4 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/merge/merge_rollup_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/merge/merge_rollup_inputs.nr @@ -28,10 +28,7 @@ impl MergeRollupInputs { let left = self.previous_rollup_data[0].base_or_merge_rollup_public_inputs; let right = self.previous_rollup_data[1].base_or_merge_rollup_public_inputs; - // check that both input proofs are either both "BASE" or "MERGE" and not a mix! - // this prevents having wonky commitment, nullifier and contract subtrees. - components::assert_both_input_proofs_of_same_rollup_type(left, right); - let current_height = components::assert_both_input_proofs_of_same_height_and_return(left, right); + components::assert_txs_filled_from_left(left, right); components::assert_equal_constants(left, right); components::assert_prev_rollups_follow_on_from_each_other(left, right); @@ -43,7 +40,7 @@ impl MergeRollupInputs { let public_inputs = BaseOrMergeRollupPublicInputs { rollup_type: MERGE_ROLLUP_TYPE, - height_in_block_tree: current_height + 1, + num_txs: left.num_txs + right.num_txs, constants: left.constants, start: left.start, end: right.end, @@ -63,7 +60,7 @@ mod tests { }; use dep::types::hash::accumulate_sha256; - #[test(should_fail_with="input proofs are of different rollup types")] + #[test(should_fail_with="The rollup should be filled greedily from L to R, but received a L base and R merge")] fn different_rollup_type_fails() { let mut inputs = default_merge_rollup_inputs(); inputs.previous_rollup_data[0].base_or_merge_rollup_public_inputs.rollup_type = 0; @@ -71,14 +68,6 @@ mod tests { let _output = inputs.merge_rollup_circuit(); } - #[test(should_fail_with="input proofs are of different rollup heights")] - fn different_height_fails() { - let mut inputs = default_merge_rollup_inputs(); - inputs.previous_rollup_data[0].base_or_merge_rollup_public_inputs.height_in_block_tree = 0; - inputs.previous_rollup_data[1].base_or_merge_rollup_public_inputs.height_in_block_tree = 1; - let _output = inputs.merge_rollup_circuit(); - } - #[test(should_fail_with="input proofs have different constants")] fn constants_different_fails() { let mut inputs = default_merge_rollup_inputs(); @@ -116,20 +105,44 @@ mod tests { let mut inputs = default_merge_rollup_inputs(); let mut outputs = inputs.merge_rollup_circuit(); assert_eq(outputs.rollup_type, 1); - assert_eq( - outputs.height_in_block_tree, inputs.previous_rollup_data[0].base_or_merge_rollup_public_inputs.height_in_block_tree + 1 - ); + assert_eq(outputs.num_txs, 2); // set inputs to have a merge rollup type and set the rollup height and test again. inputs.previous_rollup_data[0].base_or_merge_rollup_public_inputs.rollup_type = 1; - inputs.previous_rollup_data[0].base_or_merge_rollup_public_inputs.height_in_block_tree = 1; + inputs.previous_rollup_data[0].base_or_merge_rollup_public_inputs.num_txs = 2; inputs.previous_rollup_data[1].base_or_merge_rollup_public_inputs.rollup_type = 1; - inputs.previous_rollup_data[1].base_or_merge_rollup_public_inputs.height_in_block_tree = 1; + inputs.previous_rollup_data[1].base_or_merge_rollup_public_inputs.num_txs = 2; outputs = inputs.merge_rollup_circuit(); assert_eq(outputs.rollup_type, 1); - assert_eq(outputs.height_in_block_tree, 2); + assert_eq(outputs.num_txs, 4); + } + + #[test] + fn tx_subtrees_are_set_correctly() { + let mut inputs = default_merge_rollup_inputs(); + let mut outputs = inputs.merge_rollup_circuit(); + // Start with two bases => two single txs + assert_eq(outputs.num_txs, 2); + // Test one merge of 2 merged with one base + inputs.previous_rollup_data[0].base_or_merge_rollup_public_inputs.rollup_type = 1; + inputs.previous_rollup_data[0].base_or_merge_rollup_public_inputs.num_txs = 2; + outputs = inputs.merge_rollup_circuit(); + // Should have one subtree of size 2, and one of size 1 + assert_eq(outputs.num_txs, 3); + // Test two merges, each with a subtree of 2 + inputs.previous_rollup_data[1].base_or_merge_rollup_public_inputs.rollup_type = 1; + inputs.previous_rollup_data[1].base_or_merge_rollup_public_inputs.num_txs = 2; + outputs = inputs.merge_rollup_circuit(); + // Should have one subtree of size 4 + assert_eq(outputs.num_txs, 4); + + // Test two merges, one with a subtree of 16, one with subtrees of 4 and 1 + inputs.previous_rollup_data[0].base_or_merge_rollup_public_inputs.num_txs = 16; + inputs.previous_rollup_data[1].base_or_merge_rollup_public_inputs.num_txs = 5; + outputs = inputs.merge_rollup_circuit(); + assert_eq(outputs.num_txs, 21); } #[test] diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/root/root_rollup_inputs.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/root/root_rollup_inputs.nr index e0864e6b27a..512e46b78e0 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/root/root_rollup_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/root/root_rollup_inputs.nr @@ -43,8 +43,7 @@ impl RootRollupInputs { let left = self.previous_rollup_data[0].base_or_merge_rollup_public_inputs; let right = self.previous_rollup_data[1].base_or_merge_rollup_public_inputs; - components::assert_both_input_proofs_of_same_rollup_type(left, right); - let _ = components::assert_both_input_proofs_of_same_height_and_return(left, right); + components::assert_txs_filled_from_left(left, right); components::assert_equal_constants(left, right); components::assert_prev_rollups_follow_on_from_each_other(left, right); @@ -63,7 +62,7 @@ impl RootRollupInputs { let state = StateReference { l1_to_l2_message_tree: new_l1_to_l2_message_tree_snapshot, partial: right.end }; let content_commitment = ContentCommitment { - tx_tree_height: right.height_in_block_tree + 1, + num_txs: (left.num_txs + right.num_txs) as Field, txs_effects_hash: components::compute_txs_effects_hash(self.previous_rollup_data), in_hash: self.l1_to_l2_roots.public_inputs.sha_root, out_hash: components::compute_out_hash(self.previous_rollup_data) diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/tests/previous_rollup_data.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/tests/previous_rollup_data.nr index df34d71d866..52edabc33e6 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/tests/previous_rollup_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/tests/previous_rollup_data.nr @@ -59,8 +59,8 @@ pub fn default_previous_rollup_data() -> [PreviousRollupData; 2] { previous_rollup_data[0].base_or_merge_rollup_public_inputs.rollup_type = BASE_ROLLUP_TYPE; previous_rollup_data[1].base_or_merge_rollup_public_inputs.rollup_type = BASE_ROLLUP_TYPE; - previous_rollup_data[0].base_or_merge_rollup_public_inputs.height_in_block_tree = 1; - previous_rollup_data[1].base_or_merge_rollup_public_inputs.height_in_block_tree = 1; + previous_rollup_data[0].base_or_merge_rollup_public_inputs.num_txs = 1; + previous_rollup_data[1].base_or_merge_rollup_public_inputs.num_txs = 1; previous_rollup_data[0].base_or_merge_rollup_public_inputs.txs_effects_hash = 1; previous_rollup_data[1].base_or_merge_rollup_public_inputs.txs_effects_hash = 2; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/content_commitment.nr b/noir-projects/noir-protocol-circuits/crates/types/src/content_commitment.nr index 3279b6ab9f2..bc1b421134c 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/content_commitment.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/content_commitment.nr @@ -4,7 +4,7 @@ use crate::{ }; struct ContentCommitment { - tx_tree_height: Field, + num_txs: Field, txs_effects_hash: Field, in_hash: Field, out_hash: Field, @@ -14,7 +14,7 @@ impl Serialize for ContentCommitment { fn serialize(self) -> [Field; CONTENT_COMMITMENT_LENGTH] { let mut fields: BoundedVec = BoundedVec::new(); - fields.push(self.tx_tree_height); + fields.push(self.num_txs); fields.push(self.txs_effects_hash); fields.push(self.in_hash); fields.push(self.out_hash); @@ -25,7 +25,7 @@ impl Serialize for ContentCommitment { impl Deserialize for ContentCommitment { fn deserialize(serialized: [Field; CONTENT_COMMITMENT_LENGTH]) -> Self { - let tx_tree_height = serialized[0]; + let num_txs = serialized[0]; let txs_effects_hash = serialized[1]; @@ -34,7 +34,7 @@ impl Deserialize for ContentCommitment { let out_hash = serialized[3]; Self { - tx_tree_height, + num_txs, txs_effects_hash, in_hash, out_hash, @@ -45,7 +45,7 @@ impl Deserialize for ContentCommitment { impl Empty for ContentCommitment { fn empty() -> Self { Self { - tx_tree_height: 0, + num_txs: 0, txs_effects_hash: 0, in_hash: 0, out_hash: 0, @@ -55,7 +55,7 @@ impl Empty for ContentCommitment { impl Eq for ContentCommitment { fn eq(self, other: Self) -> bool { - (self.tx_tree_height == other.tx_tree_height) + (self.num_txs == other.num_txs) & (self.txs_effects_hash == other.txs_effects_hash) & (self.in_hash == other.in_hash) & (self.out_hash == other.out_hash) diff --git a/noir/noir-repo/aztec_macros/src/transforms/compute_note_hash_and_optionally_a_nullifier.rs b/noir/noir-repo/aztec_macros/src/transforms/compute_note_hash_and_optionally_a_nullifier.rs index 30c0f63a2d4..40fde39a06f 100644 --- a/noir/noir-repo/aztec_macros/src/transforms/compute_note_hash_and_optionally_a_nullifier.rs +++ b/noir/noir-repo/aztec_macros/src/transforms/compute_note_hash_and_optionally_a_nullifier.rs @@ -176,7 +176,7 @@ fn generate_compute_note_hash_and_optionally_a_nullifier_source( format!( " unconstrained fn compute_note_hash_and_optionally_a_nullifier( - contract_address: dep::aztec::protocol_types::address::AztecAddress, + contract_address: aztec::protocol_types::address::AztecAddress, nonce: Field, storage_slot: Field, note_type_id: Field, @@ -194,7 +194,7 @@ fn generate_compute_note_hash_and_optionally_a_nullifier_source( let if_statements: Vec = note_types.iter().map(|note_type| format!( "if (note_type_id == {0}::get_note_type_id()) {{ - dep::aztec::note::utils::compute_note_hash_and_optionally_a_nullifier({0}::deserialize_content, note_header, compute_nullifier, serialized_note) + aztec::note::utils::compute_note_hash_and_optionally_a_nullifier({0}::deserialize_content, note_header, compute_nullifier, serialized_note) }}" , note_type)).collect(); @@ -208,14 +208,14 @@ fn generate_compute_note_hash_and_optionally_a_nullifier_source( format!( " unconstrained fn compute_note_hash_and_optionally_a_nullifier( - contract_address: dep::aztec::protocol_types::address::AztecAddress, + contract_address: aztec::protocol_types::address::AztecAddress, nonce: Field, storage_slot: Field, note_type_id: Field, compute_nullifier: bool, serialized_note: [Field; {}], ) -> pub [Field; 4] {{ - let note_header = dep::aztec::prelude::NoteHeader::new(contract_address, nonce, storage_slot); + let note_header = aztec::prelude::NoteHeader::new(contract_address, nonce, storage_slot); {} }}", diff --git a/noir/noir-repo/aztec_macros/src/transforms/contract_interface.rs b/noir/noir-repo/aztec_macros/src/transforms/contract_interface.rs index ed451fdd998..b9323644379 100644 --- a/noir/noir-repo/aztec_macros/src/transforms/contract_interface.rs +++ b/noir/noir-repo/aztec_macros/src/transforms/contract_interface.rs @@ -30,8 +30,8 @@ use crate::utils::{ // for i in 0..third_arg.len() { // args_acc = args_acc.append(third_arg[i].serialize().as_slice()); // } -// let args_hash = dep::aztec::hash::hash_args(args_acc); -// assert(args_hash == dep::aztec::oracle::arguments::pack_arguments(args_acc)); +// let args_hash = aztec::hash::hash_args(args_acc); +// assert(args_hash == aztec::oracle::arguments::pack_arguments(args_acc)); // PublicCallInterface { // target_contract: self.target_contract, // selector: FunctionSelector::from_signature("SELECTOR_PLACEHOLDER"), @@ -137,8 +137,8 @@ pub fn stub_function(aztec_visibility: &str, func: &NoirFunction, is_static_call format!( "let mut args_acc: [Field] = &[]; {} - let args_hash = dep::aztec::hash::hash_args(args_acc); - assert(args_hash == dep::aztec::oracle::arguments::pack_arguments(args_acc));", + let args_hash = aztec::hash::hash_args(args_acc); + assert(args_hash == aztec::oracle::arguments::pack_arguments(args_acc));", call_args ) } else { @@ -234,14 +234,14 @@ pub fn generate_contract_interface( let contract_interface = format!( " struct {0} {{ - target_contract: dep::aztec::protocol_types::address::AztecAddress + target_contract: aztec::protocol_types::address::AztecAddress }} impl {0} {{ {1} pub fn at( - target_contract: dep::aztec::protocol_types::address::AztecAddress + target_contract: aztec::protocol_types::address::AztecAddress ) -> Self {{ Self {{ target_contract }} }} @@ -255,7 +255,7 @@ pub fn generate_contract_interface( #[contract_library_method] pub fn at( - target_contract: dep::aztec::protocol_types::address::AztecAddress + target_contract: aztec::protocol_types::address::AztecAddress ) -> {0} {{ {0} {{ target_contract }} }} diff --git a/noir/noir-repo/aztec_macros/src/transforms/note_interface.rs b/noir/noir-repo/aztec_macros/src/transforms/note_interface.rs index c2dfb3d86d4..49525fc2ae1 100644 --- a/noir/noir-repo/aztec_macros/src/transforms/note_interface.rs +++ b/noir/noir-repo/aztec_macros/src/transforms/note_interface.rs @@ -272,7 +272,7 @@ fn generate_note_get_header( ) -> Result { let function_source = format!( " - fn get_header(note: {}) -> dep::aztec::note::note_header::NoteHeader {{ + fn get_header(note: {}) -> aztec::note::note_header::NoteHeader {{ note.{} }} ", @@ -303,7 +303,7 @@ fn generate_note_set_header( ) -> Result { let function_source = format!( " - fn set_header(self: &mut {}, header: dep::aztec::note::note_header::NoteHeader) {{ + fn set_header(self: &mut {}, header: aztec::note::note_header::NoteHeader) {{ self.{} = header; }} ", @@ -493,7 +493,7 @@ fn generate_note_properties_fn( // Automatically generate the method to compute the note's content hash as: // fn compute_note_content_hash(self: NoteType) -> Field { -// dep::aztec::hash::pedersen_hash(self.serialize_content(), dep::aztec::protocol_types::constants::GENERATOR_INDEX__NOTE_CONTENT_HASH) +// aztec::hash::pedersen_hash(self.serialize_content(), aztec::protocol_types::constants::GENERATOR_INDEX__NOTE_CONTENT_HASH) // } // fn generate_compute_note_content_hash( @@ -503,7 +503,7 @@ fn generate_compute_note_content_hash( let function_source = format!( " fn compute_note_content_hash(self: {}) -> Field {{ - dep::aztec::hash::pedersen_hash(self.serialize_content(), dep::aztec::protocol_types::constants::GENERATOR_INDEX__NOTE_CONTENT_HASH) + aztec::hash::pedersen_hash(self.serialize_content(), aztec::protocol_types::constants::GENERATOR_INDEX__NOTE_CONTENT_HASH) }} ", note_type @@ -592,7 +592,7 @@ fn generate_note_properties_fn_source( .filter_map(|(index, (field_name, _))| { if field_name != note_header_field_name { Some(format!( - "{}: dep::aztec::note::note_getter_options::PropertySelector {{ index: {}, offset: 0, length: 32 }}", + "{}: aztec::note::note_getter_options::PropertySelector {{ index: {}, offset: 0, length: 32 }}", field_name, index )) diff --git a/noir/noir-repo/aztec_macros/src/utils/ast_utils.rs b/noir/noir-repo/aztec_macros/src/utils/ast_utils.rs index 48b3b25747b..4467c4bca4b 100644 --- a/noir/noir-repo/aztec_macros/src/utils/ast_utils.rs +++ b/noir/noir-repo/aztec_macros/src/utils/ast_utils.rs @@ -161,7 +161,7 @@ macro_rules! chained_dep { ( $base:expr $(, $tail:expr)* ) => { { let mut base_path = ident_path($base); - base_path.kind = PathKind::Dep; + base_path.kind = PathKind::Plain; $( base_path.segments.push(ident($tail)); )* diff --git a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/mod.rs b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/mod.rs index e0671d6f7ff..a3f6fa7a8e5 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/mod.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/mod.rs @@ -6,7 +6,7 @@ use std::{ use crate::{ ast::{FunctionKind, UnresolvedTraitConstraint}, hir::{ - comptime::{self, Interpreter, InterpreterError, Value}, + comptime::{self, Interpreter, Value}, def_collector::{ dc_crate::{ filter_literal_globals, CompilationError, ImplMap, UnresolvedGlobal, diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/import.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/import.rs index 282ee8a23c2..d73130411e4 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/import.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/import.rs @@ -38,8 +38,6 @@ pub(crate) type PathResolutionResult = Result From<&'a PathResolutionError> for CustomDiagnostic { PathResolutionError::Unresolved(ident) => { CustomDiagnostic::simple_error(error.to_string(), String::new(), ident.span()) } - PathResolutionError::ExternalContractUsed(ident) => CustomDiagnostic::simple_error( - error.to_string(), - "Contracts may only be referenced from within a contract".to_string(), - ident.span(), - ), // This will be upgraded to an error in future versions PathResolutionError::Private(ident) => CustomDiagnostic::simple_warning( error.to_string(), diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/traits.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/traits.rs index a6b732439b0..a1edc9fc492 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/traits.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/traits.rs @@ -67,7 +67,6 @@ pub(crate) fn resolve_traits( context.def_interner.update_trait(trait_id, |trait_def| { trait_def.set_methods(methods); - trait_def.generics = generics; }); // This check needs to be after the trait's methods are set since diff --git a/noir/noir-repo/docs/docs/how_to/how-to-oracles.md b/noir/noir-repo/docs/docs/how_to/how-to-oracles.md index d6834c09c84..2d2ed5c94b9 100644 --- a/noir/noir-repo/docs/docs/how_to/how-to-oracles.md +++ b/noir/noir-repo/docs/docs/how_to/how-to-oracles.md @@ -141,10 +141,10 @@ server.addMethod("resolve_function_call", async (params) => { if params.function !== "getSqrt" { throw Error("Unexpected foreign call") }; - const values = params.inputs[0].map((field) => { + const values = params.inputs[0].Array.map((field) => { return `${Math.sqrt(parseInt(field, 16))}`; }); - return { values }; + return { values: [{ Array: values }] }; }); ``` @@ -236,9 +236,9 @@ const foreignCallHandler = async (name, input) => { // notice that the "inputs" parameter contains *all* the inputs // in this case we to make the RPC request with the first parameter "numbers", which would be input[0] const oracleReturn = await client.request(name, [ - input[0].map((i) => i.toString("hex")), + { Array: input[0].map((i) => i.toString("hex")) }, ]); - return { values: oracleReturn }; + return [oracleReturn.values[0].Array]; }; // the rest of your NoirJS code diff --git a/noir/noir-repo/noir_stdlib/src/hash/mimc.nr b/noir/noir-repo/noir_stdlib/src/hash/mimc.nr index de4475d9446..a16a73c5bc5 100644 --- a/noir/noir-repo/noir_stdlib/src/hash/mimc.nr +++ b/noir/noir-repo/noir_stdlib/src/hash/mimc.nr @@ -116,7 +116,6 @@ global MIMC_BN254_CONSTANTS: [Field; MIMC_BN254_ROUNDS] = [ //mimc implementation with hardcoded parameters for BN254 curve. #[field(bn254)] -#[no_predicates] pub fn mimc_bn254(array: [Field; N]) -> Field { let exponent = 7; let mut r = 0; diff --git a/noir/noir-repo/noir_stdlib/src/hash/poseidon/bn254.nr b/noir/noir-repo/noir_stdlib/src/hash/poseidon/bn254.nr index 6800fac421d..103ab3d166a 100644 --- a/noir/noir-repo/noir_stdlib/src/hash/poseidon/bn254.nr +++ b/noir/noir-repo/noir_stdlib/src/hash/poseidon/bn254.nr @@ -6,7 +6,6 @@ use crate::hash::poseidon::{PoseidonConfig, absorb}; // Variable-length Poseidon-128 sponge as suggested in second bullet point of §3 of https://eprint.iacr.org/2019/458.pdf #[field(bn254)] -#[no_predicates] pub fn sponge(msg: [Field; N]) -> Field { absorb(consts::x5_5_config(), [0; 5], 4, 1, msg)[1] } diff --git a/noir/noir-repo/noir_stdlib/src/hash/poseidon2.nr b/noir/noir-repo/noir_stdlib/src/hash/poseidon2.nr index 08cf68d1f82..e34992364ab 100644 --- a/noir/noir-repo/noir_stdlib/src/hash/poseidon2.nr +++ b/noir/noir-repo/noir_stdlib/src/hash/poseidon2.nr @@ -11,7 +11,6 @@ struct Poseidon2 { } impl Poseidon2 { - #[no_predicates] pub fn hash(input: [Field; N], message_size: u32) -> Field { if message_size == N { Poseidon2::hash_internal(input, N, false) diff --git a/noir/noir-repo/noir_stdlib/src/sha256.nr b/noir/noir-repo/noir_stdlib/src/sha256.nr index 96ea8bb82c3..0161756c1d0 100644 --- a/noir/noir-repo/noir_stdlib/src/sha256.nr +++ b/noir/noir-repo/noir_stdlib/src/sha256.nr @@ -38,7 +38,6 @@ fn hash_final_block(msg_block: [u8; 64], mut state: [u32; 8]) -> [u8; 32] { } // Variable size SHA-256 hash -#[no_predicates] pub fn sha256_var(msg: [u8; N], message_size: u64) -> [u8; 32] { let mut msg_block: [u8; 64] = [0; 64]; let mut h: [u32; 8] = [1779033703, 3144134277, 1013904242, 2773480762, 1359893119, 2600822924, 528734635, 1541459225]; // Intermediate hash, starting with the canonical initial value diff --git a/noir/noir-repo/noir_stdlib/src/sha512.nr b/noir/noir-repo/noir_stdlib/src/sha512.nr index 993f328341f..aed6c2878b3 100644 --- a/noir/noir-repo/noir_stdlib/src/sha512.nr +++ b/noir/noir-repo/noir_stdlib/src/sha512.nr @@ -87,7 +87,6 @@ fn msg_u8_to_u64(msg: [u8; 128]) -> [u64; 16] { msg64 } // SHA-512 hash function -#[no_predicates] pub fn digest(msg: [u8; N]) -> [u8; 64] { let mut msg_block: [u8; 128] = [0; 128]; // noir-fmt:ignore diff --git a/noir/noir-repo/test_programs/benchmarks/bench_eddsa_poseidon/src/main.nr b/noir/noir-repo/test_programs/benchmarks/bench_eddsa_poseidon/src/main.nr index 2d38f5b1063..cb853e48c30 100644 --- a/noir/noir-repo/test_programs/benchmarks/bench_eddsa_poseidon/src/main.nr +++ b/noir/noir-repo/test_programs/benchmarks/bench_eddsa_poseidon/src/main.nr @@ -9,4 +9,4 @@ fn main( s: Field ) -> pub bool { eddsa_poseidon_verify(pub_key_x, pub_key_y, s, r8_x, r8_y, msg) -} \ No newline at end of file +} diff --git a/noir/noir-repo/test_programs/benchmarks/bench_poseidon_hash_100/src/main.nr b/noir/noir-repo/test_programs/benchmarks/bench_poseidon_hash_100/src/main.nr index 5fc9e313179..1c9bbfe61bf 100644 --- a/noir/noir-repo/test_programs/benchmarks/bench_poseidon_hash_100/src/main.nr +++ b/noir/noir-repo/test_programs/benchmarks/bench_poseidon_hash_100/src/main.nr @@ -9,4 +9,4 @@ fn main(input: [[Field; 2]; SIZE]) -> pub [Field; SIZE] { } results -} \ No newline at end of file +} diff --git a/noir/noir-repo/test_programs/benchmarks/bench_poseidon_hash_30/src/main.nr b/noir/noir-repo/test_programs/benchmarks/bench_poseidon_hash_30/src/main.nr index 3e319d2b025..3edb47e9f72 100644 --- a/noir/noir-repo/test_programs/benchmarks/bench_poseidon_hash_30/src/main.nr +++ b/noir/noir-repo/test_programs/benchmarks/bench_poseidon_hash_30/src/main.nr @@ -9,4 +9,4 @@ fn main(input: [[Field; 2]; SIZE]) -> pub [Field; SIZE] { } results -} \ No newline at end of file +} diff --git a/noir/noir-repo/test_programs/benchmarks/bench_sha256/Prover.toml b/noir/noir-repo/test_programs/benchmarks/bench_sha256/Prover.toml deleted file mode 100644 index 66779dea9d7..00000000000 --- a/noir/noir-repo/test_programs/benchmarks/bench_sha256/Prover.toml +++ /dev/null @@ -1 +0,0 @@ -input = [1,2] diff --git a/noir/noir-repo/test_programs/benchmarks/bench_sha256_100/src/main.nr b/noir/noir-repo/test_programs/benchmarks/bench_sha256_100/src/main.nr index 48b7fbac93c..6df856a83fc 100644 --- a/noir/noir-repo/test_programs/benchmarks/bench_sha256_100/src/main.nr +++ b/noir/noir-repo/test_programs/benchmarks/bench_sha256_100/src/main.nr @@ -1,4 +1,3 @@ - global SIZE = 100; fn main(input: [[u8; 2]; SIZE]) -> pub [[u8; 32]; SIZE] { @@ -8,4 +7,4 @@ fn main(input: [[u8; 2]; SIZE]) -> pub [[u8; 32]; SIZE] { } results -} \ No newline at end of file +} diff --git a/noir/noir-repo/test_programs/benchmarks/bench_sha256_30/src/main.nr b/noir/noir-repo/test_programs/benchmarks/bench_sha256_30/src/main.nr index 37c742f9667..220c1cfbbed 100644 --- a/noir/noir-repo/test_programs/benchmarks/bench_sha256_30/src/main.nr +++ b/noir/noir-repo/test_programs/benchmarks/bench_sha256_30/src/main.nr @@ -1,4 +1,3 @@ - global SIZE = 30; fn main(input: [[u8; 2]; SIZE]) -> pub [[u8; 32]; SIZE] { @@ -8,4 +7,4 @@ fn main(input: [[u8; 2]; SIZE]) -> pub [[u8; 32]; SIZE] { } results -} \ No newline at end of file +} diff --git a/noir/noir-repo/test_programs/compile_failure/invalid_main_sub_lib/Nargo.toml b/noir/noir-repo/test_programs/compile_failure/invalid_main_sub_lib/Nargo.toml index 12776f47712..16753d76598 100644 --- a/noir/noir-repo/test_programs/compile_failure/invalid_main_sub_lib/Nargo.toml +++ b/noir/noir-repo/test_programs/compile_failure/invalid_main_sub_lib/Nargo.toml @@ -2,6 +2,5 @@ name = "invalid_main_sub_lib" type = "bin" authors = [""] -compiler_version = ">=0.30.0" -[dependencies] \ No newline at end of file +[dependencies] diff --git a/noir/noir-repo/test_programs/compile_failure/negate_unsigned/src/main.nr b/noir/noir-repo/test_programs/compile_failure/negate_unsigned/src/main.nr index af4802a4ce6..4d3c5abe5a4 100644 --- a/noir/noir-repo/test_programs/compile_failure/negate_unsigned/src/main.nr +++ b/noir/noir-repo/test_programs/compile_failure/negate_unsigned/src/main.nr @@ -1,4 +1,3 @@ - fn main() { let var = -1 as u8; std::println(var); diff --git a/noir/noir-repo/test_programs/compile_failure/non_comptime_local_fn_call/Nargo.toml b/noir/noir-repo/test_programs/compile_failure/non_comptime_local_fn_call/Nargo.toml index 4ea2b75aa85..8bdefbbbd21 100644 --- a/noir/noir-repo/test_programs/compile_failure/non_comptime_local_fn_call/Nargo.toml +++ b/noir/noir-repo/test_programs/compile_failure/non_comptime_local_fn_call/Nargo.toml @@ -4,4 +4,4 @@ type = "bin" authors = [""] compiler_version = ">=0.23.0" -[dependencies] \ No newline at end of file +[dependencies] diff --git a/noir/noir-repo/test_programs/compile_failure/non_comptime_local_fn_call/src/main.nr b/noir/noir-repo/test_programs/compile_failure/non_comptime_local_fn_call/src/main.nr index 7cbf4213425..6a554c6b614 100644 --- a/noir/noir-repo/test_programs/compile_failure/non_comptime_local_fn_call/src/main.nr +++ b/noir/noir-repo/test_programs/compile_failure/non_comptime_local_fn_call/src/main.nr @@ -1,9 +1,10 @@ fn main() { - comptime { + comptime + { let _a = id(3); } } fn id(x: Field) -> Field { x -} \ No newline at end of file +} diff --git a/noir/noir-repo/test_programs/compile_failure/orphaned_trait_impl/src/main.nr b/noir/noir-repo/test_programs/compile_failure/orphaned_trait_impl/src/main.nr index dfd88d8f074..dd04aa454b2 100644 --- a/noir/noir-repo/test_programs/compile_failure/orphaned_trait_impl/src/main.nr +++ b/noir/noir-repo/test_programs/compile_failure/orphaned_trait_impl/src/main.nr @@ -1,4 +1,4 @@ -impl dep::crate1::MyTrait for dep::crate2::MyStruct { +impl crate1::MyTrait for crate2::MyStruct { } fn main(x: Field, y: pub Field) { diff --git a/noir/noir-repo/test_programs/compile_failure/restricted_bit_sizes/src/main.nr b/noir/noir-repo/test_programs/compile_failure/restricted_bit_sizes/src/main.nr index 4298c2052a7..a3fea13cc3a 100644 --- a/noir/noir-repo/test_programs/compile_failure/restricted_bit_sizes/src/main.nr +++ b/noir/noir-repo/test_programs/compile_failure/restricted_bit_sizes/src/main.nr @@ -1,3 +1,5 @@ +use std::assert_constant; + fn main() -> pub u63 { 5 } diff --git a/noir/noir-repo/test_programs/compile_failure/turbofish_generic_count/src/main.nr b/noir/noir-repo/test_programs/compile_failure/turbofish_generic_count/src/main.nr index a5f46adb6a5..4091b2f0581 100644 --- a/noir/noir-repo/test_programs/compile_failure/turbofish_generic_count/src/main.nr +++ b/noir/noir-repo/test_programs/compile_failure/turbofish_generic_count/src/main.nr @@ -1,4 +1,3 @@ - struct Bar { one: Field, two: Field, diff --git a/noir/noir-repo/test_programs/compile_success_contract/abi_attribute/Nargo.toml b/noir/noir-repo/test_programs/compile_success_contract/abi_attribute/Nargo.toml index 9fcd61c235e..e85cc2aefef 100644 --- a/noir/noir-repo/test_programs/compile_success_contract/abi_attribute/Nargo.toml +++ b/noir/noir-repo/test_programs/compile_success_contract/abi_attribute/Nargo.toml @@ -3,4 +3,6 @@ name = "abi_attribute" type = "contract" authors = [""] -[dependencies] \ No newline at end of file +[dependencies] + + diff --git a/noir/noir-repo/test_programs/compile_success_contract/abi_attribute/src/main.nr b/noir/noir-repo/test_programs/compile_success_contract/abi_attribute/src/main.nr index 0c376b54686..164512b03db 100644 --- a/noir/noir-repo/test_programs/compile_success_contract/abi_attribute/src/main.nr +++ b/noir/noir-repo/test_programs/compile_success_contract/abi_attribute/src/main.nr @@ -6,4 +6,4 @@ contract Foo { struct Bar { inner: Field } -} \ No newline at end of file +} diff --git a/noir/noir-repo/test_programs/compile_success_empty/numeric_generics/src/main.nr b/noir/noir-repo/test_programs/compile_success_empty/numeric_generics/src/main.nr index 1e03a382fed..340c18c2a1d 100644 --- a/noir/noir-repo/test_programs/compile_success_empty/numeric_generics/src/main.nr +++ b/noir/noir-repo/test_programs/compile_success_empty/numeric_generics/src/main.nr @@ -36,4 +36,3 @@ fn foo(mut s: MyStruct<2+1>) -> MyStruct<10/2-2> { s.data[0] = s.data[0] + 1; s } - diff --git a/noir/noir-repo/test_programs/compile_success_empty/reexports/src/main.nr b/noir/noir-repo/test_programs/compile_success_empty/reexports/src/main.nr index ed469ff77d0..0fd65a33564 100644 --- a/noir/noir-repo/test_programs/compile_success_empty/reexports/src/main.nr +++ b/noir/noir-repo/test_programs/compile_success_empty/reexports/src/main.nr @@ -1,4 +1,4 @@ -use dep::reexporting_lib::{FooStruct, MyStruct, lib}; +use reexporting_lib::{FooStruct, MyStruct, lib}; fn main() { let x: FooStruct = MyStruct { inner: 0 }; diff --git a/noir/noir-repo/test_programs/compile_success_empty/workspace_reexport_bug/binary/src/main.nr b/noir/noir-repo/test_programs/compile_success_empty/workspace_reexport_bug/binary/src/main.nr index ab0ae9a48b8..a4207794a8a 100644 --- a/noir/noir-repo/test_programs/compile_success_empty/workspace_reexport_bug/binary/src/main.nr +++ b/noir/noir-repo/test_programs/compile_success_empty/workspace_reexport_bug/binary/src/main.nr @@ -1,2 +1,2 @@ -use dep::library::ReExportMeFromAnotherLib; +use library::ReExportMeFromAnotherLib; fn main(_x: ReExportMeFromAnotherLib) {} diff --git a/noir/noir-repo/test_programs/compile_success_empty/workspace_reexport_bug/library/src/lib.nr b/noir/noir-repo/test_programs/compile_success_empty/workspace_reexport_bug/library/src/lib.nr index 8e84662ed03..e3a1539ea65 100644 --- a/noir/noir-repo/test_programs/compile_success_empty/workspace_reexport_bug/library/src/lib.nr +++ b/noir/noir-repo/test_programs/compile_success_empty/workspace_reexport_bug/library/src/lib.nr @@ -1,2 +1,2 @@ // Re-export -use dep::library2::ReExportMeFromAnotherLib; +use library2::ReExportMeFromAnotherLib; diff --git a/noir/noir-repo/test_programs/execution_failure/div_by_zero_numerator_witness/src/main.nr b/noir/noir-repo/test_programs/execution_failure/div_by_zero_numerator_witness/src/main.nr index 7c6cae4932e..012e823b297 100644 --- a/noir/noir-repo/test_programs/execution_failure/div_by_zero_numerator_witness/src/main.nr +++ b/noir/noir-repo/test_programs/execution_failure/div_by_zero_numerator_witness/src/main.nr @@ -1,4 +1,3 @@ - fn main(x: Field) { let a: Field = x / 0; std::println(a); diff --git a/noir/noir-repo/test_programs/execution_success/diamond_deps_0/src/main.nr b/noir/noir-repo/test_programs/execution_success/diamond_deps_0/src/main.nr index ca95c6e0aa8..690d6fc9fc8 100644 --- a/noir/noir-repo/test_programs/execution_success/diamond_deps_0/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/diamond_deps_0/src/main.nr @@ -1,6 +1,6 @@ -use dep::dep1::call_dep1_then_dep2; -use dep::dep2::call_dep2; -use dep::dep2::RESOLVE_THIS; +use dep1::call_dep1_then_dep2; +use dep2::call_dep2; +use dep2::RESOLVE_THIS; fn main(x: Field, y: pub Field) -> pub Field { call_dep1_then_dep2(x, y) + call_dep2(x, y) + RESOLVE_THIS diff --git a/noir/noir-repo/test_programs/execution_success/hashmap/src/main.nr b/noir/noir-repo/test_programs/execution_success/hashmap/src/main.nr index 56b13d6779b..8cf70cc5970 100644 --- a/noir/noir-repo/test_programs/execution_success/hashmap/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/hashmap/src/main.nr @@ -3,6 +3,7 @@ mod utils; use std::collections::map::HashMap; use std::hash::BuildHasherDefault; use std::hash::poseidon2::Poseidon2Hasher; +use std::cmp::Eq; use utils::cut; diff --git a/noir/noir-repo/test_programs/execution_success/traits_in_crates_1/crate1/src/lib.nr b/noir/noir-repo/test_programs/execution_success/traits_in_crates_1/crate1/src/lib.nr index 62dd5a2c111..e36a263093a 100644 --- a/noir/noir-repo/test_programs/execution_success/traits_in_crates_1/crate1/src/lib.nr +++ b/noir/noir-repo/test_programs/execution_success/traits_in_crates_1/crate1/src/lib.nr @@ -2,7 +2,7 @@ trait MyTrait { fn Add10(&mut self); } -impl MyTrait for dep::crate2::MyStruct { +impl MyTrait for crate2::MyStruct { fn Add10(&mut self) { self.Q += 10; } diff --git a/noir/noir-repo/test_programs/execution_success/traits_in_crates_1/src/main.nr b/noir/noir-repo/test_programs/execution_success/traits_in_crates_1/src/main.nr index 7ba2f63c5c0..2afec29ee1f 100644 --- a/noir/noir-repo/test_programs/execution_success/traits_in_crates_1/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/traits_in_crates_1/src/main.nr @@ -1,5 +1,5 @@ fn main(x: Field, y: pub Field) { - let mut V = dep::crate2::MyStruct { Q: x }; + let mut V = crate2::MyStruct { Q: x }; V.Add10(); assert(V.Q == y); } diff --git a/noir/noir-repo/test_programs/execution_success/traits_in_crates_2/crate2/src/lib.nr b/noir/noir-repo/test_programs/execution_success/traits_in_crates_2/crate2/src/lib.nr index 38870489131..fe6a94a4a95 100644 --- a/noir/noir-repo/test_programs/execution_success/traits_in_crates_2/crate2/src/lib.nr +++ b/noir/noir-repo/test_programs/execution_success/traits_in_crates_2/crate2/src/lib.nr @@ -2,7 +2,7 @@ struct MyStruct { Q: Field, } -impl dep::crate1::MyTrait for MyStruct { +impl crate1::MyTrait for MyStruct { fn Add10(&mut self) { self.Q += 10; } diff --git a/noir/noir-repo/test_programs/execution_success/traits_in_crates_2/src/main.nr b/noir/noir-repo/test_programs/execution_success/traits_in_crates_2/src/main.nr index 7ba2f63c5c0..2afec29ee1f 100644 --- a/noir/noir-repo/test_programs/execution_success/traits_in_crates_2/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/traits_in_crates_2/src/main.nr @@ -1,5 +1,5 @@ fn main(x: Field, y: pub Field) { - let mut V = dep::crate2::MyStruct { Q: x }; + let mut V = crate2::MyStruct { Q: x }; V.Add10(); assert(V.Q == y); } diff --git a/noir/noir-repo/test_programs/execution_success/verify_honk_proof/Prover.toml b/noir/noir-repo/test_programs/execution_success/verify_honk_proof/Prover.toml new file mode 100644 index 00000000000..c1ec4049fa9 --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/verify_honk_proof/Prover.toml @@ -0,0 +1,4 @@ +key_hash = "0x096129b1c6e108252fc5c829c4cc9b7e8f0d1fd9f29c2532b563d6396645e08f" +proof = ["0x0000000000000000000000000000000000000000000000000000000000000020","0x0000000000000000000000000000000000000000000000000000000000000011","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000042ab5d6d1986846cf","0x00000000000000000000000000000000000000000000000b75c020998797da78","0x0000000000000000000000000000000000000000000000005a107acb64952eca","0x000000000000000000000000000000000000000000000000000031e97a575e9d","0x00000000000000000000000000000000000000000000000b5666547acf8bd5a4","0x00000000000000000000000000000000000000000000000c410db10a01750aeb","0x00000000000000000000000000000000000000000000000d722669117f9758a4","0x000000000000000000000000000000000000000000000000000178cbf4206471","0x000000000000000000000000000000000000000000000000e91b8a11e7842c38","0x000000000000000000000000000000000000000000000007fd51009034b3357f","0x000000000000000000000000000000000000000000000009889939f81e9c7402","0x0000000000000000000000000000000000000000000000000000f94656a2ca48","0x000000000000000000000000000000000000000000000006fb128b46c1ddb67f","0x0000000000000000000000000000000000000000000000093fe27776f50224bd","0x000000000000000000000000000000000000000000000004a0c80c0da527a081","0x0000000000000000000000000000000000000000000000000001b52c2020d746","0x0000000000000000000000000000005a9bae947e1e91af9e4033d8d6aa6ed632","0x000000000000000000000000000000000025e485e013446d4ac7981c88ba6ecc","0x000000000000000000000000000000ff1e0496e30ab24a63b32b2d1120b76e62","0x00000000000000000000000000000000001afe0a8a685d7cd85d1010e55d9d7c","0x000000000000000000000000000000b0804efd6573805f991458295f510a2004","0x00000000000000000000000000000000000c81a178016e2fe18605022d5a8b0e","0x000000000000000000000000000000eba51e76eb1cfff60a53a0092a3c3dea47","0x000000000000000000000000000000000022e7466247b533282f5936ac4e6c15","0x00000000000000000000000000000071b1d76edf770edff98f00ff4deec264cd","0x00000000000000000000000000000000001e48128e68794d8861fcbb2986a383","0x000000000000000000000000000000d3a2af4915ae6d86b097adc377fafda2d4","0x000000000000000000000000000000000006359de9ca452dab3a4f1f8d9c9d98","0x0000000000000000000000000000000d9d719a8b9f020ad3642d60fe704e696f","0x00000000000000000000000000000000000ddfdbbdefc4ac1580ed38e12cfa49","0x0000000000000000000000000000008289fe9754ce48cd01b7be96a861b5e157","0x00000000000000000000000000000000000ff3e0896bdea021253b3d360fa678","0x0000000000000000000000000000000d9d719a8b9f020ad3642d60fe704e696f","0x00000000000000000000000000000000000ddfdbbdefc4ac1580ed38e12cfa49","0x0000000000000000000000000000008289fe9754ce48cd01b7be96a861b5e157","0x00000000000000000000000000000000000ff3e0896bdea021253b3d360fa678","0x000000000000000000000000000000f968b227a358a305607f3efc933823d288","0x00000000000000000000000000000000000eaf8adb390375a76d95e918b65e08","0x000000000000000000000000000000bb34b4b447aae56f5e24f81c3acd6d547f","0x00000000000000000000000000000000002175d012746260ebcfe339a91a81e1","0x0000000000000000000000000000005b739ed2075f2b046062b8fc6a2d1e9863","0x00000000000000000000000000000000001285cd1030d338c0e1603b4da2c838","0x00000000000000000000000000000027447d6c281eb38b2b937af4a516d60c04","0x000000000000000000000000000000000019bc3d980465fbb4a656a74296fc58","0x000000000000000000000000000000b484788ace8f7df86dd5e325d2e9b12599","0x00000000000000000000000000000000000a2ca0d10eb7b767114ae230b728d3","0x000000000000000000000000000000c6dfc7092f16f95795e437664498b88d53","0x0000000000000000000000000000000000131067b4e4d95a4f6f8cf5c9b5450a","0x0f413f22eec51f2a02800e0cafaeec1d92d744fbbaef213c687b9edabd6985f5","0x21230f4ff26c80ffb5d037a9d1d26c3f955ca34cbeca4f54db6656b932967a0c","0x0521f877fe35535767f99597cc50effbd283dcae6812ee0a7620d796ccbfd642","0x202b01350a9cc5c20ec0f3eaada338c0a3b793811bd539418ffa3cc4302615e2","0x2d1214d9b0d41058ad4a172d9c0aecc5bdabe95e687c3465050c6b5396509be4","0x1113b344a151b0af091cb28d728b752ebb4865da6cd7ee68471b961ca5cf69b9","0x2aa66d0954bb83e17bd5c9928d3aa7a7df75d741d409f7c15ba596804ba643fb","0x2e26bc7a530771ef7a95d5360d537e41cf94d8a0942764ff09881c107f91a106","0x0f14f32b921bb63ad1df00adab7c82af58ea8aa7f353f14b281208d8c5fab504","0x13429515c0c53b6502bbcdf545defb3cb69a986c9263e070fcbb397391aae1a3","0x1f21cac5e2f262afc1006a21454cc6bcb018c44e53ad8ab61cebbac99e539176","0x2a9886a6ddc8a61b097c668cd362fc8acdee8dde74f7b1af192c3e060bb2948f","0x2d718181e408ead2e9bcd30a84ad1fccbaf8d48ab6d1820bad4933d284b503c4","0x2634c1aafc902f14508f34d3d7e9d485f42d1a4c95b5a1ef73711ed0d3c68d77","0x092ede9777e6472ce5ffd8c963d466006189e960e2c591d338dc8d4af1a057fb","0x1cba45b17fd24f1cb1b4ab7b83eee741f6c77ba70a497dc4de259eceb7d5ea26","0x246e887c7bf2e17f919b2393b6e9b00b33e8822d862544a775aac05cb7bff710","0x04c3f539fe8689971948afcb437f1ecbd444a5bddaca1c8a450348dcd8480047","0x20c6a423ae4fd58e8951aa378d02d77baf90508ceb48856db2319d70938b186e","0x1bcf8786b554b3316d8ebdbc9d006a4e5d4865aad512ffd404b7f83550d3d030","0x09ab038260518f0970564afcd6bf22e2abf6b1fa5e12a327bbf195b6ca5edd78","0x1024e32554746f89c195286ba6ccfc9765e5d14bbe8064bc6fdf22d16ec6b495","0x17706656f8dbd7e47bb257a6428f0cb7278ea02fa9e6ce431d7bcc9133fba9c7","0x25a3e8a33c15ef2a4dd16313a6049bf1d468b4cdc141f238f2d51a1e8e1c22b3","0x1198863f08006edb27aee23164fb117a4ddec1bf1ed89807aa907e5cd24bf068","0x1862b4856b5b4d4a064f873e221703e4e2cd1ebfca1337dedca56485c38ed5a0","0x062214af1ea6dd6bf8895b92d394571c43970b6f967e1c794624d96071b25ad3","0x1e5be9428ddcf1f9b0cbafc28101e792ec5cf73852b0cd0b84fbff71b4490e09","0x2d4189bea5b1e30f63c64bd26df82f18bcaf885ec8887b54634b2557869ce87f","0x0f2e5d9a908850e9d44925e17d8b12d1adb1ed029799c9b5858598504242bbc0","0x3050dc85746a57931d99f3f35e77c2ba561fba0baa018b79ff1fd544026833ae","0x2a591a32437e5e0b875a137fd868bd1b6dbc003ff1b661f26e00627cc7c5cf47","0x27946841e1670ad9c65717016d0cedf524724217236e81b9fd0a264a36ebfb0e","0x0fc396e9d19d6e68e289602e292ee345542d0d28bf6de34fa62cc577cbdfb1df","0x08e7433a07a44c0c9c4dd4b273a2685bbd1a91fd5cf2b43409458fab42a23e1b","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x12bd9bfb029c3503a5c6deea87b0a0f11bb9f7ea584af2d48f3e48d7e09247ae","0x2ccc4810748c0a82dfc0f063d0b8c7999ffe9474653080e6ef92b3cb7a428784","0x08eb574d7fecadadb508c8bd35fdad06b99110609d679763c2e3645229b1b95a","0x0f1a65e747c8021ed7c454a4be1e89b1bce66ead9ed980fa98a7a050eafe98a1","0x1c8ff9e36684ec71614dee4c17859b06c742089f6029d3694a16e00dac9b57f1","0x0303101a8ba712aeca4da85b767ab8d3ecf489ec7d746f8ee20041717cc000e9","0x0aaf64c65e7088e5596108c9601467911fea809ca6540d79af77e6e66e36cd99","0x17caf164ce74ea7edfb1390e07763d2197797ec26661b92cde18a98d61d2fddc","0x18cb055c7ad6d01437725bb457681d81f3ecadc4f35d838a3c13daf25a44456a","0x2d78602b8bbcd32b36a99a6e2d248e7fe044ef1b50813133370412f9ef5299f0","0x2b139276ea86d426a115479e4154f72a6bd83a6253bf13e9670dc6b4664378f0","0x127c7837b384902c39a104036c09546728571c46c8166b1b9b13b3a615ebb781","0x05faa4816f83cf0189a482ad943c94b9ec6474002f2b327f8698763ad0ea0985","0x2f90359cc30ee693fb3aced96523cf7aebd152c22329eee56a398d9a4ac0628e","0x0a71beaf17a59c5a238f04c1f203848d87502c5057a78c13f0cfb0f9876e7714","0x2696c1e6d089556adaeb95c8a5e3065b00a393a38c2d69e9bd6ce8cdc49d87da","0x1f3d165a7dc6564a036e451eb9cb7f1e1cb1e6d29daa75e3f135ea3e58a79ccd","0x1473a660819bdd838d56122b72b32b267211e9f1103239480ec50fa85c9e1035","0x0a8ccaeb22451f391b3fc3467c8e6e900270a7afb7b510e8acf5a4f06f1c0888","0x03b3080afc0658cc87e307758cebc171921f43eca159b9dedf7f72aa8dd926bd","0x2dd7d6663fa0e1755dfafac352c361fcd64c7f4d53627e3646870ac169cc4a07","0x1ec54b883f5f35ccad0e75695af20790d9860104095bab34c9bf01628dd40cb9","0x193dff50f83c241f7a9e087a29ce72ecf3f6d8563593f786dcd04c32bcfd4ced","0x135122c0dae26cda8ca1c09de8225064ad86d10423ab0aaa53b481aa4626e1d6","0x08d5a56cbfab5aeed56d3cdd7fb6b30fc26b0c1a5b63fccd7fa44c53ba6fd35a","0x0d12f126dfa2daad3726d00ca339284cc22e36c6d81bb7a4b95c6f9598b60e7c","0x2e8b24bbdf2fd839d3c7cae1f0eeb96bfcfaeef30b27476f2fafcb17da78cd5e","0x2364acfe0cea39b7f749c5f303b99504977357925f810f684c60f35d16315211","0x06ca062eb70b8c51cfac35345e7b6b51f33a8ec9ebe204fb9b4911200bf508b7","0x266c0aa1ccb97186815bf69084f600d06ddd934e59a38dfe602ee5d6b9487f22","0x1d817537a49c6d0e3b4b65c6665334b91d7593142e60065048be9e55ceb5e7ab","0x05e9b7256a368df053c691952b59e9327a7c12ed322bbd6f72c669b9b9c26d49","0x05e9b7256a368df053c691952b59e9327a7c12ed322bbd6f72c669b9b9c26d49","0x25b77026673a1e613e50df0e88fb510973739d5f9064bd364079a9f884209632","0x25c9bc7a3f6aae3d43ff68b5614b34b5eaceff37157b37347995d231784ac1fd","0x085f69baef22680ae15f4801ef4361ebe9c7fc24a94b5bc2527dce8fb705439e","0x0d7c6b9ce31bfc32238a205455baf5ffe99cd30eb0f7bb5b504e1d4501e01382","0x1001a8cc4bc1221c814fba0eddcf3c40619b133373640c600de5bed0a0a05b10","0x20f5894be90e52977cb70f4f4cbd5101693db0360848939750db7e91109d54b6","0x22c09cb26db43f0599408b4daed0f4f496c66424e6affa41c14387d8e0af851b","0x24e5f41357798432426a9549d71e8cc681eaebacbe87f6e3bf38e85de5aa2f3d","0x06eb90100c736fbf2b87432d7821ecdc0b365024739bc36363d48b905973f5b9","0x000000000000000000000000000000ece6d09ed58e9f5661c01140b10558a8c2","0x000000000000000000000000000000000012b6e4f37adcb34b8e88ff8b6eebce","0x000000000000000000000000000000b226a2bb93593fa1fab19a44767828a3f5","0x00000000000000000000000000000000002b5b518342030543092e1428a7e33c","0x00000000000000000000000000000022ba33857034a0574c216eb3c1ddff3025","0x00000000000000000000000000000000001918e58df857985a7cf9eae7802165","0x00000000000000000000000000000045c2d840b96fb6106cc14dcad89dd5f675","0x00000000000000000000000000000000000afdfac1e3a1febdd0208867d44f98","0x00000000000000000000000000000042ebed6c5ec45d794f119aef24c192af0f","0x00000000000000000000000000000000002d05ef250900bbcc5751bbeb210d6a","0x00000000000000000000000000000060d604bdda48eecc90ed065bd9770e1323","0x00000000000000000000000000000000001fed91c63d0041660c1cbc84c2ffbb","0x00000000000000000000000000000054196b549cde36092e8184c7f4f7d878de","0x00000000000000000000000000000000000153f26a01294329922b492485cc31","0x00000000000000000000000000000056ebea579d10dbb440f0222931df2c0059","0x00000000000000000000000000000000000d2cbc61ce5b7cdd7fce398da4637b","0x000000000000000000000000000000e2b9512360b9797d96675d8a2fd2f7aa5d","0x000000000000000000000000000000000025742905f105ff895f74e7c3daa34a","0x000000000000000000000000000000a2dd7df55db59bd41b83518d4403fbc382","0x00000000000000000000000000000000002c1d9c3cbb9371d4cc4e9f900b9a46","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x000000000000000000000000000000bcf12ae40c9425c3e67654b84181f90502","0x00000000000000000000000000000000000b6d3faa8a71ff6ef1aa887b7307cf","0x0000000000000000000000000000001f6f719acc23b8f84808c0275d61cfb456","0x0000000000000000000000000000000000296030933ed0c134457ae71c393dfe","0x000000000000000000000000000000ebe1a57cdd7d3d763289b40ef5ed9a7ae0","0x000000000000000000000000000000000010f30483e7df51fca2316d3367603c","0x0000000000000000000000000000000149b7b283ab18060618c8e051864c03cd","0x00000000000000000000000000000000001ef7763235a3a25e241a5f06704dc3"] +public_inputs = ["0x0000000000000000000000000000000000000000000000000000000000000003"] +verification_key = ["0x0000000000000000000000000000000000000000000000000000000000000020","0x0000000000000000000000000000000000000000000000000000000000000011","0x0000000000000000000000000000000000000000000000000000000000000001","0x00000000000000000000000000000060e430ad1c23bfcf3514323aae3f206e84","0x00000000000000000000000000000000001b5c3ff4c2458d8f481b1c068f27ae","0x000000000000000000000000000000bb510ab2112def34980e4fc6998ad9dd16","0x00000000000000000000000000000000000576e7c105b43e061e13cb877fefe1","0x000000000000000000000000000000ced074785d11857b065d8199e6669a601c","0x00000000000000000000000000000000000053b48a4098c1c0ae268f273952f7","0x000000000000000000000000000000d1d4b26e941db8168cee8f6de548ae0fd8","0x00000000000000000000000000000000001a9adf5a6dadc3d948bb61dfd63f4c","0x0000000000000000000000000000009ce1faac6f8de6ebb18f1db17372c82ad5","0x00000000000000000000000000000000002002681bb417184b2df070a16a3858","0x000000000000000000000000000000161baa651a8092e0e84725594de5aba511","0x00000000000000000000000000000000000be0064399c2a1efff9eb0cdcb2223","0x0000000000000000000000000000008673be6fd1bdbe980a29d8c1ded54381e7","0x000000000000000000000000000000000008a5158a7d9648cf1d234524c9fa0c","0x0000000000000000000000000000002b4fce6e4b1c72062b296d49bca2aa4130","0x00000000000000000000000000000000002e45a9eff4b6769e55fb710cded44f","0x00000000000000000000000000000072b85bf733758b76bcf97333efb85a23e3","0x000000000000000000000000000000000017da0ea508994fc82862715e4b5592","0x00000000000000000000000000000094fa74695cf058dba8ff35aec95456c6c3","0x0000000000000000000000000000000000211acddb851061c24b8f159e832bd1","0x000000000000000000000000000000303b5e5c531384b9a792e11702ad3bcab0","0x00000000000000000000000000000000000d336dff51a60b8833d5d7f6d4314c","0x0000000000000000000000000000009f825dde88092070747180d581c342444a","0x0000000000000000000000000000000000237fbd6511a03cca8cac01b555fe01","0x0000000000000000000000000000007c313205159495df6d8de292079a4844ff","0x000000000000000000000000000000000018facdfc468530dd45e8f7a1d38ce9","0x0000000000000000000000000000000d1ce33446fc3dc4ab40ca38d92dac74e1","0x00000000000000000000000000000000000852d8e3e0e8f4435af3e94222688b","0x0000000000000000000000000000006c04ee19ec1dfec87ed47d6d04aa158de2","0x000000000000000000000000000000000013240f97a584b45184c8ec31319b5f","0x000000000000000000000000000000cefb5d240b07ceb4be26ea429b6dc9d9e0","0x00000000000000000000000000000000002dad22022121d689f57fb38ca21349","0x000000000000000000000000000000c9f189f2a91aeb664ce376d8b157ba98f8","0x00000000000000000000000000000000002531a51ad54f124d58094b219818d2","0x000000000000000000000000000000ef1e6db71809307f677677e62b4163f556","0x0000000000000000000000000000000000272da4396fb2a7ee0638b9140e523d","0x0000000000000000000000000000002e54c0244a7732c87bc4712a76dd8c83fb","0x000000000000000000000000000000000007db77b3e04b7eba9643da57cbbe4d","0x000000000000000000000000000000e0dfe1ddd7f74ae0d636c910c3e85830d8","0x00000000000000000000000000000000000466fa9b57ec4664abd1505b490862","0x0000000000000000000000000000009ee55ae8a32fe5384c79907067cc27192e","0x00000000000000000000000000000000000799d0e465cec07ecb5238c854e830","0x0000000000000000000000000000001d5910ad361e76e1c241247a823733c39f","0x00000000000000000000000000000000002b03f2ccf7507564da2e6678bef8fe","0x000000000000000000000000000000231147211b3c75e1f47d150e4bbd2fb22e","0x00000000000000000000000000000000000d19ee104a10d3c701cfd87473cbbe","0x0000000000000000000000000000006705f3f382637d00f698e2c5c94ed05ae9","0x00000000000000000000000000000000000b9c792da28bb60601dd7ce4b74e68","0x000000000000000000000000000000ac5acc8cc21e4ddb225c510670f80c80b3","0x00000000000000000000000000000000002da9d3fa57343e6998aba19429b9fa","0x0000000000000000000000000000004bacbf54b7c17a560df0af18b6d0d527be","0x00000000000000000000000000000000000faea33aeca2025b22c288964b21eb","0x000000000000000000000000000000492e756298d68d6e95de096055cc0336c3","0x00000000000000000000000000000000001a12a12f004859e5a3675c7315121b","0x000000000000000000000000000000893d521d512f30e6d32afbbc0cecd8ee00","0x00000000000000000000000000000000001674b3c1ef12c6da690631e0d86c04","0x000000000000000000000000000000aa6cb02a52e7a613873d4ac9b411349945","0x00000000000000000000000000000000001ecb1fe9c493add46751f9940f73e1","0x00000000000000000000000000000045b3d362ca82cba69fb2b9c733a5b8c351","0x000000000000000000000000000000000019a683586af466e331945b732d2f8c","0x000000000000000000000000000000fc79b052dfdfe67c0ecfc06b4267ffd694","0x00000000000000000000000000000000001336a70c396393038d5e9913744ac2","0x0000000000000000000000000000005450d29af1e9438e91cd33ddeb2548226e","0x000000000000000000000000000000000000993a602891cfd0e6f6ecf7404933","0x000000000000000000000000000000498efddab90a32e9b2db729ed6e9b40192","0x00000000000000000000000000000000002425efebe9628c63ca6fc28bdb5901","0x000000000000000000000000000000d8488157f875a21ab5f93f1c2b641f3de9","0x0000000000000000000000000000000000290f95ada3936604dc4b14df7504e3","0x0000000000000000000000000000005d6902187f3ed60dcce06fca211b40329a","0x00000000000000000000000000000000002b5870a6ba0b20aaa0178e5adfbc36","0x000000000000000000000000000000e5c2519171fa0e548fc3c4966ffc1ce570","0x00000000000000000000000000000000001cb8d8f4793b7debbdc429389dbf2d","0x000000000000000000000000000000a3ee22dd60456277b86c32a18982dcb185","0x00000000000000000000000000000000002493c99a3d068b03f8f2b8d28b57ce","0x000000000000000000000000000000f6c3731486320082c20ec71bbdc92196c1","0x00000000000000000000000000000000001ded39c4c8366469843cd63f09ecac","0x000000000000000000000000000000494997477ab161763e46601d95844837ef","0x00000000000000000000000000000000002e0cddbc5712d79b59cb3b41ebbcdd","0x000000000000000000000000000000426db4c64531d350750df62dbbc41a1bd9","0x0000000000000000000000000000000000303126892f664d8d505964d14315ec","0x00000000000000000000000000000076a6b2c6040c0c62bd59acfe3e3e125672","0x000000000000000000000000000000000000874a5ad262eecc6b565e0b085074","0x000000000000000000000000000000ef082fb517183c9c6841c2b8ef2ca1df04","0x0000000000000000000000000000000000127b2a745a1b74968c3edc18982b9b","0x000000000000000000000000000000c9efd4f8c3d56e1eb23d789a8f710d5be6","0x000000000000000000000000000000000015a18748490ff4c2b1871081954e86","0x000000000000000000000000000000a0011ef987dc016ab110eacd554a1d8bbf","0x00000000000000000000000000000000002097c84955059442a95df075833071","0x000000000000000000000000000000d38e9426ad3085b68b00a93c17897c2877","0x00000000000000000000000000000000002aecd48089890ea0798eb952c66824","0x00000000000000000000000000000078d8a9ce405ce559f441f2e71477ff3ddb","0x00000000000000000000000000000000001216bdb2f0d961bb8a7a23331d2150","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x000000000000000000000000000000ee40d90bea71fba7a412dd61fcf34e8ceb","0x0000000000000000000000000000000000140b0936c323fd2471155617b6af56","0x0000000000000000000000000000002b90071823185c5ff8e440fd3d73b6fefc","0x00000000000000000000000000000000002b6c10790a5f6631c87d652e059df4"] \ No newline at end of file diff --git a/noir/noir-repo/test_programs/execution_success/verify_honk_proof/src/main.nr b/noir/noir-repo/test_programs/execution_success/verify_honk_proof/src/main.nr new file mode 100644 index 00000000000..ecfd18f3837 --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/verify_honk_proof/src/main.nr @@ -0,0 +1,21 @@ + +// This circuit aggregates a single Honk proof from `assert_statement_recursive`. +global SIZE_OF_PROOF_IF_LOGN_IS_28 : u32 = 409; +fn main( + verification_key: [Field; 103], + // This is the proof without public inputs attached. + // + // This means: the size of this does not change with the number of public inputs. + proof: [Field; SIZE_OF_PROOF_IF_LOGN_IS_28], + public_inputs: pub [Field; 1], + // This is currently not public. It is fine given that the vk is a part of the circuit definition. + // I believe we want to eventually make it public too though. + key_hash: Field +) { + std::verify_proof( + verification_key.as_slice(), + proof.as_slice(), + public_inputs.as_slice(), + key_hash + ); +} diff --git a/noir/noir-repo/test_programs/noir_test_failure/should_fail_mismatch/src/main.nr b/noir/noir-repo/test_programs/noir_test_failure/should_fail_mismatch/src/main.nr index 62e03c153ed..614771fec17 100644 --- a/noir/noir-repo/test_programs/noir_test_failure/should_fail_mismatch/src/main.nr +++ b/noir/noir-repo/test_programs/noir_test_failure/should_fail_mismatch/src/main.nr @@ -2,9 +2,8 @@ fn test_different_string() { assert_eq(0, 1, "Different string"); } - // The failure reason is a substring of the expected message, but it should be the other way around #[test(should_fail_with = "Definitely Not equal!")] fn test_wrong_expectation() { assert_eq(0, 1, "Not equal"); -} \ No newline at end of file +} diff --git a/noir/noir-repo/test_programs/rebuild.sh b/noir/noir-repo/test_programs/rebuild.sh index 094c3902583..a8175d05066 100755 --- a/noir/noir-repo/test_programs/rebuild.sh +++ b/noir/noir-repo/test_programs/rebuild.sh @@ -1,6 +1,8 @@ #!/usr/bin/env bash set -e +NO_PARALLEL=${1:-} + process_dir() { local dir=$1 local current_dir=$2 @@ -60,7 +62,46 @@ for dir in $current_dir/benchmarks/*; do dirs_to_process+=("$dir") done +pids=() # Array to hold PIDs of background processes +dirs_map=() # Array to map PIDs to directories + +if [ -z $NO_PARALLEL ]; then + # Process directories in parallel + for dir in "${dirs_to_process[@]}"; do + process_dir "$dir" "$current_dir" & # Run process_dir in the background + pid=$! # Get PID of the last background command + pids+=($pid) # Add PID to the pids array + dirs_map[$pid]=$dir # Map PID to the directory being processed + done +else + # Process directories sequentially + for dir in "${dirs_to_process[@]}"; do + process_dir "$dir" "$current_dir" # Run process_dir in the foreground + pid=$! # Get PID of the last command + pids+=($pid) # Add PID to the pids array + dirs_map[$pid]=$dir # Map PID to the directory being processed + done +fi + +# Store the failed processes +failed_pids=() +# Check the exit status of each background job. +for pid in "${pids[@]}"; do + if ! wait $pid; then # Wait for the process to complete, check if it failed + exit_status=$? # Capture the failed exit status + failed_pids+=($pid) + fi +done -parallel -j0 process_dir {} "$current_dir" ::: ${dirs_to_process[@]} - -echo "Rebuild Succeeded!" +echo "" + +# Exit with a failure status if any job failed. +if [ ! -z "$exit_status" ]; then + echo "Rebuild failed for directories:" + # Print the failed directories after waiting for each process to complete + for pid in "${failed_pids[@]}"; do + echo "${dirs_map[$pid]}" + done + exit $exit_status +fi +echo "Rebuild Succeeded!" \ No newline at end of file diff --git a/noir/noir-repo/test_programs/test_libraries/diamond_deps_1/src/lib.nr b/noir/noir-repo/test_programs/test_libraries/diamond_deps_1/src/lib.nr index 60c001ec64e..d76ce5a05e9 100644 --- a/noir/noir-repo/test_programs/test_libraries/diamond_deps_1/src/lib.nr +++ b/noir/noir-repo/test_programs/test_libraries/diamond_deps_1/src/lib.nr @@ -1,4 +1,4 @@ -use dep::dep2::call_dep2; +use dep2::call_dep2; pub fn call_dep1_then_dep2(x: Field, y: Field) -> Field { call_dep2(x, y) diff --git a/noir/noir-repo/test_programs/test_libraries/reexporting_lib/src/lib.nr b/noir/noir-repo/test_programs/test_libraries/reexporting_lib/src/lib.nr index f12dfe01ecd..1bced548304 100644 --- a/noir/noir-repo/test_programs/test_libraries/reexporting_lib/src/lib.nr +++ b/noir/noir-repo/test_programs/test_libraries/reexporting_lib/src/lib.nr @@ -1,3 +1,3 @@ -use dep::exporting_lib::{MyStruct, FooStruct}; +use exporting_lib::{MyStruct, FooStruct}; -use dep::exporting_lib as lib; +use exporting_lib as lib; diff --git a/noir/noir-repo/tooling/acvm_cli/Cargo.toml b/noir/noir-repo/tooling/acvm_cli/Cargo.toml index a592f2d65f3..1cfd1f3b270 100644 --- a/noir/noir-repo/tooling/acvm_cli/Cargo.toml +++ b/noir/noir-repo/tooling/acvm_cli/Cargo.toml @@ -20,7 +20,7 @@ path = "src/main.rs" [dependencies] thiserror.workspace = true toml.workspace = true -color-eyre.workspace = true +color-eyre = "0.6.2" clap.workspace = true acvm.workspace = true nargo.workspace = true diff --git a/noir/noir-repo/tooling/nargo_cli/Cargo.toml b/noir/noir-repo/tooling/nargo_cli/Cargo.toml index e0e54449a6f..b9d7d7e3e48 100644 --- a/noir/noir-repo/tooling/nargo_cli/Cargo.toml +++ b/noir/noir-repo/tooling/nargo_cli/Cargo.toml @@ -43,16 +43,11 @@ prettytable-rs = "0.10" rayon = "1.8.0" thiserror.workspace = true tower.workspace = true -async-lsp = { workspace = true, features = [ - "client-monitor", - "stdio", - "tracing", - "tokio", -] } +async-lsp = { workspace = true, features = ["client-monitor", "stdio", "tracing", "tokio"] } const_format.workspace = true similar-asserts.workspace = true termcolor = "1.1.2" -color-eyre.workspace = true +color-eyre = "0.6.2" tokio = { version = "1.0", features = ["io-std", "rt"] } dap.workspace = true clap-markdown = { git = "https://github.com/noir-lang/clap-markdown", rev = "450d759532c88f0dba70891ceecdbc9ff8f25d2b", optional = true } diff --git a/noir/noir-repo/tooling/nargo_fmt/tests/expected/contract.nr b/noir/noir-repo/tooling/nargo_fmt/tests/expected/contract.nr index 14b1af4a848..e3a5877725a 100644 --- a/noir/noir-repo/tooling/nargo_fmt/tests/expected/contract.nr +++ b/noir/noir-repo/tooling/nargo_fmt/tests/expected/contract.nr @@ -3,11 +3,11 @@ // Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. // Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. contract Benchmarking { - use dep::aztec::protocol_types::abis::function_selector::FunctionSelector; + use aztec::protocol_types::abis::function_selector::FunctionSelector; use value_note::{utils::{increment, decrement}, value_note::{VALUE_NOTE_LEN, ValueNote, ValueNoteMethods}}; - use dep::aztec::{ + use aztec::{ context::Context, note::{note_getter_options::NoteGetterOptions, note_header::NoteHeader}, log::emit_unencrypted_log, state_vars::{Map, PublicMutable, PrivateSet}, types::type_serialization::field_serialization::{FieldSerializationMethods, FIELD_SERIALIZED_LEN}, diff --git a/noir/noir-repo/tooling/nargo_fmt/tests/expected/let.nr b/noir/noir-repo/tooling/nargo_fmt/tests/expected/let.nr index 7ff69e74306..0edc0eaf922 100644 --- a/noir/noir-repo/tooling/nargo_fmt/tests/expected/let.nr +++ b/noir/noir-repo/tooling/nargo_fmt/tests/expected/let.nr @@ -51,10 +51,10 @@ fn let_() { let expr = MyExpr { /*A boolean literal (true, false).*/ kind: ExprKind::Bool(true) }; - let mut V = dep::crate2::MyStruct { Q: x }; - let mut V = dep::crate2::MyStruct {}; - let mut V = dep::crate2::MyStruct {/*test*/}; - let mut V = dep::crate2::MyStruct { + let mut V = crate2::MyStruct { Q: x }; + let mut V = crate2::MyStruct {}; + let mut V = crate2::MyStruct {/*test*/}; + let mut V = crate2::MyStruct { // sad }; } diff --git a/noir/noir-repo/tooling/nargo_fmt/tests/input/contract.nr b/noir/noir-repo/tooling/nargo_fmt/tests/input/contract.nr index 14b1af4a848..e3a5877725a 100644 --- a/noir/noir-repo/tooling/nargo_fmt/tests/input/contract.nr +++ b/noir/noir-repo/tooling/nargo_fmt/tests/input/contract.nr @@ -3,11 +3,11 @@ // Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. // Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. contract Benchmarking { - use dep::aztec::protocol_types::abis::function_selector::FunctionSelector; + use aztec::protocol_types::abis::function_selector::FunctionSelector; use value_note::{utils::{increment, decrement}, value_note::{VALUE_NOTE_LEN, ValueNote, ValueNoteMethods}}; - use dep::aztec::{ + use aztec::{ context::Context, note::{note_getter_options::NoteGetterOptions, note_header::NoteHeader}, log::emit_unencrypted_log, state_vars::{Map, PublicMutable, PrivateSet}, types::type_serialization::field_serialization::{FieldSerializationMethods, FIELD_SERIALIZED_LEN}, diff --git a/noir/noir-repo/tooling/nargo_fmt/tests/input/let.nr b/noir/noir-repo/tooling/nargo_fmt/tests/input/let.nr index 37cdc6655c7..16ce0a9d7f1 100644 --- a/noir/noir-repo/tooling/nargo_fmt/tests/input/let.nr +++ b/noir/noir-repo/tooling/nargo_fmt/tests/input/let.nr @@ -26,10 +26,10 @@ kind: ExprKind::Bool(true), let expr = MyExpr {/*A boolean literal (true, false).*/kind: ExprKind::Bool(true),}; - let mut V = dep::crate2::MyStruct { Q: x }; - let mut V = dep::crate2::MyStruct {}; - let mut V = dep::crate2::MyStruct {/*test*/}; - let mut V = dep::crate2::MyStruct { + let mut V = crate2::MyStruct { Q: x }; + let mut V = crate2::MyStruct {}; + let mut V = crate2::MyStruct {/*test*/}; + let mut V = crate2::MyStruct { // sad }; } diff --git a/yarn-project/.earthlyignore b/yarn-project/.earthlyignore index 90a25913737..bd9d331e9a6 100644 --- a/yarn-project/.earthlyignore +++ b/yarn-project/.earthlyignore @@ -39,10 +39,9 @@ cmake-build-debug **/tsconfig.tsbuildinfo **/.eslintcache **/target -accounts/src/artifacts +accounts/artifacts aztec-faucet/data* aztec-node/data* -aztec-js/src/account_contract/artifacts aztec/log circuits.js/fixtures/*.json docs/dist @@ -51,8 +50,8 @@ end-to-end/log end-to-end/data end-to-end/src/web/main.js end-to-end/src/web/main.js.LICENSE.txt -entry-points/src/artifacts l1-contracts/generated +noir-protocol-circuits-types/artifacts builder/target/ builder/proofs/ builder/Prover.toml @@ -64,7 +63,7 @@ builder/Verifier.toml builder/src/target builder/src/crs builder/src/types -protocol-contracts/src/artifacts +protocol-contracts/artifacts scripts/tmp noir-contracts.js/src noir-contracts.js/artifacts/ diff --git a/yarn-project/.gitignore b/yarn-project/.gitignore index e92d481c252..e044af6d3bd 100644 --- a/yarn-project/.gitignore +++ b/yarn-project/.gitignore @@ -12,10 +12,9 @@ **/.debounce-* **/.tsc.pid **/*.result -accounts/src/artifacts +accounts/artifacts aztec-faucet/data* aztec-node/data* -aztec-js/src/account_contract/artifacts aztec/log circuits.js/fixtures/*.json circuits.js/src/structs/kernel/private_kernel_reset_circuit_private_inputs_variants.ts @@ -25,9 +24,9 @@ end-to-end/log end-to-end/data end-to-end/src/web/main.js end-to-end/src/web/main.js.LICENSE.txt -entry-points/src/artifacts l1-artifacts/generated l1-contracts/generated +noir-protocol-circuits-types/artifacts builder/target/ builder/proofs/ builder/Prover.toml @@ -40,7 +39,7 @@ builder/src/target builder/src/crs builder/src/types noir-protocol-circuits-types/src/types/ -protocol-contracts/src/artifacts +protocol-contracts/artifacts scripts/tmp noir-contracts.js/src noir-contracts.js/artifacts/ diff --git a/yarn-project/Earthfile b/yarn-project/Earthfile index 1f4e2fdc790..162949f4a43 100644 --- a/yarn-project/Earthfile +++ b/yarn-project/Earthfile @@ -73,8 +73,7 @@ bb-cli: ../barretenberg/ts/dest/browser \ aztec.js/dest/main.js \ end-to-end \ - **/src \ - **/artifacts + **/src # yarn symlinks the binary to node_modules/.bin ENTRYPOINT ["/usr/src/yarn-project/node_modules/.bin/bb-cli"] @@ -124,8 +123,7 @@ txe: ../l1-contracts \ ../barretenberg/ts/src \ ../barretenberg/ts/dest/node-cjs \ - ../barretenberg/ts/dest/browser \ - **/artifacts + ../barretenberg/ts/dest/browser SAVE ARTIFACT /usr/src /usr/src aztec-prod: @@ -140,8 +138,7 @@ aztec-prod: ../barretenberg/ts/dest/browser \ aztec.js/dest/main.js \ end-to-end \ - **/src \ - **/artifacts + **/src COPY --dir +rollup-verifier-contract/usr/src/bb /usr/src SAVE ARTIFACT /usr/src /usr/src @@ -172,8 +169,7 @@ aztec-faucet-build: ../barretenberg/ts/dest/browser \ aztec.js/dest/main.js \ end-to-end \ - **/src \ - **/artifacts + **/src SAVE ARTIFACT /usr/src /usr/src aztec-faucet: @@ -193,8 +189,7 @@ end-to-end-prod: ../l1-contracts \ ../barretenberg/ts/src \ ../barretenberg/ts/dest/node-cjs \ - ../barretenberg/ts/dest/browser \ - **/artifacts + ../barretenberg/ts/dest/browser COPY --dir +rollup-verifier-contract/usr/src/bb /usr/src SAVE ARTIFACT /usr/src /usr/src diff --git a/yarn-project/accounts/.prettierignore b/yarn-project/accounts/.prettierignore index 2ade63ee6f9..eb6b23ceb90 100644 --- a/yarn-project/accounts/.prettierignore +++ b/yarn-project/accounts/.prettierignore @@ -1 +1 @@ -src/artifacts/*.json \ No newline at end of file +artifacts/*.json \ No newline at end of file diff --git a/yarn-project/accounts/package.json b/yarn-project/accounts/package.json index 90d2d36ab83..b1209964ae4 100644 --- a/yarn-project/accounts/package.json +++ b/yarn-project/accounts/package.json @@ -28,7 +28,7 @@ "generate:noir-contracts": "./scripts/copy-contracts.sh", "build:dev": "tsc -b --watch", "build:ts": "tsc -b", - "clean": "rm -rf ./dest .tsbuildinfo ./src/artifacts", + "clean": "rm -rf ./dest .tsbuildinfo ./artifacts", "formatting": "run -T prettier --check ./src && run -T eslint ./src", "formatting:fix": "run -T eslint --fix ./src && run -T prettier -w ./src", "test": "NODE_NO_WARNINGS=1 node --experimental-vm-modules ../node_modules/.bin/jest --passWithNoTests" @@ -91,7 +91,8 @@ "files": [ "dest", "src", - "!*.test.*" + "!*.test.*", + "artifacts" ], "engines": { "node": ">=18" diff --git a/yarn-project/accounts/package.local.json b/yarn-project/accounts/package.local.json index c5987104cfc..6e3a34a9358 100644 --- a/yarn-project/accounts/package.local.json +++ b/yarn-project/accounts/package.local.json @@ -5,6 +5,12 @@ "generate:noir-contracts": "./scripts/copy-contracts.sh", "build:dev": "tsc -b --watch", "build:ts": "tsc -b", - "clean": "rm -rf ./dest .tsbuildinfo ./src/artifacts" - } -} + "clean": "rm -rf ./dest .tsbuildinfo ./artifacts" + }, + "files": [ + "dest", + "src", + "artifacts", + "!*.test.*" + ] +} \ No newline at end of file diff --git a/yarn-project/accounts/scripts/copy-contracts.sh b/yarn-project/accounts/scripts/copy-contracts.sh index 8b945155a9d..5984357006a 100755 --- a/yarn-project/accounts/scripts/copy-contracts.sh +++ b/yarn-project/accounts/scripts/copy-contracts.sh @@ -1,9 +1,17 @@ #! /bin/bash set -euo pipefail -mkdir -p ./src/artifacts +mkdir -p ./artifacts contracts=(schnorr_account_contract-SchnorrAccount ecdsa_account_contract-EcdsaAccount schnorr_single_key_account_contract-SchnorrSingleKeyAccount) +decl=$(cat < ./artifacts/${contract#*-}.d.json.ts done \ No newline at end of file diff --git a/yarn-project/accounts/src/ecdsa/artifact.ts b/yarn-project/accounts/src/ecdsa/artifact.ts index 54ec3212dd0..a38c97a094f 100644 --- a/yarn-project/accounts/src/ecdsa/artifact.ts +++ b/yarn-project/accounts/src/ecdsa/artifact.ts @@ -1,5 +1,5 @@ import { type NoirCompiledContract, loadContractArtifact } from '@aztec/aztec.js'; -import EcdsaAccountContractJson from '../artifacts/EcdsaAccount.json' assert { type: 'json' }; +import EcdsaAccountContractJson from '../../artifacts/EcdsaAccount.json' assert { type: 'json' }; export const EcdsaAccountContractArtifact = loadContractArtifact(EcdsaAccountContractJson as NoirCompiledContract); diff --git a/yarn-project/accounts/src/schnorr/artifact.ts b/yarn-project/accounts/src/schnorr/artifact.ts index f7cac3337f7..88c1c5d1e4e 100644 --- a/yarn-project/accounts/src/schnorr/artifact.ts +++ b/yarn-project/accounts/src/schnorr/artifact.ts @@ -1,5 +1,5 @@ import { type NoirCompiledContract, loadContractArtifact } from '@aztec/aztec.js'; -import SchnorrAccountContractJson from '../artifacts/SchnorrAccount.json' assert { type: 'json' }; +import SchnorrAccountContractJson from '../../artifacts/SchnorrAccount.json' assert { type: 'json' }; export const SchnorrAccountContractArtifact = loadContractArtifact(SchnorrAccountContractJson as NoirCompiledContract); diff --git a/yarn-project/accounts/src/single_key/artifact.ts b/yarn-project/accounts/src/single_key/artifact.ts index 55a819dc570..f48ee9a14e8 100644 --- a/yarn-project/accounts/src/single_key/artifact.ts +++ b/yarn-project/accounts/src/single_key/artifact.ts @@ -1,6 +1,6 @@ import { type NoirCompiledContract, loadContractArtifact } from '@aztec/aztec.js'; -import SchnorrSingleKeyAccountContractJson from '../artifacts/SchnorrSingleKeyAccount.json' assert { type: 'json' }; +import SchnorrSingleKeyAccountContractJson from '../../artifacts/SchnorrSingleKeyAccount.json' assert { type: 'json' }; export const SchnorrSingleKeyAccountContractArtifact = loadContractArtifact( SchnorrSingleKeyAccountContractJson as NoirCompiledContract, diff --git a/yarn-project/accounts/tsconfig.json b/yarn-project/accounts/tsconfig.json index 0b48acf92f7..62dae97b860 100644 --- a/yarn-project/accounts/tsconfig.json +++ b/yarn-project/accounts/tsconfig.json @@ -28,5 +28,5 @@ "path": "../types" } ], - "include": ["src", "src/**/*.json"] + "include": ["src", "artifacts/*.d.json.ts"] } diff --git a/yarn-project/aztec-node/src/aztec-node/server.ts b/yarn-project/aztec-node/src/aztec-node/server.ts index 4e1eb36c75d..a4fcecef5f7 100644 --- a/yarn-project/aztec-node/src/aztec-node/server.ts +++ b/yarn-project/aztec-node/src/aztec-node/server.ts @@ -53,7 +53,7 @@ import { createDebugLogger } from '@aztec/foundation/log'; import { type AztecKVStore } from '@aztec/kv-store'; import { AztecLmdbStore } from '@aztec/kv-store/lmdb'; import { initStoreForRollup, openTmpStore } from '@aztec/kv-store/utils'; -import { SHA256Trunc, StandardTree } from '@aztec/merkle-tree'; +import { SHA256Trunc, StandardTree, UnbalancedTree } from '@aztec/merkle-tree'; import { AztecKVTxPool, type P2P, createP2PClient } from '@aztec/p2p'; import { getCanonicalClassRegisterer } from '@aztec/protocol-contracts/class-registerer'; import { getCanonicalGasToken } from '@aztec/protocol-contracts/gas-token'; @@ -550,26 +550,16 @@ export class AztecNodeService implements AztecNode { true, ); - const l2toL1SubtreeRoots = l2toL1Subtrees.map(t => Fr.fromBuffer(t.getRoot(true))); - const treeHeight = block.header.contentCommitment.txTreeHeight.toNumber(); - // NOTE: This padding only works assuming that an 'empty' out hash is H(0,0) - const paddedl2toL1SubtreeRoots = padArrayEnd( - l2toL1SubtreeRoots, - Fr.fromBuffer(sha256Trunc(Buffer.alloc(64))), - 2 ** treeHeight, - ); + let l2toL1SubtreeRoots = l2toL1Subtrees.map(t => Fr.fromBuffer(t.getRoot(true))); + if (l2toL1SubtreeRoots.length < 2) { + l2toL1SubtreeRoots = padArrayEnd(l2toL1SubtreeRoots, Fr.fromBuffer(sha256Trunc(Buffer.alloc(64))), 2); + } + const maxTreeHeight = Math.ceil(Math.log2(l2toL1SubtreeRoots.length)); // The root of this tree is the out_hash calculated in Noir => we truncate to match Noir's SHA - const outHashTree = new StandardTree( - openTmpStore(true), - new SHA256Trunc(), - 'temp_outhash_sibling_path', - treeHeight, - 0n, - Fr, - ); - await outHashTree.appendLeaves(paddedl2toL1SubtreeRoots); + const outHashTree = new UnbalancedTree(new SHA256Trunc(), 'temp_outhash_sibling_path', maxTreeHeight, Fr); + await outHashTree.appendLeaves(l2toL1SubtreeRoots); - const pathOfTxInOutHashTree = await outHashTree.getSiblingPath(BigInt(indexOfMsgTx), true); + const pathOfTxInOutHashTree = await outHashTree.getSiblingPath(l2toL1SubtreeRoots[indexOfMsgTx].toBigInt()); // Append subtree path to out hash tree path const mergedPath = subtreePathOfL2ToL1Message.toBufferArray().concat(pathOfTxInOutHashTree.toBufferArray()); // Append binary index of subtree path to binary index of out hash tree path @@ -704,10 +694,11 @@ export class AztecNodeService implements AztecNode { * * @param contract - Address of the contract to query. * @param slot - Slot to query. + * @param blockNumber - The block number at which to get the data or 'latest'. * @returns Storage value at the given contract slot. */ - public async getPublicStorageAt(contract: AztecAddress, slot: Fr): Promise { - const committedDb = await this.#getWorldState('latest'); + public async getPublicStorageAt(contract: AztecAddress, slot: Fr, blockNumber: L2BlockNumber): Promise { + const committedDb = await this.#getWorldState(blockNumber); const leafSlot = computePublicDataTreeLeafSlot(contract, slot); const lowLeafResult = await committedDb.getPreviousValueIndex(MerkleTreeId.PUBLIC_DATA_TREE, leafSlot.toBigInt()); diff --git a/yarn-project/aztec.js/src/index.ts b/yarn-project/aztec.js/src/index.ts index 4e3d71e4d8f..38cf7e986bc 100644 --- a/yarn-project/aztec.js/src/index.ts +++ b/yarn-project/aztec.js/src/index.ts @@ -99,6 +99,7 @@ export { EncryptedLogHeader, EncryptedNoteLogIncomingBody, EncryptedLogOutgoingBody, + EventType, ExtendedNote, FunctionCall, GrumpkinPrivateKey, diff --git a/yarn-project/aztec.js/src/wallet/base_wallet.ts b/yarn-project/aztec.js/src/wallet/base_wallet.ts index 247b509fbaf..43b6753efce 100644 --- a/yarn-project/aztec.js/src/wallet/base_wallet.ts +++ b/yarn-project/aztec.js/src/wallet/base_wallet.ts @@ -1,6 +1,7 @@ import { type AuthWitness, type EventMetadata, + type EventType, type ExtendedNote, type GetUnencryptedLogsResponse, type IncomingNotesFilter, @@ -182,11 +183,15 @@ export abstract class BaseWallet implements Wallet { return this.pxe.getPXEInfo(); } getEvents( + type: EventType, + eventMetadata: EventMetadata, from: number, limit: number, - eventMetadata: EventMetadata, - ivpk: Point = this.getCompleteAddress().publicKeys.masterIncomingViewingPublicKey, - ): Promise { - return this.pxe.getEvents(from, limit, eventMetadata, ivpk); + vpks: Point[] = [ + this.getCompleteAddress().publicKeys.masterIncomingViewingPublicKey, + this.getCompleteAddress().publicKeys.masterOutgoingViewingPublicKey, + ], + ) { + return this.pxe.getEvents(type, eventMetadata, from, limit, vpks); } } diff --git a/yarn-project/aztec/terraform/node/main.tf b/yarn-project/aztec/terraform/node/main.tf index d627d416f0a..d446d334c89 100644 --- a/yarn-project/aztec/terraform/node/main.tf +++ b/yarn-project/aztec/terraform/node/main.tf @@ -57,9 +57,11 @@ locals { publisher_private_keys = [var.SEQ_1_PUBLISHER_PRIVATE_KEY, var.SEQ_2_PUBLISHER_PRIVATE_KEY] node_p2p_private_keys = [var.NODE_1_PRIVATE_KEY, var.NODE_2_PRIVATE_KEY] node_count = length(local.publisher_private_keys) - #node_count = 1 - data_dir = "/usr/src/yarn-project/aztec/data" - agents_per_sequencer = var.AGENTS_PER_SEQUENCER + data_dir = "/usr/src/yarn-project/aztec/data" +} + +output "node_count" { + value = local.node_count } resource "aws_cloudwatch_log_group" "aztec-node-log-group" { @@ -115,20 +117,6 @@ resource "aws_efs_file_system" "node_data_store" { } } -# resource "aws_efs_mount_target" "private_az1" { -# count = local.node_count -# file_system_id = aws_efs_file_system.node_data_store[count.index].id -# subnet_id = data.terraform_remote_state.setup_iac.outputs.subnet_az1_private_id -# security_groups = [data.terraform_remote_state.setup_iac.outputs.security_group_private_id] -# } - -# resource "aws_efs_mount_target" "private_az2" { -# count = local.node_count -# file_system_id = aws_efs_file_system.node_data_store[count.index].id -# subnet_id = data.terraform_remote_state.setup_iac.outputs.subnet_az2_private_id -# security_groups = [data.terraform_remote_state.setup_iac.outputs.security_group_private_id] -# } - resource "aws_efs_mount_target" "public_az1" { count = local.node_count file_system_id = aws_efs_file_system.node_data_store[count.index].id @@ -165,7 +153,7 @@ resource "aws_ecs_task_definition" "aztec-node" { [ { "name": "${var.DEPLOY_TAG}-aztec-node-${count.index + 1}", - "image": "${var.FULL_IMAGE}", + "image": "${var.DOCKERHUB_ACCOUNT}/aztec:${var.DEPLOY_TAG}", "command": ["start", "--node", "--archiver", "--sequencer", "--prover"], "essential": true, "memoryReservation": 3776, @@ -205,7 +193,7 @@ resource "aws_ecs_task_definition" "aztec-node" { }, { "name": "ETHEREUM_HOST", - "value": "https://${var.DEPLOY_TAG}-mainnet-fork.aztec.network:8545/${var.API_KEY}" + "value": "https://aztec-dev-mainnet-fork.aztec.network:8545/${var.API_KEY}" }, { "name": "DATA_DIRECTORY", @@ -357,6 +345,7 @@ resource "aws_ecs_service" "aztec-node" { deployment_maximum_percent = 100 deployment_minimum_healthy_percent = 0 platform_version = "1.4.0" + force_new_deployment = true network_configuration { @@ -373,19 +362,6 @@ resource "aws_ecs_service" "aztec-node" { container_port = 80 } - - # load_balancer { - # target_group_arn = aws_lb_target_group.aztec-node-tcp[count.index].arn - # container_name = "${var.DEPLOY_TAG}-aztec-node-${count.index + 1}" - # container_port = var.NODE_P2P_TCP_PORT + count.index - # } - - # load_balancer { - # target_group_arn = aws_lb_target_group.aztec-node-udp[count.index].arn - # container_name = "${var.DEPLOY_TAG}-aztec-node-${count.index + 1}" - # container_port = var.NODE_P2P_UDP_PORT + count.index - # } - service_registries { registry_arn = aws_service_discovery_service.aztec-node[count.index].arn container_name = "${var.DEPLOY_TAG}-aztec-node-${count.index + 1}" @@ -436,23 +412,6 @@ resource "aws_lb_listener_rule" "api" { } } -# resource "aws_lb_target_group" "aztec-node-tcp" { -# count = local.node_count -# name = "${var.DEPLOY_TAG}-node-${count.index + 1}-p2p-tcp-target" -# port = var.NODE_P2P_TCP_PORT + count.index -# protocol = "TCP" -# target_type = "ip" -# vpc_id = data.terraform_remote_state.setup_iac.outputs.vpc_id - -# health_check { -# protocol = "TCP" -# interval = 10 -# healthy_threshold = 2 -# unhealthy_threshold = 2 -# port = var.NODE_P2P_TCP_PORT + count.index -# } -# } - resource "aws_security_group_rule" "allow-node-tcp-in" { count = local.node_count type = "ingress" @@ -473,40 +432,6 @@ resource "aws_security_group_rule" "allow-node-tcp-out" { security_group_id = data.terraform_remote_state.aztec-network_iac.outputs.p2p_security_group_id } -# resource "aws_lb_listener" "aztec-node-tcp-listener" { -# count = local.node_count -# load_balancer_arn = data.terraform_remote_state.aztec-network_iac.outputs.nlb_arn -# port = var.NODE_P2P_TCP_PORT + count.index -# protocol = "TCP" - -# tags = { -# name = "aztec-node-${count.index}-tcp-listener" -# } - -# default_action { -# type = "forward" -# target_group_arn = aws_lb_target_group.aztec-node-tcp[count.index].arn -# } -# } - - -# resource "aws_lb_target_group" "aztec-node-udp" { -# count = local.node_count -# name = "${var.DEPLOY_TAG}-node-${count.index + 1}-p2p-udp-target" -# port = var.NODE_P2P_UDP_PORT + count.index -# protocol = "UDP" -# target_type = "ip" -# vpc_id = data.terraform_remote_state.setup_iac.outputs.vpc_id - -# health_check { -# protocol = "TCP" -# interval = 10 -# healthy_threshold = 2 -# unhealthy_threshold = 2 -# port = var.NODE_P2P_TCP_PORT + count.index -# } -# } - resource "aws_security_group_rule" "allow-node-udp-in" { type = "ingress" from_port = var.NODE_P2P_UDP_PORT @@ -524,235 +449,3 @@ resource "aws_security_group_rule" "allow-node-udp-out" { cidr_blocks = ["0.0.0.0/0"] security_group_id = data.terraform_remote_state.aztec-network_iac.outputs.p2p_security_group_id } - -# resource "aws_lb_listener" "aztec-node-udp-listener" { -# count = local.node_count -# load_balancer_arn = data.terraform_remote_state.aztec-network_iac.outputs.nlb_arn -# port = var.NODE_P2P_UDP_PORT + count.index -# protocol = "UDP" - -# tags = { -# name = "aztec-node-${count.index}-udp-listener" -# } - -# default_action { -# type = "forward" -# target_group_arn = aws_lb_target_group.aztec-node-udp[count.index].arn -# } -# } - - - -// Configuration for proving agents - -resource "aws_cloudwatch_log_group" "aztec-proving-agent-log-group" { - count = local.node_count - name = "/fargate/service/${var.DEPLOY_TAG}/aztec-proving-agent-group-${count.index + 1}" - retention_in_days = 14 -} - -resource "aws_service_discovery_service" "aztec-proving-agent" { - count = local.node_count - name = "${var.DEPLOY_TAG}-aztec-proving-agent-group-${count.index + 1}" - - health_check_custom_config { - failure_threshold = 1 - } - dns_config { - namespace_id = data.terraform_remote_state.setup_iac.outputs.local_service_discovery_id - dns_records { - ttl = 60 - type = "A" - } - dns_records { - ttl = 60 - type = "SRV" - } - routing_policy = "MULTIVALUE" - } - # Terraform just fails if this resource changes and you have registered instances. - provisioner "local-exec" { - when = destroy - command = "${path.module}/servicediscovery-drain.sh ${self.id}" - } -} - -# Define task definitions for each node. -resource "aws_ecs_task_definition" "aztec-proving-agent" { - count = local.node_count - family = "${var.DEPLOY_TAG}-aztec-proving-agent-group-${count.index + 1}" - requires_compatibilities = ["FARGATE"] - network_mode = "awsvpc" - cpu = "16384" - memory = "98304" - execution_role_arn = data.terraform_remote_state.setup_iac.outputs.ecs_task_execution_role_arn - task_role_arn = data.terraform_remote_state.aztec2_iac.outputs.cloudwatch_logging_ecs_role_arn - container_definitions = < { 'get_fee_per_l2_gas', 'get_fee_per_da_gas', 'get_transaction_fee', + 'get_function_selector', 'get_chain_id', 'get_version', 'get_block_number', @@ -201,9 +203,10 @@ const proveAndVerifyAvmTestContract = async ( assertionErrString?: string, ) => { const startSideEffectCounter = 0; + const functionSelector = FunctionSelector.random(); const globals = GlobalVariables.empty(); globals.timestamp = TIMESTAMP; - const environment = initExecutionEnvironment({ calldata, globals }); + const environment = initExecutionEnvironment({ functionSelector, calldata, globals }); const contractsDb = mock(); const contractInstance = new SerializableContractInstance({ diff --git a/yarn-project/bb-prover/src/bb/execute.ts b/yarn-project/bb-prover/src/bb/execute.ts index 9a5753a68ad..7c97fcede72 100644 --- a/yarn-project/bb-prover/src/bb/execute.ts +++ b/yarn-project/bb-prover/src/bb/execute.ts @@ -12,6 +12,10 @@ export const VK_FILENAME = 'vk'; export const VK_FIELDS_FILENAME = 'vk_fields.json'; export const PROOF_FILENAME = 'proof'; export const PROOF_FIELDS_FILENAME = 'proof_fields.json'; +export const AVM_BYTECODE_FILENAME = 'avm_bytecode.bin'; +export const AVM_CALLDATA_FILENAME = 'avm_calldata.bin'; +export const AVM_PUBLIC_INPUTS_FILENAME = 'avm_public_inputs.bin'; +export const AVM_HINTS_FILENAME = 'avm_hints.bin'; export enum BB_RESULT { SUCCESS, @@ -276,10 +280,10 @@ export async function generateAvmProof( } // Paths for the inputs - const bytecodePath = join(workingDirectory, 'avm_bytecode.bin'); - const calldataPath = join(workingDirectory, 'avm_calldata.bin'); - const publicInputsPath = join(workingDirectory, 'avm_public_inputs.bin'); - const avmHintsPath = join(workingDirectory, 'avm_hints.bin'); + const bytecodePath = join(workingDirectory, AVM_BYTECODE_FILENAME); + const calldataPath = join(workingDirectory, AVM_CALLDATA_FILENAME); + const publicInputsPath = join(workingDirectory, AVM_PUBLIC_INPUTS_FILENAME); + const avmHintsPath = join(workingDirectory, AVM_HINTS_FILENAME); // The proof is written to e.g. /workingDirectory/proof const outputPath = workingDirectory; diff --git a/yarn-project/circuit-types/src/body.ts b/yarn-project/circuit-types/src/body.ts index 98d8b51ecab..c0e63aa43d3 100644 --- a/yarn-project/circuit-types/src/body.ts +++ b/yarn-project/circuit-types/src/body.ts @@ -48,39 +48,52 @@ export class Body { /** * Computes the transactions effects hash for the L2 block - * This hash is also computed in the `AvailabilityOracle` and the `Circuit`. + * This hash is also computed in the `AvailabilityOracle`. * @returns The txs effects hash. */ getTxsEffectsHash() { + // Adapted from proving-state.ts -> findMergeLevel and unbalanced_tree.ts + // Calculates the tree upwards layer by layer until we reach the root + // The L1 calculation instead computes the tree from right to left (slightly cheaper gas) + // TODO: A more thorough investigation of which method is cheaper, then use that method everywhere const computeRoot = (leaves: Buffer[]): Buffer => { - const layers: Buffer[][] = [leaves]; - let activeLayer = 0; - - while (layers[activeLayer].length > 1) { - const layer: Buffer[] = []; - const layerLength = layers[activeLayer].length; - - for (let i = 0; i < layerLength; i += 2) { - const left = layers[activeLayer][i]; - const right = layers[activeLayer][i + 1]; - - layer.push(sha256Trunc(Buffer.concat([left, right]))); + const depth = Math.ceil(Math.log2(leaves.length)); + let [layerWidth, nodeToShift] = + leaves.length & 1 ? [leaves.length - 1, leaves[leaves.length - 1]] : [leaves.length, Buffer.alloc(0)]; + // Allocate this layer's leaves and init the next layer up + let thisLayer = leaves.slice(0, layerWidth); + let nextLayer = []; + for (let i = 0; i < depth; i++) { + for (let j = 0; j < layerWidth; j += 2) { + // Store the hash of each pair one layer up + nextLayer[j / 2] = sha256Trunc(Buffer.concat([thisLayer[j], thisLayer[j + 1]])); } - - layers.push(layer); - activeLayer++; + layerWidth /= 2; + if (layerWidth & 1) { + if (nodeToShift.length) { + // If the next layer has odd length, and we have a node that needs to be shifted up, add it here + nextLayer.push(nodeToShift); + layerWidth += 1; + nodeToShift = Buffer.alloc(0); + } else { + // If we don't have a node waiting to be shifted, store the next layer's final node to be shifted + layerWidth -= 1; + nodeToShift = nextLayer[layerWidth]; + } + } + // reset the layers + thisLayer = nextLayer; + nextLayer = []; } - - return layers[layers.length - 1][0]; + // return the root + return thisLayer[0]; }; const emptyTxEffectHash = TxEffect.empty().hash(); - const leaves: Buffer[] = padArrayEnd( - this.txEffects.map(txEffect => txEffect.hash()), - emptyTxEffectHash, - this.numberOfTxsIncludingPadded, - ); - + let leaves: Buffer[] = this.txEffects.map(txEffect => txEffect.hash()); + if (leaves.length < 2) { + leaves = padArrayEnd(leaves, emptyTxEffectHash, 2); + } return computeRoot(leaves); } @@ -114,20 +127,7 @@ export class Body { return 2; } - // Note that the following could be implemented in a more simple way as "2 ** Math.ceil(Math.log2(numTxEffects));" - // but we want to keep the same logic as in Solidity and there we don't have the math functions. - let v = numTxEffects; - - // The following rounds numTxEffects up to the next power of 2 (works only for 4 bytes value!) - v--; - v |= v >> 1; - v |= v >> 2; - v |= v >> 4; - v |= v >> 8; - v |= v >> 16; - v++; - - return v; + return numTxEffects; } static random( diff --git a/yarn-project/circuit-types/src/interfaces/aztec-node.ts b/yarn-project/circuit-types/src/interfaces/aztec-node.ts index 0890b0c6904..a79a28ece15 100644 --- a/yarn-project/circuit-types/src/interfaces/aztec-node.ts +++ b/yarn-project/circuit-types/src/interfaces/aztec-node.ts @@ -291,9 +291,10 @@ export interface AztecNode { * * @param contract - Address of the contract to query. * @param slot - Slot to query. + * @param blockNumber - The block number at which to get the data or 'latest'. * @returns Storage value at the given contract slot. */ - getPublicStorageAt(contract: AztecAddress, slot: Fr): Promise; + getPublicStorageAt(contract: AztecAddress, slot: Fr, blockNumber: L2BlockNumber): Promise; /** * Returns the currently committed block header. diff --git a/yarn-project/circuit-types/src/interfaces/pxe.ts b/yarn-project/circuit-types/src/interfaces/pxe.ts index 6092eda2780..b4e6e6eda2e 100644 --- a/yarn-project/circuit-types/src/interfaces/pxe.ts +++ b/yarn-project/circuit-types/src/interfaces/pxe.ts @@ -381,14 +381,21 @@ export interface PXE { isContractPubliclyDeployed(address: AztecAddress): Promise; /** - * Returns the events of a specified type. + * Returns the events of a specified type given search parameters. + * @param type - The type of the event to search for—Encrypted, or Unencrypted. + * @param eventMetadata - Identifier of the event. This should be the class generated from the contract. e.g. Contract.events.Event * @param from - The block number to search from. * @param limit - The amount of blocks to search. - * @param eventMetadata - Identifier of the event. This should be the class generated from the contract. e.g. Contract.events.Event - * @param ivpk - The incoming viewing public key that corresponds to the incoming viewing secret key that can decrypt the log. + * @param vpks - (Used for encrypted logs only) The viewing (incoming and outgoing) public keys that correspond to the viewing secret keys that can decrypt the log. * @returns - The deserialized events. */ - getEvents(from: number, limit: number, eventMetadata: EventMetadata, ivpk: Point): Promise; + getEvents( + type: EventType, + eventMetadata: EventMetadata, + from: number, + limit: number, + vpks: Point[], + ): Promise; } // docs:end:pxe-interface @@ -401,6 +408,14 @@ export interface EventMetadata { fieldNames: string[]; } +/** + * This is used in getting events via the filter + */ +export enum EventType { + Encrypted = 'Encrypted', + Unencrypted = 'Unencrypted', +} + /** * Provides basic information about the running PXE. */ diff --git a/yarn-project/circuits.js/package.json b/yarn-project/circuits.js/package.json index 524b4a62210..1444de37a2d 100644 --- a/yarn-project/circuits.js/package.json +++ b/yarn-project/circuits.js/package.json @@ -97,4 +97,4 @@ ] ] } -} +} \ No newline at end of file diff --git a/yarn-project/circuits.js/src/structs/content_commitment.ts b/yarn-project/circuits.js/src/structs/content_commitment.ts index 6de8796aa5a..92e0145bb0e 100644 --- a/yarn-project/circuits.js/src/structs/content_commitment.ts +++ b/yarn-project/circuits.js/src/structs/content_commitment.ts @@ -6,7 +6,7 @@ import { CONTENT_COMMITMENT_LENGTH } from '../constants.gen.js'; export const NUM_BYTES_PER_SHA256 = 32; export class ContentCommitment { - constructor(public txTreeHeight: Fr, public txsEffectsHash: Buffer, public inHash: Buffer, public outHash: Buffer) { + constructor(public numTxs: Fr, public txsEffectsHash: Buffer, public inHash: Buffer, public outHash: Buffer) { if (txsEffectsHash.length !== NUM_BYTES_PER_SHA256) { throw new Error(`txsEffectsHash buffer must be ${NUM_BYTES_PER_SHA256} bytes`); } @@ -32,12 +32,12 @@ export class ContentCommitment { } toBuffer() { - return serializeToBuffer(this.txTreeHeight, this.txsEffectsHash, this.inHash, this.outHash); + return serializeToBuffer(this.numTxs, this.txsEffectsHash, this.inHash, this.outHash); } toFields(): Fr[] { const serialized = [ - this.txTreeHeight, + this.numTxs, Fr.fromBuffer(this.txsEffectsHash), Fr.fromBuffer(this.inHash), Fr.fromBuffer(this.outHash), @@ -80,7 +80,7 @@ export class ContentCommitment { isEmpty(): boolean { return ( - this.txTreeHeight.isZero() && + this.numTxs.isZero() && this.txsEffectsHash.equals(Buffer.alloc(NUM_BYTES_PER_SHA256)) && this.inHash.equals(Buffer.alloc(NUM_BYTES_PER_SHA256)) && this.outHash.equals(Buffer.alloc(NUM_BYTES_PER_SHA256)) diff --git a/yarn-project/circuits.js/src/structs/rollup/base_or_merge_rollup_public_inputs.ts b/yarn-project/circuits.js/src/structs/rollup/base_or_merge_rollup_public_inputs.ts index 0bb2f4603ec..d814dd1861c 100644 --- a/yarn-project/circuits.js/src/structs/rollup/base_or_merge_rollup_public_inputs.ts +++ b/yarn-project/circuits.js/src/structs/rollup/base_or_merge_rollup_public_inputs.ts @@ -15,11 +15,9 @@ export class BaseOrMergeRollupPublicInputs { */ public rollupType: RollupTypes, /** - * Rollup sub tree height. - * Note 1: Base rollup circuit always have a sub tree height of 0. - * Note 2: With each merge, the sub tree height increases by 1. + * Number of txs in this rollup. */ - public rollupSubtreeHeight: Fr, + public numTxs: number, /** * Data which is forwarded through the rollup circuits unchanged. */ @@ -59,7 +57,7 @@ export class BaseOrMergeRollupPublicInputs { const reader = BufferReader.asReader(buffer); return new BaseOrMergeRollupPublicInputs( reader.readNumber(), - Fr.fromBuffer(reader), + reader.readNumber(), reader.readObject(ConstantRollupData), reader.readObject(PartialStateReference), reader.readObject(PartialStateReference), @@ -77,7 +75,7 @@ export class BaseOrMergeRollupPublicInputs { toBuffer() { return serializeToBuffer( this.rollupType, - this.rollupSubtreeHeight, + this.numTxs, this.constants, this.start, diff --git a/yarn-project/circuits.js/src/tests/factories.ts b/yarn-project/circuits.js/src/tests/factories.ts index 3b03eed8014..77956df0f35 100644 --- a/yarn-project/circuits.js/src/tests/factories.ts +++ b/yarn-project/circuits.js/src/tests/factories.ts @@ -922,7 +922,7 @@ export function makeBaseOrMergeRollupPublicInputs( ): BaseOrMergeRollupPublicInputs { return new BaseOrMergeRollupPublicInputs( RollupTypes.Base, - new Fr(0n), + 1, makeConstantBaseRollupData(seed + 0x200, globalVariables), makePartialStateReference(seed + 0x300), makePartialStateReference(seed + 0x400), diff --git a/yarn-project/end-to-end/src/benchmarks/bench_process_history.test.ts b/yarn-project/end-to-end/src/benchmarks/bench_process_history.test.ts index 0f146badc93..1932986a768 100644 --- a/yarn-project/end-to-end/src/benchmarks/bench_process_history.test.ts +++ b/yarn-project/end-to-end/src/benchmarks/bench_process_history.test.ts @@ -54,7 +54,7 @@ describe('benchmarks/process_history', () => { const node = await AztecNodeService.createAndSync(nodeConfig); // call getPublicStorageAt (which calls #getWorldState, which calls #syncWorldState) to force a sync with // world state to ensure the node has caught up - await node.getPublicStorageAt(AztecAddress.random(), Fr.random()); + await node.getPublicStorageAt(AztecAddress.random(), Fr.random(), 'latest'); return node; }); diff --git a/yarn-project/end-to-end/src/benchmarks/bench_publish_rollup.test.ts b/yarn-project/end-to-end/src/benchmarks/bench_publish_rollup.test.ts index b3bb55d6489..67b3a8f1c7f 100644 --- a/yarn-project/end-to-end/src/benchmarks/bench_publish_rollup.test.ts +++ b/yarn-project/end-to-end/src/benchmarks/bench_publish_rollup.test.ts @@ -37,7 +37,7 @@ describe('benchmarks/publish_rollup', () => { // world state to ensure the node has caught up context.logger.info(`Starting new aztec node`); const node = await AztecNodeService.createAndSync({ ...context.config, disableSequencer: true }); - await node.getPublicStorageAt(AztecAddress.random(), Fr.random()); + await node.getPublicStorageAt(AztecAddress.random(), Fr.random(), 'latest'); // Spin up a new pxe and sync it, we'll use it to test sync times of new accounts for the last block context.logger.info(`Starting new pxe`); diff --git a/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts b/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts index 17340f06675..af92189500d 100644 --- a/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts +++ b/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts @@ -262,7 +262,7 @@ describe('L1Publisher integration', () => { contentCommitment: { inHash: `0x${block.header.contentCommitment.inHash.toString('hex').padStart(64, '0')}`, outHash: `0x${block.header.contentCommitment.outHash.toString('hex').padStart(64, '0')}`, - txTreeHeight: Number(block.header.contentCommitment.txTreeHeight.toBigInt()), + numTxs: Number(block.header.contentCommitment.numTxs), txsEffectsHash: `0x${block.header.contentCommitment.txsEffectsHash.toString('hex').padStart(64, '0')}`, }, globalVariables: { @@ -484,6 +484,7 @@ describe('L1Publisher integration', () => { GasFees.empty(), ); const blockTicket = await buildBlock(globalVariables, txs, l1ToL2Messages); + await builder.setBlockCompleted(); const result = await blockTicket.provingPromise; expect(result.status).toBe(PROVING_STATUS.SUCCESS); const blockResult = await builder.finaliseBlock(); diff --git a/yarn-project/end-to-end/src/e2e_block_building.test.ts b/yarn-project/end-to-end/src/e2e_block_building.test.ts index 9a308a2e523..206e19e00b4 100644 --- a/yarn-project/end-to-end/src/e2e_block_building.test.ts +++ b/yarn-project/end-to-end/src/e2e_block_building.test.ts @@ -246,24 +246,6 @@ describe('e2e_block_building', () => { testContract = await TestContract.deploy(owner).send().deployed(); }, 60_000); - it('calls a method with nested unencrypted logs', async () => { - const tx = await testContract.methods.emit_unencrypted_logs([1, 2, 3, 4, 5], true).send().wait(); - const logs = (await pxe.getUnencryptedLogs({ txHash: tx.txHash })).logs.map(l => l.log); - - // First log should be contract address - expect(logs[0].data).toEqual(testContract.address.toBuffer()); - - // Second log should be array of fields - let expectedBuffer = Buffer.concat([1, 2, 3, 4, 5].map(num => new Fr(num).toBuffer())); - expect(logs[1].data.subarray(-32 * 5)).toEqual(expectedBuffer); - - // Third log should be string "test" - expectedBuffer = Buffer.concat( - ['t', 'e', 's', 't'].map(num => Buffer.concat([Buffer.alloc(31), Buffer.from(num)])), - ); - expect(logs[2].data.subarray(-32 * 5)).toEqual(expectedBuffer); - }, 60_000); - it('calls a method with nested note encrypted logs', async () => { // account setup const privateKey = new Fr(7n); diff --git a/yarn-project/end-to-end/src/e2e_event_logs.test.ts b/yarn-project/end-to-end/src/e2e_event_logs.test.ts index 02122e165d1..d49bef63dd1 100644 --- a/yarn-project/end-to-end/src/e2e_event_logs.test.ts +++ b/yarn-project/end-to-end/src/e2e_event_logs.test.ts @@ -1,4 +1,12 @@ -import { type AccountWalletWithSecretKey, type AztecNode, Fr, L1EventPayload, TaggedLog } from '@aztec/aztec.js'; +import { + type AccountWalletWithSecretKey, + type AztecNode, + EventType, + Fr, + L1EventPayload, + type PXE, + TaggedLog, +} from '@aztec/aztec.js'; import { deriveMasterIncomingViewingSecretKey } from '@aztec/circuits.js'; import { EventSelector } from '@aztec/foundation/abi'; import { makeTuple } from '@aztec/foundation/array'; @@ -17,30 +25,36 @@ describe('Logs', () => { let wallets: AccountWalletWithSecretKey[]; let node: AztecNode; + let pxe: PXE; let teardown: () => Promise; beforeAll(async () => { - ({ teardown, wallets, aztecNode: node } = await setup(2)); + ({ teardown, wallets, aztecNode: node, pxe } = await setup(2)); await publicDeployAccounts(wallets[0], wallets.slice(0, 2)); testLogContract = await TestLogContract.deploy(wallets[0]).send().deployed(); + + await pxe.registerRecipient(wallets[1].getCompleteAddress()); }); afterAll(() => teardown()); describe('functionality around emitting an encrypted log', () => { - it('emits multiple events as encrypted logs and decodes them', async () => { + it('emits multiple events as encrypted logs and decodes them one manually', async () => { const randomness = makeTuple(2, Fr.random); const preimage = makeTuple(4, Fr.random); - const tx = await testLogContract.methods.emit_encrypted_events(randomness, preimage).send().wait(); + const tx = await testLogContract.methods + .emit_encrypted_events(wallets[1].getAddress(), randomness, preimage) + .send() + .wait(); const txEffect = await node.getTxEffect(tx.txHash); const encryptedLogs = txEffect!.encryptedLogs.unrollLogs(); - expect(encryptedLogs.length).toBe(2); + expect(encryptedLogs.length).toBe(3); const decryptedLog0 = TaggedLog.decryptAsIncoming( encryptedLogs[0], @@ -66,7 +80,8 @@ describe('Logs', () => { expect(badEvent0).toBe(undefined); const decryptedLog1 = TaggedLog.decryptAsIncoming( - encryptedLogs[1], + // We want to skip the second emitted log as it is irrelevant in this test. + encryptedLogs[2], deriveMasterIncomingViewingSecretKey(wallets[0].getSecretKey()), L1EventPayload, ); @@ -94,26 +109,112 @@ describe('Logs', () => { const preimage = makeTuple(5, makeTuple.bind(undefined, 4, Fr.random)) as Tuple, 5>; let i = 0; - const firstTx = await testLogContract.methods.emit_encrypted_events(randomness[i], preimage[i]).send().wait(); + const firstTx = await testLogContract.methods + .emit_encrypted_events(wallets[1].getAddress(), randomness[i], preimage[i]) + .send() + .wait(); await Promise.all( [...new Array(3)].map(() => - testLogContract.methods.emit_encrypted_events(randomness[++i], preimage[i]).send().wait(), + testLogContract.methods + .emit_encrypted_events(wallets[1].getAddress(), randomness[++i], preimage[i]) + .send() + .wait(), ), ); - const lastTx = await testLogContract.methods.emit_encrypted_events(randomness[++i], preimage[i]).send().wait(); + const lastTx = await testLogContract.methods + .emit_encrypted_events(wallets[1].getAddress(), randomness[++i], preimage[i]) + .send() + .wait(); + // We get all the events we can decrypt with either our incoming or outgoing viewing keys const collectedEvent0s = await wallets[0].getEvents( + EventType.Encrypted, + TestLogContract.events.ExampleEvent0, + firstTx.blockNumber!, + lastTx.blockNumber! - firstTx.blockNumber! + 1, + ); + + const collectedEvent0sWithIncoming = await wallets[0].getEvents( + EventType.Encrypted, + TestLogContract.events.ExampleEvent0, firstTx.blockNumber!, lastTx.blockNumber! - firstTx.blockNumber! + 1, + // This function can be called specifying the viewing public keys associated with the encrypted event. + [wallets[0].getCompleteAddress().publicKeys.masterIncomingViewingPublicKey], + ); + + const collectedEvent0sWithOutgoing = await wallets[0].getEvents( + EventType.Encrypted, TestLogContract.events.ExampleEvent0, + firstTx.blockNumber!, + lastTx.blockNumber! - firstTx.blockNumber! + 1, + [wallets[0].getCompleteAddress().publicKeys.masterOutgoingViewingPublicKey], ); const collectedEvent1s = await wallets[0].getEvents( + EventType.Encrypted, + TestLogContract.events.ExampleEvent1, firstTx.blockNumber!, lastTx.blockNumber! - firstTx.blockNumber! + 1, + [wallets[0].getCompleteAddress().publicKeys.masterIncomingViewingPublicKey], + ); + + expect(collectedEvent0sWithIncoming.length).toBe(5); + expect(collectedEvent0sWithOutgoing.length).toBe(5); + expect(collectedEvent0s.length).toBe(10); + expect(collectedEvent1s.length).toBe(5); + + const emptyEvent1s = await wallets[0].getEvents( + EventType.Encrypted, TestLogContract.events.ExampleEvent1, - // This function can also be called specifying the incoming viewing public key associated with the encrypted event. - wallets[0].getCompleteAddress().publicKeys.masterIncomingViewingPublicKey, + firstTx.blockNumber!, + lastTx.blockNumber! - firstTx.blockNumber! + 1, + [wallets[0].getCompleteAddress().publicKeys.masterOutgoingViewingPublicKey], + ); + + expect(emptyEvent1s.length).toBe(0); + + const exampleEvent0Sort = (a: ExampleEvent0, b: ExampleEvent0) => (a.value0 > b.value0 ? 1 : -1); + expect(collectedEvent0sWithIncoming.sort(exampleEvent0Sort)).toStrictEqual( + preimage.map(preimage => ({ value0: preimage[0], value1: preimage[1] })).sort(exampleEvent0Sort), + ); + + expect(collectedEvent0sWithOutgoing.sort(exampleEvent0Sort)).toStrictEqual( + preimage.map(preimage => ({ value0: preimage[0], value1: preimage[1] })).sort(exampleEvent0Sort), + ); + + expect([...collectedEvent0sWithIncoming, ...collectedEvent0sWithOutgoing].sort(exampleEvent0Sort)).toStrictEqual( + collectedEvent0s.sort(exampleEvent0Sort), + ); + + const exampleEvent1Sort = (a: ExampleEvent1, b: ExampleEvent1) => (a.value2 > b.value2 ? 1 : -1); + expect(collectedEvent1s.sort(exampleEvent1Sort)).toStrictEqual( + preimage.map(preimage => ({ value2: preimage[2], value3: preimage[3] })).sort(exampleEvent1Sort), + ); + }); + + it('emits multiple events as unencrypted logs and decodes them', async () => { + const preimage = makeTuple(5, makeTuple.bind(undefined, 4, Fr.random)) as Tuple, 5>; + + let i = 0; + const firstTx = await testLogContract.methods.emit_unencrypted_events(preimage[i]).send().wait(); + await Promise.all( + [...new Array(3)].map(() => testLogContract.methods.emit_unencrypted_events(preimage[++i]).send().wait()), + ); + const lastTx = await testLogContract.methods.emit_unencrypted_events(preimage[++i]).send().wait(); + + const collectedEvent0s = await wallets[0].getEvents( + EventType.Unencrypted, + TestLogContract.events.ExampleEvent0, + firstTx.blockNumber!, + lastTx.blockNumber! - firstTx.blockNumber! + 1, + ); + + const collectedEvent1s = await wallets[0].getEvents( + EventType.Unencrypted, + TestLogContract.events.ExampleEvent1, + firstTx.blockNumber!, + lastTx.blockNumber! - firstTx.blockNumber! + 1, ); expect(collectedEvent0s.length).toBe(5); diff --git a/yarn-project/end-to-end/src/e2e_key_registry.test.ts b/yarn-project/end-to-end/src/e2e_key_registry.test.ts index d667eef74e3..a9d3a3c3d58 100644 --- a/yarn-project/end-to-end/src/e2e_key_registry.test.ts +++ b/yarn-project/end-to-end/src/e2e_key_registry.test.ts @@ -58,7 +58,7 @@ describe('Key Registry', () => { await expect( keyRegistry .withWallet(wallets[0]) - .methods.register( + .methods.register_npk_and_ivpk( account, account.partialAddress, // TODO(#6337): Make calling `toNoirStruct()` unnecessary @@ -108,7 +108,18 @@ describe('Key Registry', () => { it('registers', async () => { await keyRegistry .withWallet(wallets[0]) - .methods.register( + .methods.register_npk_and_ivpk( + account, + account.partialAddress, + // TODO(#6337): Make calling `toNoirStruct()` unnecessary + account.publicKeys.toNoirStruct(), + ) + .send() + .wait(); + + await keyRegistry + .withWallet(wallets[0]) + .methods.register_ovpk_and_tpk( account, account.partialAddress, // TODO(#6337): Make calling `toNoirStruct()` unnecessary diff --git a/yarn-project/end-to-end/src/e2e_non_contract_account.test.ts b/yarn-project/end-to-end/src/e2e_non_contract_account.test.ts index 1728f637e1e..54e377ad4e9 100644 --- a/yarn-project/end-to-end/src/e2e_non_contract_account.test.ts +++ b/yarn-project/end-to-end/src/e2e_non_contract_account.test.ts @@ -1,13 +1,4 @@ -import { - type DebugLogger, - ExtendedNote, - Fr, - Note, - type PXE, - SignerlessWallet, - type Wallet, - toBigInt, -} from '@aztec/aztec.js'; +import { type DebugLogger, ExtendedNote, Fr, Note, type PXE, SignerlessWallet, type Wallet } from '@aztec/aztec.js'; import { siloNullifier } from '@aztec/circuits.js/hash'; import { TestContract } from '@aztec/noir-contracts.js/Test'; @@ -50,20 +41,6 @@ describe('e2e_non_contract_account', () => { expect(siloedNullifier.equals(expectedSiloedNullifier)).toBeTruthy(); }); - it('msg.sender is 0 when a non-contract account calls a private function on a contract', async () => { - const contractWithNoContractWallet = await TestContract.at(contract.address, nonContractAccountWallet); - - // Send transaction as arbitrary non-contract account - const tx = contractWithNoContractWallet.methods.emit_msg_sender().send(); - await tx.wait({ interval: 0.1 }); - - const logs = (await tx.getUnencryptedLogs()).logs; - expect(logs.length).toBe(1); - - const msgSender = toBigInt(logs[0].log.data); - expect(msgSender).toBe(0n); - }); - // Note: This test doesn't really belong here as it doesn't have anything to do with non-contract accounts. I needed // to test the TestNote functionality and it doesn't really fit anywhere else. Creating a separate e2e test for this // seems wasteful. Move this test if a better place is found. diff --git a/yarn-project/end-to-end/src/e2e_state_vars.test.ts b/yarn-project/end-to-end/src/e2e_state_vars.test.ts index d306d976ffb..400a25e9f36 100644 --- a/yarn-project/end-to-end/src/e2e_state_vars.test.ts +++ b/yarn-project/end-to-end/src/e2e_state_vars.test.ts @@ -94,7 +94,7 @@ describe('e2e_state_vars', () => { // Jest executes the tests sequentially and the first call to initialize_shared_immutable was executed // in the previous test, so the call below should fail. await expect(contract.methods.initialize_shared_immutable(1).prove()).rejects.toThrow( - "Assertion failed: SharedImmutable already initialized 'fields_read[0] == 0'", + 'Assertion failed: SharedImmutable already initialized', ); }); }); @@ -114,7 +114,7 @@ describe('e2e_state_vars', () => { // Jest executes the tests sequentially and the first call to initialize_public_immutable was executed // in the previous test, so the call below should fail. await expect(contract.methods.initialize_public_immutable(1).prove()).rejects.toThrow( - "Assertion failed: PublicImmutable already initialized 'fields_read[0] == 0'", + 'Assertion failed: PublicImmutable already initialized', ); }); }); diff --git a/yarn-project/end-to-end/src/e2e_token_contract/transfer_private.test.ts b/yarn-project/end-to-end/src/e2e_token_contract/transfer_private.test.ts index 4d1536e4df4..8ac1bf96cda 100644 --- a/yarn-project/end-to-end/src/e2e_token_contract/transfer_private.test.ts +++ b/yarn-project/end-to-end/src/e2e_token_contract/transfer_private.test.ts @@ -1,10 +1,12 @@ import { AztecAddress, CompleteAddress, + EventType, Fr, computeAuthWitMessageHash, computeInnerAuthWitHashFromAction, } from '@aztec/aztec.js'; +import { TokenContract } from '@aztec/noir-contracts.js'; import { DUPLICATE_NULLIFIER_ERROR } from '../fixtures/fixtures.js'; import { TokenContractTest } from './token_contract_test.js'; @@ -32,8 +34,16 @@ describe('e2e_token_contract transfer private', () => { const balance0 = await asset.methods.balance_of_private(accounts[0].address).simulate(); const amount = balance0 / 2n; expect(amount).toBeGreaterThan(0n); - await asset.methods.transfer(accounts[1].address, amount).send().wait(); + const tx = await asset.methods.transfer(accounts[1].address, amount).send().wait(); tokenSim.transferPrivate(accounts[0].address, accounts[1].address, amount); + + const events = await wallets[1].getEvents(EventType.Encrypted, TokenContract.events.Transfer, tx.blockNumber!, 1); + + expect(events[0]).toEqual({ + from: accounts[0].address, + to: accounts[1].address, + amount: new Fr(amount), + }); }); it('transfer less than balance to non-deployed account', async () => { diff --git a/yarn-project/merkle-tree/src/index.ts b/yarn-project/merkle-tree/src/index.ts index 7ac5cb2dc6e..412a545aad3 100644 --- a/yarn-project/merkle-tree/src/index.ts +++ b/yarn-project/merkle-tree/src/index.ts @@ -8,6 +8,7 @@ export * from './sparse_tree/sparse_tree.js'; export { StandardIndexedTree } from './standard_indexed_tree/standard_indexed_tree.js'; export { StandardIndexedTreeWithAppend } from './standard_indexed_tree/test/standard_indexed_tree_with_append.js'; export * from './standard_tree/standard_tree.js'; +export * from './unbalanced_tree.js'; export { INITIAL_LEAF, getTreeMeta } from './tree_base.js'; export { newTree } from './new_tree.js'; export { loadTree } from './load_tree.js'; diff --git a/yarn-project/merkle-tree/src/unbalanced_tree.test.ts b/yarn-project/merkle-tree/src/unbalanced_tree.test.ts new file mode 100644 index 00000000000..14ee0252ee4 --- /dev/null +++ b/yarn-project/merkle-tree/src/unbalanced_tree.test.ts @@ -0,0 +1,273 @@ +import { sha256Trunc } from '@aztec/foundation/crypto'; +import { Fr } from '@aztec/foundation/fields'; +import { type FromBuffer } from '@aztec/foundation/serialize'; +import { openTmpStore } from '@aztec/kv-store/utils'; +import { type Hasher } from '@aztec/types/interfaces'; + +import { SHA256Trunc } from './sha_256.js'; +import { StandardTree } from './standard_tree/standard_tree.js'; +import { UnbalancedTree } from './unbalanced_tree.js'; + +const noopDeserializer: FromBuffer = { + fromBuffer: (buffer: Buffer) => buffer, +}; + +// Follows sol implementation and tests in UnbalancedMerkle.t.sol +describe('Wonky tree', () => { + let hasher: Hasher; + let tree: UnbalancedTree; + let leaves: Buffer[]; + + const createAndFillTree = async (size: number) => { + const depth = Math.ceil(Math.log2(size)); + const tree = new UnbalancedTree(hasher, `test`, depth, noopDeserializer); + const leaves = Array(size) + .fill(0) + .map((_, i) => sha256Trunc(new Fr(i).toBuffer())); + // For the final test, we make the final (shifted up) leaf be H(1, 2), so we can calculate the root + // with a standard tree easily. + if (leaves[30]) { + leaves[30] = hasher.hash(new Fr(1).toBuffer(), new Fr(2).toBuffer()); + } + await tree.appendLeaves(leaves); + return { tree, leaves }; + }; + + beforeAll(() => { + hasher = new SHA256Trunc(); + }); + + // Example - 2 txs: + // + // root + // / \ + // base base + describe('2 Transactions', () => { + beforeAll(async () => { + const res = await createAndFillTree(2); + tree = res.tree; + leaves = res.leaves; + }); + + it("Shouldn't accept more leaves", () => { + expect(() => tree.appendLeaves([Buffer.alloc(32)])).toThrow( + "Can't re-append to an unbalanced tree. Current has 2 leaves.", + ); + }); + + it('Correctly computes tree information', () => { + expect(tree.getNumLeaves()).toEqual(BigInt(leaves.length)); + expect(tree.getDepth()).toEqual(1); + expect(tree.findLeafIndex(leaves[0])).toEqual(0n); + }); + + it('Correctly computes root', () => { + const root = tree.getRoot(); + const expectedRoot = sha256Trunc(Buffer.concat([leaves[0], leaves[1]])); + expect(root).toEqual(expectedRoot); + }); + + it('Correctly computes sibling path', async () => { + const sibPath = await tree.getSiblingPath(BigInt('0x' + leaves[0].toString('hex'))); + expect(sibPath.pathSize).toEqual(1); + const expectedSibPath = [leaves[1]]; + expect(sibPath.toBufferArray()).toEqual(expectedSibPath); + }); + }); + + // Example - 3 txs: + // + // root + // / \ + // merge base + // / \ + // base base + describe('3 Transactions', () => { + beforeAll(async () => { + const res = await createAndFillTree(3); + tree = res.tree; + leaves = res.leaves; + }); + + it('Correctly computes tree information', () => { + expect(tree.getNumLeaves()).toEqual(BigInt(leaves.length)); + expect(tree.getDepth()).toEqual(2); + expect(tree.findLeafIndex(leaves[0])).toEqual(0n); + }); + + it('Correctly computes root', () => { + const root = tree.getRoot(); + const mergeNode = sha256Trunc(Buffer.concat([leaves[0], leaves[1]])); + const expectedRoot = sha256Trunc(Buffer.concat([mergeNode, leaves[2]])); + expect(root).toEqual(expectedRoot); + }); + + it('Correctly computes sibling path', async () => { + const sibPath = await tree.getSiblingPath(BigInt('0x' + leaves[0].toString('hex'))); + expect(sibPath.pathSize).toEqual(2); + const expectedSibPath = [leaves[1], leaves[2]]; + expect(sibPath.toBufferArray()).toEqual(expectedSibPath); + }); + }); + + // Example - 5 txs: + // + // root + // / \ + // merge base + // / \ + // merge merge + // / \ / \ + // base base base base + describe('5 Transactions', () => { + beforeAll(async () => { + const res = await createAndFillTree(5); + tree = res.tree; + leaves = res.leaves; + }); + + it('Correctly computes tree information', () => { + expect(tree.getNumLeaves()).toEqual(BigInt(leaves.length)); + expect(tree.getDepth()).toEqual(3); + expect(tree.findLeafIndex(leaves[0])).toEqual(0n); + }); + + it('Correctly computes root', () => { + const root = tree.getRoot(); + let leftMergeNode = sha256Trunc(Buffer.concat([leaves[0], leaves[1]])); + const rightMergeNode = sha256Trunc(Buffer.concat([leaves[2], leaves[3]])); + leftMergeNode = sha256Trunc(Buffer.concat([leftMergeNode, rightMergeNode])); + const expectedRoot = sha256Trunc(Buffer.concat([leftMergeNode, leaves[4]])); + expect(root).toEqual(expectedRoot); + }); + + it('Correctly computes sibling path', async () => { + const sibPath = await tree.getSiblingPath(BigInt('0x' + leaves[0].toString('hex'))); + expect(sibPath.pathSize).toEqual(3); + const expectedSibPath = [leaves[1], sha256Trunc(Buffer.concat([leaves[2], leaves[3]])), leaves[4]]; + expect(sibPath.toBufferArray()).toEqual(expectedSibPath); + }); + }); + + // Example - 6 txs: + // + // root + // / \ + // merge4 merge3 + // / \ / \ + // merge1 merge2 base base + // / \ / \ + // base base base base + describe('6 Transactions', () => { + beforeAll(async () => { + const res = await createAndFillTree(6); + tree = res.tree; + leaves = res.leaves; + }); + + it('Correctly computes tree information', () => { + expect(tree.getNumLeaves()).toEqual(BigInt(leaves.length)); + expect(tree.getDepth()).toEqual(3); + expect(tree.findLeafIndex(leaves[0])).toEqual(0n); + }); + + it('Correctly computes root', () => { + const root = tree.getRoot(); + let leftMergeNode = sha256Trunc(Buffer.concat([leaves[0], leaves[1]])); + let rightMergeNode = sha256Trunc(Buffer.concat([leaves[2], leaves[3]])); + leftMergeNode = sha256Trunc(Buffer.concat([leftMergeNode, rightMergeNode])); + rightMergeNode = sha256Trunc(Buffer.concat([leaves[4], leaves[5]])); + const expectedRoot = sha256Trunc(Buffer.concat([leftMergeNode, rightMergeNode])); + expect(root).toEqual(expectedRoot); + }); + + it('Correctly computes sibling path', async () => { + const sibPath = await tree.getSiblingPath(BigInt('0x' + leaves[0].toString('hex'))); + expect(sibPath.pathSize).toEqual(3); + const expectedSibPath = [ + leaves[1], + sha256Trunc(Buffer.concat([leaves[2], leaves[3]])), + sha256Trunc(Buffer.concat([leaves[4], leaves[5]])), + ]; + expect(sibPath.toBufferArray()).toEqual(expectedSibPath); + }); + }); + + // Example - 7 txs: + // + // root + // / \ + // merge3 merge5 + // / \ / \ + // merge1 merge2 merge4 base + // / \ / \ / \ + // base base base base base base + describe('7 Transactions', () => { + let secondMergeNode: Buffer; + let fifthMergeNode: Buffer; + beforeAll(async () => { + const res = await createAndFillTree(7); + tree = res.tree; + leaves = res.leaves; + }); + + it('Correctly computes tree information', () => { + expect(tree.getNumLeaves()).toEqual(BigInt(leaves.length)); + expect(tree.getDepth()).toEqual(3); + expect(tree.findLeafIndex(leaves[0])).toEqual(0n); + }); + + it('Correctly computes root', () => { + const root = tree.getRoot(); + const firstMergeNode = sha256Trunc(Buffer.concat([leaves[0], leaves[1]])); + secondMergeNode = sha256Trunc(Buffer.concat([leaves[2], leaves[3]])); + const thirdMergeNode = sha256Trunc(Buffer.concat([firstMergeNode, secondMergeNode])); + const fourthMergeNode = sha256Trunc(Buffer.concat([leaves[4], leaves[5]])); + fifthMergeNode = sha256Trunc(Buffer.concat([fourthMergeNode, leaves[6]])); + const expectedRoot = sha256Trunc(Buffer.concat([thirdMergeNode, fifthMergeNode])); + expect(root).toEqual(expectedRoot); + }); + + it('Correctly computes sibling path', async () => { + const sibPath = await tree.getSiblingPath(BigInt('0x' + leaves[0].toString('hex'))); + expect(sibPath.pathSize).toEqual(3); + const expectedSibPath = [leaves[1], secondMergeNode, fifthMergeNode]; + expect(sibPath.toBufferArray()).toEqual(expectedSibPath); + }); + }); + + // Example - 31 txs: + // The same as a standard 32 leaf balanced tree, but with the last 'leaf' shifted up one. + describe('31 Transactions', () => { + let stdTree: StandardTree; + beforeAll(async () => { + const res = await createAndFillTree(31); + tree = res.tree; + leaves = res.leaves; + stdTree = new StandardTree(openTmpStore(true), hasher, `temp`, 5, 0n, noopDeserializer); + // We have set the last leaf to be H(1, 2), so we can fill a 32 size tree with: + await stdTree.appendLeaves([...res.leaves.slice(0, 30), new Fr(1).toBuffer(), new Fr(2).toBuffer()]); + }); + + it('Correctly computes tree information', () => { + expect(tree.getNumLeaves()).toEqual(BigInt(leaves.length)); + expect(tree.getDepth()).toEqual(5); + expect(tree.findLeafIndex(leaves[0])).toEqual(0n); + }); + + it('Correctly computes root', () => { + const root = tree.getRoot(); + const expectedRoot = stdTree.getRoot(true); + expect(root).toEqual(expectedRoot); + }); + + it('Correctly computes sibling paths', async () => { + let sibPath = await tree.getSiblingPath(BigInt('0x' + leaves[0].toString('hex'))); + let expectedSibPath = await stdTree.getSiblingPath(0n, true); + expect(sibPath).toEqual(expectedSibPath); + sibPath = await tree.getSiblingPath(BigInt('0x' + leaves[27].toString('hex'))); + expectedSibPath = await stdTree.getSiblingPath(27n, true); + expect(sibPath).toEqual(expectedSibPath); + }); + }); +}); diff --git a/yarn-project/merkle-tree/src/unbalanced_tree.ts b/yarn-project/merkle-tree/src/unbalanced_tree.ts new file mode 100644 index 00000000000..6920b5d1278 --- /dev/null +++ b/yarn-project/merkle-tree/src/unbalanced_tree.ts @@ -0,0 +1,239 @@ +import { SiblingPath } from '@aztec/circuit-types'; +import { type Bufferable, type FromBuffer, serializeToBuffer } from '@aztec/foundation/serialize'; +import { type Hasher } from '@aztec/types/interfaces'; + +import { HasherWithStats } from './hasher_with_stats.js'; +import { type MerkleTree } from './interfaces/merkle_tree.js'; + +const indexToKeyHash = (name: string, level: number, index: bigint) => `${name}:${level}:${index}`; + +/** + * An ephemeral unbalanced Merkle tree implementation. + * Follows the rollup implementation which greedily hashes pairs of nodes up the tree. + * Remaining rightmost nodes are shifted up until they can be paired. See proving-state.ts -> findMergeLevel. + */ +export class UnbalancedTree implements MerkleTree { + // This map stores index and depth -> value + private cache: { [key: string]: Buffer } = {}; + // This map stores value -> index and depth, since we have variable depth + private valueCache: { [key: string]: string } = {}; + protected size: bigint = 0n; + protected readonly maxIndex: bigint; + + protected hasher: HasherWithStats; + root: Buffer = Buffer.alloc(32); + + public constructor( + hasher: Hasher, + private name: string, + private maxDepth: number = 0, + protected deserializer: FromBuffer, + ) { + this.hasher = new HasherWithStats(hasher); + this.maxIndex = 2n ** BigInt(this.maxDepth) - 1n; + } + + /** + * Returns the root of the tree. + * @returns The root of the tree. + */ + public getRoot(): Buffer { + return this.root; + } + + /** + * Returns the number of leaves in the tree. + * @returns The number of leaves in the tree. + */ + public getNumLeaves() { + return this.size; + } + + /** + * Returns the max depth of the tree. + * @returns The max depth of the tree. + */ + public getDepth(): number { + return this.maxDepth; + } + + /** + * @remark A wonky tree is (currently) only ever ephemeral, so we don't use any db to commit to. + * The fn must exist to implement MerkleTree however. + */ + public commit(): Promise { + throw new Error("Unsupported function - cannot commit on an unbalanced tree as it's always ephemeral."); + return Promise.resolve(); + } + + /** + * Rolls back the not-yet-committed changes. + * @returns Empty promise. + */ + public rollback(): Promise { + this.clearCache(); + return Promise.resolve(); + } + + /** + * Clears the cache. + */ + private clearCache() { + this.cache = {}; + this.size = 0n; + } + + /** + * @remark A wonky tree can validly have duplicate indices: + * e.g. 001 (index 1 at level 3) and 01 (index 1 at level 2) + * So this function cannot reliably give the expected leaf value. + * We cannot add level as an input as its based on the MerkleTree class's function. + */ + public getLeafValue(_index: bigint): undefined { + throw new Error('Unsupported function - cannot get leaf value from an index in an unbalanced tree.'); + } + + /** + * Returns the index of a leaf given its value, or undefined if no leaf with that value is found. + * @param leaf - The leaf value to look for. + * @returns The index of the first leaf found with a given value (undefined if not found). + * @remark This is NOT the index as inserted, but the index which will be used to calculate path structure. + */ + public findLeafIndex(value: T): bigint | undefined { + const key = this.valueCache[serializeToBuffer(value).toString('hex')]; + const [, , index] = key.split(':'); + return BigInt(index); + } + + /** + * Returns the first index containing a leaf value after `startIndex`. + * @param value - The leaf value to look for. + * @param startIndex - The index to start searching from. + * @returns The index of the first leaf found with a given value (undefined if not found). + * @remark This is not really used for a wonky tree, but required to implement MerkleTree. + */ + public findLeafIndexAfter(value: T, startIndex: bigint): bigint | undefined { + const index = this.findLeafIndex(value); + if (!index || index < startIndex) { + return undefined; + } + return index; + } + + /** + * Returns the node at the given level and index + * @param level - The level of the element (root is at level 0). + * @param index - The index of the element. + * @returns Leaf or node value, or undefined. + */ + public getNode(level: number, index: bigint): Buffer | undefined { + if (level < 0 || level > this.maxDepth) { + throw Error('Invalid level: ' + level); + } + + if (index < 0 || index >= this.maxIndex) { + throw Error('Invalid index: ' + index); + } + + return this.cache[indexToKeyHash(this.name, level, index)]; + } + + /** + * Returns a sibling path for the element at the given index. + * @param value - The value of the element. + * @returns A sibling path for the element. + * Note: The sibling path is an array of sibling hashes, with the lowest hash (leaf hash) first, and the highest hash last. + */ + public getSiblingPath(value: bigint): Promise> { + const path: Buffer[] = []; + const [, depth, _index] = this.valueCache[serializeToBuffer(value).toString('hex')].split(':'); + let level = parseInt(depth, 10); + let index = BigInt(_index); + while (level > 0) { + const isRight = index & 0x01n; + const key = indexToKeyHash(this.name, level, isRight ? index - 1n : index + 1n); + const sibling = this.cache[key]; + path.push(sibling); + level -= 1; + index >>= 1n; + } + return Promise.resolve(new SiblingPath(parseInt(depth, 10) as N, path)); + } + + /** + * Appends the given leaves to the tree. + * @param leaves - The leaves to append. + * @returns Empty promise. + */ + public appendLeaves(leaves: T[]): Promise { + this.hasher.reset(); + if (this.size != BigInt(0)) { + throw Error(`Can't re-append to an unbalanced tree. Current has ${this.size} leaves.`); + } + if (this.size + BigInt(leaves.length) - 1n > this.maxIndex) { + throw Error(`Can't append beyond max index. Max index: ${this.maxIndex}`); + } + const root = this.batchInsert(leaves); + this.root = root; + + return Promise.resolve(); + } + + /** + * Calculates root while adding leaves and nodes to the cache. + * @param leaves - The leaves to append. + * @returns Resulting root of the tree. + */ + private batchInsert(_leaves: T[]): Buffer { + // If we have an even number of leaves, hash them all in pairs + // Otherwise, store the final leaf to be shifted up to the next odd sized level + let [layerWidth, nodeToShift] = + _leaves.length & 1 + ? [_leaves.length - 1, serializeToBuffer(_leaves[_leaves.length - 1])] + : [_leaves.length, Buffer.alloc(0)]; + // Allocate this layer's leaves and init the next layer up + let thisLayer = _leaves.slice(0, layerWidth).map(l => serializeToBuffer(l)); + let nextLayer = []; + // Store the bottom level leaves + thisLayer.forEach((leaf, i) => this.storeNode(leaf, this.maxDepth, BigInt(i))); + for (let i = 0; i < this.maxDepth; i++) { + for (let j = 0; j < layerWidth; j += 2) { + // Store the hash of each pair one layer up + nextLayer[j / 2] = this.hasher.hash(serializeToBuffer(thisLayer[j]), serializeToBuffer(thisLayer[j + 1])); + this.storeNode(nextLayer[j / 2], this.maxDepth - i - 1, BigInt(j >> 1)); + } + layerWidth /= 2; + if (layerWidth & 1) { + if (nodeToShift.length) { + // If the next layer has odd length, and we have a node that needs to be shifted up, add it here + nextLayer.push(serializeToBuffer(nodeToShift)); + this.storeNode(nodeToShift, this.maxDepth - i - 1, BigInt((layerWidth * 2) >> 1)); + layerWidth += 1; + nodeToShift = Buffer.alloc(0); + } else { + // If we don't have a node waiting to be shifted, store the next layer's final node to be shifted + layerWidth -= 1; + nodeToShift = nextLayer[layerWidth]; + } + } + // reset the layers + thisLayer = nextLayer; + nextLayer = []; + } + this.size += BigInt(_leaves.length); + // return the root + return thisLayer[0]; + } + + /** + * Stores the given node in the cache. + * @param value - The value to store. + * @param depth - The depth of the node in the full tree. + * @param index - The index of the node at the given depth. + */ + private storeNode(value: T | Buffer, depth: number, index: bigint) { + const key = indexToKeyHash(this.name, depth, index); + this.cache[key] = serializeToBuffer(value); + this.valueCache[serializeToBuffer(value).toString('hex')] = key; + } +} diff --git a/yarn-project/noir-contracts.js/package.json b/yarn-project/noir-contracts.js/package.json index 881226f0a93..6bf009796df 100644 --- a/yarn-project/noir-contracts.js/package.json +++ b/yarn-project/noir-contracts.js/package.json @@ -3,14 +3,14 @@ "version": "0.1.0", "type": "module", "exports": { - ".": "./dest/src/index.js", - "./artifacts/*": "./dest/artifacts/*.json", - "./*": "./dest/src/*.js" + ".": "./dest/index.js", + "./artifacts/*": "./artifacts/*.json", + "./*": "./dest/*.js" }, "scripts": { "build": "yarn clean && yarn generate", "build:dev": "tsc -b --watch", - "clean": "rm -rf .tsbuildinfo ./artifacts ./codegenCache.json", + "clean": "rm -rf ./dest .tsbuildinfo ./artifacts ./src ./codegenCache.json", "formatting": "run -T prettier --check ./src && run -T eslint ./src", "formatting:fix": "run -T eslint --fix ./src && run -T prettier -w ./src", "test": "NODE_NO_WARNINGS=1 node --experimental-vm-modules ../node_modules/.bin/jest --passWithNoTests", diff --git a/yarn-project/noir-contracts.js/package.local.json b/yarn-project/noir-contracts.js/package.local.json index 5dd3e0100f9..4cab71fc4dd 100644 --- a/yarn-project/noir-contracts.js/package.local.json +++ b/yarn-project/noir-contracts.js/package.local.json @@ -3,6 +3,6 @@ "build": "yarn clean && yarn generate", "generate": "yarn generate:noir-contracts", "generate:noir-contracts": "./scripts/generate-types.sh && run -T prettier -w ./src --loglevel warn", - "clean": "rm -rf .tsbuildinfo ./artifacts ./codegenCache.json" + "clean": "rm -rf ./dest .tsbuildinfo ./artifacts ./src ./codegenCache.json" } -} +} \ No newline at end of file diff --git a/yarn-project/noir-contracts.js/scripts/generate-types.sh b/yarn-project/noir-contracts.js/scripts/generate-types.sh index f7355440508..8c1168b24e8 100755 --- a/yarn-project/noir-contracts.js/scripts/generate-types.sh +++ b/yarn-project/noir-contracts.js/scripts/generate-types.sh @@ -19,12 +19,21 @@ echo "// Auto generated module - do not edit!" >"$INDEX" # Ensure the artifacts directory exists mkdir -p artifacts +decl=$(cat < "artifacts/$dts_file" done # Generate types for the contracts diff --git a/yarn-project/noir-contracts.js/tsconfig.json b/yarn-project/noir-contracts.js/tsconfig.json index caf5e40c801..92add33fb36 100644 --- a/yarn-project/noir-contracts.js/tsconfig.json +++ b/yarn-project/noir-contracts.js/tsconfig.json @@ -2,7 +2,7 @@ "extends": "..", "compilerOptions": { "outDir": "dest", - "rootDir": ".", + "rootDir": "src", "tsBuildInfoFile": ".tsbuildinfo" }, "references": [ @@ -15,8 +15,7 @@ ], "include": [ "src", - "artifacts", - "artifacts/*.json" + "artifacts/*.d.json.ts" ], "exclude": [ "dest" diff --git a/yarn-project/noir-protocol-circuits-types/.prettierignore b/yarn-project/noir-protocol-circuits-types/.prettierignore index 595a24e0611..2adf7da0bda 100644 --- a/yarn-project/noir-protocol-circuits-types/.prettierignore +++ b/yarn-project/noir-protocol-circuits-types/.prettierignore @@ -1,2 +1,2 @@ crates -src/target +artifacts diff --git a/yarn-project/noir-protocol-circuits-types/package.json b/yarn-project/noir-protocol-circuits-types/package.json index dab1d3a0e72..4f1b5e1fd38 100644 --- a/yarn-project/noir-protocol-circuits-types/package.json +++ b/yarn-project/noir-protocol-circuits-types/package.json @@ -12,12 +12,12 @@ ], "scripts": { "build": "yarn clean && yarn generate && tsc -b", - "clean": "rm -rf ./dest .tsbuildinfo src/types src/target", + "clean": "rm -rf ./dest .tsbuildinfo src/types artifacts", "formatting": "run -T prettier --check ./src && run -T eslint ./src", "formatting:fix": "run -T eslint --fix ./src && run -T prettier -w ./src", "formatting:fix:types": "NODE_OPTIONS='--max-old-space-size=8096' run -T eslint --fix ./src/types && run -T prettier -w ./src/types", "generate": "yarn generate:noir-circuits", - "generate:noir-circuits": "mkdir -p ./src/target && cp ../../noir-projects/noir-protocol-circuits/target/* ./src/target && node --no-warnings --loader ts-node/esm src/scripts/generate_ts_from_abi.ts && run -T prettier -w ./src/types", + "generate:noir-circuits": "mkdir -p ./artifacts && cp ../../noir-projects/noir-protocol-circuits/target/* ./artifacts && node --no-warnings --loader ts-node/esm src/scripts/generate_declaration_files.ts && node --no-warnings --loader ts-node/esm src/scripts/generate_ts_from_abi.ts && run -T prettier -w ./src/types", "test": "NODE_NO_WARNINGS=1 node --experimental-vm-modules ../node_modules/.bin/jest --passWithNoTests", "codegen": "yarn noir-codegen", "build:dev": "tsc -b --watch" @@ -82,7 +82,8 @@ "files": [ "dest", "src", - "!*.test.*" + "!*.test.*", + "artifacts" ], "types": "./dest/index.d.ts", "engines": { diff --git a/yarn-project/noir-protocol-circuits-types/package.local.json b/yarn-project/noir-protocol-circuits-types/package.local.json index 9ade866233e..e3deaa112a7 100644 --- a/yarn-project/noir-protocol-circuits-types/package.local.json +++ b/yarn-project/noir-protocol-circuits-types/package.local.json @@ -1,6 +1,12 @@ { "scripts": { "build": "yarn clean && yarn generate && tsc -b", - "clean": "rm -rf ./dest .tsbuildinfo src/types src/target" - } -} + "clean": "rm -rf ./dest .tsbuildinfo src/types artifacts" + }, + "files": [ + "dest", + "src", + "artifacts", + "!*.test.*" + ] +} \ No newline at end of file diff --git a/yarn-project/noir-protocol-circuits-types/src/index.ts b/yarn-project/noir-protocol-circuits-types/src/index.ts index b6ba9bd4097..789ff0f92f7 100644 --- a/yarn-project/noir-protocol-circuits-types/src/index.ts +++ b/yarn-project/noir-protocol-circuits-types/src/index.ts @@ -30,40 +30,40 @@ import { type Abi, abiDecode, abiEncode } from '@noir-lang/noirc_abi'; import { type WitnessMap } from '@noir-lang/types'; import { strict as assert } from 'assert'; -import EmptyNestedJson from './target/empty_nested.json' assert { type: 'json' }; -import EmptyNestedSimulatedJson from './target/empty_nested_simulated.json' assert { type: 'json' }; -import BaseParityJson from './target/parity_base.json' assert { type: 'json' }; -import RootParityJson from './target/parity_root.json' assert { type: 'json' }; -import PrivateKernelEmptyJson from './target/private_kernel_empty.json' assert { type: 'json' }; -import PrivateKernelEmptySimulatedJson from './target/private_kernel_empty_simulated.json' assert { type: 'json' }; -import PrivateKernelInitJson from './target/private_kernel_init.json' assert { type: 'json' }; -import PrivateKernelInitSimulatedJson from './target/private_kernel_init_simulated.json' assert { type: 'json' }; -import PrivateKernelInnerJson from './target/private_kernel_inner.json' assert { type: 'json' }; -import PrivateKernelInnerSimulatedJson from './target/private_kernel_inner_simulated.json' assert { type: 'json' }; -import PrivateKernelResetJson from './target/private_kernel_reset.json' assert { type: 'json' }; -import PrivateKernelResetBigJson from './target/private_kernel_reset_big.json' assert { type: 'json' }; -import PrivateKernelResetMediumJson from './target/private_kernel_reset_medium.json' assert { type: 'json' }; -import PrivateKernelResetSimulatedJson from './target/private_kernel_reset_simulated.json' assert { type: 'json' }; -import PrivateKernelResetBigSimulatedJson from './target/private_kernel_reset_simulated_big.json' assert { type: 'json' }; -import PrivateKernelResetMediumSimulatedJson from './target/private_kernel_reset_simulated_medium.json' assert { type: 'json' }; -import PrivateKernelResetSmallSimulatedJson from './target/private_kernel_reset_simulated_small.json' assert { type: 'json' }; -import PrivateKernelResetSmallJson from './target/private_kernel_reset_small.json' assert { type: 'json' }; -import PrivateKernelTailJson from './target/private_kernel_tail.json' assert { type: 'json' }; -import PrivateKernelTailSimulatedJson from './target/private_kernel_tail_simulated.json' assert { type: 'json' }; -import PrivateKernelTailToPublicJson from './target/private_kernel_tail_to_public.json' assert { type: 'json' }; -import PrivateKernelTailToPublicSimulatedJson from './target/private_kernel_tail_to_public_simulated.json' assert { type: 'json' }; -import PublicKernelAppLogicJson from './target/public_kernel_app_logic.json' assert { type: 'json' }; -import PublicKernelAppLogicSimulatedJson from './target/public_kernel_app_logic_simulated.json' assert { type: 'json' }; -import PublicKernelSetupJson from './target/public_kernel_setup.json' assert { type: 'json' }; -import PublicKernelSetupSimulatedJson from './target/public_kernel_setup_simulated.json' assert { type: 'json' }; -import PublicKernelTailJson from './target/public_kernel_tail.json' assert { type: 'json' }; -import PublicKernelTailSimulatedJson from './target/public_kernel_tail_simulated.json' assert { type: 'json' }; -import PublicKernelTeardownJson from './target/public_kernel_teardown.json' assert { type: 'json' }; -import PublicKernelTeardownSimulatedJson from './target/public_kernel_teardown_simulated.json' assert { type: 'json' }; -import BaseRollupJson from './target/rollup_base.json' assert { type: 'json' }; -import BaseRollupSimulatedJson from './target/rollup_base_simulated.json' assert { type: 'json' }; -import MergeRollupJson from './target/rollup_merge.json' assert { type: 'json' }; -import RootRollupJson from './target/rollup_root.json' assert { type: 'json' }; +import EmptyNestedJson from '../artifacts/empty_nested.json' assert { type: 'json' }; +import EmptyNestedSimulatedJson from '../artifacts/empty_nested_simulated.json' assert { type: 'json' }; +import BaseParityJson from '../artifacts/parity_base.json' assert { type: 'json' }; +import RootParityJson from '../artifacts/parity_root.json' assert { type: 'json' }; +import PrivateKernelEmptyJson from '../artifacts/private_kernel_empty.json' assert { type: 'json' }; +import PrivateKernelEmptySimulatedJson from '../artifacts/private_kernel_empty_simulated.json' assert { type: 'json' }; +import PrivateKernelInitJson from '../artifacts/private_kernel_init.json' assert { type: 'json' }; +import PrivateKernelInitSimulatedJson from '../artifacts/private_kernel_init_simulated.json' assert { type: 'json' }; +import PrivateKernelInnerJson from '../artifacts/private_kernel_inner.json' assert { type: 'json' }; +import PrivateKernelInnerSimulatedJson from '../artifacts/private_kernel_inner_simulated.json' assert { type: 'json' }; +import PrivateKernelResetJson from '../artifacts/private_kernel_reset.json' assert { type: 'json' }; +import PrivateKernelResetBigJson from '../artifacts/private_kernel_reset_big.json' assert { type: 'json' }; +import PrivateKernelResetMediumJson from '../artifacts/private_kernel_reset_medium.json' assert { type: 'json' }; +import PrivateKernelResetSimulatedJson from '../artifacts/private_kernel_reset_simulated.json' assert { type: 'json' }; +import PrivateKernelResetBigSimulatedJson from '../artifacts/private_kernel_reset_simulated_big.json' assert { type: 'json' }; +import PrivateKernelResetMediumSimulatedJson from '../artifacts/private_kernel_reset_simulated_medium.json' assert { type: 'json' }; +import PrivateKernelResetSmallSimulatedJson from '../artifacts/private_kernel_reset_simulated_small.json' assert { type: 'json' }; +import PrivateKernelResetSmallJson from '../artifacts/private_kernel_reset_small.json' assert { type: 'json' }; +import PrivateKernelTailJson from '../artifacts/private_kernel_tail.json' assert { type: 'json' }; +import PrivateKernelTailSimulatedJson from '../artifacts/private_kernel_tail_simulated.json' assert { type: 'json' }; +import PrivateKernelTailToPublicJson from '../artifacts/private_kernel_tail_to_public.json' assert { type: 'json' }; +import PrivateKernelTailToPublicSimulatedJson from '../artifacts/private_kernel_tail_to_public_simulated.json' assert { type: 'json' }; +import PublicKernelAppLogicJson from '../artifacts/public_kernel_app_logic.json' assert { type: 'json' }; +import PublicKernelAppLogicSimulatedJson from '../artifacts/public_kernel_app_logic_simulated.json' assert { type: 'json' }; +import PublicKernelSetupJson from '../artifacts/public_kernel_setup.json' assert { type: 'json' }; +import PublicKernelSetupSimulatedJson from '../artifacts/public_kernel_setup_simulated.json' assert { type: 'json' }; +import PublicKernelTailJson from '../artifacts/public_kernel_tail.json' assert { type: 'json' }; +import PublicKernelTailSimulatedJson from '../artifacts/public_kernel_tail_simulated.json' assert { type: 'json' }; +import PublicKernelTeardownJson from '../artifacts/public_kernel_teardown.json' assert { type: 'json' }; +import PublicKernelTeardownSimulatedJson from '../artifacts/public_kernel_teardown_simulated.json' assert { type: 'json' }; +import BaseRollupJson from '../artifacts/rollup_base.json' assert { type: 'json' }; +import BaseRollupSimulatedJson from '../artifacts/rollup_base_simulated.json' assert { type: 'json' }; +import MergeRollupJson from '../artifacts/rollup_merge.json' assert { type: 'json' }; +import RootRollupJson from '../artifacts/rollup_root.json' assert { type: 'json' }; import { mapBaseOrMergeRollupPublicInputsFromNoir, mapBaseParityInputsToNoir, diff --git a/yarn-project/noir-protocol-circuits-types/src/scripts/generate_declaration_files.ts b/yarn-project/noir-protocol-circuits-types/src/scripts/generate_declaration_files.ts new file mode 100644 index 00000000000..98a5f2f06b4 --- /dev/null +++ b/yarn-project/noir-protocol-circuits-types/src/scripts/generate_declaration_files.ts @@ -0,0 +1,17 @@ +import { fileURLToPath } from '@aztec/foundation/url'; + +import { readdir, writeFile } from 'fs/promises'; +import { join } from 'path'; + +const content = `\ +import { type NoirCompiledCircuit } from '@aztec/types/noir'; +const circuit: NoirCompiledCircuit; +export = circuit; +`; + +const target = fileURLToPath(new URL('../../artifacts', import.meta.url).href); +const files = await readdir(target); +for (const file of files) { + const name = file.replace('.json', ''); + await writeFile(join(target, `${name}.d.json.ts`), content); +} diff --git a/yarn-project/noir-protocol-circuits-types/src/scripts/generate_ts_from_abi.ts b/yarn-project/noir-protocol-circuits-types/src/scripts/generate_ts_from_abi.ts index 4c3734e42e6..acb52af5f5b 100644 --- a/yarn-project/noir-protocol-circuits-types/src/scripts/generate_ts_from_abi.ts +++ b/yarn-project/noir-protocol-circuits-types/src/scripts/generate_ts_from_abi.ts @@ -45,7 +45,7 @@ const main = async () => { const programs: [string, CompiledCircuit][] = []; // Collect all circuits for (const circuit of circuits) { - const rawData = await fs.readFile(`./src/target/${circuit}.json`, 'utf-8'); + const rawData = await fs.readFile(`./artifacts/${circuit}.json`, 'utf-8'); const abiObj: CompiledCircuit = JSON.parse(rawData); programs.push([pascalCase(circuit), abiObj]); } diff --git a/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts b/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts index c276fc8a16d..28448f316c1 100644 --- a/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts +++ b/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts @@ -1965,7 +1965,7 @@ export function mapBaseOrMergeRollupPublicInputsToNoir( ): BaseOrMergeRollupPublicInputsNoir { return { rollup_type: mapFieldToNoir(new Fr(baseOrMergeRollupPublicInputs.rollupType)), - height_in_block_tree: mapFieldToNoir(new Fr(baseOrMergeRollupPublicInputs.rollupSubtreeHeight)), + num_txs: mapFieldToNoir(new Fr(baseOrMergeRollupPublicInputs.numTxs)), constants: mapConstantRollupDataToNoir(baseOrMergeRollupPublicInputs.constants), start: mapPartialStateReferenceToNoir(baseOrMergeRollupPublicInputs.start), end: mapPartialStateReferenceToNoir(baseOrMergeRollupPublicInputs.end), @@ -2012,7 +2012,7 @@ export function mapBaseOrMergeRollupPublicInputsFromNoir( ): BaseOrMergeRollupPublicInputs { return new BaseOrMergeRollupPublicInputs( mapNumberFromNoir(baseOrMergeRollupPublicInputs.rollup_type), - mapFieldFromNoir(baseOrMergeRollupPublicInputs.height_in_block_tree), + mapNumberFromNoir(baseOrMergeRollupPublicInputs.num_txs), mapConstantRollupDataFromNoir(baseOrMergeRollupPublicInputs.constants), mapPartialStateReferenceFromNoir(baseOrMergeRollupPublicInputs.start), mapPartialStateReferenceFromNoir(baseOrMergeRollupPublicInputs.end), @@ -2183,7 +2183,7 @@ export function mapHeaderFromNoir(header: HeaderNoir): Header { */ export function mapContentCommitmentToNoir(contentCommitment: ContentCommitment): ContentCommitmentNoir { return { - tx_tree_height: mapFieldToNoir(contentCommitment.txTreeHeight), + num_txs: mapFieldToNoir(contentCommitment.numTxs), txs_effects_hash: mapSha256HashToNoir(contentCommitment.txsEffectsHash), in_hash: mapSha256HashToNoir(contentCommitment.inHash), out_hash: mapSha256HashToNoir(contentCommitment.outHash), @@ -2196,7 +2196,7 @@ export function mapContentCommitmentToNoir(contentCommitment: ContentCommitment) */ export function mapContentCommitmentFromNoir(contentCommitment: ContentCommitmentNoir): ContentCommitment { return new ContentCommitment( - mapFieldFromNoir(contentCommitment.tx_tree_height), + mapFieldFromNoir(contentCommitment.num_txs), mapSha256HashFromNoir(contentCommitment.txs_effects_hash), mapSha256HashFromNoir(contentCommitment.in_hash), mapSha256HashFromNoir(contentCommitment.out_hash), diff --git a/yarn-project/noir-protocol-circuits-types/tsconfig.json b/yarn-project/noir-protocol-circuits-types/tsconfig.json index 632b9eed778..390735ab54c 100644 --- a/yarn-project/noir-protocol-circuits-types/tsconfig.json +++ b/yarn-project/noir-protocol-circuits-types/tsconfig.json @@ -3,7 +3,8 @@ "compilerOptions": { "outDir": "dest", "rootDir": "src", - "tsBuildInfoFile": ".tsbuildinfo" + "tsBuildInfoFile": ".tsbuildinfo", + "resolveJsonModule": true }, "references": [ { @@ -28,6 +29,5 @@ "path": "../merkle-tree" } ], - "include": ["src", "src/**/*.json"], - "exclude": ["src/contracts"] + "include": ["src", "artifacts/*.d.json.ts"] } diff --git a/yarn-project/p2p-bootstrap/terraform/main.tf b/yarn-project/p2p-bootstrap/terraform/main.tf index 3536c88ee06..31b76cb33cd 100644 --- a/yarn-project/p2p-bootstrap/terraform/main.tf +++ b/yarn-project/p2p-bootstrap/terraform/main.tf @@ -104,7 +104,7 @@ resource "aws_ecs_task_definition" "p2p-bootstrap" { container_definitions = <=18" diff --git a/yarn-project/protocol-contracts/package.local.json b/yarn-project/protocol-contracts/package.local.json index c5987104cfc..6e3a34a9358 100644 --- a/yarn-project/protocol-contracts/package.local.json +++ b/yarn-project/protocol-contracts/package.local.json @@ -5,6 +5,12 @@ "generate:noir-contracts": "./scripts/copy-contracts.sh", "build:dev": "tsc -b --watch", "build:ts": "tsc -b", - "clean": "rm -rf ./dest .tsbuildinfo ./src/artifacts" - } -} + "clean": "rm -rf ./dest .tsbuildinfo ./artifacts" + }, + "files": [ + "dest", + "src", + "artifacts", + "!*.test.*" + ] +} \ No newline at end of file diff --git a/yarn-project/protocol-contracts/scripts/copy-contracts.sh b/yarn-project/protocol-contracts/scripts/copy-contracts.sh index 239445f9bbc..5001bf8c254 100755 --- a/yarn-project/protocol-contracts/scripts/copy-contracts.sh +++ b/yarn-project/protocol-contracts/scripts/copy-contracts.sh @@ -1,6 +1,6 @@ #! /bin/bash set -euo pipefail -mkdir -p ./src/artifacts +mkdir -p ./artifacts contracts=( contract_class_registerer_contract-ContractClassRegisterer @@ -11,6 +11,15 @@ contracts=( multi_call_entrypoint_contract-MultiCallEntrypoint ) + +decl=$(cat < ./artifacts/${contract#*-}.d.json.ts done diff --git a/yarn-project/protocol-contracts/src/auth-registry/artifact.ts b/yarn-project/protocol-contracts/src/auth-registry/artifact.ts index d33c2a9820f..030414f5d45 100644 --- a/yarn-project/protocol-contracts/src/auth-registry/artifact.ts +++ b/yarn-project/protocol-contracts/src/auth-registry/artifact.ts @@ -1,6 +1,6 @@ import { loadContractArtifact } from '@aztec/types/abi'; import { type NoirCompiledContract } from '@aztec/types/noir'; -import AuthRegistryJson from '../artifacts/AuthRegistry.json' assert { type: 'json' }; +import AuthRegistryJson from '../../artifacts/AuthRegistry.json' assert { type: 'json' }; export const AuthRegistryArtifact = loadContractArtifact(AuthRegistryJson as NoirCompiledContract); diff --git a/yarn-project/protocol-contracts/src/class-registerer/artifact.ts b/yarn-project/protocol-contracts/src/class-registerer/artifact.ts index 433bf7b269c..9f1f360b4c5 100644 --- a/yarn-project/protocol-contracts/src/class-registerer/artifact.ts +++ b/yarn-project/protocol-contracts/src/class-registerer/artifact.ts @@ -1,7 +1,7 @@ import { loadContractArtifact } from '@aztec/types/abi'; import { type NoirCompiledContract } from '@aztec/types/noir'; -import ContractClassRegistererJson from '../artifacts/ContractClassRegisterer.json' assert { type: 'json' }; +import ContractClassRegistererJson from '../../artifacts/ContractClassRegisterer.json' assert { type: 'json' }; export const ContractClassRegistererArtifact = loadContractArtifact( ContractClassRegistererJson as NoirCompiledContract, diff --git a/yarn-project/protocol-contracts/src/gas-token/artifact.ts b/yarn-project/protocol-contracts/src/gas-token/artifact.ts index 0dbaf8c2d74..9d83dd2d21b 100644 --- a/yarn-project/protocol-contracts/src/gas-token/artifact.ts +++ b/yarn-project/protocol-contracts/src/gas-token/artifact.ts @@ -1,6 +1,6 @@ import { loadContractArtifact } from '@aztec/types/abi'; import { type NoirCompiledContract } from '@aztec/types/noir'; -import GasTokenJson from '../artifacts/GasToken.json' assert { type: 'json' }; +import GasTokenJson from '../../artifacts/GasToken.json' assert { type: 'json' }; export const GasTokenArtifact = loadContractArtifact(GasTokenJson as NoirCompiledContract); diff --git a/yarn-project/protocol-contracts/src/instance-deployer/artifact.ts b/yarn-project/protocol-contracts/src/instance-deployer/artifact.ts index 809e35873ac..03dffc51462 100644 --- a/yarn-project/protocol-contracts/src/instance-deployer/artifact.ts +++ b/yarn-project/protocol-contracts/src/instance-deployer/artifact.ts @@ -1,7 +1,7 @@ import { loadContractArtifact } from '@aztec/types/abi'; import { type NoirCompiledContract } from '@aztec/types/noir'; -import ContractInstanceDeployerJson from '../artifacts/ContractInstanceDeployer.json' assert { type: 'json' }; +import ContractInstanceDeployerJson from '../../artifacts/ContractInstanceDeployer.json' assert { type: 'json' }; export const ContractInstanceDeployerArtifact = loadContractArtifact( ContractInstanceDeployerJson as NoirCompiledContract, diff --git a/yarn-project/protocol-contracts/src/key-registry/artifact.ts b/yarn-project/protocol-contracts/src/key-registry/artifact.ts index 89436d313e6..5feb280a624 100644 --- a/yarn-project/protocol-contracts/src/key-registry/artifact.ts +++ b/yarn-project/protocol-contracts/src/key-registry/artifact.ts @@ -1,6 +1,6 @@ import { loadContractArtifact } from '@aztec/types/abi'; import { type NoirCompiledContract } from '@aztec/types/noir'; -import KeyRegistryJson from '../artifacts/KeyRegistry.json' assert { type: 'json' }; +import KeyRegistryJson from '../../artifacts/KeyRegistry.json' assert { type: 'json' }; export const KeyRegistryArtifact = loadContractArtifact(KeyRegistryJson as NoirCompiledContract); diff --git a/yarn-project/protocol-contracts/src/multi-call-entrypoint/artifact.ts b/yarn-project/protocol-contracts/src/multi-call-entrypoint/artifact.ts index b3cf23f9f41..9f259a2d824 100644 --- a/yarn-project/protocol-contracts/src/multi-call-entrypoint/artifact.ts +++ b/yarn-project/protocol-contracts/src/multi-call-entrypoint/artifact.ts @@ -1,6 +1,6 @@ import { loadContractArtifact } from '@aztec/types/abi'; import { type NoirCompiledContract } from '@aztec/types/noir'; -import MultiCallEntrypoint from '../artifacts/MultiCallEntrypoint.json' assert { type: 'json' }; +import MultiCallEntrypoint from '../../artifacts/MultiCallEntrypoint.json' assert { type: 'json' }; export const MultiCallEntrypointArtifact = loadContractArtifact(MultiCallEntrypoint as NoirCompiledContract); diff --git a/yarn-project/protocol-contracts/tsconfig.json b/yarn-project/protocol-contracts/tsconfig.json index 01c876235ce..96ab4e32557 100644 --- a/yarn-project/protocol-contracts/tsconfig.json +++ b/yarn-project/protocol-contracts/tsconfig.json @@ -16,5 +16,5 @@ "path": "../types" } ], - "include": ["src", "src/**/*.json"] + "include": ["src", "artifacts/*.d.json.ts"] } diff --git a/yarn-project/prover-client/src/orchestrator/orchestrator.ts b/yarn-project/prover-client/src/orchestrator/orchestrator.ts index c6159039a72..1f68ce4c4ef 100644 --- a/yarn-project/prover-client/src/orchestrator/orchestrator.ts +++ b/yarn-project/prover-client/src/orchestrator/orchestrator.ts @@ -135,10 +135,8 @@ export class ProvingOrchestrator { this.initialHeader = await this.db.buildInitialHeader(); } - // Check that the length of the array of txs is a power of two - // See https://graphics.stanford.edu/~seander/bithacks.html#DetermineIfPowerOf2 - if (!Number.isInteger(numTxs) || numTxs < 2 || (numTxs & (numTxs - 1)) !== 0) { - throw new Error(`Length of txs for the block should be a power of two and at least two (got ${numTxs})`); + if (!Number.isInteger(numTxs) || numTxs < 2) { + throw new Error(`Length of txs for the block should be at least two (got ${numTxs})`); } // Cancel any currently proving block before starting a new one this.cancelBlock(); @@ -225,12 +223,17 @@ export class ProvingOrchestrator { logger.info(`Received transaction: ${tx.hash}`); + if (tx.isEmpty) { + logger.warn(`Ignoring empty transaction ${tx.hash} - it will not be added to this block`); + return; + } + const [inputs, treeSnapshots] = await this.prepareTransaction(tx, this.provingState); this.enqueueFirstProof(inputs, treeSnapshots, tx, this.provingState); } /** - * Marks the block as full and pads it to the full power of 2 block size, no more transactions will be accepted. + * Marks the block as full and pads it if required, no more transactions will be accepted. */ @trackSpan('ProvingOrchestrator.setBlockCompleted', function () { if (!this.provingState) { @@ -252,10 +255,15 @@ export class ProvingOrchestrator { const paddingTxCount = this.provingState.totalNumTxs - this.provingState.transactionsReceived; if (paddingTxCount === 0) { return; + } else if (this.provingState.totalNumTxs > 2) { + throw new Error(`Block not ready for completion: expecting ${paddingTxCount} more transactions.`); } logger.debug(`Padding rollup with ${paddingTxCount} empty transactions`); // Make an empty padding transaction + // Required for: + // 0 (when we want an empty block, largely for testing), or + // 1 (we need to pad with one tx as all rollup circuits require a pair of inputs) txs // Insert it into the tree the required number of times to get all of the // base rollup inputs // Then enqueue the proving of all the transactions @@ -579,13 +587,18 @@ export class ProvingOrchestrator { VerificationKeyAsFields, ], ) { - const mergeLevel = currentLevel - 1n; - const indexWithinMergeLevel = currentIndex >> 1n; + const [mergeLevel, indexWithinMergeLevel, indexWithinMerge] = provingState.findMergeLevel( + currentLevel, + currentIndex, + ); const mergeIndex = 2n ** mergeLevel - 1n + indexWithinMergeLevel; - const subscript = Number(mergeIndex); - const indexWithinMerge = Number(currentIndex & 1n); - const ready = provingState.storeMergeInputs(mergeInputs, indexWithinMerge, subscript); - return { ready, indexWithinMergeLevel, mergeLevel, mergeInputData: provingState.getMergeInputs(subscript) }; + const ready = provingState.storeMergeInputs(mergeInputs, Number(indexWithinMerge), Number(mergeIndex)); + return { + ready, + indexWithinMergeLevel, + mergeLevel, + mergeInputData: provingState.getMergeInputs(Number(mergeIndex)), + }; } // Executes the base rollup circuit and stored the output as intermediate state for the parent merge/root circuit diff --git a/yarn-project/prover-client/src/orchestrator/orchestrator_errors.test.ts b/yarn-project/prover-client/src/orchestrator/orchestrator_errors.test.ts index 01e9ee52eb4..e4ae1e55a4a 100644 --- a/yarn-project/prover-client/src/orchestrator/orchestrator_errors.test.ts +++ b/yarn-project/prover-client/src/orchestrator/orchestrator_errors.test.ts @@ -70,6 +70,13 @@ describe('prover/orchestrator/errors', () => { ); }); + it('throws if setting an incomplete block completed', async () => { + await context.orchestrator.startNewBlock(3, context.globalVariables, [], getMockVerificationKeys()); + await expect(async () => await context.orchestrator.setBlockCompleted()).rejects.toThrow( + `Block not ready for completion: expecting ${3} more transactions.`, + ); + }); + it('throws if finalising an already finalised block', async () => { const txs = await Promise.all([ makeEmptyProcessedTestTx(context.actualDb), @@ -80,13 +87,10 @@ describe('prover/orchestrator/errors', () => { txs.length, context.globalVariables, [], - getMockVerificationKeys(), ); - for (const tx of txs) { - await context.orchestrator.addNewTx(tx); - } + await context.orchestrator.setBlockCompleted(); const result = await blockTicket.provingPromise; expect(result.status).toBe(PROVING_STATUS.SUCCESS); @@ -111,7 +115,7 @@ describe('prover/orchestrator/errors', () => { ).rejects.toThrow('Rollup not accepting further transactions'); }); - it.each([[-4], [0], [1], [3], [8.1], [7]] as const)( + it.each([[-4], [0], [1], [8.1]] as const)( 'fails to start a block with %i transactions', async (blockSize: number) => { await expect( @@ -123,7 +127,7 @@ describe('prover/orchestrator/errors', () => { getMockVerificationKeys(), ), - ).rejects.toThrow(`Length of txs for the block should be a power of two and at least two (got ${blockSize})`); + ).rejects.toThrow(`Length of txs for the block should be at least two (got ${blockSize})`); }, ); diff --git a/yarn-project/prover-client/src/orchestrator/orchestrator_failures.test.ts b/yarn-project/prover-client/src/orchestrator/orchestrator_failures.test.ts index d53cb3aff11..6e31aebd688 100644 --- a/yarn-project/prover-client/src/orchestrator/orchestrator_failures.test.ts +++ b/yarn-project/prover-client/src/orchestrator/orchestrator_failures.test.ts @@ -7,7 +7,7 @@ import { NoopTelemetryClient } from '@aztec/telemetry-client/noop'; import { jest } from '@jest/globals'; import { TestCircuitProver } from '../../../bb-prover/src/test/test_circuit_prover.js'; -import { makeEmptyProcessedTestTx } from '../mocks/fixtures.js'; +import { makeBloatedProcessedTx } from '../mocks/fixtures.js'; import { TestContext } from '../mocks/test_context.js'; import { ProvingOrchestrator } from './orchestrator.js'; @@ -67,10 +67,9 @@ describe('prover/orchestrator/failures', () => { ] as const)('handles a %s error', async (message: string, fn: () => void) => { fn(); const txs = await Promise.all([ - makeEmptyProcessedTestTx(context.actualDb), - makeEmptyProcessedTestTx(context.actualDb), - makeEmptyProcessedTestTx(context.actualDb), - makeEmptyProcessedTestTx(context.actualDb), + makeBloatedProcessedTx(context.actualDb, 1), + makeBloatedProcessedTx(context.actualDb, 2), + makeBloatedProcessedTx(context.actualDb, 3), ]); const blockTicket = await orchestrator.startNewBlock( diff --git a/yarn-project/prover-client/src/orchestrator/orchestrator_mixed_blocks.test.ts b/yarn-project/prover-client/src/orchestrator/orchestrator_mixed_blocks.test.ts index 7cd3a337b8f..5c686a472a5 100644 --- a/yarn-project/prover-client/src/orchestrator/orchestrator_mixed_blocks.test.ts +++ b/yarn-project/prover-client/src/orchestrator/orchestrator_mixed_blocks.test.ts @@ -30,9 +30,8 @@ describe('prover/orchestrator/mixed-blocks', () => { const l1ToL2Messages = range(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, 1 + 0x400).map(fr); - // this needs to be a 4 tx block that will need to be completed const blockTicket = await context.orchestrator.startNewBlock( - 4, + 3, context.globalVariables, l1ToL2Messages, diff --git a/yarn-project/prover-client/src/orchestrator/orchestrator_mixed_blocks_2.test.ts b/yarn-project/prover-client/src/orchestrator/orchestrator_mixed_blocks_2.test.ts index c9f8b930df2..3000e349085 100644 --- a/yarn-project/prover-client/src/orchestrator/orchestrator_mixed_blocks_2.test.ts +++ b/yarn-project/prover-client/src/orchestrator/orchestrator_mixed_blocks_2.test.ts @@ -7,7 +7,7 @@ import { createDebugLogger } from '@aztec/foundation/log'; import { openTmpStore } from '@aztec/kv-store/utils'; import { type MerkleTreeOperations, MerkleTrees } from '@aztec/world-state'; -import { makeBloatedProcessedTx, makeEmptyProcessedTestTx, updateExpectedTreesFromTxs } from '../mocks/fixtures.js'; +import { makeBloatedProcessedTx, updateExpectedTreesFromTxs } from '../mocks/fixtures.js'; import { TestContext } from '../mocks/test_context.js'; const logger = createDebugLogger('aztec:orchestrator-mixed-blocks-2'); @@ -26,51 +26,37 @@ describe('prover/orchestrator/mixed-blocks', () => { }); describe('blocks', () => { - it.each([ - [0, 2], - [1, 2], - [4, 4], - [5, 8], - ] as const)( - 'builds an L2 block with %i bloated txs and %i txs total', - async (bloatedCount: number, totalCount: number) => { - const noteHashTreeBefore = await context.actualDb.getTreeInfo(MerkleTreeId.NOTE_HASH_TREE); - const txs = [ - ...(await Promise.all(times(bloatedCount, (i: number) => makeBloatedProcessedTx(context.actualDb, i)))), - ...(await Promise.all(times(totalCount - bloatedCount, _ => makeEmptyProcessedTestTx(context.actualDb)))), - ]; + it.each([2, 4, 5, 8] as const)('builds an L2 block with %i bloated txs', async (totalCount: number) => { + const txs = [ + ...(await Promise.all(times(totalCount, (i: number) => makeBloatedProcessedTx(context.actualDb, i)))), + ]; - const l1ToL2Messages = range(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, 1 + 0x400).map(fr); + const l1ToL2Messages = range(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, 1 + 0x400).map(fr); - const blockTicket = await context.orchestrator.startNewBlock( - txs.length, - context.globalVariables, - l1ToL2Messages, + const blockTicket = await context.orchestrator.startNewBlock( + txs.length, + context.globalVariables, + l1ToL2Messages, - getMockVerificationKeys(), - ); + getMockVerificationKeys(), + ); - for (const tx of txs) { - await context.orchestrator.addNewTx(tx); - } + for (const tx of txs) { + await context.orchestrator.addNewTx(tx); + } - const result = await blockTicket.provingPromise; - expect(result.status).toBe(PROVING_STATUS.SUCCESS); + const result = await blockTicket.provingPromise; + expect(result.status).toBe(PROVING_STATUS.SUCCESS); - const finalisedBlock = await context.orchestrator.finaliseBlock(); + const finalisedBlock = await context.orchestrator.finaliseBlock(); - expect(finalisedBlock.block.number).toEqual(context.blockNumber); + expect(finalisedBlock.block.number).toEqual(context.blockNumber); - await updateExpectedTreesFromTxs(expectsDb, txs); - const noteHashTreeAfter = await context.actualDb.getTreeInfo(MerkleTreeId.NOTE_HASH_TREE); + await updateExpectedTreesFromTxs(expectsDb, txs); + const noteHashTreeAfter = await context.actualDb.getTreeInfo(MerkleTreeId.NOTE_HASH_TREE); - if (bloatedCount > 0) { - expect(noteHashTreeAfter.root).not.toEqual(noteHashTreeBefore.root); - } - - const expectedNoteHashTreeAfter = await expectsDb.getTreeInfo(MerkleTreeId.NOTE_HASH_TREE).then(t => t.root); - expect(noteHashTreeAfter.root).toEqual(expectedNoteHashTreeAfter); - }, - ); + const expectedNoteHashTreeAfter = await expectsDb.getTreeInfo(MerkleTreeId.NOTE_HASH_TREE).then(t => t.root); + expect(noteHashTreeAfter.root).toEqual(expectedNoteHashTreeAfter); + }); }); }); diff --git a/yarn-project/prover-client/src/orchestrator/orchestrator_single_blocks.test.ts b/yarn-project/prover-client/src/orchestrator/orchestrator_single_blocks.test.ts index 808aa3dae8d..635d1dec429 100644 --- a/yarn-project/prover-client/src/orchestrator/orchestrator_single_blocks.test.ts +++ b/yarn-project/prover-client/src/orchestrator/orchestrator_single_blocks.test.ts @@ -7,7 +7,7 @@ import { sleep } from '@aztec/foundation/sleep'; import { openTmpStore } from '@aztec/kv-store/utils'; import { type MerkleTreeOperations, MerkleTrees } from '@aztec/world-state'; -import { makeBloatedProcessedTx, makeEmptyProcessedTestTx, updateExpectedTreesFromTxs } from '../mocks/fixtures.js'; +import { makeBloatedProcessedTx, updateExpectedTreesFromTxs } from '../mocks/fixtures.js'; import { TestContext } from '../mocks/test_context.js'; const logger = createDebugLogger('aztec:orchestrator-single-blocks'); @@ -27,21 +27,14 @@ describe('prover/orchestrator/blocks', () => { describe('blocks', () => { it('builds an empty L2 block', async () => { - const txs = await Promise.all([ - makeEmptyProcessedTestTx(context.actualDb), - makeEmptyProcessedTestTx(context.actualDb), - ]); - const blockTicket = await context.orchestrator.startNewBlock( - txs.length, + 2, context.globalVariables, [], getMockVerificationKeys(), ); - for (const tx of txs) { - await context.orchestrator.addNewTx(tx); - } + await context.orchestrator.setBlockCompleted(); const result = await blockTicket.provingPromise; expect(result.status).toBe(PROVING_STATUS.SUCCESS); diff --git a/yarn-project/prover-client/src/orchestrator/proving-state.ts b/yarn-project/prover-client/src/orchestrator/proving-state.ts index d2b92000f61..51004578237 100644 --- a/yarn-project/prover-client/src/orchestrator/proving-state.ts +++ b/yarn-project/prover-client/src/orchestrator/proving-state.ts @@ -71,6 +71,32 @@ export class ProvingState { return BigInt(Math.ceil(Math.log2(this.totalNumTxs)) - 1); } + // Calculates the index and level of the parent rollup circuit + // Based on tree implementation in unbalanced_tree.ts -> batchInsert() + public findMergeLevel(currentLevel: bigint, currentIndex: bigint) { + const moveUpMergeLevel = (levelSize: number, index: bigint, nodeToShift: boolean) => { + levelSize /= 2; + if (levelSize & 1) { + [levelSize, nodeToShift] = nodeToShift ? [levelSize + 1, false] : [levelSize - 1, true]; + } + index >>= 1n; + return { thisLevelSize: levelSize, thisIndex: index, shiftUp: nodeToShift }; + }; + let [thisLevelSize, shiftUp] = this.totalNumTxs & 1 ? [this.totalNumTxs - 1, true] : [this.totalNumTxs, false]; + const maxLevel = this.numMergeLevels + 1n; + let placeholder = currentIndex; + for (let i = 0; i < maxLevel - currentLevel; i++) { + ({ thisLevelSize, thisIndex: placeholder, shiftUp } = moveUpMergeLevel(thisLevelSize, placeholder, shiftUp)); + } + let thisIndex = currentIndex; + let mergeLevel = currentLevel; + while (thisIndex >= thisLevelSize && mergeLevel != 0n) { + mergeLevel -= 1n; + ({ thisLevelSize, thisIndex, shiftUp } = moveUpMergeLevel(thisLevelSize, thisIndex, shiftUp)); + } + return [mergeLevel - 1n, thisIndex >> 1n, thisIndex & 1n]; + } + // Adds a transaction to the proving state, returns it's index // Will update the proving life cycle if this is the last transaction public addNewTx(tx: TxProvingState) { diff --git a/yarn-project/pxe/src/pxe_service/pxe_service.ts b/yarn-project/pxe/src/pxe_service/pxe_service.ts index cf351c5bf9b..7549f45efef 100644 --- a/yarn-project/pxe/src/pxe_service/pxe_service.ts +++ b/yarn-project/pxe/src/pxe_service/pxe_service.ts @@ -4,6 +4,7 @@ import { EncryptedNoteTxL2Logs, EncryptedTxL2Logs, type EventMetadata, + EventType, ExtendedNote, type FunctionCall, type GetUnencryptedLogsResponse, @@ -35,7 +36,13 @@ import { getContractClassFromArtifact, } from '@aztec/circuits.js'; import { computeNoteHashNonce, siloNullifier } from '@aztec/circuits.js/hash'; -import { type ContractArtifact, type DecodedReturn, FunctionSelector, encodeArguments } from '@aztec/foundation/abi'; +import { + type ContractArtifact, + type DecodedReturn, + EventSelector, + FunctionSelector, + encodeArguments, +} from '@aztec/foundation/abi'; import { type Fq, Fr, type Point } from '@aztec/foundation/fields'; import { SerialQueue } from '@aztec/foundation/fifo'; import { type DebugLogger, createDebugLogger } from '@aztec/foundation/log'; @@ -286,7 +293,7 @@ export class PXEService implements PXE { if (!(await this.getContractInstance(contract))) { throw new Error(`Contract ${contract.toString()} is not deployed`); } - return await this.node.getPublicStorageAt(contract, slot); + return await this.node.getPublicStorageAt(contract, slot, 'latest'); } public async getIncomingNotes(filter: IncomingNotesFilter): Promise { @@ -834,7 +841,43 @@ export class PXEService implements PXE { return !!(await this.node.getContract(address)); } - public async getEvents(from: number, limit: number, eventMetadata: EventMetadata, ivpk: Point): Promise { + public getEvents( + type: EventType.Encrypted, + eventMetadata: EventMetadata, + from: number, + limit: number, + vpks: Point[], + ): Promise; + public getEvents( + type: EventType.Unencrypted, + eventMetadata: EventMetadata, + from: number, + limit: number, + ): Promise; + public getEvents( + type: EventType, + eventMetadata: EventMetadata, + from: number, + limit: number, + vpks: Point[] = [], + ): Promise { + if (type.includes(EventType.Encrypted)) { + return this.getEncryptedEvents(from, limit, eventMetadata, vpks); + } + + return this.getUnencryptedEvents(from, limit, eventMetadata); + } + + async getEncryptedEvents( + from: number, + limit: number, + eventMetadata: EventMetadata, + vpks: Point[], + ): Promise { + if (vpks.length === 0) { + throw new Error('Tried to get encrypted events without supplying any viewing public keys'); + } + const blocks = await this.node.getBlocks(from, limit); const txEffects = blocks.flatMap(block => block.body.txEffects); @@ -842,11 +885,20 @@ export class PXEService implements PXE { const encryptedLogs = encryptedTxLogs.flatMap(encryptedTxLog => encryptedTxLog.unrollLogs()); - const ivsk = await this.keyStore.getMasterSecretKey(ivpk); + const vsks = await Promise.all(vpks.map(vpk => this.keyStore.getMasterSecretKey(vpk))); + + const visibleEvents = encryptedLogs.flatMap(encryptedLog => { + for (const sk of vsks) { + const decryptedLog = + TaggedLog.decryptAsIncoming(encryptedLog, sk, L1EventPayload) ?? + TaggedLog.decryptAsOutgoing(encryptedLog, sk, L1EventPayload); + if (decryptedLog !== undefined) { + return [decryptedLog]; + } + } - const visibleEvents = encryptedLogs - .map(encryptedLog => TaggedLog.decryptAsIncoming(encryptedLog, ivsk, L1EventPayload)) - .filter(item => item !== undefined) as TaggedLog[]; + return []; + }); const decodedEvents = visibleEvents .map(visibleEvent => { @@ -874,4 +926,40 @@ export class PXEService implements PXE { return decodedEvents; } + + async getUnencryptedEvents(from: number, limit: number, eventMetadata: EventMetadata): Promise { + const { logs: unencryptedLogs } = await this.node.getUnencryptedLogs({ + fromBlock: from, + toBlock: from + limit, + }); + + const decodedEvents = unencryptedLogs + .map(unencryptedLog => { + const unencryptedLogBuf = unencryptedLog.log.data; + if ( + !EventSelector.fromBuffer(unencryptedLogBuf.subarray(unencryptedLogBuf.byteLength - 4)).equals( + eventMetadata.eventSelector, + ) + ) { + return undefined; + } + + if (unencryptedLogBuf.byteLength !== eventMetadata.fieldNames.length * 32 + 32) { + throw new Error( + 'Something is weird here, we have matching FunctionSelectors, but the actual payload has mismatched length', + ); + } + + return eventMetadata.fieldNames.reduce( + (acc, curr, i) => ({ + ...acc, + [curr]: new Fr(unencryptedLogBuf.subarray(i * 32, i * 32 + 32)), + }), + {} as T, + ); + }) + .filter(unencryptedLog => unencryptedLog !== undefined) as T[]; + + return decodedEvents; + } } diff --git a/yarn-project/sequencer-client/src/sequencer/sequencer.ts b/yarn-project/sequencer-client/src/sequencer/sequencer.ts index 0a441453780..fb20cb3507f 100644 --- a/yarn-project/sequencer-client/src/sequencer/sequencer.ts +++ b/yarn-project/sequencer-client/src/sequencer/sequencer.ts @@ -258,9 +258,7 @@ export class Sequencer { const processor = await this.publicProcessorFactory.create(historicalHeader, newGlobalVariables); const numRealTxs = validTxs.length; - const pow2 = Math.log2(numRealTxs); - const totalTxs = 2 ** Math.ceil(pow2); - const blockSize = Math.max(2, totalTxs); + const blockSize = Math.max(2, numRealTxs); const blockBuildingTimer = new Timer(); const blockTicket = await this.prover.startNewBlock(blockSize, newGlobalVariables, l1ToL2Messages); diff --git a/yarn-project/simulator/src/acvm/oracle/oracle.ts b/yarn-project/simulator/src/acvm/oracle/oracle.ts index d2cd8ddf7d1..b3f04b97429 100644 --- a/yarn-project/simulator/src/acvm/oracle/oracle.ts +++ b/yarn-project/simulator/src/acvm/oracle/oracle.ts @@ -287,8 +287,18 @@ export class Oracle { return message.toFields().map(toACVMField); } - async storageRead([startStorageSlot]: ACVMField[], [numberOfElements]: ACVMField[]): Promise { - const values = await this.typedOracle.storageRead(fromACVMField(startStorageSlot), +numberOfElements); + async storageRead( + [contractAddress]: ACVMField[], + [startStorageSlot]: ACVMField[], + [blockNumber]: ACVMField[], + [numberOfElements]: ACVMField[], + ): Promise { + const values = await this.typedOracle.storageRead( + fromACVMField(contractAddress), + fromACVMField(startStorageSlot), + +blockNumber, + +numberOfElements, + ); return values.map(toACVMField); } diff --git a/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts b/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts index 690ccf8ac86..fdda81ac6ae 100644 --- a/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts +++ b/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts @@ -190,7 +190,12 @@ export abstract class TypedOracle { throw new OracleMethodNotAvailableError('getL1ToL2MembershipWitness'); } - storageRead(_startStorageSlot: Fr, _numberOfElements: number): Promise { + storageRead( + _contractAddress: Fr, + _startStorageSlot: Fr, + _blockNumber: number, + _numberOfElements: number, + ): Promise { throw new OracleMethodNotAvailableError('storageRead'); } diff --git a/yarn-project/simulator/src/avm/avm_context.ts b/yarn-project/simulator/src/avm/avm_context.ts index c9c5e13ef76..b0ca8d3b2df 100644 --- a/yarn-project/simulator/src/avm/avm_context.ts +++ b/yarn-project/simulator/src/avm/avm_context.ts @@ -43,13 +43,13 @@ export class AvmContext { calldata: Fr[], allocatedGas: Gas, callType: 'CALL' | 'STATICCALL', - temporaryFunctionSelector: FunctionSelector = FunctionSelector.empty(), + functionSelector: FunctionSelector = FunctionSelector.empty(), ): AvmContext { const deriveFn = callType === 'CALL' ? this.environment.deriveEnvironmentForNestedCall : this.environment.deriveEnvironmentForNestedStaticCall; - const newExecutionEnvironment = deriveFn.call(this.environment, address, calldata, temporaryFunctionSelector); + const newExecutionEnvironment = deriveFn.call(this.environment, address, calldata, functionSelector); const forkedWorldState = this.persistableState.fork(); const machineState = AvmMachineState.fromState(gasToGasLeft(allocatedGas)); return new AvmContext(forkedWorldState, newExecutionEnvironment, machineState); diff --git a/yarn-project/simulator/src/avm/avm_execution_environment.ts b/yarn-project/simulator/src/avm/avm_execution_environment.ts index 2e73d8e384e..27a1e32ec9c 100644 --- a/yarn-project/simulator/src/avm/avm_execution_environment.ts +++ b/yarn-project/simulator/src/avm/avm_execution_environment.ts @@ -1,15 +1,15 @@ -import { FunctionSelector, type GasSettings, type GlobalVariables, type Header } from '@aztec/circuits.js'; +import { FunctionSelector, type GlobalVariables, type Header } from '@aztec/circuits.js'; import { computeVarArgsHash } from '@aztec/circuits.js/hash'; import { type AztecAddress } from '@aztec/foundation/aztec-address'; import { Fr } from '@aztec/foundation/fields'; export class AvmContextInputs { - static readonly SIZE = 3; + static readonly SIZE = 2; - constructor(private selector: Fr, private argsHash: Fr, private isStaticCall: boolean) {} + constructor(private argsHash: Fr, private isStaticCall: boolean) {} public toFields(): Fr[] { - return [this.selector, this.argsHash, new Fr(this.isStaticCall)]; + return [this.argsHash, new Fr(this.isStaticCall)]; } } @@ -18,36 +18,23 @@ export class AvmContextInputs { * These variables are provided by the public kernel circuit */ export class AvmExecutionEnvironment { - private readonly calldataPrefixLength; constructor( public readonly address: AztecAddress, public readonly storageAddress: AztecAddress, public readonly sender: AztecAddress, - public readonly feePerL2Gas: Fr, - public readonly feePerDaGas: Fr, + public readonly functionSelector: FunctionSelector, // may be temporary (#7224) public readonly contractCallDepth: Fr, + public readonly transactionFee: Fr, public readonly header: Header, public readonly globals: GlobalVariables, public readonly isStaticCall: boolean, public readonly isDelegateCall: boolean, public readonly calldata: Fr[], - public readonly gasSettings: GasSettings, - public readonly transactionFee: Fr, - - // Function selector may be temporary since eventually public contract bytecode will likely be one - // blob containing all functions, and function selector will become an application-level mechanism - // (e.g. first few bytes of calldata + compiler-generated jump table) - public readonly functionSelector: FunctionSelector, ) { // We encode some extra inputs (AvmContextInputs) in calldata. // This will have to go once we move away from one proof per call. - const inputs = new AvmContextInputs( - functionSelector.toField(), - computeVarArgsHash(calldata), - isStaticCall, - ).toFields(); + const inputs = new AvmContextInputs(computeVarArgsHash(calldata), isStaticCall).toFields(); this.calldata = [...inputs, ...calldata]; - this.calldataPrefixLength = inputs.length; } private deriveEnvironmentForNestedCallInternal( @@ -61,17 +48,14 @@ export class AvmExecutionEnvironment { /*address=*/ targetAddress, /*storageAddress=*/ targetAddress, /*sender=*/ this.address, - this.feePerL2Gas, - this.feePerDaGas, + functionSelector, this.contractCallDepth.add(Fr.ONE), + this.transactionFee, this.header, this.globals, isStaticCall, isDelegateCall, calldata, - this.gasSettings, - this.transactionFee, - functionSelector, ); } @@ -113,6 +97,6 @@ export class AvmExecutionEnvironment { public getCalldataWithoutPrefix(): Fr[] { // clip off the first few entries - return this.calldata.slice(this.calldataPrefixLength); + return this.calldata.slice(AvmContextInputs.SIZE); } } diff --git a/yarn-project/simulator/src/avm/avm_gas.ts b/yarn-project/simulator/src/avm/avm_gas.ts index d951f20fa32..d571234ee25 100644 --- a/yarn-project/simulator/src/avm/avm_gas.ts +++ b/yarn-project/simulator/src/avm/avm_gas.ts @@ -76,7 +76,7 @@ const BaseGasCosts: Record = { [Opcode.FEEPERL2GAS]: DefaultBaseGasCost, [Opcode.FEEPERDAGAS]: DefaultBaseGasCost, [Opcode.TRANSACTIONFEE]: DefaultBaseGasCost, - [Opcode.CONTRACTCALLDEPTH]: DefaultBaseGasCost, + [Opcode.FUNCTIONSELECTOR]: DefaultBaseGasCost, [Opcode.CHAINID]: DefaultBaseGasCost, [Opcode.VERSION]: DefaultBaseGasCost, [Opcode.BLOCKNUMBER]: DefaultBaseGasCost, diff --git a/yarn-project/simulator/src/avm/avm_simulator.test.ts b/yarn-project/simulator/src/avm/avm_simulator.test.ts index 097a19cdfb4..b8475277283 100644 --- a/yarn-project/simulator/src/avm/avm_simulator.test.ts +++ b/yarn-project/simulator/src/avm/avm_simulator.test.ts @@ -1,3 +1,4 @@ +import { GasFees } from '@aztec/circuits.js'; import { Grumpkin } from '@aztec/circuits.js/barretenberg'; import { computeVarArgsHash } from '@aztec/circuits.js/hash'; import { FunctionSelector } from '@aztec/foundation/abi'; @@ -6,9 +7,11 @@ import { keccak256, pedersenHash, poseidon2Hash, sha256 } from '@aztec/foundatio import { Fq, Fr } from '@aztec/foundation/fields'; import { type Fieldable } from '@aztec/foundation/serialize'; +import { randomInt } from 'crypto'; import { mock } from 'jest-mock-extended'; import { type PublicSideEffectTraceInterface } from '../public/side_effect_trace_interface.js'; +import { type AvmContext } from './avm_context.js'; import { type AvmExecutionEnvironment } from './avm_execution_environment.js'; import { AvmMachineState } from './avm_machine_state.js'; import { type MemoryValue, TypeTag, type Uint8 } from './avm_memory_types.js'; @@ -234,73 +237,58 @@ describe('AVM simulator: transpiled Noir contracts', () => { }); describe('Environment getters', () => { - const testEnvGetter = async (valueName: string, value: any, functionName: string, globalVar: boolean = false) => { - // Execute - let overrides = {}; - if (globalVar === true) { - const globals = initGlobalVariables({ [valueName]: value }); - overrides = { globals }; - } else { - overrides = { [valueName]: value }; - } - const context = initContext({ env: initExecutionEnvironment(overrides) }); - const bytecode = getAvmTestContractBytecode(functionName); - const results = await new AvmSimulator(context).executeBytecode(bytecode); - - expect(results.reverted).toBe(false); - - const returnData = results.output; - expect(returnData).toEqual([value.toField()]); - }; - - it('address', async () => { - const address = AztecAddress.fromField(new Fr(1)); - await testEnvGetter('address', address, 'get_address'); - }); - - it('storageAddress', async () => { - const storageAddress = AztecAddress.fromField(new Fr(1)); - await testEnvGetter('storageAddress', storageAddress, 'get_storage_address'); + const address = AztecAddress.random(); + const storageAddress = AztecAddress.random(); + const sender = AztecAddress.random(); + const functionSelector = FunctionSelector.random(); + const transactionFee = Fr.random(); + const chainId = Fr.random(); + const version = Fr.random(); + const blockNumber = Fr.random(); + const timestamp = new Fr(randomInt(100000)); // cap timestamp since must fit in u64 + const feePerDaGas = Fr.random(); + const feePerL2Gas = Fr.random(); + const gasFees = new GasFees(feePerDaGas, feePerL2Gas); + const globals = initGlobalVariables({ + chainId, + version, + blockNumber, + timestamp, + gasFees, }); - - it('sender', async () => { - const sender = AztecAddress.fromField(new Fr(1)); - await testEnvGetter('sender', sender, 'get_sender'); - }); - - it('getFeePerL2Gas', async () => { - const fee = new Fr(1); - await testEnvGetter('feePerL2Gas', fee, 'get_fee_per_l2_gas'); + const env = initExecutionEnvironment({ + address, + storageAddress, + sender, + functionSelector, + transactionFee, + globals, }); - - it('getFeePerDaGas', async () => { - const fee = new Fr(1); - await testEnvGetter('feePerDaGas', fee, 'get_fee_per_da_gas'); - }); - - it('getTransactionFee', async () => { - const fee = new Fr(1); - await testEnvGetter('transactionFee', fee, 'get_transaction_fee'); - }); - - it('chainId', async () => { - const chainId = new Fr(1); - await testEnvGetter('chainId', chainId, 'get_chain_id', /*globalVar=*/ true); + let context: AvmContext; + beforeEach(() => { + context = initContext({ env }); }); - it('version', async () => { - const version = new Fr(1); - await testEnvGetter('version', version, 'get_version', /*globalVar=*/ true); - }); + it.each([ + ['address', address.toField(), 'get_address'], + ['storageAddress', storageAddress.toField(), 'get_storage_address'], + ['sender', sender.toField(), 'get_sender'], + ['functionSelector', functionSelector.toField(), 'get_function_selector'], + ['transactionFee', transactionFee.toField(), 'get_transaction_fee'], + ['chainId', chainId.toField(), 'get_chain_id'], + ['version', version.toField(), 'get_version'], + ['blockNumber', blockNumber.toField(), 'get_block_number'], + ['timestamp', timestamp.toField(), 'get_timestamp'], + ['feePerDaGas', feePerDaGas.toField(), 'get_fee_per_da_gas'], + ['feePerL2Gas', feePerL2Gas.toField(), 'get_fee_per_l2_gas'], + ])('%s getter', async (_name: string, value: Fr, functionName: string) => { + const bytecode = getAvmTestContractBytecode(functionName); + const results = await new AvmSimulator(context).executeBytecode(bytecode); - it('blockNumber', async () => { - const blockNumber = new Fr(1); - await testEnvGetter('blockNumber', blockNumber, 'get_block_number', /*globalVar=*/ true); - }); + expect(results.reverted).toBe(false); - it('timestamp', async () => { - const timestamp = new Fr(1); - await testEnvGetter('timestamp', timestamp, 'get_timestamp', /*globalVar=*/ true); + const returnData = results.output; + expect(returnData).toEqual([value]); }); }); diff --git a/yarn-project/simulator/src/avm/fixtures/index.ts b/yarn-project/simulator/src/avm/fixtures/index.ts index fdcb07c8d31..4534dd90587 100644 --- a/yarn-project/simulator/src/avm/fixtures/index.ts +++ b/yarn-project/simulator/src/avm/fixtures/index.ts @@ -1,4 +1,4 @@ -import { GasFees, GasSettings, GlobalVariables, Header } from '@aztec/circuits.js'; +import { GasFees, GlobalVariables, Header } from '@aztec/circuits.js'; import { FunctionSelector } from '@aztec/foundation/abi'; import { AztecAddress } from '@aztec/foundation/aztec-address'; import { EthAddress } from '@aztec/foundation/eth-address'; @@ -72,17 +72,14 @@ export function initExecutionEnvironment(overrides?: Partial> = new Map(); - // FIXME: storage ^ should be private, but its value is used in tests for "currentStorageValue" + // FIXME: storage ^ should be private, but its value is used in commitToDB /** * Read a staged value from storage, if it has been previously written to. diff --git a/yarn-project/simulator/src/avm/opcodes/environment_getters.test.ts b/yarn-project/simulator/src/avm/opcodes/environment_getters.test.ts index 3b447af01a4..abf0b7e3936 100644 --- a/yarn-project/simulator/src/avm/opcodes/environment_getters.test.ts +++ b/yarn-project/simulator/src/avm/opcodes/environment_getters.test.ts @@ -1,5 +1,11 @@ +import { GasFees } from '@aztec/circuits.js'; +import { FunctionSelector as FunctionSelectorType } from '@aztec/foundation/abi'; +import { AztecAddress } from '@aztec/foundation/aztec-address'; import { Fr } from '@aztec/foundation/fields'; +import { randomInt } from 'crypto'; + +import { type AvmContext } from '../avm_context.js'; import { TypeTag } from '../avm_memory_types.js'; import { initContext, initExecutionEnvironment, initGlobalVariables } from '../fixtures/index.js'; import { @@ -8,6 +14,7 @@ import { ChainId, FeePerDAGas, FeePerL2Gas, + FunctionSelector, Sender, StorageAddress, Timestamp, @@ -15,76 +22,84 @@ import { Version, } from './environment_getters.js'; -type EnvInstruction = - | typeof FeePerL2Gas - | typeof FeePerDAGas +type GetterInstruction = | typeof Sender | typeof StorageAddress | typeof Address - | typeof TransactionFee; - -describe.each([ - [FeePerL2Gas, 'feePerL2Gas'], - [FeePerDAGas, 'feePerDaGas'], - [Sender, 'sender'], - [StorageAddress, 'storageAddress'], - [Address, 'address'], - [TransactionFee, 'transactionFee'], -])('Environment getters instructions', (clsValue: EnvInstruction, key: string) => { - it(`${clsValue.name} should (de)serialize correctly`, () => { - const buf = Buffer.from([ - clsValue.opcode, // opcode - 0x01, // indirect - ...Buffer.from('12345678', 'hex'), // dstOffset - ]); - const inst = new clsValue(/*indirect=*/ 0x01, /*dstOffset=*/ 0x12345678); + | typeof FunctionSelector + | typeof TransactionFee + | typeof ChainId + | typeof Version + | typeof BlockNumber + | typeof Timestamp + | typeof FeePerDAGas + | typeof FeePerL2Gas; - expect(clsValue.deserialize(buf)).toEqual(inst); - expect(inst.serialize()).toEqual(buf); +describe('Environment getters', () => { + const address = AztecAddress.random(); + const storageAddress = AztecAddress.random(); + const sender = AztecAddress.random(); + const functionSelector = FunctionSelectorType.random(); + const transactionFee = Fr.random(); + const chainId = Fr.random(); + const version = Fr.random(); + const blockNumber = Fr.random(); + const timestamp = new Fr(randomInt(100000)); // cap timestamp since must fit in u64 + const feePerDaGas = Fr.random(); + const feePerL2Gas = Fr.random(); + const gasFees = new GasFees(feePerDaGas, feePerL2Gas); + const globals = initGlobalVariables({ + chainId, + version, + blockNumber, + timestamp, + gasFees, }); - - it(`${clsValue.name} should read '${key}' correctly`, async () => { - const value = new Fr(123456n); - const instruction = new clsValue(/*indirect=*/ 0, /*dstOffset=*/ 0); - const context = initContext({ env: initExecutionEnvironment({ [key]: value }) }); - - await instruction.execute(context); - - expect(context.machineState.memory.getTag(0)).toBe(TypeTag.FIELD); - const actual = context.machineState.memory.get(0).toFr(); - expect(actual).toEqual(value); + const env = initExecutionEnvironment({ + address, + storageAddress, + sender, + functionSelector, + transactionFee, + globals, }); -}); - -type GlobalsInstruction = typeof ChainId | typeof Version | typeof BlockNumber | typeof Timestamp; -describe.each([ - [ChainId, 'chainId', TypeTag.FIELD], - [Version, 'version', TypeTag.FIELD], - [BlockNumber, 'blockNumber', TypeTag.FIELD], - [Timestamp, 'timestamp', TypeTag.UINT64], -])('Global Variables', (clsValue: GlobalsInstruction, key: string, tag: TypeTag) => { - it(`${clsValue.name} should (de)serialize correctly`, () => { - const buf = Buffer.from([ - clsValue.opcode, // opcode - 0x01, // indirect - ...Buffer.from('12345678', 'hex'), // dstOffset - ]); - const inst = new clsValue(/*indirect=*/ 0x01, /*dstOffset=*/ 0x12345678); - - expect(clsValue.deserialize(buf)).toEqual(inst); - expect(inst.serialize()).toEqual(buf); + let context: AvmContext; + beforeEach(() => { + context = initContext({ env }); }); - it(`${clsValue.name} should read '${key}' correctly`, async () => { - const value = new Fr(123456n); - const instruction = new clsValue(/*indirect=*/ 0, /*dstOffset=*/ 0); - const globals = initGlobalVariables({ [key]: value }); - const context = initContext({ env: initExecutionEnvironment({ globals }) }); + describe.each([ + [Address, address.toField()], + [StorageAddress, storageAddress.toField()], + [Sender, sender.toField()], + [FunctionSelector, functionSelector.toField(), TypeTag.UINT32], + [TransactionFee, transactionFee.toField()], + [ChainId, chainId.toField()], + [Version, version.toField()], + [BlockNumber, blockNumber.toField()], + [Timestamp, timestamp.toField(), TypeTag.UINT64], + [FeePerDAGas, feePerDaGas.toField()], + [FeePerL2Gas, feePerL2Gas.toField()], + ])('Environment getters instructions', (instrClass: GetterInstruction, value: Fr, tag: TypeTag = TypeTag.FIELD) => { + it(`${instrClass.name} should (de)serialize correctly`, () => { + const buf = Buffer.from([ + instrClass.opcode, // opcode + 0x01, // indirect + ...Buffer.from('12345678', 'hex'), // dstOffset + ]); + const instr = new instrClass(/*indirect=*/ 0x01, /*dstOffset=*/ 0x12345678); + + expect(instrClass.deserialize(buf)).toEqual(instr); + expect(instr.serialize()).toEqual(buf); + }); + it(`${instrClass.name} should read '${instrClass.type}' correctly`, async () => { + const instruction = new instrClass(/*indirect=*/ 0, /*dstOffset=*/ 0); - await instruction.execute(context); + await instruction.execute(context); - expect(context.machineState.memory.getTag(0)).toBe(tag); - const actual = context.machineState.memory.get(0).toFr(); - expect(actual).toEqual(value); + expect(context.machineState.memory.getTag(0)).toBe(tag); + const actual = context.machineState.memory.get(0).toFr(); + expect(actual).toEqual(value); + }); }); }); diff --git a/yarn-project/simulator/src/avm/opcodes/environment_getters.ts b/yarn-project/simulator/src/avm/opcodes/environment_getters.ts index 53dbb24cfe5..6373382acf6 100644 --- a/yarn-project/simulator/src/avm/opcodes/environment_getters.ts +++ b/yarn-project/simulator/src/avm/opcodes/environment_getters.ts @@ -1,6 +1,6 @@ import type { AvmContext } from '../avm_context.js'; import type { AvmExecutionEnvironment } from '../avm_execution_environment.js'; -import { Field, type MemoryValue, Uint64 } from '../avm_memory_types.js'; +import { Field, type MemoryValue, Uint32, Uint64 } from '../avm_memory_types.js'; import { Opcode } from '../serialization/instruction_serialization.js'; import { GetterInstruction } from './instruction_impl.js'; @@ -39,21 +39,12 @@ export class Sender extends EnvironmentGetterInstruction { } } -export class FeePerL2Gas extends EnvironmentGetterInstruction { - static type: string = 'FEEPERL2GAS'; - static readonly opcode: Opcode = Opcode.FEEPERL2GAS; - - protected getEnvironmentValue(env: AvmExecutionEnvironment) { - return new Field(env.feePerL2Gas); - } -} - -export class FeePerDAGas extends EnvironmentGetterInstruction { - static type: string = 'FEEPERDAGAS'; - static readonly opcode: Opcode = Opcode.FEEPERDAGAS; +export class FunctionSelector extends EnvironmentGetterInstruction { + static type: string = 'FUNCTIONSELECTOR'; + static readonly opcode: Opcode = Opcode.FUNCTIONSELECTOR; protected getEnvironmentValue(env: AvmExecutionEnvironment) { - return new Field(env.feePerDaGas); + return new Uint32(env.functionSelector.value); } } @@ -101,3 +92,21 @@ export class Timestamp extends EnvironmentGetterInstruction { return new Uint64(env.globals.timestamp.toBigInt()); } } + +export class FeePerL2Gas extends EnvironmentGetterInstruction { + static type: string = 'FEEPERL2GAS'; + static readonly opcode: Opcode = Opcode.FEEPERL2GAS; + + protected getEnvironmentValue(env: AvmExecutionEnvironment) { + return new Field(env.globals.gasFees.feePerL2Gas); + } +} + +export class FeePerDAGas extends EnvironmentGetterInstruction { + static type: string = 'FEEPERDAGAS'; + static readonly opcode: Opcode = Opcode.FEEPERDAGAS; + + protected getEnvironmentValue(env: AvmExecutionEnvironment) { + return new Field(env.globals.gasFees.feePerDaGas); + } +} diff --git a/yarn-project/simulator/src/avm/serialization/bytecode_serialization.test.ts b/yarn-project/simulator/src/avm/serialization/bytecode_serialization.test.ts index 82641334b25..4dd26fb13dd 100644 --- a/yarn-project/simulator/src/avm/serialization/bytecode_serialization.test.ts +++ b/yarn-project/simulator/src/avm/serialization/bytecode_serialization.test.ts @@ -84,7 +84,7 @@ describe('Bytecode Serialization', () => { /*retOffset=*/ 0xd2345678, /*retSize=*/ 0xe2345678, /*successOffset=*/ 0xf2345678, - /*temporaryFunctionSelectorOffset=*/ 0xf3345678, + /*functionSelectorOffset=*/ 0xf3345678, ), new StaticCall( /*indirect=*/ 0x01, @@ -95,7 +95,7 @@ describe('Bytecode Serialization', () => { /*retOffset=*/ 0xd2345678, /*retSize=*/ 0xe2345678, /*successOffset=*/ 0xf2345678, - /*temporaryFunctionSelectorOffset=*/ 0xf3345678, + /*functionSelectorOffset=*/ 0xf3345678, ), ]; const bytecode = Buffer.concat(instructions.map(i => i.serialize())); @@ -119,7 +119,7 @@ describe('Bytecode Serialization', () => { /*retOffset=*/ 0xd2345678, /*retSize=*/ 0xe2345678, /*successOffset=*/ 0xf2345678, - /*temporaryFunctionSelectorOffset=*/ 0xf3345678, + /*functionSelectorOffset=*/ 0xf3345678, ), new StaticCall( /*indirect=*/ 0x01, @@ -130,7 +130,7 @@ describe('Bytecode Serialization', () => { /*retOffset=*/ 0xd2345678, /*retSize=*/ 0xe2345678, /*successOffset=*/ 0xf2345678, - /*temporaryFunctionSelectorOffset=*/ 0xf3345678, + /*functionSelectorOffset=*/ 0xf3345678, ), ]; diff --git a/yarn-project/simulator/src/avm/serialization/bytecode_serialization.ts b/yarn-project/simulator/src/avm/serialization/bytecode_serialization.ts index f3afe05e088..c011b3a33cb 100644 --- a/yarn-project/simulator/src/avm/serialization/bytecode_serialization.ts +++ b/yarn-project/simulator/src/avm/serialization/bytecode_serialization.ts @@ -21,6 +21,7 @@ import { FeePerDAGas, FeePerL2Gas, FieldDiv, + FunctionSelector, GetContractInstance, InternalCall, InternalReturn, @@ -85,16 +86,16 @@ const INSTRUCTION_SET = () => [Address.opcode, Address], [StorageAddress.opcode, StorageAddress], [Sender.opcode, Sender], - [FeePerL2Gas.opcode, FeePerL2Gas], - [FeePerDAGas.opcode, FeePerDAGas], + [FunctionSelector.opcode, FunctionSelector], [TransactionFee.opcode, TransactionFee], - //[Contractcalldepth.opcode, Contractcalldepth], // Execution Environment - Globals [ChainId.opcode, ChainId], [Version.opcode, Version], [BlockNumber.opcode, BlockNumber], [Timestamp.opcode, Timestamp], //[Coinbase.opcode, Coinbase], + [FeePerL2Gas.opcode, FeePerL2Gas], + [FeePerDAGas.opcode, FeePerDAGas], //[Blockl2gaslimit.opcode, Blockl2gaslimit], //[Blockdagaslimit.opcode, Blockdagaslimit], // Execution Environment - Calldata diff --git a/yarn-project/simulator/src/avm/serialization/instruction_serialization.ts b/yarn-project/simulator/src/avm/serialization/instruction_serialization.ts index 0a4ee888fcf..27aa64d3e1f 100644 --- a/yarn-project/simulator/src/avm/serialization/instruction_serialization.ts +++ b/yarn-project/simulator/src/avm/serialization/instruction_serialization.ts @@ -27,15 +27,15 @@ export enum Opcode { ADDRESS, STORAGEADDRESS, SENDER, - FEEPERL2GAS, - FEEPERDAGAS, + FUNCTIONSELECTOR, TRANSACTIONFEE, - CONTRACTCALLDEPTH, CHAINID, VERSION, BLOCKNUMBER, TIMESTAMP, COINBASE, + FEEPERL2GAS, + FEEPERDAGAS, BLOCKL2GASLIMIT, BLOCKDAGASLIMIT, CALLDATACOPY, diff --git a/yarn-project/simulator/src/client/client_execution_context.ts b/yarn-project/simulator/src/client/client_execution_context.ts index 7da0e48928d..f8f78336619 100644 --- a/yarn-project/simulator/src/client/client_execution_context.ts +++ b/yarn-project/simulator/src/client/client_execution_context.ts @@ -678,16 +678,25 @@ export class ClientExecutionContext extends ViewDataOracle { /** * Read the public storage data. + * @param contractAddress - The address to read storage from. * @param startStorageSlot - The starting storage slot. + * @param blockNumber - The block number to read storage at. * @param numberOfElements - Number of elements to read from the starting storage slot. */ - public override async storageRead(startStorageSlot: Fr, numberOfElements: number): Promise { + public override async storageRead( + contractAddress: Fr, + startStorageSlot: Fr, + blockNumber: number, + numberOfElements: number, + ): Promise { const values = []; for (let i = 0n; i < numberOfElements; i++) { const storageSlot = new Fr(startStorageSlot.value + i); - const value = await this.aztecNode.getPublicStorageAt(this.callContext.storageContractAddress, storageSlot); - this.log.debug(`Oracle storage read: slot=${storageSlot.toString()} value=${value}`); + const value = await this.aztecNode.getPublicStorageAt(contractAddress, storageSlot, blockNumber); + this.log.debug( + `Oracle storage read: slot=${storageSlot.toString()} address-${contractAddress.toString()} value=${value}`, + ); values.push(value); } diff --git a/yarn-project/simulator/src/client/private_execution.test.ts b/yarn-project/simulator/src/client/private_execution.test.ts index c46153495fb..8b439279a91 100644 --- a/yarn-project/simulator/src/client/private_execution.test.ts +++ b/yarn-project/simulator/src/client/private_execution.test.ts @@ -2,6 +2,7 @@ import { type AztecNode, EncryptedNoteFunctionL2Logs, type L1ToL2Message, + type L2BlockNumber, Note, PackedValues, PublicDataWitness, @@ -67,7 +68,7 @@ import { MessageLoadOracleInputs } from '../acvm/index.js'; import { buildL1ToL2Message } from '../test/utils.js'; import { computeSlotForMapping } from '../utils.js'; import { type DBOracle } from './db_oracle.js'; -import { type ExecutionResult, collectSortedEncryptedLogs, collectSortedUnencryptedLogs } from './execution_result.js'; +import { type ExecutionResult, collectSortedEncryptedLogs } from './execution_result.js'; import { AcirSimulator } from './simulator.js'; jest.setTimeout(60_000); @@ -262,45 +263,16 @@ describe('Private Execution test suite', () => { ), ); + node = mock(); + // eslint-disable-next-line @typescript-eslint/no-unused-vars + node.getPublicStorageAt.mockImplementation((address: Fr, storageSlot: Fr, blockNumber: L2BlockNumber) => { + return Promise.resolve(Fr.ZERO); + }); + acirSimulator = new AcirSimulator(oracle, node); }); describe('no constructor', () => { - it('emits a field as an unencrypted log', async () => { - const artifact = getFunctionArtifact(TestContractArtifact, 'emit_msg_sender'); - const result = await runSimulator({ artifact, msgSender: owner }); - - const newUnencryptedLogs = getNonEmptyItems(result.callStackItem.publicInputs.unencryptedLogsHashes); - expect(newUnencryptedLogs).toHaveLength(1); - - const functionLogs = collectSortedUnencryptedLogs(result); - expect(functionLogs.logs).toHaveLength(1); - - const [unencryptedLog] = newUnencryptedLogs; - expect(unencryptedLog.value).toEqual(Fr.fromBuffer(functionLogs.logs[0].hash())); - expect(unencryptedLog.length).toEqual(new Fr(functionLogs.getKernelLength())); - // Test that the log payload (ie ignoring address, selector, and header) matches what we emitted - expect(functionLogs.logs[0].data.subarray(-32).toString('hex')).toEqual(owner.toBuffer().toString('hex')); - }); - - it('emits a field array as an unencrypted log', async () => { - const artifact = getFunctionArtifact(TestContractArtifact, 'emit_unencrypted_logs'); - const args = times(5, () => Fr.random()); - const result = await runSimulator({ artifact, msgSender: owner, args: [args, false] }); - - const newUnencryptedLogs = getNonEmptyItems(result.callStackItem.publicInputs.unencryptedLogsHashes); - expect(newUnencryptedLogs).toHaveLength(1); - const functionLogs = collectSortedUnencryptedLogs(result); - expect(functionLogs.logs).toHaveLength(1); - - const [unencryptedLog] = newUnencryptedLogs; - expect(unencryptedLog.value).toEqual(Fr.fromBuffer(functionLogs.logs[0].hash())); - expect(unencryptedLog.length).toEqual(new Fr(functionLogs.getKernelLength())); - // Test that the log payload (ie ignoring address, selector, and header) matches what we emitted - const expected = Buffer.concat(args.map(arg => arg.toBuffer())).toString('hex'); - expect(functionLogs.logs[0].data.subarray(-32 * 5).toString('hex')).toEqual(expected); - }); - it('emits a field array as an encrypted log', async () => { // NB: this test does NOT cover correct enc/dec of values, just whether // the kernels correctly populate non-note encrypted logs @@ -952,7 +924,7 @@ describe('Private Execution test suite', () => { describe('setting fee payer', () => { it('should default to not being a fee payer', async () => { // arbitrary random function that doesn't set a fee payer - const entrypoint = getFunctionArtifact(TestContractArtifact, 'emit_msg_sender'); + const entrypoint = getFunctionArtifact(TestContractArtifact, 'get_this_address'); const contractAddress = AztecAddress.random(); const result = await runSimulator({ artifact: entrypoint, contractAddress }); expect(result.callStackItem.publicInputs.isFeePayer).toBe(false); diff --git a/yarn-project/simulator/src/client/view_data_oracle.ts b/yarn-project/simulator/src/client/view_data_oracle.ts index fd1710205dc..75e7f180233 100644 --- a/yarn-project/simulator/src/client/view_data_oracle.ts +++ b/yarn-project/simulator/src/client/view_data_oracle.ts @@ -260,16 +260,25 @@ export class ViewDataOracle extends TypedOracle { /** * Read the public storage data. + * @param contractAddress - The address to read storage from. * @param startStorageSlot - The starting storage slot. + * @param blockNumber - The block number to read storage at. * @param numberOfElements - Number of elements to read from the starting storage slot. */ - public override async storageRead(startStorageSlot: Fr, numberOfElements: number) { + public override async storageRead( + contractAddress: Fr, + startStorageSlot: Fr, + blockNumber: number, + numberOfElements: number, + ) { const values = []; for (let i = 0n; i < numberOfElements; i++) { const storageSlot = new Fr(startStorageSlot.value + i); - const value = await this.aztecNode.getPublicStorageAt(this.contractAddress, storageSlot); + const value = await this.aztecNode.getPublicStorageAt(contractAddress, storageSlot, blockNumber); - this.log.debug(`Oracle storage read: slot=${storageSlot.toString()} value=${value}`); + this.log.debug( + `Oracle storage read: slot=${storageSlot.toString()} address-${contractAddress.toString()} value=${value}`, + ); values.push(value); } return values; diff --git a/yarn-project/simulator/src/public/executor.ts b/yarn-project/simulator/src/public/executor.ts index 3eefbba2dea..9a524c458c8 100644 --- a/yarn-project/simulator/src/public/executor.ts +++ b/yarn-project/simulator/src/public/executor.ts @@ -1,13 +1,5 @@ import { type AvmSimulationStats } from '@aztec/circuit-types/stats'; -import { - Fr, - Gas, - type GasSettings, - type GlobalVariables, - type Header, - type Nullifier, - type TxContext, -} from '@aztec/circuits.js'; +import { Fr, Gas, type GlobalVariables, type Header, type Nullifier, type TxContext } from '@aztec/circuits.js'; import { createDebugLogger } from '@aztec/foundation/log'; import { Timer } from '@aztec/foundation/timer'; @@ -18,7 +10,7 @@ import { AvmSimulator } from '../avm/avm_simulator.js'; import { HostStorage } from '../avm/journal/host_storage.js'; import { AvmPersistableStateManager } from '../avm/journal/index.js'; import { type CommitmentsDB, type PublicContractsDB, type PublicStateDB } from './db_interfaces.js'; -import { type PublicExecutionRequest, type PublicExecutionResult, checkValidStaticCall } from './execution.js'; +import { type PublicExecutionRequest, type PublicExecutionResult } from './execution.js'; import { PublicSideEffectTrace } from './side_effect_trace.js'; /** @@ -26,7 +18,7 @@ import { PublicSideEffectTrace } from './side_effect_trace.js'; */ export class PublicExecutor { constructor( - private readonly stateDb: PublicStateDB, + private readonly publicStorageDB: PublicStateDB, private readonly contractsDb: PublicContractsDB, private readonly commitmentsDb: CommitmentsDB, private readonly header: Header, @@ -49,7 +41,7 @@ export class PublicExecutor { executionRequest: PublicExecutionRequest, globalVariables: GlobalVariables, availableGas: Gas, - txContext: TxContext, + _txContext: TxContext, pendingSiloedNullifiers: Nullifier[], transactionFee: Fr = Fr.ZERO, startSideEffectCounter: number = 0, @@ -61,7 +53,7 @@ export class PublicExecutor { PublicExecutor.log.verbose(`[AVM] Executing public external function ${fnName}.`); const timer = new Timer(); - const hostStorage = new HostStorage(this.stateDb, this.contractsDb, this.commitmentsDb); + const hostStorage = new HostStorage(this.publicStorageDB, this.contractsDb, this.commitmentsDb); const trace = new PublicSideEffectTrace(startSideEffectCounter); const avmPersistableState = AvmPersistableStateManager.newWithPendingSiloedNullifiers( hostStorage, @@ -73,7 +65,6 @@ export class PublicExecutor { executionRequest, this.header, globalVariables, - txContext.gasSettings, transactionFee, ); @@ -83,7 +74,7 @@ export class PublicExecutor { const avmResult = await simulator.execute(); const bytecode = simulator.getBytecode()!; - // Commit the journals state to the DBs since this is a top-level execution. + // Commit the public storage state to the DBs since this is a top-level execution. // Observe that this will write all the state changes to the DBs, not only the latest for each slot. // However, the underlying DB keep a cache and will only write the latest state to disk. // TODO(dbanks12): this should be unnecessary here or should be exposed by state manager @@ -113,18 +104,6 @@ export class PublicExecutor { // (which counts the request itself) ); - // TODO(https://github.com/AztecProtocol/aztec-packages/issues/5818): is this really needed? - // should already be handled in simulation. - if (executionRequest.callContext.isStaticCall) { - checkValidStaticCall( - publicExecutionResult.newNoteHashes, - publicExecutionResult.newNullifiers, - publicExecutionResult.contractStorageUpdateRequests, - publicExecutionResult.newL2ToL1Messages, - publicExecutionResult.unencryptedLogs, - ); - } - return publicExecutionResult; } } @@ -140,23 +119,19 @@ function createAvmExecutionEnvironment( executionRequest: PublicExecutionRequest, header: Header, globalVariables: GlobalVariables, - gasSettings: GasSettings, transactionFee: Fr, ): AvmExecutionEnvironment { return new AvmExecutionEnvironment( executionRequest.contractAddress, executionRequest.callContext.storageContractAddress, executionRequest.callContext.msgSender, - globalVariables.gasFees.feePerL2Gas, - globalVariables.gasFees.feePerDaGas, + executionRequest.functionSelector, /*contractCallDepth=*/ Fr.zero(), + transactionFee, header, globalVariables, executionRequest.callContext.isStaticCall, executionRequest.callContext.isDelegateCall, executionRequest.args, - gasSettings, - transactionFee, - executionRequest.functionSelector, ); } diff --git a/yarn-project/simulator/src/public/public_kernel.ts b/yarn-project/simulator/src/public/public_kernel.ts index c48c9ed4512..6910123b54e 100644 --- a/yarn-project/simulator/src/public/public_kernel.ts +++ b/yarn-project/simulator/src/public/public_kernel.ts @@ -21,8 +21,9 @@ import { convertSimulatedPublicTeardownInputsToWitnessMap, convertSimulatedPublicTeardownOutputFromWitnessMap, } from '@aztec/noir-protocol-circuits-types'; -import { type SimulationProvider, WASMSimulator } from '@aztec/simulator'; +import { WASMSimulator } from '../providers/acvm_wasm.js'; +import { type SimulationProvider } from '../providers/simulation_provider.js'; import { type PublicKernelCircuitSimulator } from './public_kernel_circuit_simulator.js'; /** diff --git a/yarn-project/simulator/src/rollup/rollup.ts b/yarn-project/simulator/src/rollup/rollup.ts index 114873499a7..58c72653d8f 100644 --- a/yarn-project/simulator/src/rollup/rollup.ts +++ b/yarn-project/simulator/src/rollup/rollup.ts @@ -28,7 +28,9 @@ import { convertSimulatedBaseRollupInputsToWitnessMap, convertSimulatedBaseRollupOutputsFromWitnessMap, } from '@aztec/noir-protocol-circuits-types'; -import { type SimulationProvider, WASMSimulator } from '@aztec/simulator'; + +import { WASMSimulator } from '../providers/acvm_wasm.js'; +import { type SimulationProvider } from '../providers/simulation_provider.js'; /** * Circuit simulator for the rollup circuits. diff --git a/yarn-project/tsconfig.json b/yarn-project/tsconfig.json index 52b02c625b2..68777079e4a 100644 --- a/yarn-project/tsconfig.json +++ b/yarn-project/tsconfig.json @@ -16,7 +16,8 @@ "resolveJsonModule": true, "composite": true, "skipLibCheck": true, - "noImplicitOverride": true + "noImplicitOverride": true, + "allowArbitraryExtensions": true }, "references": [ { "path": "accounts/tsconfig.json" }, @@ -50,5 +51,5 @@ { "path": "cli/tsconfig.json" } ], "files": ["./@types/jest/index.d.ts"], - "exclude": ["node_modules"] + "exclude": ["node_modules", "**/node_modules", "**/.*/"] } diff --git a/yarn-project/txe/src/oracle/txe_oracle.ts b/yarn-project/txe/src/oracle/txe_oracle.ts index 567bf0a656d..eb805c21d08 100644 --- a/yarn-project/txe/src/oracle/txe_oracle.ts +++ b/yarn-project/txe/src/oracle/txe_oracle.ts @@ -434,13 +434,18 @@ export class TXE implements TypedOracle { throw new Error('Method not implemented.'); } - async storageRead(startStorageSlot: Fr, numberOfElements: number): Promise { + async storageRead( + contractAddress: Fr, + startStorageSlot: Fr, + blockNumber: number, // TODO(#7230): use block number + numberOfElements: number, + ): Promise { const db = this.trees.asLatest(); const values = []; for (let i = 0n; i < numberOfElements; i++) { const storageSlot = startStorageSlot.add(new Fr(i)); - const leafSlot = computePublicDataTreeLeafSlot(this.contractAddress, storageSlot).toBigInt(); + const leafSlot = computePublicDataTreeLeafSlot(contractAddress, storageSlot).toBigInt(); const lowLeafResult = await db.getPreviousValueIndex(MerkleTreeId.PUBLIC_DATA_TREE, leafSlot); diff --git a/yarn-project/txe/src/txe_service/txe_service.ts b/yarn-project/txe/src/txe_service/txe_service.ts index de25cc81299..bfd99bd74d1 100644 --- a/yarn-project/txe/src/txe_service/txe_service.ts +++ b/yarn-project/txe/src/txe_service/txe_service.ts @@ -308,9 +308,16 @@ export class TXEService { return toForeignCallResult([]); } - async storageRead(startStorageSlot: ForeignCallSingle, numberOfElements: ForeignCallSingle) { + async storageRead( + contractAddress: ForeignCallSingle, + startStorageSlot: ForeignCallSingle, + blockNumber: ForeignCallSingle, + numberOfElements: ForeignCallSingle, + ) { const values = await this.typedOracle.storageRead( + fromSingle(contractAddress), fromSingle(startStorageSlot), + fromSingle(blockNumber).toNumber(), fromSingle(numberOfElements).toNumber(), ); return toForeignCallResult([toArray(values)]); diff --git a/yarn-project/types/src/noir/index.ts b/yarn-project/types/src/noir/index.ts index 7361d6687db..41b860a3719 100644 --- a/yarn-project/types/src/noir/index.ts +++ b/yarn-project/types/src/noir/index.ts @@ -18,6 +18,8 @@ export const AZTEC_VIEW_ATTRIBUTE = 'aztec(view)'; export interface NoirFunctionAbi { /** The parameters of the function. */ parameters: ABIParameter[]; + /** TODO */ + error_types: Record; /** The return type of the function. */ return_type: { /**