diff --git a/cpp/src/aztec3/circuits/kernel/private/.test.cpp b/cpp/src/aztec3/circuits/kernel/private/.test.cpp index 42874541..a5eee5a2 100644 --- a/cpp/src/aztec3/circuits/kernel/private/.test.cpp +++ b/cpp/src/aztec3/circuits/kernel/private/.test.cpp @@ -480,9 +480,6 @@ TEST(private_kernel_tests, test_basic_contract_deployment) NT::fr(uint256_t(0x01071e9a23e0f7edULL, 0x5d77b35d1830fa3eULL, 0xc6ba3660bb1f0c0bULL, 0x2ef9f7f09867fd6eULL)); const NT::address tx_origin = msg_sender; - Composer constructor_composer = Composer("../barretenberg/cpp/srs_db/ignition"); - DB db; - FunctionData function_data{ .function_selector = 1, // TODO: deduce this from the contract, somehow. .is_private = true, @@ -498,9 +495,48 @@ TEST(private_kernel_tests, test_basic_contract_deployment) .is_contract_deployment = true, }; - std::shared_ptr constructor_vk = constructor_composer.compute_verification_key(); + NT::fr arg0 = 5; + NT::fr arg1 = 1; + NT::fr arg2 = 999; + + Composer dummy_constructor_composer = Composer("../barretenberg/cpp/srs_db/ignition"); + { + // Dummmy invokation, in order to derive the vk of this circuit + + // We need to use _dummy_ contract_deployment_data first, because the _proper_ version of the + // contract_deployment_data will need to contain the constructor_vk_hash... but the constructor's vk can only be + // computed after the composer has composed the circuit! + ContractDeploymentData dummy_contract_deployment_data{ + .constructor_vk_hash = 0, // dummy + .function_tree_root = 0, // TODO actually get this? + .contract_address_salt = contract_address_salt, + .portal_contract_address = new_portal_contract_address, + }; + + DB dummy_db; + NativeOracle dummy_constructor_oracle = NativeOracle(dummy_db, + new_contract_address, + function_data, + call_context, + dummy_contract_deployment_data, + msg_sender_private_key); + OracleWrapper dummy_constructor_oracle_wrapper = + OracleWrapper(dummy_constructor_composer, dummy_constructor_oracle); + + FunctionExecutionContext dummy_constructor_ctx(dummy_constructor_composer, dummy_constructor_oracle_wrapper); + + constructor(dummy_constructor_ctx, arg0, arg1, arg2); + } + + // Now we can derive the vk: + std::shared_ptr constructor_vk = dummy_constructor_composer.compute_verification_key(); auto constructor_vk_hash = stdlib::recursion::verification_key::compress_native(constructor_vk); + // Now, we can proceed with the proper (non-dummy) invokation of our constructor circuit: + + Composer constructor_composer = Composer("../barretenberg/cpp/srs_db/ignition"); + DB db; + ContractDeploymentData contract_deployment_data{ .constructor_vk_hash = constructor_vk_hash, // TODO actually get this? .function_tree_root = 0, // TODO actually get this? @@ -514,10 +550,6 @@ TEST(private_kernel_tests, test_basic_contract_deployment) FunctionExecutionContext constructor_ctx(constructor_composer, constructor_oracle_wrapper); - auto arg0 = NT::fr(5); - auto arg1 = NT::fr(1); - auto arg2 = NT::fr(999); - OptionalPrivateCircuitPublicInputs opt_constructor_public_inputs = constructor(constructor_ctx, arg0, arg1, arg2); @@ -678,9 +710,6 @@ TEST(private_kernel_tests, test_native_basic_contract_deployment) * convert it to native types, so that it can be fed into the kernel circuit. * */ - Composer constructor_composer = Composer("../barretenberg/cpp/srs_db/ignition"); - DB db; - FunctionData function_data{ .function_selector = 1, // TODO: deduce this from the contract, somehow. .is_private = true, @@ -696,9 +725,48 @@ TEST(private_kernel_tests, test_native_basic_contract_deployment) .is_contract_deployment = true, }; - std::shared_ptr constructor_vk = constructor_composer.compute_verification_key(); + NT::fr arg0 = 5; + NT::fr arg1 = 1; + NT::fr arg2 = 999; + + Composer dummy_constructor_composer = Composer("../barretenberg/cpp/srs_db/ignition"); + { + // Dummmy invokation, in order to derive the vk of this circuit + + // We need to use _dummy_ contract_deployment_data first, because the _proper_ version of the + // contract_deployment_data will need to contain the constructor_vk_hash... but the constructor's vk can only be + // computed after the composer has composed the circuit! + ContractDeploymentData dummy_contract_deployment_data{ + .constructor_vk_hash = 0, // dummy + .function_tree_root = 0, // TODO actually get this? + .contract_address_salt = contract_address_salt, + .portal_contract_address = new_portal_contract_address, + }; + + DB dummy_db; + NativeOracle dummy_constructor_oracle = NativeOracle(dummy_db, + new_contract_address, + function_data, + call_context, + dummy_contract_deployment_data, + msg_sender_private_key); + OracleWrapper dummy_constructor_oracle_wrapper = + OracleWrapper(dummy_constructor_composer, dummy_constructor_oracle); + + FunctionExecutionContext dummy_constructor_ctx(dummy_constructor_composer, dummy_constructor_oracle_wrapper); + + constructor(dummy_constructor_ctx, arg0, arg1, arg2); + } + + // Now we can derive the vk: + std::shared_ptr constructor_vk = dummy_constructor_composer.compute_verification_key(); auto constructor_vk_hash = stdlib::recursion::verification_key::compress_native(constructor_vk); + // Now, we can proceed with the proper (non-dummy) invokation of our constructor circuit: + + Composer constructor_composer = Composer("../barretenberg/cpp/srs_db/ignition"); + DB db; + ContractDeploymentData contract_deployment_data{ .constructor_vk_hash = constructor_vk_hash, // TODO actually get this? .function_tree_root = 0, // TODO actually get this? @@ -712,10 +780,6 @@ TEST(private_kernel_tests, test_native_basic_contract_deployment) FunctionExecutionContext constructor_ctx(constructor_composer, constructor_oracle_wrapper); - auto arg0 = NT::fr(5); - auto arg1 = NT::fr(1); - auto arg2 = NT::fr(999); - OptionalPrivateCircuitPublicInputs opt_constructor_public_inputs = constructor(constructor_ctx, arg0, arg1, arg2); diff --git a/cpp/src/aztec3/utils/array.hpp b/cpp/src/aztec3/utils/array.hpp index ead442a6..dabb20b2 100644 --- a/cpp/src/aztec3/utils/array.hpp +++ b/cpp/src/aztec3/utils/array.hpp @@ -82,42 +82,28 @@ template NT::boolean is_array_empty(std::array const /** * Inserts the `source` array at the first zero-valued index of the `target` array. + * Ensures that all values after the first zero-valued index are zeros too. * Fails if the `source` array is too large vs the remaining capacity of the `target` array. - * TODO: this is an awful mess and should be improved! */ template void push_array_to_array(std::array const& source, std::array& target) { - // TODO: inefficient to get length this way within this function. Probably best to inline the checks that we need - // into the below loops directly. - NT::fr target_length = array_length(target); - NT::fr target_capacity = NT::fr(target.size()); - const NT::fr overflow_capacity = target_capacity + 1; - - // ASSERT(uint256_t(target_capacity.get_value()) + 1 > - // uint256_t(target_length.get_value()) + uint256_t(source_length.get_value())); - - NT::fr j_ct = 0; // circuit-type index for the inner loop - NT::fr next_target_index = target_length; - for (size_t i = 0; i < source.size(); ++i) { - auto& s = source[i]; - - // Triangular loop: - for (size_t j = i; j < target.size() - source.size() + i + 1; ++j) { - auto& t = target[j]; - - NT::boolean at_next_index = j_ct == next_target_index; - - t = at_next_index ? s : t; - - j_ct++; + // Check if the `source` array is too large vs the remaining capacity of the `target` array + size_t source_size = static_cast(uint256_t(array_length(source))); + size_t target_size = static_cast(uint256_t(array_length(target))); + ASSERT(source_size <= size_2 - target_size); + + // Ensure that there are no non-zero values in the `target` array after the first zero-valued index + for (size_t i = target_size; i < size_2; i++) { + ASSERT(target[i] == NT::fr(0)); + } + // Copy the non-zero elements of the `source` array to the `target` array at the first zero-valued index + auto zero_index = target_size; + for (size_t i = 0; i < size_1; i++) { + if (source[i] != NT::fr(0)) { + target[zero_index] = source[i]; + zero_index++; } - - next_target_index++; - - ASSERT(next_target_index != overflow_capacity); //"push_array_to_array target array capacity exceeded" - - j_ct = i + 1; } }