diff --git a/circuits/cpp/src/aztec3/circuits/abis/c_bind.cpp b/circuits/cpp/src/aztec3/circuits/abis/c_bind.cpp index 688a63351cc..ee3d32c326e 100644 --- a/circuits/cpp/src/aztec3/circuits/abis/c_bind.cpp +++ b/circuits/cpp/src/aztec3/circuits/abis/c_bind.cpp @@ -524,6 +524,13 @@ WASM_EXPORT const char* abis__test_roundtrip_serialize_private_circuit_public_in size); } +WASM_EXPORT const char* abis__test_roundtrip_serialize_public_circuit_public_inputs( + uint8_t const* public_circuits_public_inputs_buf, uint32_t* size) +{ + return as_string_output>(public_circuits_public_inputs_buf, + size); +} + WASM_EXPORT const char* abis__test_roundtrip_serialize_function_data(uint8_t const* function_data_buf, uint32_t* size) { return as_string_output>(function_data_buf, size); diff --git a/circuits/cpp/src/aztec3/circuits/abis/historic_block_data.hpp b/circuits/cpp/src/aztec3/circuits/abis/historic_block_data.hpp index 417a79a9388..43ab18e1d93 100644 --- a/circuits/cpp/src/aztec3/circuits/abis/historic_block_data.hpp +++ b/circuits/cpp/src/aztec3/circuits/abis/historic_block_data.hpp @@ -9,6 +9,8 @@ #include +#include + namespace aztec3::circuits::abis { using aztec3::utils::types::CircuitTypes; @@ -96,6 +98,18 @@ template struct HistoricBlockData { global_variables_hash.set_public(); } + std::array to_array() const + { + return { private_data_tree_root, + nullifier_tree_root, + contract_tree_root, + l1_to_l2_messages_tree_root, + blocks_tree_root, // Note private_kernel_vk_tree_root, is not included yet as + // it is not present in noir, + public_data_tree_root, + global_variables_hash }; + } + fr hash() { diff --git a/circuits/cpp/src/aztec3/circuits/abis/packers.hpp b/circuits/cpp/src/aztec3/circuits/abis/packers.hpp index e32d0689692..8c125d860c4 100644 --- a/circuits/cpp/src/aztec3/circuits/abis/packers.hpp +++ b/circuits/cpp/src/aztec3/circuits/abis/packers.hpp @@ -68,7 +68,7 @@ struct ConstantsPacker { MAX_NOTES_PER_PAGE, VIEW_NOTE_ORACLE_RETURN_LENGTH, CALL_CONTEXT_LENGTH, - CONSTANT_HISTORIC_BLOCK_DATA_LENGTH, + HISTORIC_BLOCK_DATA_LENGTH, FUNCTION_DATA_LENGTH, CONTRACT_DEPLOYMENT_DATA_LENGTH, PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH, diff --git a/circuits/cpp/src/aztec3/circuits/abis/private_circuit_public_inputs.hpp b/circuits/cpp/src/aztec3/circuits/abis/private_circuit_public_inputs.hpp index 89b09358218..64a7c4db195 100644 --- a/circuits/cpp/src/aztec3/circuits/abis/private_circuit_public_inputs.hpp +++ b/circuits/cpp/src/aztec3/circuits/abis/private_circuit_public_inputs.hpp @@ -50,8 +50,8 @@ template class PrivateCircuitPublicInputs { fr historic_contract_tree_root = 0; fr historic_l1_to_l2_messages_tree_root = 0; fr historic_blocks_tree_root = 0; - fr historic_global_variables_hash = 0; fr historic_public_data_tree_root = 0; + fr historic_global_variables_hash = 0; ContractDeploymentData contract_deployment_data{}; @@ -78,8 +78,8 @@ template class PrivateCircuitPublicInputs { historic_contract_tree_root, historic_l1_to_l2_messages_tree_root, historic_blocks_tree_root, - historic_global_variables_hash, historic_public_data_tree_root, + historic_global_variables_hash, contract_deployment_data, chain_id, version); @@ -100,8 +100,8 @@ template class PrivateCircuitPublicInputs { historic_contract_tree_root == other.historic_contract_tree_root && historic_l1_to_l2_messages_tree_root == other.historic_l1_to_l2_messages_tree_root && historic_blocks_tree_root == other.historic_blocks_tree_root && - historic_global_variables_hash == other.historic_global_variables_hash && historic_public_data_tree_root == other.historic_public_data_tree_root && + historic_global_variables_hash == other.historic_global_variables_hash && contract_deployment_data == other.contract_deployment_data && chain_id == other.chain_id && version == other.version; }; @@ -142,8 +142,8 @@ template class PrivateCircuitPublicInputs { to_ct(historic_contract_tree_root), to_ct(historic_l1_to_l2_messages_tree_root), to_ct(historic_blocks_tree_root), - to_ct(historic_global_variables_hash), to_ct(historic_public_data_tree_root), + to_ct(historic_global_variables_hash), to_circuit_type(contract_deployment_data), @@ -187,8 +187,8 @@ template class PrivateCircuitPublicInputs { to_nt(historic_contract_tree_root), to_nt(historic_l1_to_l2_messages_tree_root), to_nt(historic_blocks_tree_root), - to_nt(historic_global_variables_hash), to_nt(historic_public_data_tree_root), + to_nt(historic_global_variables_hash), to_native_type(contract_deployment_data), @@ -231,8 +231,8 @@ template class PrivateCircuitPublicInputs { inputs.push_back(historic_contract_tree_root); inputs.push_back(historic_l1_to_l2_messages_tree_root); inputs.push_back(historic_blocks_tree_root); - inputs.push_back(historic_global_variables_hash); inputs.push_back(historic_public_data_tree_root); + inputs.push_back(historic_global_variables_hash); inputs.push_back(contract_deployment_data.hash()); @@ -287,8 +287,8 @@ template class OptionalPrivateCircuitPublicInputs { opt_fr historic_contract_tree_root; opt_fr historic_l1_to_l2_messages_tree_root; opt_fr historic_blocks_tree_root; - opt_fr historic_global_variables_hash; opt_fr historic_public_data_tree_root; + opt_fr historic_global_variables_hash; std::optional> contract_deployment_data; @@ -315,8 +315,8 @@ template class OptionalPrivateCircuitPublicInputs { historic_contract_tree_root, historic_l1_to_l2_messages_tree_root, historic_blocks_tree_root, - historic_global_variables_hash, historic_public_data_tree_root, + historic_global_variables_hash, contract_deployment_data, chain_id, version); @@ -350,8 +350,8 @@ template class OptionalPrivateCircuitPublicInputs { opt_fr const& historic_contract_tree_root, opt_fr const& historic_l1_to_l2_messages_tree_root, opt_fr const& historic_blocks_tree_root, - opt_fr const& historic_global_variables_hash, opt_fr const& historic_public_data_tree_root, + opt_fr const& historic_global_variables_hash, std::optional> const& contract_deployment_data, @@ -376,8 +376,8 @@ template class OptionalPrivateCircuitPublicInputs { , historic_contract_tree_root(historic_contract_tree_root) , historic_l1_to_l2_messages_tree_root(historic_l1_to_l2_messages_tree_root) , historic_blocks_tree_root(historic_blocks_tree_root) - , historic_global_variables_hash(historic_global_variables_hash) , historic_public_data_tree_root(historic_public_data_tree_root) + , historic_global_variables_hash(historic_global_variables_hash) , contract_deployment_data(contract_deployment_data) , chain_id(chain_id) , version(version){}; @@ -414,8 +414,8 @@ template class OptionalPrivateCircuitPublicInputs { new_inputs.historic_contract_tree_root = std::nullopt; new_inputs.historic_l1_to_l2_messages_tree_root = std::nullopt; new_inputs.historic_blocks_tree_root = std::nullopt; - new_inputs.historic_global_variables_hash = std::nullopt; new_inputs.historic_public_data_tree_root = std::nullopt; + new_inputs.historic_global_variables_hash = std::nullopt; new_inputs.contract_deployment_data = std::nullopt; @@ -485,8 +485,8 @@ template class OptionalPrivateCircuitPublicInputs { make_unused_element_zero(builder, historic_contract_tree_root); make_unused_element_zero(builder, historic_l1_to_l2_messages_tree_root); make_unused_element_zero(builder, historic_blocks_tree_root); - make_unused_element_zero(builder, historic_global_variables_hash); make_unused_element_zero(builder, historic_public_data_tree_root); + make_unused_element_zero(builder, historic_global_variables_hash); make_unused_element_zero(builder, contract_deployment_data); @@ -530,8 +530,8 @@ template class OptionalPrivateCircuitPublicInputs { (*historic_contract_tree_root).set_public(); (*historic_l1_to_l2_messages_tree_root).set_public(); (*historic_blocks_tree_root).set_public(); - (*historic_global_variables_hash).set_public(); (*historic_public_data_tree_root).set_public(); + (*historic_global_variables_hash).set_public(); (*contract_deployment_data).set_public(); @@ -577,8 +577,8 @@ template class OptionalPrivateCircuitPublicInputs { to_ct(historic_contract_tree_root), to_ct(historic_l1_to_l2_messages_tree_root), to_ct(historic_blocks_tree_root), - to_ct(historic_global_variables_hash), to_ct(historic_public_data_tree_root), + to_ct(historic_global_variables_hash), to_circuit_type(contract_deployment_data), @@ -624,8 +624,8 @@ template class OptionalPrivateCircuitPublicInputs { to_nt(historic_contract_tree_root), to_nt(historic_l1_to_l2_messages_tree_root), to_nt(historic_blocks_tree_root), - to_nt(historic_global_variables_hash), to_nt(historic_public_data_tree_root), + to_nt(historic_global_variables_hash), to_native_type(contract_deployment_data), @@ -672,8 +672,8 @@ template class OptionalPrivateCircuitPublicInputs { inputs.push_back(*historic_contract_tree_root); inputs.push_back(*historic_l1_to_l2_messages_tree_root); inputs.push_back(*historic_blocks_tree_root); - inputs.push_back(*historic_global_variables_hash); inputs.push_back(*historic_public_data_tree_root); + inputs.push_back(*historic_global_variables_hash); inputs.push_back((*contract_deployment_data).hash()); @@ -715,8 +715,8 @@ template class OptionalPrivateCircuitPublicInputs { .historic_contract_tree_root = historic_contract_tree_root.value(), .historic_l1_to_l2_messages_tree_root = historic_l1_to_l2_messages_tree_root.value(), .historic_blocks_tree_root = historic_blocks_tree_root.value(), - .historic_global_variables_hash = historic_global_variables_hash.value(), .historic_public_data_tree_root = historic_public_data_tree_root.value(), + .historic_global_variables_hash = historic_global_variables_hash.value(), .contract_deployment_data = contract_deployment_data.value(), diff --git a/circuits/cpp/src/aztec3/circuits/abis/public_circuit_public_inputs.hpp b/circuits/cpp/src/aztec3/circuits/abis/public_circuit_public_inputs.hpp index ba9d7a954e8..863292fd208 100644 --- a/circuits/cpp/src/aztec3/circuits/abis/public_circuit_public_inputs.hpp +++ b/circuits/cpp/src/aztec3/circuits/abis/public_circuit_public_inputs.hpp @@ -5,6 +5,7 @@ #include "contract_storage_update_request.hpp" #include "../../constants.hpp" +#include "aztec3/circuits/abis/historic_block_data.hpp" #include "aztec3/utils/msgpack_derived_output.hpp" #include "aztec3/utils/types/circuit_types.hpp" #include "aztec3/utils/types/native_types.hpp" @@ -42,7 +43,7 @@ template struct PublicCircuitPublicInputs { // variable-length data. fr unencrypted_log_preimages_length = 0; - fr historic_public_data_tree_root = 0; + HistoricBlockData historic_block_data{}; address prover_address; @@ -58,7 +59,7 @@ template struct PublicCircuitPublicInputs { new_l2_to_l1_msgs, unencrypted_logs_hash, unencrypted_log_preimages_length, - historic_public_data_tree_root, + historic_block_data, prover_address); boolean operator==(PublicCircuitPublicInputs const& other) const @@ -91,7 +92,7 @@ template struct PublicCircuitPublicInputs { .unencrypted_logs_hash = to_ct(unencrypted_logs_hash), .unencrypted_log_preimages_length = to_ct(unencrypted_log_preimages_length), - .historic_public_data_tree_root = to_ct(historic_public_data_tree_root), + .historic_block_data = to_ct(historic_block_data), .prover_address = to_ct(prover_address), }; @@ -121,7 +122,7 @@ template struct PublicCircuitPublicInputs { spread_arr_into_vec(unencrypted_logs_hash, inputs); inputs.push_back(unencrypted_log_preimages_length); - inputs.push_back(historic_public_data_tree_root); + spread_arr_into_vec(historic_block_data.to_array(), inputs); inputs.push_back(prover_address); if (inputs.size() != PUBLIC_CIRCUIT_PUBLIC_INPUTS_HASH_INPUT_LENGTH) { diff --git a/circuits/cpp/src/aztec3/circuits/kernel/public/.test.cpp b/circuits/cpp/src/aztec3/circuits/kernel/public/.test.cpp index f0175204823..643c0a137c9 100644 --- a/circuits/cpp/src/aztec3/circuits/kernel/public/.test.cpp +++ b/circuits/cpp/src/aztec3/circuits/kernel/public/.test.cpp @@ -326,7 +326,16 @@ PublicKernelInputs get_kernel_inputs_with_previous_kernel(NT::boolean privat std::array const unencrypted_logs_hash = array_of_values(seed, NUM_FIELDS_PER_SHA256); fr const unencrypted_log_preimages_length = ++seed; - fr const historic_public_data_tree_root = ++seed; + HistoricBlockData block_data = { + .private_data_tree_root = ++seed, + .nullifier_tree_root = ++seed, + .contract_tree_root = ++seed, + .l1_to_l2_messages_tree_root = ++seed, + .blocks_tree_root = ++seed, + .private_kernel_vk_tree_root = ++seed, + .public_data_tree_root = ++seed, + .global_variables_hash = ++seed, + }; // create the public circuit public inputs auto const public_circuit_public_inputs = PublicCircuitPublicInputs{ @@ -341,7 +350,7 @@ PublicKernelInputs get_kernel_inputs_with_previous_kernel(NT::boolean privat .new_l2_to_l1_msgs = new_l2_to_l1_msgs, .unencrypted_logs_hash = unencrypted_logs_hash, .unencrypted_log_preimages_length = unencrypted_log_preimages_length, - .historic_public_data_tree_root = historic_public_data_tree_root, + .historic_block_data = block_data, }; const PublicCallStackItem call_stack_item{ diff --git a/circuits/cpp/src/aztec3/circuits/kernel/public/native_public_kernel_circuit_private_previous_kernel.cpp b/circuits/cpp/src/aztec3/circuits/kernel/public/native_public_kernel_circuit_private_previous_kernel.cpp index a3887e48304..fa5b8f2563b 100644 --- a/circuits/cpp/src/aztec3/circuits/kernel/public/native_public_kernel_circuit_private_previous_kernel.cpp +++ b/circuits/cpp/src/aztec3/circuits/kernel/public/native_public_kernel_circuit_private_previous_kernel.cpp @@ -62,7 +62,7 @@ KernelCircuitPublicInputs native_public_kernel_circuit_private_previous_kern // validate the kernel execution common to all invocation circumstances common_validate_kernel_execution(builder, public_kernel_inputs); - // vallidate our public call hash + // validate our public call hash validate_this_public_call_hash(builder, public_kernel_inputs, public_inputs); // update the public end state of the circuit diff --git a/circuits/cpp/src/aztec3/constants.hpp b/circuits/cpp/src/aztec3/constants.hpp index 82f3d324277..0baa59f5d9c 100644 --- a/circuits/cpp/src/aztec3/constants.hpp +++ b/circuits/cpp/src/aztec3/constants.hpp @@ -221,7 +221,7 @@ constexpr size_t VIEW_NOTE_ORACLE_RETURN_LENGTH = MAX_NOTES_PER_PAGE * (MAX_NOTE constexpr size_t CALL_CONTEXT_LENGTH = 6; // Must be updated if any data is added into the block hash calculation. -constexpr size_t CONSTANT_HISTORIC_BLOCK_DATA_LENGTH = 7; +constexpr size_t HISTORIC_BLOCK_DATA_LENGTH = 7; constexpr size_t FUNCTION_DATA_LENGTH = 4; constexpr size_t CONTRACT_DEPLOYMENT_DATA_LENGTH = 6; @@ -233,14 +233,14 @@ constexpr size_t PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH = + RETURN_VALUES_LENGTH + MAX_READ_REQUESTS_PER_CALL + MAX_NEW_COMMITMENTS_PER_CALL + 2 * MAX_NEW_NULLIFIERS_PER_CALL + MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL + MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL + MAX_NEW_L2_TO_L1_MSGS_PER_CALL + NUM_FIELDS_PER_SHA256 + NUM_FIELDS_PER_SHA256 + 2 // + 2 for logs preimage lengths - + CONSTANT_HISTORIC_BLOCK_DATA_LENGTH + CONTRACT_DEPLOYMENT_DATA_LENGTH + 2; // + 2 for chain_id and version + + HISTORIC_BLOCK_DATA_LENGTH + CONTRACT_DEPLOYMENT_DATA_LENGTH + 2; // + 2 for chain_id and version constexpr size_t PRIVATE_CIRCUIT_PUBLIC_INPUTS_HASH_INPUT_LENGTH = 1 + 1 // call_context_hash + args_hash + RETURN_VALUES_LENGTH + MAX_READ_REQUESTS_PER_CALL + MAX_NEW_COMMITMENTS_PER_CALL + 2 * MAX_NEW_NULLIFIERS_PER_CALL + MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL + MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL + MAX_NEW_L2_TO_L1_MSGS_PER_CALL + NUM_FIELDS_PER_SHA256 + NUM_FIELDS_PER_SHA256 + 2 // + 2 for logs preimage lengths - + CONSTANT_HISTORIC_BLOCK_DATA_LENGTH + 3; // + 3 for contract_deployment_data.hash(), chain_id, version + + HISTORIC_BLOCK_DATA_LENGTH + 3; // + 3 for contract_deployment_data.hash(), chain_id, version constexpr size_t CONTRACT_STORAGE_UPDATE_REQUEST_LENGTH = 3; constexpr size_t CONTRACT_STORAGE_READ_LENGTH = 2; @@ -251,15 +251,15 @@ constexpr size_t PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH = MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL * CONTRACT_STORAGE_UPDATE_REQUEST_LENGTH + MAX_PUBLIC_DATA_READS_PER_CALL * CONTRACT_STORAGE_READ_LENGTH + MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL + MAX_NEW_COMMITMENTS_PER_CALL + MAX_NEW_NULLIFIERS_PER_CALL + MAX_NEW_L2_TO_L1_MSGS_PER_CALL + - NUM_FIELDS_PER_SHA256 + 1 + // + 1 for unencrypted logs preimage length - CONSTANT_HISTORIC_BLOCK_DATA_LENGTH + 2; // + 2 for chain_id and version + NUM_FIELDS_PER_SHA256 + 1 + // + 1 for unencrypted logs preimage length + HISTORIC_BLOCK_DATA_LENGTH + 2; // + 2 for chain_id and version constexpr size_t PUBLIC_CIRCUIT_PUBLIC_INPUTS_HASH_INPUT_LENGTH = 2 + RETURN_VALUES_LENGTH + // + 1 for args_hash + 1 call_context.hash MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL + MAX_PUBLIC_DATA_READS_PER_CALL + MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL + MAX_NEW_COMMITMENTS_PER_CALL + MAX_NEW_NULLIFIERS_PER_CALL + MAX_NEW_L2_TO_L1_MSGS_PER_CALL + - NUM_FIELDS_PER_SHA256 + // unencrypted_logs_hash (being represented by NUM_FIELDS_PER_SHA256) - 3; // unencrypted_log_preimages_length + historic_public_data_tree_root + prover_address + NUM_FIELDS_PER_SHA256 + // unencrypted_logs_hash (being represented by NUM_FIELDS_PER_SHA256) + HISTORIC_BLOCK_DATA_LENGTH + 2; // unencrypted_log_preimages_length + prover_address // Size of the return value of a private function call, diff --git a/l1-contracts/src/core/libraries/ConstantsGen.sol b/l1-contracts/src/core/libraries/ConstantsGen.sol index 0c540095c66..c6d6dea7c43 100644 --- a/l1-contracts/src/core/libraries/ConstantsGen.sol +++ b/l1-contracts/src/core/libraries/ConstantsGen.sol @@ -65,7 +65,7 @@ library Constants { uint256 internal constant MAX_NOTES_PER_PAGE = 10; uint256 internal constant VIEW_NOTE_ORACLE_RETURN_LENGTH = 212; uint256 internal constant CALL_CONTEXT_LENGTH = 6; - uint256 internal constant CONSTANT_HISTORIC_BLOCK_DATA_LENGTH = 7; + uint256 internal constant HISTORIC_BLOCK_DATA_LENGTH = 7; uint256 internal constant FUNCTION_DATA_LENGTH = 4; uint256 internal constant CONTRACT_DEPLOYMENT_DATA_LENGTH = 6; uint256 internal constant PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH = 58; @@ -75,7 +75,7 @@ library Constants { uint256 internal constant GET_NOTES_ORACLE_RETURN_LENGTH = 86; uint256 internal constant EMPTY_NULLIFIED_COMMITMENT = 1000000; uint256 internal constant CALL_PRIVATE_FUNCTION_RETURN_SIZE = 64; - uint256 internal constant PUBLIC_CIRCUIT_PUBLIC_INPUTS_HASH_INPUT_LENGTH = 41; + uint256 internal constant PUBLIC_CIRCUIT_PUBLIC_INPUTS_HASH_INPUT_LENGTH = 47; uint256 internal constant PRIVATE_CIRCUIT_PUBLIC_INPUTS_HASH_INPUT_LENGTH = 48; uint256 internal constant COMMITMENTS_NUM_BYTES_PER_BASE_ROLLUP = 1024; uint256 internal constant NULLIFIERS_NUM_BYTES_PER_BASE_ROLLUP = 1024; diff --git a/yarn-project/acir-simulator/src/acvm/deserialize.ts b/yarn-project/acir-simulator/src/acvm/deserialize.ts index 40f46cbb7ed..99d5498ff07 100644 --- a/yarn-project/acir-simulator/src/acvm/deserialize.ts +++ b/yarn-project/acir-simulator/src/acvm/deserialize.ts @@ -1,19 +1,26 @@ import { CallContext, ContractDeploymentData, + ContractStorageRead, + ContractStorageUpdateRequest, + HistoricBlockData, MAX_NEW_COMMITMENTS_PER_CALL, MAX_NEW_L2_TO_L1_MSGS_PER_CALL, MAX_NEW_NULLIFIERS_PER_CALL, MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, + MAX_PUBLIC_DATA_READS_PER_CALL, + MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, MAX_READ_REQUESTS_PER_CALL, NUM_FIELDS_PER_SHA256, PrivateCircuitPublicInputs, + PublicCircuitPublicInputs, RETURN_VALUES_LENGTH, } from '@aztec/circuits.js'; import { AztecAddress } from '@aztec/foundation/aztec-address'; import { EthAddress } from '@aztec/foundation/eth-address'; import { Fr, Point } from '@aztec/foundation/fields'; +import { Tuple } from '@aztec/foundation/serialize'; import { getReturnWitness } from 'acvm_js'; @@ -96,12 +103,12 @@ export class PublicInputsReader { * @param length - The length of the array. * @returns The array of fields. */ - public readFieldArray(length: number): Fr[] { + public readFieldArray(length: N): Tuple { const array: Fr[] = []; for (let i = 0; i < length; i++) { array.push(this.readField()); } - return array; + return array as Tuple; } } @@ -111,7 +118,10 @@ export class PublicInputsReader { * @param acir - The ACIR bytecode. * @returns The public inputs. */ -export function extractPublicInputs(partialWitness: ACVMWitness, acir: Buffer): PrivateCircuitPublicInputs { +export function extractPrivateCircuitPublicInputs( + partialWitness: ACVMWitness, + acir: Buffer, +): PrivateCircuitPublicInputs { const witnessReader = new PublicInputsReader(partialWitness, acir); const callContext = new CallContext( @@ -184,3 +194,81 @@ export function extractPublicInputs(partialWitness: ACVMWitness, acir: Buffer): version, ); } + +/** + * Extracts the public circuit public inputs from the ACVM generated partial witness. + * @param partialWitness - The partial witness. + * @param acir - The ACIR bytecode. + * @returns The public inputs. + */ +export function extractPublicCircuitPublicInputs(partialWitness: ACVMWitness, acir: Buffer): PublicCircuitPublicInputs { + const witnessReader = new PublicInputsReader(partialWitness, acir); + + const callContext = new CallContext( + frToAztecAddress(witnessReader.readField()), + frToAztecAddress(witnessReader.readField()), + witnessReader.readField(), + frToBoolean(witnessReader.readField()), + frToBoolean(witnessReader.readField()), + frToBoolean(witnessReader.readField()), + ); + + const argsHash = witnessReader.readField(); + const returnValues = witnessReader.readFieldArray(RETURN_VALUES_LENGTH); + + const contractStorageUpdateRequests = new Array(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL).fill( + ContractStorageUpdateRequest.empty(), + ); + for (let i = 0; i < MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL; i++) { + const request = new ContractStorageUpdateRequest( + witnessReader.readField(), + witnessReader.readField(), + witnessReader.readField(), + ); + contractStorageUpdateRequests[i] = request; + } + const contractStorageReads = new Array(MAX_PUBLIC_DATA_READS_PER_CALL).fill(ContractStorageRead.empty()); + for (let i = 0; i < MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL; i++) { + const request = new ContractStorageRead(witnessReader.readField(), witnessReader.readField()); + contractStorageReads[i] = request; + } + + const publicCallStack = witnessReader.readFieldArray(MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL); + const newCommitments = witnessReader.readFieldArray(MAX_NEW_COMMITMENTS_PER_CALL); + const newNullifiers = witnessReader.readFieldArray(MAX_NEW_NULLIFIERS_PER_CALL); + const newL2ToL1Msgs = witnessReader.readFieldArray(MAX_NEW_L2_TO_L1_MSGS_PER_CALL); + + const unencryptedLogsHash = witnessReader.readFieldArray(NUM_FIELDS_PER_SHA256); + const unencryptedLogPreimagesLength = witnessReader.readField(); + + const historicBlockData = new HistoricBlockData( + witnessReader.readField(), + witnessReader.readField(), + witnessReader.readField(), + witnessReader.readField(), + witnessReader.readField(), + Fr.ZERO, + witnessReader.readField(), + witnessReader.readField(), + ); + const proverAddress = AztecAddress.fromField(witnessReader.readField()); + + return new PublicCircuitPublicInputs( + callContext, + argsHash, + returnValues, + contractStorageUpdateRequests as Tuple< + ContractStorageUpdateRequest, + typeof MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL + >, + contractStorageReads as Tuple, + publicCallStack, + newCommitments, + newNullifiers, + newL2ToL1Msgs, + unencryptedLogsHash, + unencryptedLogPreimagesLength, + historicBlockData, + proverAddress, + ); +} diff --git a/yarn-project/acir-simulator/src/client/private_execution.ts b/yarn-project/acir-simulator/src/client/private_execution.ts index 03da34d109d..e10ccb6098a 100644 --- a/yarn-project/acir-simulator/src/client/private_execution.ts +++ b/yarn-project/acir-simulator/src/client/private_execution.ts @@ -13,7 +13,7 @@ import { createDebugLogger } from '@aztec/foundation/log'; import { to2Fields } from '@aztec/foundation/serialize'; import { FunctionL2Logs, NotePreimage, NoteSpendingInfo } from '@aztec/types'; -import { extractPublicInputs, frToAztecAddress, frToSelector } from '../acvm/deserialize.js'; +import { extractPrivateCircuitPublicInputs, frToAztecAddress, frToSelector } from '../acvm/deserialize.js'; import { ZERO_ACVM_FIELD, acvm, @@ -53,7 +53,7 @@ export class PrivateFunctionExecution { this.log(`Executing external function ${this.contractAddress.toString()}:${selector}`); const acir = Buffer.from(this.abi.bytecode, 'base64'); - const initialWitness = this.writeInputs(); + const initialWitness = this.getInitialWitness(); // TODO: Move to ClientTxExecutionContext. const newNotePreimages: NewNoteData[] = []; @@ -174,7 +174,7 @@ export class PrivateFunctionExecution { }, }); - const publicInputs = extractPublicInputs(partialWitness, acir); + const publicInputs = extractPrivateCircuitPublicInputs(partialWitness, acir); // TODO(https://github.com/AztecProtocol/aztec-packages/issues/1165) --> set this in Noir publicInputs.encryptedLogsHash = to2Fields(encryptedLogs.hash()); @@ -213,7 +213,7 @@ export class PrivateFunctionExecution { * Writes the function inputs to the initial witness. * @returns The initial witness. */ - private writeInputs() { + private getInitialWitness() { const contractDeploymentData = this.context.txContext.contractDeploymentData ?? ContractDeploymentData.empty(); const blockData = this.context.historicBlockData; @@ -231,8 +231,8 @@ export class PrivateFunctionExecution { blockData.contractTreeRoot, blockData.l1ToL2MessagesTreeRoot, blockData.blocksTreeRoot, - blockData.globalVariablesHash, blockData.publicDataTreeRoot, + blockData.globalVariablesHash, contractDeploymentData.deployerPublicKey.x, contractDeploymentData.deployerPublicKey.y, diff --git a/yarn-project/acir-simulator/src/public/executor.ts b/yarn-project/acir-simulator/src/public/executor.ts index 996f892de4a..5276e84d0b3 100644 --- a/yarn-project/acir-simulator/src/public/executor.ts +++ b/yarn-project/acir-simulator/src/public/executor.ts @@ -15,7 +15,7 @@ import { ZERO_ACVM_FIELD, acvm, convertACVMFieldToBuffer, - extractReturnWitness, + extractPublicCircuitPublicInputs, frToAztecAddress, frToSelector, fromACVMField, @@ -160,7 +160,7 @@ export class PublicExecutor { }, }); - const returnValues = extractReturnWitness(acir, partialWitness).map(fromACVMField); + const { returnValues } = extractPublicCircuitPublicInputs(partialWitness, acir); const [contractStorageReads, contractStorageUpdateRequests] = storageActions.collect(); diff --git a/yarn-project/acir-simulator/src/public/index.test.ts b/yarn-project/acir-simulator/src/public/index.test.ts index 1e9a72308b1..eb59fa34d44 100644 --- a/yarn-project/acir-simulator/src/public/index.test.ts +++ b/yarn-project/acir-simulator/src/public/index.test.ts @@ -85,7 +85,7 @@ describe('ACIR public execution simulator', () => { const result = await executor.execute(execution, GlobalVariables.empty()); const expectedBalance = new Fr(160n); - expect(result.returnValues).toEqual([expectedBalance]); + expect(result.returnValues[0]).toEqual(expectedBalance); const storageSlot = computeSlotForMapping(new Fr(1n), recipient.toField(), circuitsWasm); expect(result.contractStorageUpdateRequests).toEqual([ @@ -154,7 +154,7 @@ describe('ACIR public execution simulator', () => { const expectedRecipientBalance = new Fr(160n); const expectedSenderBalance = new Fr(60n); - expect(result.returnValues).toEqual([expectedRecipientBalance]); + expect(result.returnValues[0]).toEqual(expectedRecipientBalance); expect(result.contractStorageUpdateRequests).toEqual([ { storageSlot: senderStorageSlot, oldValue: senderBalance, newValue: expectedSenderBalance }, @@ -174,7 +174,7 @@ describe('ACIR public execution simulator', () => { const result = await executor.execute(execution, GlobalVariables.empty()); - expect(result.returnValues).toEqual([recipientBalance]); + expect(result.returnValues[0]).toEqual(recipientBalance); expect(result.contractStorageReads).toEqual([ { storageSlot: recipientStorageSlot, value: recipientBalance }, @@ -245,7 +245,7 @@ describe('ACIR public execution simulator', () => { } else { const result = await executor.execute(execution, globalVariables); - expect(result.returnValues).toEqual([ + expect(result.returnValues[0]).toEqual( new Fr( initialValue + globalVariables.chainId.value + @@ -253,7 +253,7 @@ describe('ACIR public execution simulator', () => { globalVariables.blockNumber.value + globalVariables.timestamp.value, ), - ]); + ); } }, 20_000, diff --git a/yarn-project/aztec.js/src/abis/ecdsa_account_contract.json b/yarn-project/aztec.js/src/abis/ecdsa_account_contract.json index 34eecee9402..3b1c5f54ec1 100644 --- a/yarn-project/aztec.js/src/abis/ecdsa_account_contract.json +++ b/yarn-project/aztec.js/src/abis/ecdsa_account_contract.json @@ -152,7 +152,7 @@ } ], "returnTypes": [], - "bytecode": "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", + "bytecode": "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", "verificationKey": "0000000200000800000000740000000f00000003515f3109623eb3c25aa5b16a1a79fd558bac7a7ce62c4560a8c537c77ce80dd339128d1d37b6582ee9e6df9567efb64313471dfa18f520f9ce53161b50dbf7731bc5f900000003515f322bc4cce83a486a92c92fd59bd84e0f92595baa639fc2ed86b00ffa0dfded2a092a669a3bdb7a273a015eda494457cc7ed5236f26cee330c290d45a33b9daa94800000003515f332729426c008c085a81bd34d8ef12dd31e80130339ef99d50013a89e4558eee6d0fa4ffe2ee7b7b62eb92608b2251ac31396a718f9b34978888789042b790a30100000003515f342be6b6824a913eb7a57b03cb1ee7bfb4de02f2f65fe8a4e97baa7766ddb353a82a8a25c49dc63778cd9fe96173f12a2bc77f3682f4c4448f98f1df82c75234a100000003515f351f85760d6ab567465aadc2f180af9eae3800e6958fec96aef53fd8a7b195d7c000c6267a0dd5cfc22b3fe804f53e266069c0e36f51885baec1e7e67650c62e170000000c515f41524954484d455449430d9d0f8ece2aa12012fa21e6e5c859e97bd5704e5c122064a66051294bc5e04213f61f54a0ebdf6fee4d4a6ecf693478191de0c2899bcd8e86a636c8d3eff43400000003515f43224a99d02c86336737c8dd5b746c40d2be6aead8393889a76a18d664029096e90f7fe81adcc92a74350eada9622ac453f49ebac24a066a1f83b394df54dfa0130000000c515f46495845445f42415345060e8a013ed289c2f9fd7473b04f6594b138ddb4b4cf6b901622a14088f04b8d2c83ff74fce56e3d5573b99c7b26d85d5046ce0c6559506acb7a675e7713eb3a00000007515f4c4f4749430721a91cb8da4b917e054f72147e1760cfe0ef3d45090ac0f4961d84ec1996961a25e787b26bd8b50b1a99450f77a424a83513c2b33af268cd253b0587ff50c700000003515f4d05dbd8623b8652511e1eb38d38887a69eceb082f807514f09e127237c5213b401b9325b48c6c225968002318095f89d0ef9cf629b2b7f0172e03bc39aacf6ed800000007515f52414e474504b57a3805e41df328f5ca9aefa40fad5917391543b7b65c6476e60b8f72e9ad07c92f3b3e11c8feae96dedc4b14a6226ef3201244f37cfc1ee5b96781f48d2b000000075349474d415f3125001d1954a18571eaa007144c5a567bb0d2be4def08a8be918b8c05e3b27d312c59ed41e09e144eab5de77ca89a2fd783be702a47c951d3112e3de02ce6e47c000000075349474d415f3223994e6a23618e60fa01c449a7ab88378709197e186d48d604bfb6931ffb15ad11c5ec7a0700570f80088fd5198ab5d5c227f2ad2a455a6edeec024156bb7beb000000075349474d415f3300cda5845f23468a13275d18bddae27c6bb189cf9aa95b6a03a0cb6688c7e8d829639b45cf8607c525cc400b55ebf90205f2f378626dc3406cc59b2d1b474fba000000075349474d415f342d299e7928496ea2d37f10b43afd6a80c90a33b483090d18069ffa275eedb2fc2f82121e8de43dc036d99b478b6227ceef34248939987a19011f065d8b5cef5c0000000010000000000000000100000002000000030000000400000005000000060000000700000008000000090000000a0000000b0000000c0000000d0000000e0000000f" } ] diff --git a/yarn-project/aztec.js/src/abis/schnorr_account_contract.json b/yarn-project/aztec.js/src/abis/schnorr_account_contract.json index b644dceb9a2..7a0f83664a7 100644 --- a/yarn-project/aztec.js/src/abis/schnorr_account_contract.json +++ b/yarn-project/aztec.js/src/abis/schnorr_account_contract.json @@ -140,7 +140,7 @@ } ], "returnTypes": [], - "bytecode": "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", + "bytecode": "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", "verificationKey": "0000000200000800000000740000000f00000003515f3109623eb3c25aa5b16a1a79fd558bac7a7ce62c4560a8c537c77ce80dd339128d1d37b6582ee9e6df9567efb64313471dfa18f520f9ce53161b50dbf7731bc5f900000003515f322bc4cce83a486a92c92fd59bd84e0f92595baa639fc2ed86b00ffa0dfded2a092a669a3bdb7a273a015eda494457cc7ed5236f26cee330c290d45a33b9daa94800000003515f332729426c008c085a81bd34d8ef12dd31e80130339ef99d50013a89e4558eee6d0fa4ffe2ee7b7b62eb92608b2251ac31396a718f9b34978888789042b790a30100000003515f342be6b6824a913eb7a57b03cb1ee7bfb4de02f2f65fe8a4e97baa7766ddb353a82a8a25c49dc63778cd9fe96173f12a2bc77f3682f4c4448f98f1df82c75234a100000003515f351f85760d6ab567465aadc2f180af9eae3800e6958fec96aef53fd8a7b195d7c000c6267a0dd5cfc22b3fe804f53e266069c0e36f51885baec1e7e67650c62e170000000c515f41524954484d455449430d9d0f8ece2aa12012fa21e6e5c859e97bd5704e5c122064a66051294bc5e04213f61f54a0ebdf6fee4d4a6ecf693478191de0c2899bcd8e86a636c8d3eff43400000003515f43224a99d02c86336737c8dd5b746c40d2be6aead8393889a76a18d664029096e90f7fe81adcc92a74350eada9622ac453f49ebac24a066a1f83b394df54dfa0130000000c515f46495845445f42415345060e8a013ed289c2f9fd7473b04f6594b138ddb4b4cf6b901622a14088f04b8d2c83ff74fce56e3d5573b99c7b26d85d5046ce0c6559506acb7a675e7713eb3a00000007515f4c4f4749430721a91cb8da4b917e054f72147e1760cfe0ef3d45090ac0f4961d84ec1996961a25e787b26bd8b50b1a99450f77a424a83513c2b33af268cd253b0587ff50c700000003515f4d05dbd8623b8652511e1eb38d38887a69eceb082f807514f09e127237c5213b401b9325b48c6c225968002318095f89d0ef9cf629b2b7f0172e03bc39aacf6ed800000007515f52414e474504b57a3805e41df328f5ca9aefa40fad5917391543b7b65c6476e60b8f72e9ad07c92f3b3e11c8feae96dedc4b14a6226ef3201244f37cfc1ee5b96781f48d2b000000075349474d415f3125001d1954a18571eaa007144c5a567bb0d2be4def08a8be918b8c05e3b27d312c59ed41e09e144eab5de77ca89a2fd783be702a47c951d3112e3de02ce6e47c000000075349474d415f3223994e6a23618e60fa01c449a7ab88378709197e186d48d604bfb6931ffb15ad11c5ec7a0700570f80088fd5198ab5d5c227f2ad2a455a6edeec024156bb7beb000000075349474d415f3300cda5845f23468a13275d18bddae27c6bb189cf9aa95b6a03a0cb6688c7e8d829639b45cf8607c525cc400b55ebf90205f2f378626dc3406cc59b2d1b474fba000000075349474d415f342d299e7928496ea2d37f10b43afd6a80c90a33b483090d18069ffa275eedb2fc2f82121e8de43dc036d99b478b6227ceef34248939987a19011f065d8b5cef5c0000000010000000000000000100000002000000030000000400000005000000060000000700000008000000090000000a0000000b0000000c0000000d0000000e0000000f" } ] diff --git a/yarn-project/aztec.js/src/abis/schnorr_single_key_account_contract.json b/yarn-project/aztec.js/src/abis/schnorr_single_key_account_contract.json index 7c6243b45be..b74a7de8350 100644 --- a/yarn-project/aztec.js/src/abis/schnorr_single_key_account_contract.json +++ b/yarn-project/aztec.js/src/abis/schnorr_single_key_account_contract.json @@ -95,7 +95,7 @@ } ], "returnTypes": [], - "bytecode": "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", + "bytecode": "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", "verificationKey": "0000000200000800000000740000000f00000003515f3109623eb3c25aa5b16a1a79fd558bac7a7ce62c4560a8c537c77ce80dd339128d1d37b6582ee9e6df9567efb64313471dfa18f520f9ce53161b50dbf7731bc5f900000003515f322bc4cce83a486a92c92fd59bd84e0f92595baa639fc2ed86b00ffa0dfded2a092a669a3bdb7a273a015eda494457cc7ed5236f26cee330c290d45a33b9daa94800000003515f332729426c008c085a81bd34d8ef12dd31e80130339ef99d50013a89e4558eee6d0fa4ffe2ee7b7b62eb92608b2251ac31396a718f9b34978888789042b790a30100000003515f342be6b6824a913eb7a57b03cb1ee7bfb4de02f2f65fe8a4e97baa7766ddb353a82a8a25c49dc63778cd9fe96173f12a2bc77f3682f4c4448f98f1df82c75234a100000003515f351f85760d6ab567465aadc2f180af9eae3800e6958fec96aef53fd8a7b195d7c000c6267a0dd5cfc22b3fe804f53e266069c0e36f51885baec1e7e67650c62e170000000c515f41524954484d455449430d9d0f8ece2aa12012fa21e6e5c859e97bd5704e5c122064a66051294bc5e04213f61f54a0ebdf6fee4d4a6ecf693478191de0c2899bcd8e86a636c8d3eff43400000003515f43224a99d02c86336737c8dd5b746c40d2be6aead8393889a76a18d664029096e90f7fe81adcc92a74350eada9622ac453f49ebac24a066a1f83b394df54dfa0130000000c515f46495845445f42415345060e8a013ed289c2f9fd7473b04f6594b138ddb4b4cf6b901622a14088f04b8d2c83ff74fce56e3d5573b99c7b26d85d5046ce0c6559506acb7a675e7713eb3a00000007515f4c4f4749430721a91cb8da4b917e054f72147e1760cfe0ef3d45090ac0f4961d84ec1996961a25e787b26bd8b50b1a99450f77a424a83513c2b33af268cd253b0587ff50c700000003515f4d05dbd8623b8652511e1eb38d38887a69eceb082f807514f09e127237c5213b401b9325b48c6c225968002318095f89d0ef9cf629b2b7f0172e03bc39aacf6ed800000007515f52414e474504b57a3805e41df328f5ca9aefa40fad5917391543b7b65c6476e60b8f72e9ad07c92f3b3e11c8feae96dedc4b14a6226ef3201244f37cfc1ee5b96781f48d2b000000075349474d415f3125001d1954a18571eaa007144c5a567bb0d2be4def08a8be918b8c05e3b27d312c59ed41e09e144eab5de77ca89a2fd783be702a47c951d3112e3de02ce6e47c000000075349474d415f3223994e6a23618e60fa01c449a7ab88378709197e186d48d604bfb6931ffb15ad11c5ec7a0700570f80088fd5198ab5d5c227f2ad2a455a6edeec024156bb7beb000000075349474d415f3300cda5845f23468a13275d18bddae27c6bb189cf9aa95b6a03a0cb6688c7e8d829639b45cf8607c525cc400b55ebf90205f2f378626dc3406cc59b2d1b474fba000000075349474d415f342d299e7928496ea2d37f10b43afd6a80c90a33b483090d18069ffa275eedb2fc2f82121e8de43dc036d99b478b6227ceef34248939987a19011f065d8b5cef5c0000000010000000000000000100000002000000030000000400000005000000060000000700000008000000090000000a0000000b0000000c0000000d0000000e0000000f" } ] diff --git a/yarn-project/canary/src/uniswap_trade_on_l1_from_l2.test.ts b/yarn-project/canary/src/uniswap_trade_on_l1_from_l2.test.ts index 264c1e41821..cf2e0031773 100644 --- a/yarn-project/canary/src/uniswap_trade_on_l1_from_l2.test.ts +++ b/yarn-project/canary/src/uniswap_trade_on_l1_from_l2.test.ts @@ -137,10 +137,7 @@ async function deployAllContracts( }; } -const getL2BalanceOf = async ( - owner: AztecAddress, - l2Contract: NonNativeTokenContract -) => { +const getL2BalanceOf = async (owner: AztecAddress, l2Contract: NonNativeTokenContract) => { return await l2Contract.methods.getBalance(owner).view({ from: owner }); }; diff --git a/yarn-project/circuits.js/src/cbind/circuits.gen.ts b/yarn-project/circuits.js/src/cbind/circuits.gen.ts index df4a2887b20..943da3019e6 100644 --- a/yarn-project/circuits.js/src/cbind/circuits.gen.ts +++ b/yarn-project/circuits.js/src/cbind/circuits.gen.ts @@ -1243,7 +1243,7 @@ interface MsgpackPublicCircuitPublicInputs { new_l2_to_l1_msgs: Tuple; unencrypted_logs_hash: Tuple; unencrypted_log_preimages_length: Buffer; - historic_public_data_tree_root: Buffer; + historic_block_data: MsgpackHistoricBlockData; prover_address: Buffer; } @@ -1281,8 +1281,8 @@ export function toPublicCircuitPublicInputs(o: MsgpackPublicCircuitPublicInputs) if (o.unencrypted_log_preimages_length === undefined) { throw new Error('Expected unencrypted_log_preimages_length in PublicCircuitPublicInputs deserialization'); } - if (o.historic_public_data_tree_root === undefined) { - throw new Error('Expected historic_public_data_tree_root in PublicCircuitPublicInputs deserialization'); + if (o.historic_block_data === undefined) { + throw new Error('Expected historic_block_data in PublicCircuitPublicInputs deserialization'); } if (o.prover_address === undefined) { throw new Error('Expected prover_address in PublicCircuitPublicInputs deserialization'); @@ -1301,7 +1301,7 @@ export function toPublicCircuitPublicInputs(o: MsgpackPublicCircuitPublicInputs) mapTuple(o.new_l2_to_l1_msgs, (v: Buffer) => Fr.fromBuffer(v)), mapTuple(o.unencrypted_logs_hash, (v: Buffer) => Fr.fromBuffer(v)), Fr.fromBuffer(o.unencrypted_log_preimages_length), - Fr.fromBuffer(o.historic_public_data_tree_root), + toHistoricBlockData(o.historic_block_data), Address.fromBuffer(o.prover_address), ); } @@ -1340,8 +1340,8 @@ export function fromPublicCircuitPublicInputs(o: PublicCircuitPublicInputs): Msg if (o.unencryptedLogPreimagesLength === undefined) { throw new Error('Expected unencryptedLogPreimagesLength in PublicCircuitPublicInputs serialization'); } - if (o.historicPublicDataTreeRoot === undefined) { - throw new Error('Expected historicPublicDataTreeRoot in PublicCircuitPublicInputs serialization'); + if (o.historicBlockData === undefined) { + throw new Error('Expected historicBlockData in PublicCircuitPublicInputs serialization'); } if (o.proverAddress === undefined) { throw new Error('Expected proverAddress in PublicCircuitPublicInputs serialization'); @@ -1360,7 +1360,7 @@ export function fromPublicCircuitPublicInputs(o: PublicCircuitPublicInputs): Msg new_l2_to_l1_msgs: mapTuple(o.newL2ToL1Msgs, (v: Fr) => toBuffer(v)), unencrypted_logs_hash: mapTuple(o.unencryptedLogsHash, (v: Fr) => toBuffer(v)), unencrypted_log_preimages_length: toBuffer(o.unencryptedLogPreimagesLength), - historic_public_data_tree_root: toBuffer(o.historicPublicDataTreeRoot), + historic_block_data: fromHistoricBlockData(o.historicBlockData), prover_address: toBuffer(o.proverAddress), }; } diff --git a/yarn-project/circuits.js/src/cbind/constants.gen.ts b/yarn-project/circuits.js/src/cbind/constants.gen.ts index b3441f962e1..8d5718bb67e 100644 --- a/yarn-project/circuits.js/src/cbind/constants.gen.ts +++ b/yarn-project/circuits.js/src/cbind/constants.gen.ts @@ -51,7 +51,7 @@ export const GET_NOTE_ORACLE_RETURN_LENGTH = 23; export const MAX_NOTES_PER_PAGE = 10; export const VIEW_NOTE_ORACLE_RETURN_LENGTH = 212; export const CALL_CONTEXT_LENGTH = 6; -export const CONSTANT_HISTORIC_BLOCK_DATA_LENGTH = 7; +export const HISTORIC_BLOCK_DATA_LENGTH = 7; export const FUNCTION_DATA_LENGTH = 4; export const CONTRACT_DEPLOYMENT_DATA_LENGTH = 6; export const PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH = 58; @@ -61,7 +61,7 @@ export const PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH = 77; export const GET_NOTES_ORACLE_RETURN_LENGTH = 86; export const EMPTY_NULLIFIED_COMMITMENT = 1000000; export const CALL_PRIVATE_FUNCTION_RETURN_SIZE = 64; -export const PUBLIC_CIRCUIT_PUBLIC_INPUTS_HASH_INPUT_LENGTH = 41; +export const PUBLIC_CIRCUIT_PUBLIC_INPUTS_HASH_INPUT_LENGTH = 47; export const PRIVATE_CIRCUIT_PUBLIC_INPUTS_HASH_INPUT_LENGTH = 48; export const COMMITMENTS_NUM_BYTES_PER_BASE_ROLLUP = 1024; export const NULLIFIERS_NUM_BYTES_PER_BASE_ROLLUP = 1024; diff --git a/yarn-project/circuits.js/src/structs/__snapshots__/private_circuit_public_inputs.test.ts.snap b/yarn-project/circuits.js/src/structs/__snapshots__/private_circuit_public_inputs.test.ts.snap index 2c2419e786b..88f16d51e30 100644 --- a/yarn-project/circuits.js/src/structs/__snapshots__/private_circuit_public_inputs.test.ts.snap +++ b/yarn-project/circuits.js/src/structs/__snapshots__/private_circuit_public_inputs.test.ts.snap @@ -27,8 +27,8 @@ historic_nullifier_tree_root: 0xf00 historic_contract_tree_root: 0xd00 historic_l1_to_l2_messages_tree_root: 0x1000 historic_blocks_tree_root: 0x1100 -historic_global_variables_hash: 0x1200 -historic_public_data_tree_root: 0x1300 +historic_public_data_tree_root: 0x1200 +historic_global_variables_hash: 0x1300 contract_deployment_data: deployer_public_key: x: 0x1 y: 0x2 diff --git a/yarn-project/circuits.js/src/structs/__snapshots__/public_circuit_public_inputs.test.ts.snap b/yarn-project/circuits.js/src/structs/__snapshots__/public_circuit_public_inputs.test.ts.snap new file mode 100644 index 00000000000..b9d35e7016f --- /dev/null +++ b/yarn-project/circuits.js/src/structs/__snapshots__/public_circuit_public_inputs.test.ts.snap @@ -0,0 +1,73 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`basic PublicCircuitPublicInputs serialization serializes a trivial PublicCircuitPublicInputs and prints it 1`] = ` +"call_context: +msg_sender: 0x0 +storage_contract_address: 0x1 +portal_contract_address: 0x202020202020202020202020202020202020202 +is_delegate_call: 0 +is_static_call: 0 +is_contract_deployment: 0 + +args_hash: 0x100 +return_values: [ 0x200 0x201 0x0 0x0 ] +contract_storage_update_requests: [ storage_slot: 0x400 +old_value: 0x401 +new_value: 0x402 + storage_slot: 0x401 +old_value: 0x402 +new_value: 0x403 + storage_slot: 0x402 +old_value: 0x403 +new_value: 0x404 + storage_slot: 0x403 +old_value: 0x404 +new_value: 0x405 + storage_slot: 0x0 +old_value: 0x1 +new_value: 0x2 + storage_slot: 0x0 +old_value: 0x1 +new_value: 0x2 + storage_slot: 0x0 +old_value: 0x1 +new_value: 0x2 + storage_slot: 0x0 +old_value: 0x1 +new_value: 0x2 + ] +contract_storage_reads: [ storage_slot: 0x500 +current_value: 0x501 + storage_slot: 0x501 +current_value: 0x502 + storage_slot: 0x502 +current_value: 0x503 + storage_slot: 0x503 +current_value: 0x504 + storage_slot: 0x0 +current_value: 0x1 + storage_slot: 0x0 +current_value: 0x1 + storage_slot: 0x0 +current_value: 0x1 + storage_slot: 0x0 +current_value: 0x1 + ] +public_call_stack: [ 0x600 0x601 0x0 0x0 ] +new_commitments: [ 0x700 0x701 0x0 0x0 ] +new_nullifiers: [ 0x800 0x801 0x0 0x0 ] +new_l2_to_l1_msgs: [ 0x900 0x0 ] +unencrypted_logs_hash: [ 0x901 0x0 ] +unencrypted_log_preimages_length: 0x902 +historic_block_data: private_data_tree_root: 0xa00 +nullifier_tree_root: 0xa01 +contract_tree_root: 0xa02 +l1_to_l2_messages_tree_root: 0xa03 +blocks_tree_root: 0xa04 +private_kernel_vk_tree_root: 0xa05 +public_data_tree_root: 0xa06 +global_variables_hash: 0xa07 + +prover_address: 0xb01 +" +`; diff --git a/yarn-project/circuits.js/src/structs/kernel/__snapshots__/index.test.ts.snap b/yarn-project/circuits.js/src/structs/kernel/__snapshots__/index.test.ts.snap index b1284b63e80..c5fcc831466 100644 --- a/yarn-project/circuits.js/src/structs/kernel/__snapshots__/index.test.ts.snap +++ b/yarn-project/circuits.js/src/structs/kernel/__snapshots__/index.test.ts.snap @@ -481,8 +481,8 @@ historic_nullifier_tree_root: 0x1f11 historic_contract_tree_root: 0x1d11 historic_l1_to_l2_messages_tree_root: 0x2011 historic_blocks_tree_root: 0x2111 -historic_global_variables_hash: 0x2211 -historic_public_data_tree_root: 0x2311 +historic_public_data_tree_root: 0x2211 +historic_global_variables_hash: 0x2311 contract_deployment_data: deployer_public_key: x: 0x1 y: 0x2 @@ -529,8 +529,8 @@ historic_nullifier_tree_root: 0x1f21 historic_contract_tree_root: 0x1d21 historic_l1_to_l2_messages_tree_root: 0x2021 historic_blocks_tree_root: 0x2121 -historic_global_variables_hash: 0x2221 -historic_public_data_tree_root: 0x2321 +historic_public_data_tree_root: 0x2221 +historic_global_variables_hash: 0x2321 contract_deployment_data: deployer_public_key: x: 0x1 y: 0x2 @@ -576,8 +576,8 @@ historic_nullifier_tree_root: 0x1f22 historic_contract_tree_root: 0x1d22 historic_l1_to_l2_messages_tree_root: 0x2022 historic_blocks_tree_root: 0x2122 -historic_global_variables_hash: 0x2222 -historic_public_data_tree_root: 0x2322 +historic_public_data_tree_root: 0x2222 +historic_global_variables_hash: 0x2322 contract_deployment_data: deployer_public_key: x: 0x1 y: 0x2 @@ -623,8 +623,8 @@ historic_nullifier_tree_root: 0x1f23 historic_contract_tree_root: 0x1d23 historic_l1_to_l2_messages_tree_root: 0x2023 historic_blocks_tree_root: 0x2123 -historic_global_variables_hash: 0x2223 -historic_public_data_tree_root: 0x2323 +historic_public_data_tree_root: 0x2223 +historic_global_variables_hash: 0x2323 contract_deployment_data: deployer_public_key: x: 0x1 y: 0x2 @@ -670,8 +670,8 @@ historic_nullifier_tree_root: 0x1f24 historic_contract_tree_root: 0x1d24 historic_l1_to_l2_messages_tree_root: 0x2024 historic_blocks_tree_root: 0x2124 -historic_global_variables_hash: 0x2224 -historic_public_data_tree_root: 0x2324 +historic_public_data_tree_root: 0x2224 +historic_global_variables_hash: 0x2324 contract_deployment_data: deployer_public_key: x: 0x1 y: 0x2 @@ -990,8 +990,8 @@ historic_nullifier_tree_root: 0x1f11 historic_contract_tree_root: 0x1d11 historic_l1_to_l2_messages_tree_root: 0x2011 historic_blocks_tree_root: 0x2111 -historic_global_variables_hash: 0x2211 -historic_public_data_tree_root: 0x2311 +historic_public_data_tree_root: 0x2211 +historic_global_variables_hash: 0x2311 contract_deployment_data: deployer_public_key: x: 0x1 y: 0x2 @@ -1038,8 +1038,8 @@ historic_nullifier_tree_root: 0x1f21 historic_contract_tree_root: 0x1d21 historic_l1_to_l2_messages_tree_root: 0x2021 historic_blocks_tree_root: 0x2121 -historic_global_variables_hash: 0x2221 -historic_public_data_tree_root: 0x2321 +historic_public_data_tree_root: 0x2221 +historic_global_variables_hash: 0x2321 contract_deployment_data: deployer_public_key: x: 0x1 y: 0x2 @@ -1085,8 +1085,8 @@ historic_nullifier_tree_root: 0x1f22 historic_contract_tree_root: 0x1d22 historic_l1_to_l2_messages_tree_root: 0x2022 historic_blocks_tree_root: 0x2122 -historic_global_variables_hash: 0x2222 -historic_public_data_tree_root: 0x2322 +historic_public_data_tree_root: 0x2222 +historic_global_variables_hash: 0x2322 contract_deployment_data: deployer_public_key: x: 0x1 y: 0x2 @@ -1132,8 +1132,8 @@ historic_nullifier_tree_root: 0x1f23 historic_contract_tree_root: 0x1d23 historic_l1_to_l2_messages_tree_root: 0x2023 historic_blocks_tree_root: 0x2123 -historic_global_variables_hash: 0x2223 -historic_public_data_tree_root: 0x2323 +historic_public_data_tree_root: 0x2223 +historic_global_variables_hash: 0x2323 contract_deployment_data: deployer_public_key: x: 0x1 y: 0x2 @@ -1179,8 +1179,8 @@ historic_nullifier_tree_root: 0x1f24 historic_contract_tree_root: 0x1d24 historic_l1_to_l2_messages_tree_root: 0x2024 historic_blocks_tree_root: 0x2124 -historic_global_variables_hash: 0x2224 -historic_public_data_tree_root: 0x2324 +historic_public_data_tree_root: 0x2224 +historic_global_variables_hash: 0x2324 contract_deployment_data: deployer_public_key: x: 0x1 y: 0x2 @@ -1743,13 +1743,21 @@ current_value: 0x1 storage_slot: 0x0 current_value: 0x1 ] -public_call_stack: [ 0x136824172dbc34c53430101e3a04e1ab503cebad18c5bfa6c529af15d79e8843 0x1b21b2e1c216fccf7b51f75cf1f98de9945755ee23ab1dd6336b5513a64befaa 0x143ce8bf3701eb9f520cf686440db29c7a5385ebc6543bfcbbc0c8ea589ef1c1 0x1093a857092bc1ce7d1ca2fe1cd9216294429424b63f76513e3a5be183095ade ] +public_call_stack: [ 0x969e86085622075da29cdba0432a18b67fbcf164a5dda8785cba8f4bf5cdd8d 0xe8aef22899a38f44f2b48fc12f51d0f0bd3146f15aae6a4e3de529e9daccf0b 0xb87bacccf7202cd576213b03d15dd98585c697de6571d5c37e915b8a35460c1 0x2f4095e46083b42757f0f7aabedc690037044e8ad4464d02a27ebd89d2ddf464 ] new_commitments: [ 0x1711 0x1712 0x0 0x0 ] new_nullifiers: [ 0x1811 0x1812 0x0 0x0 ] new_l2_to_l1_msgs: [ 0x1911 0x0 ] unencrypted_logs_hash: [ 0x1912 0x0 ] unencrypted_log_preimages_length: 0x1913 -historic_public_data_tree_root: 0x1a11 +historic_block_data: private_data_tree_root: 0x1a11 +nullifier_tree_root: 0x1a12 +contract_tree_root: 0x1a13 +l1_to_l2_messages_tree_root: 0x1a14 +blocks_tree_root: 0x1a15 +private_kernel_vk_tree_root: 0x1a16 +public_data_tree_root: 0x1a17 +global_variables_hash: 0x1a18 + prover_address: 0x1b12 is_execution_request: 0 @@ -1818,7 +1826,15 @@ new_nullifiers: [ 0x1b11 0x1b12 0x0 0x0 ] new_l2_to_l1_msgs: [ 0x1c11 0x0 ] unencrypted_logs_hash: [ 0x1c12 0x0 ] unencrypted_log_preimages_length: 0x1c13 -historic_public_data_tree_root: 0x1d11 +historic_block_data: private_data_tree_root: 0x1d11 +nullifier_tree_root: 0x1d12 +contract_tree_root: 0x1d13 +l1_to_l2_messages_tree_root: 0x1d14 +blocks_tree_root: 0x1d15 +private_kernel_vk_tree_root: 0x1d16 +public_data_tree_root: 0x1d17 +global_variables_hash: 0x1d18 + prover_address: 0x1e12 is_execution_request: 0 @@ -1886,7 +1902,15 @@ new_nullifiers: [ 0x1b12 0x1b13 0x0 0x0 ] new_l2_to_l1_msgs: [ 0x1c12 0x0 ] unencrypted_logs_hash: [ 0x1c13 0x0 ] unencrypted_log_preimages_length: 0x1c14 -historic_public_data_tree_root: 0x1d12 +historic_block_data: private_data_tree_root: 0x1d12 +nullifier_tree_root: 0x1d13 +contract_tree_root: 0x1d14 +l1_to_l2_messages_tree_root: 0x1d15 +blocks_tree_root: 0x1d16 +private_kernel_vk_tree_root: 0x1d17 +public_data_tree_root: 0x1d18 +global_variables_hash: 0x1d19 + prover_address: 0x1e13 is_execution_request: 0 @@ -1954,7 +1978,15 @@ new_nullifiers: [ 0x1b13 0x1b14 0x0 0x0 ] new_l2_to_l1_msgs: [ 0x1c13 0x0 ] unencrypted_logs_hash: [ 0x1c14 0x0 ] unencrypted_log_preimages_length: 0x1c15 -historic_public_data_tree_root: 0x1d13 +historic_block_data: private_data_tree_root: 0x1d13 +nullifier_tree_root: 0x1d14 +contract_tree_root: 0x1d15 +l1_to_l2_messages_tree_root: 0x1d16 +blocks_tree_root: 0x1d17 +private_kernel_vk_tree_root: 0x1d18 +public_data_tree_root: 0x1d19 +global_variables_hash: 0x1d1a + prover_address: 0x1e14 is_execution_request: 0 @@ -2022,7 +2054,15 @@ new_nullifiers: [ 0x1b14 0x1b15 0x0 0x0 ] new_l2_to_l1_msgs: [ 0x1c14 0x0 ] unencrypted_logs_hash: [ 0x1c15 0x0 ] unencrypted_log_preimages_length: 0x1c16 -historic_public_data_tree_root: 0x1d14 +historic_block_data: private_data_tree_root: 0x1d14 +nullifier_tree_root: 0x1d15 +contract_tree_root: 0x1d16 +l1_to_l2_messages_tree_root: 0x1d17 +blocks_tree_root: 0x1d18 +private_kernel_vk_tree_root: 0x1d19 +public_data_tree_root: 0x1d1a +global_variables_hash: 0x1d1b + prover_address: 0x1e15 is_execution_request: 0 diff --git a/yarn-project/circuits.js/src/structs/kernel/historic_block_data.ts b/yarn-project/circuits.js/src/structs/kernel/historic_block_data.ts index 7b7c8895554..82001f67a82 100644 --- a/yarn-project/circuits.js/src/structs/kernel/historic_block_data.ts +++ b/yarn-project/circuits.js/src/structs/kernel/historic_block_data.ts @@ -36,11 +36,11 @@ export class HistoricBlockData { /** * Current public state tree hash. */ - public readonly publicDataTreeRoot: Fr, + public publicDataTreeRoot: Fr, /** * Previous globals hash, this value is used to recalculate the block hash. */ - public readonly globalVariablesHash: Fr, + public globalVariablesHash: Fr, ) {} static from(fields: FieldsOf) { diff --git a/yarn-project/circuits.js/src/structs/public_circuit_public_inputs.test.ts b/yarn-project/circuits.js/src/structs/public_circuit_public_inputs.test.ts new file mode 100644 index 00000000000..7f65acd2fd2 --- /dev/null +++ b/yarn-project/circuits.js/src/structs/public_circuit_public_inputs.test.ts @@ -0,0 +1,12 @@ +import { expectSerializeToMatchSnapshot } from '../tests/expectSerialize.js'; +import { makePublicCircuitPublicInputs } from '../tests/factories.js'; + +describe('basic PublicCircuitPublicInputs serialization', () => { + it(`serializes a trivial PublicCircuitPublicInputs and prints it`, async () => { + // Test the data case: writing (mostly) sequential numbers + await expectSerializeToMatchSnapshot( + makePublicCircuitPublicInputs().toBuffer(), + 'abis__test_roundtrip_serialize_public_circuit_public_inputs', + ); + }); +}); diff --git a/yarn-project/circuits.js/src/structs/public_circuit_public_inputs.ts b/yarn-project/circuits.js/src/structs/public_circuit_public_inputs.ts index 9fbc10502a9..04955b697fa 100644 --- a/yarn-project/circuits.js/src/structs/public_circuit_public_inputs.ts +++ b/yarn-project/circuits.js/src/structs/public_circuit_public_inputs.ts @@ -16,6 +16,7 @@ import { import { FieldsOf, assertMemberLength, makeTuple } from '../utils/jsUtils.js'; import { serializeToBuffer } from '../utils/serialize.js'; import { CallContext } from './call_context.js'; +import { HistoricBlockData } from './index.js'; /** * Contract storage read operation on a specific contract. @@ -185,9 +186,9 @@ export class PublicCircuitPublicInputs { */ public unencryptedLogPreimagesLength: Fr, /** - * Root of the public data tree when the call started. + * Root of the commitment trees when the call started. */ - public historicPublicDataTreeRoot: Fr, + public historicBlockData: HistoricBlockData, /** * Address of the prover. */ @@ -229,7 +230,7 @@ export class PublicCircuitPublicInputs { makeTuple(MAX_NEW_L2_TO_L1_MSGS_PER_CALL, Fr.zero), makeTuple(2, Fr.zero), Fr.ZERO, - Fr.ZERO, + HistoricBlockData.empty(), AztecAddress.ZERO, ); } @@ -248,7 +249,7 @@ export class PublicCircuitPublicInputs { isFrArrayEmpty(this.newL2ToL1Msgs) && isFrArrayEmpty(this.unencryptedLogsHash) && this.unencryptedLogPreimagesLength.isZero() && - this.historicPublicDataTreeRoot.isZero() && + this.historicBlockData.isEmpty() && this.proverAddress.isZero() ); } @@ -271,7 +272,7 @@ export class PublicCircuitPublicInputs { fields.newL2ToL1Msgs, fields.unencryptedLogsHash, fields.unencryptedLogPreimagesLength, - fields.historicPublicDataTreeRoot, + fields.historicBlockData, fields.proverAddress, ] as const; } diff --git a/yarn-project/circuits.js/src/tests/factories.ts b/yarn-project/circuits.js/src/tests/factories.ts index 286053b6a31..3268d8235b7 100644 --- a/yarn-project/circuits.js/src/tests/factories.ts +++ b/yarn-project/circuits.js/src/tests/factories.ts @@ -327,7 +327,7 @@ export function makePublicCircuitPublicInputs( tupleGenerator(MAX_NEW_L2_TO_L1_MSGS_PER_CALL, fr, seed + 0x900), tupleGenerator(2, fr, seed + 0x901), fr(seed + 0x902), - fr(seed + 0xa00), + makeHistoricBlockData(seed + 0xa00), makeAztecAddress(seed + 0xb01), ); } diff --git a/yarn-project/foundation/src/aztec-address/index.ts b/yarn-project/foundation/src/aztec-address/index.ts index c66330c78cb..3910a5ab125 100644 --- a/yarn-project/foundation/src/aztec-address/index.ts +++ b/yarn-project/foundation/src/aztec-address/index.ts @@ -106,6 +106,15 @@ export class AztecAddress { return `${str.slice(0, 10)}...${str.slice(-4)}`; } + /** + * Returns this address from a Field element. + * @param field - The Field element to convert. + * @returns An Address Object from a Field element with the same value. + */ + static fromField(field: Fr): AztecAddress { + return new AztecAddress(toBufferBE(field.value, AztecAddress.SIZE_IN_BYTES)); + } + /** * Returns this address as a field element. * @returns A field element with the same value as the address. diff --git a/yarn-project/noir-compiler/src/contract-interface-gen/noir.ts b/yarn-project/noir-compiler/src/contract-interface-gen/noir.ts index 2e38b9fea2c..b5773e23469 100644 --- a/yarn-project/noir-compiler/src/contract-interface-gen/noir.ts +++ b/yarn-project/noir-compiler/src/contract-interface-gen/noir.ts @@ -142,7 +142,11 @@ function generateFunctionInterface(functionData: FunctionAbi) { const selector = '0x' + generateFunctionSelector(name, parameters).toString('hex'); const serialisation = generateSerialisation(parameters); const callStatement = generateCallStatement(selector, functionData.functionType); - const allParams = ['self', 'context: &mut Context', ...parameters.map(p => generateParameter(p, functionData))]; + const allParams = [ + 'self', + 'context: &mut PrivateContext', + ...parameters.map(p => generateParameter(p, functionData)), + ]; const retType = isPrivateCall(functionData.functionType) ? `-> [Field; RETURN_VALUES_LENGTH] ` : ``; return ` @@ -161,7 +165,7 @@ ${callStatement} */ function generateStaticImports() { return `use dep::std; -use dep::aztec::context::Context; +use dep::aztec::context::PrivateContext; use dep::aztec::constants_gen::RETURN_VALUES_LENGTH;`; } diff --git a/yarn-project/noir-contracts/scripts/install_noirup.sh b/yarn-project/noir-contracts/scripts/install_noirup.sh index 45d1cbda8f2..86d056bc185 100755 --- a/yarn-project/noir-contracts/scripts/install_noirup.sh +++ b/yarn-project/noir-contracts/scripts/install_noirup.sh @@ -3,7 +3,6 @@ set -eu SPECIFIED_HOME=${1:-$HOME} -VERSION="aztec" export NARGO_HOME="$SPECIFIED_HOME/.nargo" NARGO_BIN_DIR="$NARGO_HOME/bin" diff --git a/yarn-project/noir-contracts/src/contracts/child_contract/src/main.nr b/yarn-project/noir-contracts/src/contracts/child_contract/src/main.nr index 7d80aaaeffd..56e2a1e87e0 100644 --- a/yarn-project/noir-contracts/src/contracts/child_contract/src/main.nr +++ b/yarn-project/noir-contracts/src/contracts/child_contract/src/main.nr @@ -5,14 +5,17 @@ contract Child { use dep::aztec::abi; use dep::aztec::abi::PrivateContextInputs; use dep::aztec::abi::PublicContextInputs; - use dep::aztec::context::Context; + use dep::aztec::context::{ + PrivateContext, + PublicContext + }; use crate::storage::Storage; fn constructor( inputs: PrivateContextInputs, ) -> distinct pub abi::PrivateCircuitPublicInputs { // Return private circuit public inputs. All private functions need to return this as it is part of the input of the private kernel. - Context::new(inputs, 0).finish() + PrivateContext::new(inputs, 0).finish() } // Returns a sum of the input and the chain id and version of the contract in private circuit public input's return_values. @@ -20,21 +23,28 @@ contract Child { inputs: PrivateContextInputs, input: Field, ) -> distinct pub abi::PrivateCircuitPublicInputs { - let mut context = Context::new(inputs, abi::hash_args([input])); + let mut context = PrivateContext::new(inputs, abi::hash_args([input])); - context.return_values.push(input + inputs.private_global_variables.chain_id + inputs.private_global_variables.version); + context.return_values.push(input + context.chain_id() + context.version()); // Return private circuit public inputs. All private functions need to return this as it is part of the input of the private kernel. context.finish() } // Returns base_value + 42. - open fn pubValue(inputs: PublicContextInputs, base_value: Field) -> pub Field { - base_value + inputs.public_global_variables.chain_id + inputs.public_global_variables.version + inputs.public_global_variables.block_number + inputs.public_global_variables.timestamp + open fn pubValue(inputs: PublicContextInputs, base_value: Field) -> pub abi::PublicCircuitPublicInputs { + let mut context = PublicContext::new(inputs, abi::hash_args([base_value])); + + let returnValue = base_value + context.chain_id() + context.version() + context.block_number() + context.timestamp(); + + context.return_values.push(returnValue); + context.finish() } // Increments `current_value` by `new_value` and returns `new_value` + 1. - open fn pubStoreValue(_inputs: PublicContextInputs, new_value: Field) -> pub Field { + open fn pubStoreValue(inputs: PublicContextInputs, new_value: Field) -> pub abi::PublicCircuitPublicInputs { + let mut context = PublicContext::new(inputs, abi::hash_args([new_value])); + let storage = Storage::init(); let old_value = storage.current_value.read(); // Compiler complains if we don't assign the result to anything @@ -42,7 +52,9 @@ contract Child { // Compiler fails with "we do not allow private ABI inputs to be returned as public outputs" if we try to // return new_value as-is, but then it also complains if we add `pub` to `new_value` in the args, so we // just assign it to another variable and tweak it so it's not the same value, and the compiler is happy. - let ret_value = new_value + 1; - ret_value + let return_value = new_value + 1; + + context.return_values.push(return_value); + context.finish() } } diff --git a/yarn-project/noir-contracts/src/contracts/easy_private_token_contract/src/main.nr b/yarn-project/noir-contracts/src/contracts/easy_private_token_contract/src/main.nr index a0cdab38ad8..107dbdbd7e1 100644 --- a/yarn-project/noir-contracts/src/contracts/easy_private_token_contract/src/main.nr +++ b/yarn-project/noir-contracts/src/contracts/easy_private_token_contract/src/main.nr @@ -13,7 +13,7 @@ contract EasyPrivateToken { use dep::aztec::{ abi, abi::PrivateContextInputs, - context::Context, + context::PrivateContext, log::emit_unencrypted_log, note::{ note_header::NoteHeader, @@ -33,7 +33,7 @@ contract EasyPrivateToken { initial_supply: u120, owner: Field, ) -> distinct pub abi::PrivateCircuitPublicInputs { - let mut context = Context::new(inputs, abi::hash_args([initial_supply as Field, owner])); + let mut context = PrivateContext::new(inputs, abi::hash_args([initial_supply as Field, owner])); let storage = Storage::init(); let balances = storage.balances; @@ -54,7 +54,7 @@ contract EasyPrivateToken { amount: u120, owner: Field, ) -> distinct pub abi::PrivateCircuitPublicInputs { - let mut context = Context::new(inputs, abi::hash_args([amount as Field, owner])); + let mut context = PrivateContext::new(inputs, abi::hash_args([amount as Field, owner])); let storage = Storage::init(); let balances = storage.balances; @@ -76,7 +76,7 @@ contract EasyPrivateToken { sender: Field, recipient: Field, ) -> distinct pub abi::PrivateCircuitPublicInputs { - let mut context = Context::new(inputs, abi::hash_args([amount as Field, sender, recipient])); + let mut context = PrivateContext::new(inputs, abi::hash_args([amount as Field, sender, recipient])); let storage = Storage::init(); let balances = storage.balances; diff --git a/yarn-project/noir-contracts/src/contracts/ecdsa_account_contract/src/main.nr b/yarn-project/noir-contracts/src/contracts/ecdsa_account_contract/src/main.nr index 1e85b2cb668..3d04b868185 100644 --- a/yarn-project/noir-contracts/src/contracts/ecdsa_account_contract/src/main.nr +++ b/yarn-project/noir-contracts/src/contracts/ecdsa_account_contract/src/main.nr @@ -10,7 +10,7 @@ contract EcdsaAccount { use dep::aztec::abi; use dep::aztec::abi::PrivateContextInputs; use dep::aztec::abi::CallContext; - use dep::aztec::context::Context; + use dep::aztec::context::PrivateContext; use dep::aztec::log::emit_encrypted_log; use dep::aztec::oracle::get_public_key::get_public_key; use dep::aztec::types::vec::BoundedVec; @@ -40,7 +40,7 @@ contract EcdsaAccount { let mut args: BoundedVec = BoundedVec::new(0); args.push_array(payload.serialize()); for byte in signature { args.push(byte as Field); } - let mut context = Context::new(inputs, abi::hash_args(args.storage)); + let mut context = PrivateContext::new(inputs, abi::hash_args(args.storage)); // Load public key from storage let storage = Storage::init(); @@ -71,10 +71,10 @@ contract EcdsaAccount { let mut args: BoundedVec = BoundedVec::new(0); for byte in signing_pub_key_x { args.push(byte as Field); } for byte in signing_pub_key_y { args.push(byte as Field); } - let mut context = Context::new(inputs, abi::hash_args(args.storage)); + let mut context = PrivateContext::new(inputs, abi::hash_args(args.storage)); - let this = inputs.call_context.storage_contract_address; - let mut pub_key_note = EcdsaPublicKeyNote::new(signing_pub_key_x, signing_pub_key_y, inputs.call_context.storage_contract_address); + let this = context.this_address(); + let mut pub_key_note = EcdsaPublicKeyNote::new(signing_pub_key_x, signing_pub_key_y, this); storage.public_key.initialise(&mut context, &mut pub_key_note); emit_encrypted_log( diff --git a/yarn-project/noir-contracts/src/contracts/escrow_contract/src/main.nr b/yarn-project/noir-contracts/src/contracts/escrow_contract/src/main.nr index 98b49b41a7a..22770af2310 100644 --- a/yarn-project/noir-contracts/src/contracts/escrow_contract/src/main.nr +++ b/yarn-project/noir-contracts/src/contracts/escrow_contract/src/main.nr @@ -8,7 +8,7 @@ contract Escrow { use dep::aztec::abi::PrivateContextInputs; use dep::aztec::abi::CallContext; use dep::aztec::private_call_stack_item::PrivateCallStackItem; - use dep::aztec::context::Context; + use dep::aztec::context::PrivateContext; use dep::aztec::log::emit_encrypted_log; use dep::aztec::oracle::get_public_key::get_public_key; @@ -30,8 +30,8 @@ contract Escrow { inputs: pub PrivateContextInputs, owner: pub Field ) -> distinct pub abi::PrivateCircuitPublicInputs { - let mut context = Context::new(inputs, abi::hash_args([owner])); - let this = inputs.call_context.storage_contract_address; + let mut context = PrivateContext::new(inputs, abi::hash_args([owner])); + let this = context.this_address(); let storage = Storage::init(); let mut note = AddressNote::new(owner, this); @@ -54,9 +54,9 @@ contract Escrow { amount: pub Field, recipient: pub Field, ) -> distinct pub abi::PrivateCircuitPublicInputs { - let mut context = Context::new(inputs, abi::hash_args([token, amount, recipient])); - let this = inputs.call_context.storage_contract_address; - let sender = inputs.call_context.msg_sender; + let mut context = PrivateContext::new(inputs, abi::hash_args([token, amount, recipient])); + let this = context.this_address(); + let sender = context.msg_sender(); let storage = Storage::init(); // TODO: Do we need to manually nullify and recreate this note for access control? Or does Set handle it for us? Or since we have no methods for updating it, we're good? diff --git a/yarn-project/noir-contracts/src/contracts/example_public_state_increment_BROKE/src/main.nr b/yarn-project/noir-contracts/src/contracts/example_public_state_increment_BROKE/src/main.nr index 4f3119f716b..0ec68fbb492 100644 --- a/yarn-project/noir-contracts/src/contracts/example_public_state_increment_BROKE/src/main.nr +++ b/yarn-project/noir-contracts/src/contracts/example_public_state_increment_BROKE/src/main.nr @@ -4,7 +4,10 @@ contract ExamplePublicStateIncrement { use dep::aztec::abi; use dep::aztec::abi::PrivateContextInputs; use dep::aztec::abi::PublicContextInputs; - use dep::aztec::context::Context; + use dep::aztec::context::{ + PrivateContext, + PublicContext, + }; use dep::aztec::oracle::logs::emit_unencrypted_log; use dep::aztec::types::point::Point; use crate::storage::Storage; @@ -19,7 +22,7 @@ contract ExamplePublicStateIncrement { fn constructor( inputs: PrivateContextInputs, ) -> distinct pub abi::PrivateCircuitPublicInputs { - let mut context = Context::new(inputs, 0); + let mut context = PrivateContext::new(inputs, 0); let initialise_a_function_selector: Field = 1234; let _return_values = context.call_public_function_no_args(context.this_address(), initialise_a_function_selector); @@ -29,20 +32,28 @@ contract ExamplePublicStateIncrement { // a = 100; open internal fn initialise_a( - _inputs: PublicContextInputs, - ) { + inputs: PublicContextInputs, + ) -> pub abi::PublicCircuitPublicInputs { + let mut context = PublicContext::new(inputs, abi::hash_args([])); + let storage = Storage::init(); storage.a.write(100); + + context.finish() } // a += b; open fn increment_a( - _inputs: PublicContextInputs, + inputs: PublicContextInputs, b: Field, - ) { + ) -> pub abi::PublicCircuitPublicInputs { + let mut context = PublicContext::new(inputs, abi::hash_args([b])); + let storage = Storage::init(); let mut a = storage.a.read(); a += b; storage.a.write(a); + + context.finish() } } diff --git a/yarn-project/noir-contracts/src/contracts/import_test_contract/src/main.nr b/yarn-project/noir-contracts/src/contracts/import_test_contract/src/main.nr index 2eb0637b369..3ebdeca7131 100644 --- a/yarn-project/noir-contracts/src/contracts/import_test_contract/src/main.nr +++ b/yarn-project/noir-contracts/src/contracts/import_test_contract/src/main.nr @@ -5,7 +5,7 @@ mod test_contract_interface; contract ImportTest { use dep::aztec::abi; use dep::aztec::abi::PrivateContextInputs; - use dep::aztec::context::Context; + use dep::aztec::context::PrivateContext; use crate::test_contract_interface::{ TestContractInterface, @@ -18,7 +18,7 @@ contract ImportTest { fn constructor( inputs: PrivateContextInputs, ) -> distinct pub abi::PrivateCircuitPublicInputs { - Context::new(inputs, 0).finish() + PrivateContext::new(inputs, 0).finish() } // Calls the testCodeGen on the Test contract at the target address @@ -29,7 +29,7 @@ contract ImportTest { inputs: PrivateContextInputs, target: Field ) -> distinct pub abi::PrivateCircuitPublicInputs { - let mut context = Context::new(inputs, abi::hash_args([target])); + let mut context = PrivateContext::new(inputs, abi::hash_args([target])); let test_contract_instance = TestContractInterface::at(target); let return_values = test_contract_instance.testCodeGen( &mut context, @@ -61,7 +61,7 @@ contract ImportTest { inputs: PrivateContextInputs, target: Field ) -> distinct pub abi::PrivateCircuitPublicInputs { - let mut context = Context::new(inputs, abi::hash_args([target])); + let mut context = PrivateContext::new(inputs, abi::hash_args([target])); let test_contract_instance = TestContractInterface::at(target); let return_values = test_contract_instance.getThisAddress(&mut context); context.return_values.push(return_values[0]); @@ -75,7 +75,7 @@ contract ImportTest { inputs: PrivateContextInputs, target: Field, ) -> distinct pub abi::PrivateCircuitPublicInputs { - let mut context = Context::new(inputs, abi::hash_args([target])); + let mut context = PrivateContext::new(inputs, abi::hash_args([target])); let test_contract_instance = TestContractInterface::at(target); test_contract_instance.createNullifierPublic(&mut context, 1, 2); context.finish() diff --git a/yarn-project/noir-contracts/src/contracts/lending_contract/src/main.nr b/yarn-project/noir-contracts/src/contracts/lending_contract/src/main.nr index a9833571907..516f2b094a1 100644 --- a/yarn-project/noir-contracts/src/contracts/lending_contract/src/main.nr +++ b/yarn-project/noir-contracts/src/contracts/lending_contract/src/main.nr @@ -7,16 +7,15 @@ contract Lending { abi::PrivateContextInputs, abi::PublicContextInputs }; - use dep::aztec::context::Context; + use dep::aztec::context::{ + PrivateContext, + PublicContext + }; use dep::aztec::oracle::{ logs::emit_unencrypted_log, create_nullifier::create_nullifier, }; - use dep::aztec::public_call_stack_item::{ - PublicCallStackItem, - call_public_function, - call_public_function_no_args, - }; + use dep::aztec::public_call_stack_item::PublicCallStackItem; use crate::storage::{Storage, Tot, Account}; struct Pos { @@ -29,12 +28,14 @@ contract Lending { inputs: PrivateContextInputs ) -> distinct pub abi::PrivateCircuitPublicInputs { // Return private circuit public inputs. All private functions need to return this as it is part of the input of the private kernel. - Context::new(inputs, 0).finish() + PrivateContext::new(inputs, 0).finish() } open fn init( inputs: PublicContextInputs - ) -> pub Field { + ) -> pub abi::PublicCircuitPublicInputs { + let mut context = PublicContext::new(inputs, abi::hash_args([])); + let storage = Storage::init(); let asset = storage.assets.at(0); @@ -46,23 +47,25 @@ contract Lending { asset.write(Tot { interest_accumulator: 1000000000, - last_updated_ts: inputs.public_global_variables.timestamp as u120, + last_updated_ts: context.timestamp() as u120, }); - 1 + context.return_values.push(1); + context.finish() } // Create a position. open fn update_tot( inputs: PublicContextInputs - ) -> pub Field { + ) -> pub abi::PublicCircuitPublicInputs { + let mut context = PublicContext::new(inputs, abi::hash_args([])); let storage = Storage::init(); let asset = storage.assets.at(0); let mut tot = asset.read(); - let dt: u120 = inputs.public_global_variables.timestamp as u120 - tot.last_updated_ts; + let dt: u120 = context.timestamp() as u120 - tot.last_updated_ts; // Need proper interest computation here. // Assume constant rate because too few reads :cry: @@ -72,11 +75,12 @@ contract Lending { let divisor: u120 = 1000000000; tot.interest_accumulator = (tot.interest_accumulator * multiplier) / divisor; - tot.last_updated_ts = inputs.public_global_variables.timestamp as u120; + tot.last_updated_ts = context.timestamp() as u120; asset.write(tot); - 1 + context.return_values.push(1); + context.finish() } // This don't need to be on behalf of self. We should be able to repay on behalf of someone else. @@ -86,7 +90,7 @@ contract Lending { owner: Field, amount: Field ) -> distinct pub abi::PrivateCircuitPublicInputs { - let mut context = Context::new(inputs, abi::hash_args([ + let mut context = PrivateContext::new(inputs, abi::hash_args([ secret, owner, amount @@ -94,7 +98,7 @@ contract Lending { assert (!((secret == 0) as bool & (owner == 0) as bool)); let mut account = owner; - let me = inputs.call_context.msg_sender; + let me = context.msg_sender(); if (secret != 0) { account = Account::new(me, secret).key(); @@ -104,7 +108,7 @@ contract Lending { // _deposit(account, amount) let _callStackItem = context.call_public_function( - inputs.call_context.storage_contract_address, + context.this_address(), 3009041984, [account, amount] ); @@ -116,18 +120,24 @@ contract Lending { inputs: PublicContextInputs, owner: Field, amount: Field - ) -> pub Field { + ) -> pub abi::PublicCircuitPublicInputs { + let mut context = PublicContext::new(inputs, abi::hash_args([owner, amount])); // @todo @LHerskind Transfer tokens into this contract. We can't do it now because too few writes. - call_public_function(inputs.call_context.storage_contract_address, 3009041984, [owner, amount])[0] + let return_values = context.call_public_function(context.this_address(), 3009041984, [owner, amount]); + + context.return_values.push(return_values[0]); + context.finish() } open internal fn _deposit( inputs: PublicContextInputs, owner: Field, amount: Field - ) -> pub Field { - let _void = call_public_function_no_args(inputs.call_context.storage_contract_address, 1259373467)[0]; + ) -> pub abi::PublicCircuitPublicInputs { + let mut context = PublicContext::new(inputs, abi::hash_args([owner, amount])); + + let _void = context.call_public_function_no_args(context.this_address(), 1259373467)[0]; let storage = Storage::init(); @@ -135,7 +145,9 @@ contract Lending { let collateral = coll_loc.read(); coll_loc.write(collateral + amount); - 1 + + context.return_values.push(1); + context.finish() } fn withdraw_private( @@ -143,15 +155,15 @@ contract Lending { secret: Field, amount: Field ) -> distinct pub abi::PrivateCircuitPublicInputs { - let mut context = Context::new(inputs, abi::hash_args([ + let mut context = PrivateContext::new(inputs, abi::hash_args([ secret, amount ])); - let me = inputs.call_context.msg_sender; + let me = context.msg_sender(); let account = Account::new(me, secret).key(); let _callStackItem = context.call_public_function( - inputs.call_context.storage_contract_address, + context.this_address(), 1065861440, [account, amount] ); @@ -163,10 +175,14 @@ contract Lending { open fn withdraw_public( inputs: PublicContextInputs, amount: Field - ) -> pub Field { + ) -> pub abi::PublicCircuitPublicInputs { + let mut context = PublicContext::new(inputs, abi::hash_args([amount])); // @todo @LHerskind Transfer tokens into this contract. We can't do it now because too few writes. - call_public_function(inputs.call_context.storage_contract_address, 1065861440, [inputs.call_context.msg_sender, amount])[0] + let return_values = context.call_public_function(context.this_address(), 1065861440, [context.msg_sender(), amount]); + + context.return_values.push(return_values[0]); + context.finish() } open internal fn _withdraw( @@ -174,9 +190,11 @@ contract Lending { owner: Field, // recipient: Field, amount: Field - ) -> pub Field { + ) -> pub abi::PublicCircuitPublicInputs { // Access control. - let _void = call_public_function_no_args(inputs.call_context.storage_contract_address, 1259373467)[0]; + let mut context = PublicContext::new(inputs, abi::hash_args([owner, amount])); + + let _void = context.call_public_function_no_args(context.this_address(), 1259373467)[0]; let storage = Storage::init(); @@ -192,7 +210,8 @@ contract Lending { coll_loc.write(collateral - amount); // Transfer tokens to recipient (could be with shielding or without, for now, can't to either). - 1 + context.return_values.push(1); + context.finish() } fn borrow_private( @@ -200,16 +219,16 @@ contract Lending { secret: Field, amount: Field ) -> distinct pub abi::PrivateCircuitPublicInputs { - let mut context = Context::new(inputs, abi::hash_args([ + let mut context = PrivateContext::new(inputs, abi::hash_args([ secret, amount ])); - let me = inputs.call_context.msg_sender; + let me = context.msg_sender(); let account = Account::new(me, secret).key(); let _callStackItem = context.call_public_function( - inputs.call_context.storage_contract_address, + context.this_address(), 1462609836, [account, amount] ); @@ -220,17 +239,22 @@ contract Lending { open fn borrow_public( inputs: PublicContextInputs, amount: Field - ) -> pub Field { - call_public_function(inputs.call_context.storage_contract_address, 1462609836, [inputs.call_context.msg_sender, amount])[0] + ) -> pub abi::PublicCircuitPublicInputs { + let mut context = PublicContext::new(inputs, abi::hash_args([amount])); + let return_values = context.call_public_function(context.this_address(), 1462609836, [context.msg_sender(), amount]); + + context.return_values.push(return_values[0]); + context.finish() } open internal fn _borrow( inputs: PublicContextInputs, owner: Field, amount: Field - ) -> pub Field { + ) -> pub abi::PublicCircuitPublicInputs { + let mut context = PublicContext::new(inputs, abi::hash_args([owner, amount])); // Access control. - let _void = call_public_function_no_args(inputs.call_context.storage_contract_address, 1259373467)[0]; + let _void = context.call_public_function_no_args(context.this_address(), 1259373467)[0]; let storage = Storage::init(); @@ -246,7 +270,8 @@ contract Lending { // @todo @LHerskind Transferring funds to the recipient. - 1 + context.return_values.push(1); + context.finish() } // This don't need to be on behalf of self. We should be able to repay on behalf of someone else. @@ -256,7 +281,7 @@ contract Lending { owner: Field, amount: Field ) -> distinct pub abi::PrivateCircuitPublicInputs { - let mut context = Context::new(inputs, abi::hash_args([ + let mut context = PrivateContext::new(inputs, abi::hash_args([ secret, owner, amount @@ -264,7 +289,7 @@ contract Lending { assert (!((secret == 0) as bool & (owner == 0) as bool)); let mut account = owner; - let me = inputs.call_context.msg_sender; + let me = context.msg_sender(); if (secret != 0) { account = Account::new(me, secret).key(); @@ -273,7 +298,7 @@ contract Lending { // @todo @lherskind Transfer tokens from me to this contract. let _callStackItem = context.call_public_function( - inputs.call_context.storage_contract_address, + context.this_address(), 3985016136, [account, amount] ); @@ -285,17 +310,22 @@ contract Lending { inputs: PublicContextInputs, owner: Field, amount: Field - ) -> pub Field { + ) -> pub abi::PublicCircuitPublicInputs { + let mut context = PublicContext::new(inputs, abi::hash_args([owner, amount])); // @todo @LHerskind Transfer tokens from msg.sender to this contract. - call_public_function(inputs.call_context.storage_contract_address, 3985016136, [owner, amount])[0] + let return_values = context.call_public_function(context.this_address(), 3985016136, [owner, amount]); + + context.return_values.push(return_values[0]); + context.finish() } open internal fn _repay( inputs: PublicContextInputs, owner: Field, amount: Field - ) -> pub Field { - let _void = call_public_function_no_args(inputs.call_context.storage_contract_address, 1259373467)[0]; + ) -> pub abi::PublicCircuitPublicInputs { + let mut context = PublicContext::new(inputs, abi::hash_args([owner, amount])); + let _void = context.call_public_function_no_args(context.this_address(), 1259373467)[0]; let storage = Storage::init(); // Should constrain access from private. @@ -310,7 +340,9 @@ contract Lending { assert (static_debt as u120 >= amount as u120); debt_loc.write(static_debt - amount); - 1 + + context.return_values.push(1); + context.finish() } unconstrained fn getTot( diff --git a/yarn-project/noir-contracts/src/contracts/non_native_token_contract/src/main.nr b/yarn-project/noir-contracts/src/contracts/non_native_token_contract/src/main.nr index dd0e130ac99..b4bcba1b941 100644 --- a/yarn-project/noir-contracts/src/contracts/non_native_token_contract/src/main.nr +++ b/yarn-project/noir-contracts/src/contracts/non_native_token_contract/src/main.nr @@ -33,7 +33,10 @@ contract NonNativeToken { use crate::storage::Storage; use crate::hash::{get_mint_content_hash, get_withdraw_content_hash}; - use dep::aztec::context::Context; + use dep::aztec::context::{ + PrivateContext, + PublicContext, + }; use dep::aztec::types::point::Point; use dep::aztec::{ abi, @@ -68,7 +71,7 @@ contract NonNativeToken { ) -> distinct pub abi::PrivateCircuitPublicInputs { let storage = Storage::init(); - let mut context = Context::new(inputs, abi::hash_args([initial_supply, owner])); + let mut context = PrivateContext::new(inputs, abi::hash_args([initial_supply, owner])); let balance = storage.balances.at(owner); send_note(&mut context, balance, initial_supply, owner); @@ -94,7 +97,7 @@ contract NonNativeToken { ) -> distinct pub abi::PrivateCircuitPublicInputs { let storage = Storage::init(); - let mut context = Context::new(inputs, abi::hash_args([ + let mut context = PrivateContext::new(inputs, abi::hash_args([ amount, owner, msg_key, secret, canceller ])); @@ -124,7 +127,7 @@ contract NonNativeToken { callerOnL1: Field, // ethereum address that can call this function on the L1 portal (0x0 if anyone can call) ) -> distinct pub abi::PrivateCircuitPublicInputs { let storage = Storage::init(); - let mut context = Context::new(inputs, abi::hash_args([ + let mut context = PrivateContext::new(inputs, abi::hash_args([ amount, sender, recipient, callerOnL1 ])); @@ -152,7 +155,9 @@ contract NonNativeToken { msg_key: Field, secret: Field, canceller: Field, - ) -> pub Field { + ) -> pub abi::PublicCircuitPublicInputs { + let mut context = PublicContext::new(inputs, abi::hash_args([amount, owner_address, msg_key, secret, canceller])); + let storage = Storage::init(); let public_balances = storage.public_balances; @@ -165,7 +170,10 @@ contract NonNativeToken { let recipient_balance = public_balances.at(owner_address); let new_balance = recipient_balance.read() + amount; recipient_balance.write(new_balance); - new_balance + + // Push the return value into the context + context.return_values.push(new_balance); + context.finish() } @@ -178,11 +186,13 @@ contract NonNativeToken { amount: Field, recipient: Field, callerOnL1: Field, // ethereum address that can call this function on the L1 portal (0x0 if anyone can call) - ) { + ) -> pub abi::PublicCircuitPublicInputs { + let mut context = PublicContext::new(inputs, abi::hash_args([amount, recipient, callerOnL1])); + let storage = Storage::init(); let public_balances = storage.public_balances; - let sender = inputs.call_context.msg_sender; + let sender = context.msg_sender(); let sender_balance = public_balances.at(sender); let current_sender_balance: Field = sender_balance.read(); @@ -196,7 +206,11 @@ contract NonNativeToken { let content = get_withdraw_content_hash(amount, recipient, callerOnL1); // Emit the l2 to l1 message + // TODO: make in the context create_l2_to_l1_message(content); + + // Push the return value into the context + context.finish() } @@ -212,7 +226,7 @@ contract NonNativeToken { recipient: Field, ) -> distinct pub abi::PrivateCircuitPublicInputs { let storage = Storage::init(); - let mut context = Context::new(inputs, abi::hash_args([ + let mut context = PrivateContext::new(inputs, abi::hash_args([ amount, sender, recipient ])); @@ -232,13 +246,15 @@ contract NonNativeToken { inputs: PublicContextInputs, amount: Field, secretHash: Field, - ) { + ) -> pub abi::PublicCircuitPublicInputs { + let mut context = PublicContext::new(inputs, abi::hash_args([amount, secretHash])); + let storage = Storage::init(); let public_balances = storage.public_balances; let pending_shields = storage.pending_shields; // Decrease user's balance. - let sender = inputs.call_context.msg_sender; + let sender = context.msg_sender(); let sender_balance = public_balances.at(sender); let current_sender_balance: Field = sender_balance.read(); @@ -251,7 +267,9 @@ contract NonNativeToken { // and insert it into the set of "pending_shields" and therefore // (eventually) the private data tree. let mut note = TransparentNote::new(amount, secretHash); - pending_shields.insert_from_public(inputs, &mut note); + pending_shields.insert_from_public(context, &mut note); + + context.finish() } // The shield function takes a public balance, and creates a commitment containing the amount of tokens @@ -265,7 +283,7 @@ contract NonNativeToken { let storage = Storage::init(); let pending_shields = storage.pending_shields; - let mut context = Context::new(inputs, abi::hash_args([ + let mut context = PrivateContext::new(inputs, abi::hash_args([ amount, secret, owner ])); @@ -301,7 +319,7 @@ contract NonNativeToken { recipient: Field, ) -> distinct pub abi::PrivateCircuitPublicInputs { let storage = Storage::init(); - let mut context = Context::new(inputs, abi::hash_args([ + let mut context = PrivateContext::new(inputs, abi::hash_args([ amount, owner, recipient ])); @@ -310,7 +328,7 @@ contract NonNativeToken { spend_notes(&mut context, sender_balance, amount, owner); // enqueue a public function to perform the public state update. - let thisAddress = inputs.call_context.storage_contract_address; + let thisAddress = context.this_address(); // addUnshieldedBalance selector (in decimal) // recompute by: `cast keccak addUnshieldedBalance(field,field)` -> convert to decimal @@ -321,16 +339,20 @@ contract NonNativeToken { } open fn addUnshieldedBalance( - _inputs: PublicContextInputs, + inputs: PublicContextInputs, amount: Field, recipient: Field, - ) { + ) -> pub abi::PublicCircuitPublicInputs { + let mut context = PublicContext::new(inputs, abi::hash_args([amount, recipient])); + let storage = Storage::init(); let recipient_balance = storage.public_balances.at(recipient); let current_balance = recipient_balance.read(); let new_balance = current_balance + amount; recipient_balance.write(new_balance); + + context.finish() } unconstrained fn getBalance( diff --git a/yarn-project/noir-contracts/src/contracts/parent_contract/src/main.nr b/yarn-project/noir-contracts/src/contracts/parent_contract/src/main.nr index 9c3dca33ed7..0a0446d1d88 100644 --- a/yarn-project/noir-contracts/src/contracts/parent_contract/src/main.nr +++ b/yarn-project/noir-contracts/src/contracts/parent_contract/src/main.nr @@ -3,13 +3,15 @@ contract Parent { use dep::aztec::abi; use dep::aztec::abi::PrivateContextInputs; use dep::aztec::abi::PublicContextInputs; - use dep::aztec::context::Context; - use dep::aztec::public_call_stack_item::call_public_function; + use dep::aztec::context::{ + PrivateContext, + PublicContext, + }; fn constructor( inputs: PrivateContextInputs, ) -> distinct pub abi::PrivateCircuitPublicInputs { - Context::new(inputs, 0).finish() + PrivateContext::new(inputs, 0).finish() } // Private function to call another private function in the targetContract using the provided selector @@ -18,7 +20,7 @@ contract Parent { targetContract: Field, targetSelector: Field, ) -> distinct pub abi::PrivateCircuitPublicInputs { - let mut context = Context::new(inputs, abi::hash_args([ + let mut context = PrivateContext::new(inputs, abi::hash_args([ targetContract, targetSelector, ])); @@ -35,14 +37,34 @@ contract Parent { } // Public function to directly call another public function to the targetContract using the selector and value provided - open fn pubEntryPoint(_inputs: PublicContextInputs, targetContract: Field, targetSelector: Field, initValue: Field) -> pub Field { - call_public_function(targetContract, targetSelector, [initValue])[0] + open fn pubEntryPoint( + inputs: PublicContextInputs, + targetContract: Field, + targetSelector: Field, + initValue: Field + ) -> pub abi::PublicCircuitPublicInputs { + let mut context = PublicContext::new(inputs, abi::hash_args([targetContract, targetSelector, initValue])); + + let return_values = context.call_public_function(targetContract, targetSelector, [initValue]); + + context.return_values.push(return_values[0]); + context.finish() } // Same as pubEntryPoint, but calls the target contract twice, using the return value from the first invocation as the argument for the second. - open fn pubEntryPointTwice(_inputs: PublicContextInputs, targetContract: Field, targetSelector: Field, initValue: Field) -> pub Field { - let returnValue = call_public_function(targetContract, targetSelector, [initValue])[0]; - call_public_function(targetContract, targetSelector, [returnValue])[0] + open fn pubEntryPointTwice( + inputs: PublicContextInputs, + targetContract: Field, + targetSelector: Field, + initValue: Field + ) -> pub abi::PublicCircuitPublicInputs { + let mut context = PublicContext::new(inputs, abi::hash_args([targetContract, targetSelector, initValue])); + + let returnValue = context.call_public_function(targetContract, targetSelector, [initValue])[0]; + let return_values = context.call_public_function(targetContract, targetSelector, [returnValue]); + + context.return_values.push(return_values[0]); + context.finish() } // Private function to enqueue a call to the targetContract address using the selector and argument provided @@ -52,7 +74,7 @@ contract Parent { targetSelector: Field, targetValue: Field, ) -> distinct pub abi::PrivateCircuitPublicInputs { - let mut context = Context::new(inputs, abi::hash_args([ + let mut context = PrivateContext::new(inputs, abi::hash_args([ targetContract, targetSelector, targetValue, @@ -71,7 +93,7 @@ contract Parent { targetSelector: Field, targetValue: Field, ) -> distinct pub abi::PrivateCircuitPublicInputs { - let mut context = Context::new(inputs, abi::hash_args([ + let mut context = PrivateContext::new(inputs, abi::hash_args([ targetContract, targetSelector, targetValue, @@ -93,15 +115,15 @@ contract Parent { targetSelector: Field, targetValue: Field, ) -> distinct pub abi::PrivateCircuitPublicInputs { - let mut context = Context::new(inputs, abi::hash_args([ + let mut context = PrivateContext::new(inputs, abi::hash_args([ targetContract, targetSelector, targetValue, ])); let pubEntryPointSelector = 3221316504; - let thisAddress = inputs.call_context.storage_contract_address; - context.call_public_function(thisAddress, pubEntryPointSelector, [targetContract, targetSelector, targetValue]); + let thisAddress = context.this_address(); + let _void = context.call_public_function(thisAddress, pubEntryPointSelector, [targetContract, targetSelector, targetValue]); // Return private circuit public inputs. All private functions need to return this as it is part of the input of the private kernel. context.finish() @@ -114,14 +136,14 @@ contract Parent { targetSelector: Field, targetValue: Field, ) -> distinct pub abi::PrivateCircuitPublicInputs { - let mut context = Context::new(inputs, abi::hash_args([ + let mut context = PrivateContext::new(inputs, abi::hash_args([ targetContract, targetSelector, targetValue, ])); let pubEntryPointSelector = 3221316504; - let thisAddress = inputs.call_context.storage_contract_address; + let thisAddress = context.this_address(); context.call_public_function(thisAddress, pubEntryPointSelector, [targetContract, targetSelector, targetValue]); diff --git a/yarn-project/noir-contracts/src/contracts/pending_commitments_contract/src/main.nr b/yarn-project/noir-contracts/src/contracts/pending_commitments_contract/src/main.nr index 996e46b4a85..9ed46a1988c 100644 --- a/yarn-project/noir-contracts/src/contracts/pending_commitments_contract/src/main.nr +++ b/yarn-project/noir-contracts/src/contracts/pending_commitments_contract/src/main.nr @@ -17,7 +17,7 @@ contract PendingCommitments { use dep::aztec::constants_gen::ARGS_LENGTH; use dep::aztec::abi; use dep::aztec::abi::PrivateContextInputs; - use dep::aztec::context::Context; + use dep::aztec::context::PrivateContext; use dep::aztec::note::{ note_getter::NoteGetterOptions, note_header::NoteHeader, @@ -35,7 +35,7 @@ contract PendingCommitments { inputs: PrivateContextInputs //*********************************/ ) -> distinct pub abi::PrivateCircuitPublicInputs { - let context = Context::new(inputs, 0); + let context = PrivateContext::new(inputs, 0); context.finish() } @@ -51,7 +51,7 @@ contract PendingCommitments { owner: Field, ) -> distinct pub abi::PrivateCircuitPublicInputs { let storage = Storage::init(); - let mut context = Context::new(inputs, abi::hash_args([amount, owner])); + let mut context = PrivateContext::new(inputs, abi::hash_args([amount, owner])); let owner_balance = storage.balances.at(owner); let mut note = ValueNote::new(amount, owner); @@ -91,7 +91,7 @@ contract PendingCommitments { owner: Field, ) -> distinct pub abi::PrivateCircuitPublicInputs { let storage = Storage::init(); - let mut context = Context::new(inputs, abi::hash_args([amount, owner])); + let mut context = PrivateContext::new(inputs, abi::hash_args([amount, owner])); let owner_balance = storage.balances.at(owner); @@ -128,7 +128,7 @@ contract PendingCommitments { owner: Field, ) -> distinct pub abi::PrivateCircuitPublicInputs { let storage = Storage::init(); - let mut context = Context::new(inputs, abi::hash_args([amount, owner])); + let mut context = PrivateContext::new(inputs, abi::hash_args([amount, owner])); let owner_balance = storage.balances.at(owner); let mut note = ValueNote::new(amount, owner); @@ -156,7 +156,7 @@ contract PendingCommitments { owner: Field, ) -> distinct pub abi::PrivateCircuitPublicInputs { let storage = Storage::init(); - let mut context = Context::new(inputs, abi::hash_args([expected_value, owner])); + let mut context = PrivateContext::new(inputs, abi::hash_args([expected_value, owner])); let owner_balance = storage.balances.at(owner); @@ -181,7 +181,7 @@ contract PendingCommitments { owner: Field, ) -> distinct pub abi::PrivateCircuitPublicInputs { let storage = Storage::init(); - let mut context = Context::new(inputs, abi::hash_args([owner])); + let mut context = PrivateContext::new(inputs, abi::hash_args([owner])); let owner_balance = storage.balances.at(owner); @@ -208,7 +208,7 @@ contract PendingCommitments { get_then_nullify_fn_selector: Field, get_note_zero_fn_selector: Field, ) -> distinct pub abi::PrivateCircuitPublicInputs { - let mut context = Context::new(inputs, abi::hash_args([amount, owner, insert_fn_selector, get_then_nullify_fn_selector, get_note_zero_fn_selector])); + let mut context = PrivateContext::new(inputs, abi::hash_args([amount, owner, insert_fn_selector, get_then_nullify_fn_selector, get_note_zero_fn_selector])); // args for nested calls let mut args = [0; ARGS_LENGTH]; @@ -236,7 +236,7 @@ contract PendingCommitments { insert_fn_selector: Field, get_then_nullify_fn_selector: Field, ) -> distinct pub abi::PrivateCircuitPublicInputs { - let mut context = Context::new(inputs, abi::hash_args([amount, owner, insert_fn_selector, get_then_nullify_fn_selector])); + let mut context = PrivateContext::new(inputs, abi::hash_args([amount, owner, insert_fn_selector, get_then_nullify_fn_selector])); // args for nested calls let mut args = [0; ARGS_LENGTH]; @@ -267,7 +267,7 @@ contract PendingCommitments { insert_fn_selector: Field, get_then_nullify_fn_selector: Field, ) -> distinct pub abi::PrivateCircuitPublicInputs { - let mut context = Context::new(inputs, abi::hash_args([amount, owner, insert_fn_selector, get_then_nullify_fn_selector])); + let mut context = PrivateContext::new(inputs, abi::hash_args([amount, owner, insert_fn_selector, get_then_nullify_fn_selector])); // args for nested calls let mut args = [0; ARGS_LENGTH]; @@ -297,8 +297,8 @@ contract PendingCommitments { get_then_nullify_fn_selector: Field, get_note_zero_fn_selector: Field, ) -> distinct pub abi::PrivateCircuitPublicInputs { - //let mut context = Context::new(inputs, abi::hash_args([amount, owner, insert_fn_selector, get_then_nullify_fn_selector])); - let mut context = Context::new(inputs, abi::hash_args([amount, owner, insert_fn_selector, get_then_nullify_fn_selector, get_note_zero_fn_selector])); + //let mut context = PrivateContext::new(inputs, abi::hash_args([amount, owner, insert_fn_selector, get_then_nullify_fn_selector])); + let mut context = PrivateContext::new(inputs, abi::hash_args([amount, owner, insert_fn_selector, get_then_nullify_fn_selector, get_note_zero_fn_selector])); // args for nested calls let mut args = [0; ARGS_LENGTH]; diff --git a/yarn-project/noir-contracts/src/contracts/pokeable_token_contract/src/main.nr b/yarn-project/noir-contracts/src/contracts/pokeable_token_contract/src/main.nr index a3ca3c328a3..256eeab371f 100644 --- a/yarn-project/noir-contracts/src/contracts/pokeable_token_contract/src/main.nr +++ b/yarn-project/noir-contracts/src/contracts/pokeable_token_contract/src/main.nr @@ -11,7 +11,7 @@ contract PokeableToken { }; use dep::aztec::abi; use dep::aztec::abi::PrivateContextInputs; - use dep::aztec::context::Context; + use dep::aztec::context::PrivateContext; use dep::aztec::note::{ note_getter::NoteGetterOptions, note_header::{NoteHeader}, @@ -34,7 +34,7 @@ contract PokeableToken { recipient: Field ) -> distinct pub abi::PrivateCircuitPublicInputs { let storage = Storage::init(); - let mut context = Context::new(inputs, abi::hash_args([initial_supply, sender, recipient])); + let mut context = PrivateContext::new(inputs, abi::hash_args([initial_supply, sender, recipient])); let mut sender_note = AddressNote::new(sender); let mut recipient_note = AddressNote::new(recipient); @@ -59,7 +59,7 @@ contract PokeableToken { sender: Field, recipient: Field ) -> distinct pub abi::PrivateCircuitPublicInputs { - let mut context = Context::new(inputs, abi::hash_args([sender, recipient])); + let mut context = PrivateContext::new(inputs, abi::hash_args([sender, recipient])); let storage = Storage::init(); // TODO: This check is not satisfying constraints diff --git a/yarn-project/noir-contracts/src/contracts/private_token_airdrop_contract/src/main.nr b/yarn-project/noir-contracts/src/contracts/private_token_airdrop_contract/src/main.nr index e5b1331ebdb..6f8427ff41f 100644 --- a/yarn-project/noir-contracts/src/contracts/private_token_airdrop_contract/src/main.nr +++ b/yarn-project/noir-contracts/src/contracts/private_token_airdrop_contract/src/main.nr @@ -11,7 +11,7 @@ contract PrivateTokenAirdrop { use dep::aztec::abi; use dep::aztec::abi::PrivateContextInputs; - use dep::aztec::context::Context; + use dep::aztec::context::PrivateContext; use dep::aztec::note::{ note_header::NoteHeader, utils as note_utils, @@ -32,7 +32,7 @@ contract PrivateTokenAirdrop { owner: Field ) -> distinct pub abi::PrivateCircuitPublicInputs { let storage = Storage::init(); - let mut context = Context::new(inputs, abi::hash_args([initial_supply, owner])); + let mut context = PrivateContext::new(inputs, abi::hash_args([initial_supply, owner])); // Insert new note to a set of user notes and emit the newly created encrypted note preimage via oracle call. let owner_balance = storage.balances.at(owner); @@ -55,7 +55,7 @@ contract PrivateTokenAirdrop { owner: Field ) -> distinct pub abi::PrivateCircuitPublicInputs { let storage = Storage::init(); - let mut context = Context::new(inputs, abi::hash_args([amount, owner])); + let mut context = PrivateContext::new(inputs, abi::hash_args([amount, owner])); // Insert new note to a set of user notes and emit the newly created encrypted note preimage via oracle call. let owner_balance = storage.balances.at(owner); @@ -77,7 +77,7 @@ contract PrivateTokenAirdrop { recipient: Field, ) -> distinct pub abi::PrivateCircuitPublicInputs { let storage = Storage::init(); - let mut context = Context::new(inputs, abi::hash_args([amount, sender, recipient])); + let mut context = PrivateContext::new(inputs, abi::hash_args([amount, sender, recipient])); // Pick from the set of sender's notes to spend amount. let sender_balance = storage.balances.at(sender); @@ -103,7 +103,7 @@ contract PrivateTokenAirdrop { sender: Field ) -> distinct pub abi::PrivateCircuitPublicInputs { let storage = Storage::init(); - let mut context = Context::new(inputs, abi::hash_args([amounts[0], amounts[1], secrets[0], secrets[1], sender])); + let mut context = PrivateContext::new(inputs, abi::hash_args([amounts[0], amounts[1], secrets[0], secrets[1], sender])); // Pick from the set of sender's notes to spend amount. let sender_balance = storage.balances.at(sender); @@ -133,7 +133,7 @@ contract PrivateTokenAirdrop { owner: Field ) -> distinct pub abi::PrivateCircuitPublicInputs { let storage = Storage::init(); - let mut context = Context::new(inputs, abi::hash_args([amount, secret, owner])); + let mut context = PrivateContext::new(inputs, abi::hash_args([amount, secret, owner])); // Remove the claim note if it exists in the set. let mut note = ClaimNote::new(amount, secret); diff --git a/yarn-project/noir-contracts/src/contracts/private_token_contract/src/main.nr b/yarn-project/noir-contracts/src/contracts/private_token_contract/src/main.nr index b96fcdc38ac..a2b256a3ad0 100644 --- a/yarn-project/noir-contracts/src/contracts/private_token_contract/src/main.nr +++ b/yarn-project/noir-contracts/src/contracts/private_token_contract/src/main.nr @@ -10,7 +10,7 @@ contract PrivateToken { use dep::aztec::abi; use dep::aztec::abi::PrivateContextInputs; - use dep::aztec::context::Context; + use dep::aztec::context::PrivateContext; use dep::aztec::note::{ note_header::NoteHeader, utils as note_utils, @@ -31,7 +31,7 @@ contract PrivateToken { owner: Field ) -> distinct pub abi::PrivateCircuitPublicInputs { let storage = Storage::init(); - let mut context = Context::new(inputs, abi::hash_args([initial_supply, owner])); + let mut context = PrivateContext::new(inputs, abi::hash_args([initial_supply, owner])); // Insert new note to a set of user notes and emit the newly created encrypted note preimage via oracle call. let owner_balance = storage.balances.at(owner); @@ -54,7 +54,7 @@ contract PrivateToken { owner: Field ) -> distinct pub abi::PrivateCircuitPublicInputs { let storage = Storage::init(); - let mut context = Context::new(inputs, abi::hash_args([amount, owner])); + let mut context = PrivateContext::new(inputs, abi::hash_args([amount, owner])); // Insert new note to a set of user notes and emit the newly created encrypted note preimage via oracle call. let owner_balance = storage.balances.at(owner); @@ -76,7 +76,7 @@ contract PrivateToken { recipient: Field, ) -> distinct pub abi::PrivateCircuitPublicInputs { let storage = Storage::init(); - let mut context = Context::new(inputs, abi::hash_args([amount, sender, recipient])); + let mut context = PrivateContext::new(inputs, abi::hash_args([amount, sender, recipient])); // Pick from the set of sender's notes to spend amount. let sender_balance = storage.balances.at(sender); diff --git a/yarn-project/noir-contracts/src/contracts/public_token_contract/src/main.nr b/yarn-project/noir-contracts/src/contracts/public_token_contract/src/main.nr index 07e4a32458a..6ddc646f951 100644 --- a/yarn-project/noir-contracts/src/contracts/public_token_contract/src/main.nr +++ b/yarn-project/noir-contracts/src/contracts/public_token_contract/src/main.nr @@ -4,7 +4,10 @@ contract PublicToken { use dep::aztec::abi; use dep::aztec::abi::PrivateContextInputs; use dep::aztec::abi::PublicContextInputs; - use dep::aztec::context::Context; + use dep::aztec::context::{ + PrivateContext, + PublicContext + }; use dep::aztec::oracle::logs::emit_unencrypted_log; use crate::storage::Storage; @@ -13,22 +16,27 @@ contract PublicToken { inputs: PrivateContextInputs, ) -> distinct pub abi::PrivateCircuitPublicInputs { // Return private circuit public inputs. All private functions need to return this as it is part of the input of the private kernel. - Context::new(inputs, 0).finish() + PrivateContext::new(inputs, 0).finish() } // Mints `amount` of tokens to a `recipient`. open fn mint( - _inputs: PublicContextInputs, + inputs: PublicContextInputs, amount: Field, recipient: Field, - ) -> pub Field { + ) -> pub abi::PublicCircuitPublicInputs { + let mut context = PublicContext::new(inputs, abi::hash_args([amount, recipient])); + let storage = Storage::init(); let recipient_balance = storage.balances.at(recipient); let new_amount = recipient_balance.read() + amount; // TODO: Remove return value. let _hash = emit_unencrypted_log("Coins minted"); recipient_balance.write(new_amount); - new_amount + + context.return_values.push(new_amount); + + context.finish() } // Transfers `amount` of tokens from `msg_sender` to `recipient`. @@ -36,9 +44,11 @@ contract PublicToken { inputs: PublicContextInputs, amount: Field, recipient: Field, - ) -> pub Field { + ) -> pub abi::PublicCircuitPublicInputs { + let mut context = PublicContext::new(inputs, abi::hash_args([amount, recipient])); + let storage = Storage::init(); - let sender = inputs.call_context.msg_sender; + let sender = context.msg_sender(); let sender_balance = storage.balances.at(sender); let recipient_balance = storage.balances.at(recipient); @@ -47,17 +57,22 @@ contract PublicToken { let current_recipient_balance = recipient_balance.read(); // TODO: Should support larger numbers. + let mut return_value = 0; + if (current_sender_balance as u126 > amount as u126) { sender_balance.write(current_sender_balance - amount); // TODO: Compiler complains if we don't assign the result of the write to anything let _hash = emit_unencrypted_log("Coins transferred"); let amount = current_recipient_balance + amount; recipient_balance.write(amount); - amount + return_value = amount; } else { // TODO: Revert if there is not enough balance - current_recipient_balance + return_value = current_recipient_balance; } + context.return_values.push(return_value); + + context.finish() } unconstrained fn publicBalanceOf( diff --git a/yarn-project/noir-contracts/src/contracts/schnorr_account_contract/src/main.nr b/yarn-project/noir-contracts/src/contracts/schnorr_account_contract/src/main.nr index 8f25c8cbea7..b8f311054d9 100644 --- a/yarn-project/noir-contracts/src/contracts/schnorr_account_contract/src/main.nr +++ b/yarn-project/noir-contracts/src/contracts/schnorr_account_contract/src/main.nr @@ -12,7 +12,7 @@ contract SchnorrAccount { use dep::aztec::abi::CallContext; use dep::aztec::private_call_stack_item::PrivateCallStackItem; use dep::aztec::public_call_stack_item::PublicCallStackItem; - use dep::aztec::context::Context; + use dep::aztec::context::PrivateContext; use dep::aztec::log::emit_encrypted_log; use dep::aztec::oracle::get_public_key::get_public_key; use dep::aztec::types::vec::BoundedVec; @@ -38,7 +38,7 @@ contract SchnorrAccount { let mut args: BoundedVec = BoundedVec::new(0); args.push_array(payload.serialize()); for byte in signature { args.push(byte as Field); } - let mut context = Context::new(inputs, abi::hash_args(args.storage)); + let mut context = PrivateContext::new(inputs, abi::hash_args(args.storage)); // Load public key from storage let storage = Storage::init(); @@ -67,9 +67,9 @@ contract SchnorrAccount { ) -> distinct pub abi::PrivateCircuitPublicInputs { let storage = Storage::init(); - let mut context = Context::new(inputs, abi::hash_args([signing_pub_key_x, signing_pub_key_y])); + let mut context = PrivateContext::new(inputs, abi::hash_args([signing_pub_key_x, signing_pub_key_y])); - let this = inputs.call_context.storage_contract_address; + let this = context.this_address(); let mut pub_key_note = PublicKeyNote::new(signing_pub_key_x, signing_pub_key_y, this); storage.signing_public_key.initialise(&mut context, &mut pub_key_note); diff --git a/yarn-project/noir-contracts/src/contracts/schnorr_single_key_account_contract/src/main.nr b/yarn-project/noir-contracts/src/contracts/schnorr_single_key_account_contract/src/main.nr index 0f1853d1e76..74ba92023fd 100644 --- a/yarn-project/noir-contracts/src/contracts/schnorr_single_key_account_contract/src/main.nr +++ b/yarn-project/noir-contracts/src/contracts/schnorr_single_key_account_contract/src/main.nr @@ -10,7 +10,7 @@ contract SchnorrSingleKeyAccount { use dep::aztec::abi::CallContext; use dep::aztec::private_call_stack_item::PrivateCallStackItem; use dep::aztec::public_call_stack_item::PublicCallStackItem; - use dep::aztec::context::Context; + use dep::aztec::context::PrivateContext; use dep::aztec::types::vec::BoundedVec; use dep::aztec::types::point::Point; use dep::aztec::constants_gen::GENERATOR_INDEX__CONTRACT_ADDRESS; @@ -30,7 +30,7 @@ contract SchnorrSingleKeyAccount { for byte in owner { args.push(byte as Field); } for byte in signature { args.push(byte as Field); } args.push(partial_address); - let mut context = Context::new(inputs, abi::hash_args(args.storage)); + let mut context = PrivateContext::new(inputs, abi::hash_args(args.storage)); // Verify payload signature let payload_fields: [Field; entrypoint::ENTRYPOINT_PAYLOAD_SIZE] = payload.serialize(); @@ -56,7 +56,7 @@ contract SchnorrSingleKeyAccount { // Verify public key against address let reproduced_address = dep::std::hash::pedersen_with_separator([x, y, partial_address], GENERATOR_INDEX__CONTRACT_ADDRESS)[0]; - assert(reproduced_address == inputs.call_context.storage_contract_address); + assert(reproduced_address == context.this_address()); // Execute calls payload.execute_calls(&mut context); @@ -69,6 +69,6 @@ contract SchnorrSingleKeyAccount { inputs: pub PrivateContextInputs, ) -> distinct pub abi::PrivateCircuitPublicInputs { // Return private circuit public inputs. All private functions need to return this as it is part of the input of the private kernel. - Context::new(inputs, 0).finish() + PrivateContext::new(inputs, 0).finish() } } diff --git a/yarn-project/noir-contracts/src/contracts/test_contract/src/main.nr b/yarn-project/noir-contracts/src/contracts/test_contract/src/main.nr index 33c03660f08..c8efeae1edb 100644 --- a/yarn-project/noir-contracts/src/contracts/test_contract/src/main.nr +++ b/yarn-project/noir-contracts/src/contracts/test_contract/src/main.nr @@ -8,7 +8,10 @@ contract Test { PrivateContextInputs } }; - use dep::aztec::context::Context; + use dep::aztec::context::{ + PrivateContext, + PublicContext + }; use dep::aztec::oracle::{ create_l2_to_l1_message::create_l2_to_l1_message, @@ -22,14 +25,14 @@ contract Test { inputs: PrivateContextInputs, ) -> distinct pub abi::PrivateCircuitPublicInputs { // Return private circuit public inputs. All private functions need to return this as it is part of the input of the private kernel. - Context::new(inputs, 0).finish() + PrivateContext::new(inputs, 0).finish() } fn getPublicKey( inputs: PrivateContextInputs, address: Field, ) -> distinct pub abi::PrivateCircuitPublicInputs { - let mut context = Context::new(inputs, abi::hash_args([address])); + let mut context = PrivateContext::new(inputs, abi::hash_args([address])); let pub_key = get_public_key(address); context.return_values.push_array([pub_key.x, pub_key.y]); context.finish() @@ -40,7 +43,7 @@ contract Test { inputs: PrivateContextInputs, aztec_address: Field ) -> distinct pub abi::PrivateCircuitPublicInputs { - let mut context = Context::new(inputs, abi::hash_args([])); + let mut context = PrivateContext::new(inputs, abi::hash_args([])); let portal_address = get_portal_address(aztec_address); context.return_values.push_array([portal_address]); context.finish() @@ -50,7 +53,7 @@ contract Test { fn getThisPortalAddress( inputs: PrivateContextInputs, ) -> distinct pub abi::PrivateCircuitPublicInputs { - let mut context = Context::new(inputs, abi::hash_args([])); + let mut context = PrivateContext::new(inputs, abi::hash_args([])); let this_portal_address = context.this_portal_address(); context.return_values.push_array([this_portal_address]); context.finish() @@ -60,7 +63,7 @@ contract Test { fn getThisAddress( inputs: PrivateContextInputs, ) -> distinct pub abi::PrivateCircuitPublicInputs { - let mut context = Context::new(inputs, abi::hash_args([])); + let mut context = PrivateContext::new(inputs, abi::hash_args([])); let this_address = context.this_address(); context.return_values.push_array([this_address]); context.finish() @@ -93,37 +96,42 @@ contract Test { args.push(note.secretHash); } let args_hash = abi::hash_args(args.storage); - let mut context = Context::new(inputs, args_hash); + let mut context = PrivateContext::new(inputs, args_hash); context.return_values.push(args_hash); context.finish() } // Purely exists for testing open fn createL2ToL1MessagePublic( - _inputs: PublicContextInputs, + inputs: PublicContextInputs, amount: Field, secretHash: Field, - ) { + ) -> pub abi::PublicCircuitPublicInputs { + let mut context = PublicContext::new(inputs, abi::hash_args([amount, secretHash])); // Create a commitment to the amount let note = DummyNote::new(amount, secretHash); // Public oracle call to emit new commitment. create_l2_to_l1_message(note.get_commitment()); + + context.finish() } // Purely exists for testing open fn createNullifierPublic( - _inputs: PublicContextInputs, + inputs: PublicContextInputs, amount: Field, secretHash: Field, - ) -> pub Field { + ) -> pub abi::PublicCircuitPublicInputs { + let mut context = PublicContext::new(inputs, abi::hash_args([amount, secretHash])); // Create a commitment to the amount let note = DummyNote::new(amount, secretHash); // Public oracle call to emit new commitment. create_nullifier(note.get_commitment()); - 0 + + context.finish() } // Purely exists for testing diff --git a/yarn-project/noir-contracts/src/contracts/test_contract/src/test_contract_interface.nr b/yarn-project/noir-contracts/src/contracts/test_contract/src/test_contract_interface.nr index 32603d90544..c9d32dc8e7d 100644 --- a/yarn-project/noir-contracts/src/contracts/test_contract/src/test_contract_interface.nr +++ b/yarn-project/noir-contracts/src/contracts/test_contract/src/test_contract_interface.nr @@ -1,7 +1,7 @@ /* Autogenerated file, do not edit! */ use dep::std; -use dep::aztec::context::Context; +use dep::aztec::context::PrivateContext; use dep::aztec::constants_gen::RETURN_VALUES_LENGTH; struct AStructTestCodeGenStruct { @@ -39,7 +39,7 @@ impl TestContractInterface { fn createL2ToL1MessagePublic( self, - context: &mut Context, + context: &mut PrivateContext, amount: Field, secretHash: Field ) { @@ -53,7 +53,7 @@ impl TestContractInterface { fn createNullifierPublic( self, - context: &mut Context, + context: &mut PrivateContext, amount: Field, secretHash: Field ) { @@ -67,7 +67,7 @@ impl TestContractInterface { fn getPortalContractAddress( self, - context: &mut Context, + context: &mut PrivateContext, aztec_address: Field ) -> [Field; RETURN_VALUES_LENGTH] { let mut serialised_args = [0; 1]; @@ -79,7 +79,7 @@ impl TestContractInterface { fn getPublicKey( self, - context: &mut Context, + context: &mut PrivateContext, address: Field ) -> [Field; RETURN_VALUES_LENGTH] { let mut serialised_args = [0; 1]; @@ -91,7 +91,7 @@ impl TestContractInterface { fn getThisAddress( self, - context: &mut Context + context: &mut PrivateContext ) -> [Field; RETURN_VALUES_LENGTH] { let mut serialised_args = [0; 0]; @@ -101,7 +101,7 @@ impl TestContractInterface { fn getThisPortalAddress( self, - context: &mut Context + context: &mut PrivateContext ) -> [Field; RETURN_VALUES_LENGTH] { let mut serialised_args = [0; 0]; @@ -111,7 +111,7 @@ impl TestContractInterface { fn testCodeGen( self, - context: &mut Context, + context: &mut PrivateContext, aField: Field, aBool: bool, aNumber: u32, diff --git a/yarn-project/noir-contracts/src/contracts/uniswap_contract/src/main.nr b/yarn-project/noir-contracts/src/contracts/uniswap_contract/src/main.nr index f8c213173cd..61992b1b253 100644 --- a/yarn-project/noir-contracts/src/contracts/uniswap_contract/src/main.nr +++ b/yarn-project/noir-contracts/src/contracts/uniswap_contract/src/main.nr @@ -3,7 +3,7 @@ contract Uniswap { use dep::aztec::abi; use dep::aztec::abi::PrivateContextInputs; use dep::aztec::abi::PublicContextInputs; - use dep::aztec::context::Context; + use dep::aztec::context::PrivateContext; use dep::aztec::oracle::{ public_call, context::get_portal_address @@ -16,7 +16,7 @@ contract Uniswap { inputs: PrivateContextInputs, ) -> distinct pub abi::PrivateCircuitPublicInputs { // Return private circuit public inputs. All private functions need to return this as it is part of the input of the private kernel. - Context::new(inputs, 0).finish() + PrivateContext::new(inputs, 0).finish() } // What we need to make this nicer: @@ -42,7 +42,7 @@ contract Uniswap { cancellerForL1ToL2Message: Field, // L1 address of who can cancel the message to consume assets on L2. callerOnL1: Field, // ethereum address that can call this function on the L1 portal (0x0 if anyone can call) ) -> distinct pub abi::PrivateCircuitPublicInputs { - let mut context = Context::new(inputs, abi::hash_args([ + let mut context = PrivateContext::new(inputs, abi::hash_args([ withdrawFnSelector, inputAsset, inputAmount, diff --git a/yarn-project/noir-libs/easy-private-state/src/easy_private_state.nr b/yarn-project/noir-libs/easy-private-state/src/easy_private_state.nr index 5bbb77e3608..5bbbf082825 100644 --- a/yarn-project/noir-libs/easy-private-state/src/easy_private_state.nr +++ b/yarn-project/noir-libs/easy-private-state/src/easy_private_state.nr @@ -8,7 +8,7 @@ use dep::value_note::{ }; use dep::aztec::{ - context::Context, + context::PrivateContext, log::emit_encrypted_log, note::note_getter_options::NoteGetterOptions, oracle::get_public_key::get_public_key, @@ -39,7 +39,7 @@ impl EasyPrivateUint { // Very similar to `send_note`. fn add( self, - context: &mut Context, + context: &mut PrivateContext, addend: u120, owner: Field, ) { @@ -53,7 +53,7 @@ impl EasyPrivateUint { let owner_key = get_public_key(owner); emit_encrypted_log( context, - context.inputs.call_context.storage_contract_address, + (*context).this_address(), self.set.storage_slot, owner_key, addend_note.serialise(), @@ -63,7 +63,7 @@ impl EasyPrivateUint { // Very similar to `spend_note`. fn sub( self, - context: &mut Context, + context: &mut PrivateContext, subtrahend: u120, owner: Field, ) { @@ -106,7 +106,7 @@ impl EasyPrivateUint { emit_encrypted_log( context, - context.inputs.call_context.storage_contract_address, + (*context).this_address(), self.set.storage_slot, owner_key, encrypted_data, diff --git a/yarn-project/noir-libs/noir-aztec/src/abi.nr b/yarn-project/noir-libs/noir-aztec/src/abi.nr index a8a861349de..4e0b93b0839 100644 --- a/yarn-project/noir-libs/noir-aztec/src/abi.nr +++ b/yarn-project/noir-libs/noir-aztec/src/abi.nr @@ -10,7 +10,7 @@ use crate::constants_gen::{ MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, MAX_PUBLIC_DATA_READS_PER_CALL, GENERATOR_INDEX__FUNCTION_ARGS, - CONSTANT_HISTORIC_BLOCK_DATA_LENGTH, + HISTORIC_BLOCK_DATA_LENGTH, CONTRACT_DEPLOYMENT_DATA_LENGTH, CALL_CONTEXT_LENGTH, PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH, @@ -132,27 +132,27 @@ struct HistoricBlockData { contract_tree_root : Field, l1_to_l2_messages_tree_root : Field, blocks_tree_root: Field, - prev_global_variables_hash: Field, public_data_tree_root: Field, + global_variables_hash: Field, } impl HistoricBlockData { // NOTE: this order must match the order in `private_circuit_public_inputs.hpp` - fn serialize(self) -> [Field; CONSTANT_HISTORIC_BLOCK_DATA_LENGTH] { + fn serialize(self) -> [Field; HISTORIC_BLOCK_DATA_LENGTH] { [ self.private_data_tree_root, self.nullifier_tree_root, self.contract_tree_root, self.l1_to_l2_messages_tree_root, self.blocks_tree_root, - self.prev_global_variables_hash, - self.public_data_tree_root + self.public_data_tree_root, + self.global_variables_hash, ] } -} -fn empty_block_data() -> HistoricBlockData { - HistoricBlockData{ private_data_tree_root: 0, nullifier_tree_root: 0, contract_tree_root: 0, l1_to_l2_messages_tree_root: 0, blocks_tree_root: 0, prev_global_variables_hash: 0, public_data_tree_root: 0 } + fn empty() -> Self { + Self { private_data_tree_root: 0, nullifier_tree_root: 0, contract_tree_root: 0, l1_to_l2_messages_tree_root: 0, blocks_tree_root: 0, public_data_tree_root: 0, global_variables_hash: 0 } + } } struct FunctionData { @@ -249,10 +249,6 @@ struct ContractStorageRead { value: Field, } -fn empty_contract_storage_read() -> ContractStorageRead { - ContractStorageRead { storage_slot: 0, value: 0 } -} - impl ContractStorageRead { fn serialize(self) -> [Field; CONTRACT_STORAGE_READ_LENGTH] { [self.storage_slot, self.value] @@ -261,6 +257,10 @@ impl ContractStorageRead { fn hash(self) -> Field { dep::std::hash::pedersen_with_separator(self.serialize(), GENERATOR_INDEX__PUBLIC_DATA_READ)[0] } + + fn empty() -> Self { + Self { storage_slot: 0, value: 0 } + } } struct ContractStorageUpdateRequest { @@ -277,10 +277,10 @@ impl ContractStorageUpdateRequest { fn hash(self) -> Field { dep::std::hash::pedersen_with_separator(self.serialize(), GENERATOR_INDEX__PUBLIC_DATA_UPDATE_REQUEST)[0] } -} -fn empty_contract_storage_update_request() -> ContractStorageUpdateRequest { - ContractStorageUpdateRequest { storage_slot: 0, old_value: 0, new_value: 0 } + fn empty() -> Self { + Self { storage_slot: 0, old_value: 0, new_value: 0 } + } } @@ -297,8 +297,10 @@ struct PublicCircuitPublicInputs { unencrypted_logs_hash: [Field; NUM_FIELDS_PER_SHA256], unencrypted_log_preimages_length: Field, block_data: HistoricBlockData, - historic_public_data_tree_root: Field, prover_address: Field, + + // TODO: include globals in here and check them elsewhere + // https://github.com/AztecProtocol/aztec-packages/issues/1567 } impl PublicCircuitPublicInputs { @@ -320,11 +322,10 @@ impl PublicCircuitPublicInputs { inputs.push_array(self.new_l2_to_l1_msgs); // We do not include block_data since it's not in the cpp hash - // inputs.push(self.block_data.hash()); see https://github.com/AztecProtocol/aztec-packages/issues/1473 inputs.push_array(self.unencrypted_logs_hash); inputs.push(self.unencrypted_log_preimages_length); - inputs.push(self.historic_public_data_tree_root); + inputs.push_array(self.block_data.serialize()); // see https://github.com/AztecProtocol/aztec-packages/issues/1473 inputs.push(self.prover_address); dep::std::hash::pedersen_with_separator(inputs.storage, GENERATOR_INDEX__PUBLIC_CIRCUIT_PUBLIC_INPUTS)[0] @@ -348,7 +349,6 @@ impl PublicCircuitPublicInputs { fields.push_array(self.unencrypted_logs_hash); fields.push(self.unencrypted_log_preimages_length); fields.push_array(self.block_data.serialize()); - fields.push(self.historic_public_data_tree_root); fields.push(self.prover_address); fields.storage } diff --git a/yarn-project/noir-libs/noir-aztec/src/constants_gen.nr b/yarn-project/noir-libs/noir-aztec/src/constants_gen.nr index 5eee6127df7..aac66a0a8d7 100644 --- a/yarn-project/noir-libs/noir-aztec/src/constants_gen.nr +++ b/yarn-project/noir-libs/noir-aztec/src/constants_gen.nr @@ -50,7 +50,7 @@ global GET_NOTE_ORACLE_RETURN_LENGTH: comptime Field = 23; global MAX_NOTES_PER_PAGE: comptime Field = 10; global VIEW_NOTE_ORACLE_RETURN_LENGTH: comptime Field = 212; global CALL_CONTEXT_LENGTH: comptime Field = 6; -global CONSTANT_HISTORIC_BLOCK_DATA_LENGTH: comptime Field = 7; +global HISTORIC_BLOCK_DATA_LENGTH: comptime Field = 7; global FUNCTION_DATA_LENGTH: comptime Field = 4; global CONTRACT_DEPLOYMENT_DATA_LENGTH: comptime Field = 6; global PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH: comptime Field = 58; @@ -60,7 +60,7 @@ global PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH: comptime Field = 77; global GET_NOTES_ORACLE_RETURN_LENGTH: comptime Field = 86; global EMPTY_NULLIFIED_COMMITMENT: comptime Field = 1000000; global CALL_PRIVATE_FUNCTION_RETURN_SIZE: comptime Field = 64; -global PUBLIC_CIRCUIT_PUBLIC_INPUTS_HASH_INPUT_LENGTH: comptime Field = 41; +global PUBLIC_CIRCUIT_PUBLIC_INPUTS_HASH_INPUT_LENGTH: comptime Field = 47; global PRIVATE_CIRCUIT_PUBLIC_INPUTS_HASH_INPUT_LENGTH: comptime Field = 48; global COMMITMENTS_NUM_BYTES_PER_BASE_ROLLUP: comptime Field = 1024; global NULLIFIERS_NUM_BYTES_PER_BASE_ROLLUP: comptime Field = 1024; diff --git a/yarn-project/noir-libs/noir-aztec/src/context.nr b/yarn-project/noir-libs/noir-aztec/src/context.nr index 7923a70b0f6..b7da9ee519c 100644 --- a/yarn-project/noir-libs/noir-aztec/src/context.nr +++ b/yarn-project/noir-libs/noir-aztec/src/context.nr @@ -15,9 +15,6 @@ use crate::constants_gen::{ use crate::abi; use crate::abi::{ - empty_block_data, - empty_contract_storage_read, - empty_contract_storage_update_request, hash_args, CallContext, ContractDeploymentData, @@ -52,7 +49,7 @@ use crate::oracle::{ // When finished, one can call .finish() to convert back to the abi -struct Context { +struct PrivateContext { inputs: abi::PrivateContextInputs, args_hash : Field, @@ -68,14 +65,16 @@ struct Context { public_call_stack : BoundedVec, new_l2_to_l1_msgs : BoundedVec, + block_data: HistoricBlockData, + // TODO(https://github.com/AztecProtocol/aztec-packages/issues/1165) // encrypted_logs_preimages: Vec, // unencrypted_logs_preimages: Vec, } -impl Context { - fn new(inputs: abi::PrivateContextInputs, args_hash: Field) -> Context { - Context { +impl PrivateContext { + fn new(inputs: abi::PrivateContextInputs, args_hash: Field) -> PrivateContext { + PrivateContext { inputs: inputs, args_hash: args_hash, @@ -87,6 +86,8 @@ impl Context { new_nullifiers: BoundedVec::new(0), nullified_commitments: BoundedVec::new(0), + block_data: inputs.block_data, + private_call_stack: BoundedVec::new(0), public_call_stack: BoundedVec::new(0), new_l2_to_l1_msgs: BoundedVec::new(0), @@ -139,7 +140,7 @@ impl Context { unencrypted_logs_hash: unencrypted_logs_hash, encrypted_log_preimages_length: encrypted_log_preimages_length, unencrypted_log_preimages_length: unencrypted_log_preimages_length, - block_data: self.inputs.block_data, + block_data: self.block_data, contract_deployment_data: self.inputs.contract_deployment_data, chain_id: self.inputs.private_global_variables.chain_id, version: self.inputs.private_global_variables.version, @@ -254,8 +255,8 @@ impl Context { contract_tree_root : fields[50], l1_to_l2_messages_tree_root : fields[51], blocks_tree_root : fields[52], - prev_global_variables_hash: fields[53], - public_data_tree_root: fields[54], + public_data_tree_root: fields[53], + global_variables_hash: fields[54], }, contract_deployment_data: ContractDeploymentData { deployer_public_key: Point::new(fields[55], fields[56]), @@ -341,16 +342,15 @@ impl Context { }, args_hash: fields[11], return_values: [0; RETURN_VALUES_LENGTH], - contract_storage_update_requests: [empty_contract_storage_update_request(); MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL], - contract_storage_read: [empty_contract_storage_read(); MAX_PUBLIC_DATA_READS_PER_CALL], + contract_storage_update_requests: [ContractStorageUpdateRequest::empty(); MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL], + contract_storage_read: [ContractStorageRead::empty(); MAX_PUBLIC_DATA_READS_PER_CALL], public_call_stack: [0; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL], new_commitments: [0; MAX_NEW_COMMITMENTS_PER_CALL], new_nullifiers: [0; MAX_NEW_NULLIFIERS_PER_CALL], new_l2_to_l1_msgs:[0; MAX_NEW_L2_TO_L1_MSGS_PER_CALL], unencrypted_logs_hash:[0; NUM_FIELDS_PER_SHA256], unencrypted_log_preimages_length: 0, - block_data: empty_block_data(), - historic_public_data_tree_root: 0, + block_data: HistoricBlockData::empty(), prover_address: 0, }, is_execution_request: true, @@ -374,3 +374,178 @@ impl Context { self.public_call_stack.push(item.hash()); } } + +use crate::abi::{ + ContractStorageRead, + ContractStorageUpdateRequest +}; + +struct PublicContext { + inputs: abi::PublicContextInputs, + + args_hash : Field, + return_values : BoundedVec, + + contract_storage_update_requests: BoundedVec, + contract_storage_read: BoundedVec, + public_call_stack: BoundedVec, + + new_commitments: BoundedVec, + new_nullifiers: BoundedVec, + + new_l2_to_l1_msgs: BoundedVec, + + unencrypted_logs_hash: BoundedVec, + unencrypted_logs_preimages_length: Field, + + block_data: HistoricBlockData, + prover_address: Field, +} + +impl PublicContext { + fn new(inputs: abi::PublicContextInputs, args_hash: Field) -> PublicContext { + let empty_storage_read = ContractStorageRead::empty(); + let empty_storage_update = ContractStorageUpdateRequest::empty(); + PublicContext { + inputs: inputs, + + args_hash: args_hash, + return_values: BoundedVec::new(0), + + contract_storage_update_requests: BoundedVec::new(empty_storage_update), + contract_storage_read: BoundedVec::new(empty_storage_read), + public_call_stack: BoundedVec::new(0), + + new_commitments: BoundedVec::new(0), + new_nullifiers: BoundedVec::new(0), + + new_l2_to_l1_msgs: BoundedVec::new(0), + + + unencrypted_logs_hash: BoundedVec::new(0), + unencrypted_logs_preimages_length: 0, + + block_data: inputs.block_data, + prover_address: 0, + + // TODO(https://github.com/AztecProtocol/aztec-packages/issues/1165) + // encrypted_logs_preimages: Vec::new(), + // unencrypted_logs_preimages: Vec::new(), + } + } + + fn msg_sender(self) -> Field { + self.inputs.call_context.msg_sender + } + + fn this_address(self) -> Field { + self.inputs.call_context.storage_contract_address + } + + fn this_portal_address(self) -> Field { + self.inputs.call_context.portal_contract_address + } + + fn chain_id(self) -> Field { + self.inputs.public_global_variables.chain_id + } + + fn version(self) -> Field { + self.inputs.public_global_variables.version + } + + fn block_number(self) -> Field { + self.inputs.public_global_variables.block_number + } + + fn timestamp(self) -> Field { + self.inputs.public_global_variables.timestamp + } + + fn finish(self) -> abi::PublicCircuitPublicInputs { + // TODO(https://github.com/AztecProtocol/aztec-packages/issues/1165) + let unencrypted_logs_hash = [0; NUM_FIELDS_PER_SHA256]; + let unencrypted_log_preimages_length = 0; + + + // Compute the public call stack hashes + let pub_circuit_pub_inputs = abi::PublicCircuitPublicInputs { + call_context: self.inputs.call_context, // Done + args_hash: self.args_hash, // Done + contract_storage_update_requests: self.contract_storage_update_requests.storage, + contract_storage_read: self.contract_storage_read.storage, + return_values: self.return_values.storage, + new_commitments: self.new_commitments.storage, + new_nullifiers: self.new_nullifiers.storage, + public_call_stack: self.public_call_stack.storage, + new_l2_to_l1_msgs: self.new_l2_to_l1_msgs.storage, + unencrypted_logs_hash: unencrypted_logs_hash, + unencrypted_log_preimages_length: unencrypted_log_preimages_length, + block_data: self.inputs.block_data, + prover_address: self.prover_address, + }; + pub_circuit_pub_inputs + } + + fn push_new_note_hash(&mut self, note_hash: Field) { + self.new_commitments.push(note_hash); + } + + fn push_new_nullifier(&mut self, nullifier: Field, _nullified_commitment: Field) { + self.new_nullifiers.push(nullifier); + } + + fn message_portal(&mut self, msg: Field) { + self.new_l2_to_l1_msgs.push(msg); + } + + // PrivateContextInputs must be temporarily passed in to prevent too many unknowns + // Note this returns self to get around an issue where mutable structs do not maintain mutations unless reassigned + fn consume_l1_to_l2_message(&mut self, msg_key: Field, content: Field, secret: Field) { + let this = (*self).this_address(); + let nullifier = process_l1_to_l2_message(self.block_data.l1_to_l2_messages_tree_root, this, msg_key, content, secret); + + // Push nullifier (and the "commitment" corresponding to this can be "empty") + self.push_new_nullifier(nullifier, EMPTY_NULLIFIED_COMMITMENT) + } + + fn accumulate_encrypted_logs(&mut self, log: [Field; N]) { + let _void1 = self; + let _void2 = log; + // TODO(https://github.com/AztecProtocol/aztec-packages/issues/1165) + } + + fn accumulate_unencrypted_logs(&mut self, log: T) { + let _void1 = self; + let _void2 = log; + // TODO(https://github.com/AztecProtocol/aztec-packages/issues/1165) + } + + fn call_public_function( + _self: Self, + contract_address: Field, + function_selector: Field, + args: [Field; ARGS_COUNT], + ) -> [Field; RETURN_VALUES_LENGTH] { + let args_hash = abi::hash_args(args); + assert(args_hash == arguments::pack_arguments(args)); + call_public_function_internal( + contract_address, + function_selector, + args_hash, + ) + } + + fn call_public_function_no_args( + _self: Self, + contract_address: Field, + function_selector: Field, + ) -> [Field; RETURN_VALUES_LENGTH] { + call_public_function_internal( + contract_address, + function_selector, + 0, + ) + } + +} \ No newline at end of file diff --git a/yarn-project/noir-libs/noir-aztec/src/entrypoint.nr b/yarn-project/noir-libs/noir-aztec/src/entrypoint.nr index c812612f1ad..bad450d75db 100644 --- a/yarn-project/noir-libs/noir-aztec/src/entrypoint.nr +++ b/yarn-project/noir-libs/noir-aztec/src/entrypoint.nr @@ -1,6 +1,6 @@ use crate::abi; use crate::types::vec::BoundedVec; -use crate::context::Context; +use crate::context::PrivateContext; use crate::private_call_stack_item::PrivateCallStackItem; use crate::public_call_stack_item::PublicCallStackItem; @@ -88,7 +88,7 @@ impl EntrypointPayload { } // Executes all private and public calls - fn execute_calls(self, context: &mut Context) { + fn execute_calls(self, context: &mut PrivateContext) { for i in 0..ACCOUNT_MAX_PRIVATE_CALLS { let target_address = self.flattened_targets[i]; if target_address != 0 { diff --git a/yarn-project/noir-libs/noir-aztec/src/log.nr b/yarn-project/noir-libs/noir-aztec/src/log.nr index 2077eb2f778..5ddbe4c5605 100644 --- a/yarn-project/noir-libs/noir-aztec/src/log.nr +++ b/yarn-project/noir-libs/noir-aztec/src/log.nr @@ -1,9 +1,9 @@ -use crate::context::Context; +use crate::context::PrivateContext; use crate::oracle; use crate::types::point::Point; fn emit_encrypted_log( - context: &mut Context, + context: &mut PrivateContext, contract_address: Field, storage_slot: Field, encryption_pub_key: Point, @@ -14,7 +14,7 @@ fn emit_encrypted_log( } fn emit_unencrypted_log( - context: &mut Context, + context: &mut PrivateContext, log: T, ) { let _ = oracle::logs::emit_unencrypted_log(log); diff --git a/yarn-project/noir-libs/noir-aztec/src/note/lifecycle.nr b/yarn-project/noir-libs/noir-aztec/src/note/lifecycle.nr index ff5a1b45082..ddea040a624 100644 --- a/yarn-project/noir-libs/noir-aztec/src/note/lifecycle.nr +++ b/yarn-project/noir-libs/noir-aztec/src/note/lifecycle.nr @@ -1,5 +1,8 @@ use crate::abi::PublicContextInputs; -use crate::context::Context; +use crate::context::{ + PrivateContext, + PublicContext, +}; use crate::note::{ note_header::NoteHeader, note_interface::NoteInterface, @@ -11,12 +14,12 @@ use crate::constants_gen::EMPTY_NULLIFIED_COMMITMENT; use crate::types::option::Option; fn create_note( - context: &mut Context, + context: &mut PrivateContext, storage_slot: Field, note: &mut Note, note_interface: NoteInterface, ) { - let contract_address = context.inputs.call_context.storage_contract_address; + let contract_address = (*context).this_address(); let header = NoteHeader { contract_address, storage_slot, nonce: 0 }; let set_header = note_interface.set_header; @@ -31,12 +34,12 @@ fn create_note( } fn create_note_hash_from_public( - inputs: PublicContextInputs, + context: PublicContext, storage_slot: Field, note: &mut Note, note_interface: NoteInterface, ) { - let contract_address = inputs.call_context.storage_contract_address; + let contract_address = context.this_address(); let header = NoteHeader { contract_address, storage_slot, nonce: 0 }; let set_header = note_interface.set_header; @@ -47,7 +50,7 @@ fn create_note_hash_from_public( } fn destroy_note( - context: &mut Context, + context: &mut PrivateContext, storage_slot: Field, note: Note, note_interface: NoteInterface, diff --git a/yarn-project/noir-libs/noir-aztec/src/note/note_getter.nr b/yarn-project/noir-libs/noir-aztec/src/note/note_getter.nr index af17c68ceb2..b9d0f07baa6 100644 --- a/yarn-project/noir-libs/noir-aztec/src/note/note_getter.nr +++ b/yarn-project/noir-libs/noir-aztec/src/note/note_getter.nr @@ -5,7 +5,7 @@ use crate::constants_gen::{ MAX_NOTES_PER_PAGE, VIEW_NOTE_ORACLE_RETURN_LENGTH, }; -use crate::context::Context; +use crate::context::PrivateContext; use crate::note::{ note_getter_options::NoteGetterOptions, note_interface::NoteInterface, @@ -20,20 +20,20 @@ use crate::oracle; use crate::types::option::Option; fn check_note_header( - context: Context, + context: PrivateContext, storage_slot: Field, note_interface: NoteInterface, note: Note, ) { let get_header = note_interface.get_header; let header = get_header(note); - let contract_address = context.inputs.call_context.storage_contract_address; + let contract_address = context.this_address(); assert(header.contract_address == contract_address); assert(header.storage_slot == storage_slot); } fn ensure_note_exists( - context: &mut Context, + context: &mut PrivateContext, storage_slot: Field, note_interface: NoteInterface, note: &mut Note, @@ -56,7 +56,7 @@ fn ensure_note_exists( // notes via the oracle. // Modifies the note by populating it with header info. fn ensure_note_hash_exists( - context: &mut Context, + context: &mut PrivateContext, storage_slot: Field, note_interface: NoteInterface, note: &mut Note, @@ -67,7 +67,7 @@ fn ensure_note_hash_exists( // - and the nonce (used in the unique siloed note hash) let set_header = note_interface.set_header; let note_header = NoteHeader { - contract_address: context.inputs.call_context.storage_contract_address, + contract_address: (*context).this_address(), // TODO(https://github.com/AztecProtocol/aztec-packages/issues/1386): should be // real nonce (once public kernel applies nonces). nonce: 0, @@ -98,7 +98,7 @@ fn ensure_note_hash_exists( } fn get_note( - context: &mut Context, + context: &mut PrivateContext, storage_slot: Field, note_interface: NoteInterface, ) -> Note { @@ -113,7 +113,7 @@ fn get_note( } fn get_notes( - context: &mut Context, + context: &mut PrivateContext, storage_slot: Field, note_interface: NoteInterface, options: NoteGetterOptions, diff --git a/yarn-project/noir-libs/noir-aztec/src/public_call_stack_item.nr b/yarn-project/noir-libs/noir-aztec/src/public_call_stack_item.nr index 7942f16032a..25318b221c3 100644 --- a/yarn-project/noir-libs/noir-aztec/src/public_call_stack_item.nr +++ b/yarn-project/noir-libs/noir-aztec/src/public_call_stack_item.nr @@ -13,8 +13,6 @@ use crate::constants_gen::{ // oracles use crate::oracle::{ enqueue_public_function_call::enqueue_public_function_call_internal, - public_call::call_public_function_internal, - arguments, }; struct PublicCallStackItem { @@ -34,28 +32,3 @@ impl PublicCallStackItem { } } -// An open function doesn't have a context, so we call this pure function instead of going via Context. -fn call_public_function( - contract_address: Field, - function_selector: Field, - args: [Field; N], -) -> [Field; RETURN_VALUES_LENGTH] { - let args_hash = abi::hash_args(args); - assert(args_hash == arguments::pack_arguments(args)); - call_public_function_internal( - contract_address, - function_selector, - args_hash, - ) -} - -fn call_public_function_no_args( - contract_address: Field, - function_selector: Field, -) -> [Field; RETURN_VALUES_LENGTH] { - call_public_function_internal( - contract_address, - function_selector, - 0, - ) -} diff --git a/yarn-project/noir-libs/noir-aztec/src/state_vars/immutable_singleton.nr b/yarn-project/noir-libs/noir-aztec/src/state_vars/immutable_singleton.nr index a04c3b6afda..461405799f9 100644 --- a/yarn-project/noir-libs/noir-aztec/src/state_vars/immutable_singleton.nr +++ b/yarn-project/noir-libs/noir-aztec/src/state_vars/immutable_singleton.nr @@ -1,5 +1,5 @@ use dep::std::hash::pedersen_with_separator; -use crate::context::Context; +use crate::context::PrivateContext; use crate::note::lifecycle::create_note; use crate::note::note_getter::{ get_note, @@ -27,7 +27,7 @@ impl ImmutableSingleton { oracle::notes::is_nullifier_emitted(nullifier) } - fn initialise(self, context: &mut Context, note: &mut Note) { + fn initialise(self, context: &mut PrivateContext, note: &mut Note) { // Nullify the storage slot. let nullifier = self.compute_initialisation_nullifier(); context.push_new_nullifier(nullifier, EMPTY_NULLIFIED_COMMITMENT); @@ -39,12 +39,12 @@ impl ImmutableSingleton { pedersen_with_separator([self.storage_slot], GENERATOR_INDEX__INITIALISATION_NULLIFIER)[0] } - fn get_note(self, context: &mut Context) -> Note { + fn get_note(self, context: &mut PrivateContext) -> Note { let storage_slot = self.storage_slot; get_note(context, storage_slot, self.note_interface) } - fn assert_contains(self, context: &mut Context, note: &mut Note) { + fn assert_contains(self, context: &mut PrivateContext, note: &mut Note) { ensure_note_exists(context, self.storage_slot, self.note_interface, note); } } \ No newline at end of file diff --git a/yarn-project/noir-libs/noir-aztec/src/state_vars/set.nr b/yarn-project/noir-libs/noir-aztec/src/state_vars/set.nr index 28e9f3ccd38..1d38cbe608d 100644 --- a/yarn-project/noir-libs/noir-aztec/src/state_vars/set.nr +++ b/yarn-project/noir-libs/noir-aztec/src/state_vars/set.nr @@ -1,5 +1,8 @@ use crate::abi::PublicContextInputs; -use crate::context::Context; +use crate::context::{ + PrivateContext, + PublicContext, +}; use crate::note::lifecycle::{create_note, create_note_hash_from_public, destroy_note}; use crate::note::{ note_getter::{get_notes, ensure_note_exists, ensure_note_hash_exists}, @@ -19,32 +22,32 @@ impl Set { Set { storage_slot, note_interface } } - fn insert(self, context: &mut Context, note: &mut Note) { + fn insert(self, context: &mut PrivateContext, note: &mut Note) { create_note(context, self.storage_slot, note, self.note_interface); } - fn insert_from_public(self, inputs: PublicContextInputs, note: &mut Note) { - create_note_hash_from_public(inputs, self.storage_slot, note, self.note_interface); + fn insert_from_public(self, context: PublicContext, note: &mut Note) { + create_note_hash_from_public(context, self.storage_slot, note, self.note_interface); } - fn assert_contains(self, context: &mut Context, note: &mut Note) { + fn assert_contains(self, context: &mut PrivateContext, note: &mut Note) { ensure_note_exists(context, self.storage_slot, self.note_interface, note); } // TODO(https://github.com/AztecProtocol/aztec-packages/issues/1386): rename to // `assert_contains` and replace function above ^ once public kernel injects // nonces to note hashes. - fn assert_contains_note_hash(self, context: &mut Context, note: &mut Note) { + fn assert_contains_note_hash(self, context: &mut PrivateContext, note: &mut Note) { ensure_note_hash_exists(context, self.storage_slot, self.note_interface, note) } - fn remove(self, context: &mut Context, note: Note) { + fn remove(self, context: &mut PrivateContext, note: Note) { destroy_note(context, self.storage_slot, note, self.note_interface); } fn get_notes( self, - context: &mut Context, + context: &mut PrivateContext, options: NoteGetterOptions, ) -> [Option; S] { let storage_slot = self.storage_slot; diff --git a/yarn-project/noir-libs/noir-aztec/src/state_vars/singleton.nr b/yarn-project/noir-libs/noir-aztec/src/state_vars/singleton.nr index 510bad40512..d6eb1c7725b 100644 --- a/yarn-project/noir-libs/noir-aztec/src/state_vars/singleton.nr +++ b/yarn-project/noir-libs/noir-aztec/src/state_vars/singleton.nr @@ -1,5 +1,5 @@ use dep::std::hash::pedersen_with_separator; -use crate::context::Context; +use crate::context::PrivateContext; use crate::oracle; use crate::note::{ lifecycle::{ @@ -29,7 +29,7 @@ impl Singleton { oracle::notes::is_nullifier_emitted(nullifier) } - fn initialise(self, context: &mut Context, note: &mut Note) { + fn initialise(self, context: &mut PrivateContext, note: &mut Note) { // Nullify the storage slot. let nullifier = self.compute_initialisation_nullifier(); context.push_new_nullifier(nullifier, EMPTY_NULLIFIED_COMMITMENT); @@ -41,7 +41,7 @@ impl Singleton { pedersen_with_separator([self.storage_slot], GENERATOR_INDEX__INITIALISATION_NULLIFIER)[0] } - fn replace(self, context: &mut Context, new_note: &mut Note) { + fn replace(self, context: &mut PrivateContext, new_note: &mut Note) { let prev_note = get_note(context, self.storage_slot, self.note_interface); // Nullify previous note. @@ -51,7 +51,7 @@ impl Singleton { create_note(context, self.storage_slot, new_note, self.note_interface); } - fn get_note(self, context: &mut Context) -> Note { + fn get_note(self, context: &mut PrivateContext) -> Note { let mut note = get_note(context, self.storage_slot, self.note_interface); // Nullify current note to make sure it's reading the latest note. diff --git a/yarn-project/noir-libs/value-note/src/utils.nr b/yarn-project/noir-libs/value-note/src/utils.nr index 7b951efebc5..974ae8d8c5e 100644 --- a/yarn-project/noir-libs/value-note/src/utils.nr +++ b/yarn-project/noir-libs/value-note/src/utils.nr @@ -1,4 +1,4 @@ -use dep::aztec::context::Context; +use dep::aztec::context::PrivateContext; use dep::aztec::log::emit_encrypted_log; use dep::aztec::note::note_getter_options::NoteGetterOptions; use dep::aztec::oracle::get_public_key::get_public_key; @@ -10,7 +10,7 @@ use crate::{ }; fn spend_notes( - context: &mut Context, + context: &mut PrivateContext, balance: Set, amount: Field, owner: Field, @@ -50,7 +50,7 @@ fn spend_notes( let encryption_pub_key = get_public_key(owner); emit_encrypted_log( context, - context.inputs.call_context.storage_contract_address, + (*context).this_address(), balance.storage_slot, encryption_pub_key, encrypted_data, @@ -58,7 +58,7 @@ fn spend_notes( } fn send_note( - context: &mut Context, + context: &mut PrivateContext, balance: Set, amount: Field, recipient: Field, @@ -73,7 +73,7 @@ fn send_note( let encryption_pub_key = get_public_key(recipient); emit_encrypted_log( context, - context.inputs.call_context.storage_contract_address, + (*context).this_address(), balance.storage_slot, encryption_pub_key, note.serialise(), diff --git a/yarn-project/sequencer-client/src/sequencer/public_processor.ts b/yarn-project/sequencer-client/src/sequencer/public_processor.ts index fc3cfdefd38..19e1d29b691 100644 --- a/yarn-project/sequencer-client/src/sequencer/public_processor.ts +++ b/yarn-project/sequencer-client/src/sequencer/public_processor.ts @@ -155,6 +155,7 @@ export class PublicProcessor { executionStack.push(...result.nestedExecutions); const preimages = await this.getPublicCallStackPreimages(result); const callData = await this.getPublicCallData(result, preimages, isExecutionRequest); + [kernelOutput, kernelProof] = await this.runKernelCircuit(callData, kernelOutput, kernelProof); } @@ -200,9 +201,11 @@ export class PublicProcessor { protected async getPublicCircuitPublicInputs(result: PublicExecutionResult) { const publicDataTreeInfo = await this.db.getTreeInfo(MerkleTreeId.PUBLIC_DATA_TREE); - const historicPublicDataTreeRoot = Fr.fromBuffer(publicDataTreeInfo.root); + this.blockData.publicDataTreeRoot = Fr.fromBuffer(publicDataTreeInfo.root); + const callStackPreimages = await this.getPublicCallStackPreimages(result); const wasm = await CircuitsWasm.get(); + const publicCallStack = mapTuple(callStackPreimages, item => item.isEmpty() ? Fr.zero() : computeCallStackItemHash(wasm, item), ); @@ -232,7 +235,7 @@ export class PublicProcessor { publicCallStack, unencryptedLogsHash, unencryptedLogPreimagesLength, - historicPublicDataTreeRoot, + historicBlockData: this.blockData, }); }