Skip to content

Commit

Permalink
feat: FunctionSelector type (#1518)
Browse files Browse the repository at this point in the history
Fixes #1424
  • Loading branch information
benesjan committed Aug 24, 2023
1 parent 79df831 commit 942f705
Show file tree
Hide file tree
Showing 70 changed files with 621 additions and 389 deletions.
10 changes: 8 additions & 2 deletions circuits/cpp/src/aztec3/circuits/abis/.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,10 @@ TEST(abi_tests, native_read_write_call_context)
TEST(abi_tests, native_read_write_function_data)
{
FunctionData<NT> const function_data = {
.function_selector = 11,
.function_selector =
FunctionSelector<NT>{
.value = 11,
},
.is_private = false,
.is_constructor = false,
};
Expand All @@ -67,7 +70,10 @@ TEST(abi_tests, native_read_write_function_data)
TEST(abi_tests, native_to_circuit_function_data)
{
FunctionData<NT> const native_function_data = {
.function_selector = 11,
.function_selector =
FunctionSelector<NT>{
.value = 11,
},
.is_private = false,
.is_constructor = false,
};
Expand Down
12 changes: 10 additions & 2 deletions circuits/cpp/src/aztec3/circuits/abis/c_bind.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,10 @@ TEST(abi_tests, compute_function_leaf)
{
// Construct FunctionLeafPreimage with some randomized fields
auto const preimage = FunctionLeafPreimage<NT>{
.function_selector = engine.get_random_uint32(),
.function_selector =
FunctionSelector<NT>{
.value = engine.get_random_uint32(),
},
.is_private = static_cast<bool>(engine.get_random_uint8() & 1),
.vk_hash = NT::fr::random_element(),
.acir_hash = NT::fr::random_element(),
Expand Down Expand Up @@ -279,7 +282,12 @@ TEST(abi_tests, compute_function_tree)
TEST(abi_tests, hash_constructor)
{
// Randomize required values
auto const func_data = FunctionData<NT>{ .function_selector = 10, .is_private = true, .is_constructor = false };
auto const func_data = FunctionData<NT>{ .function_selector =
FunctionSelector<NT>{
.value = 10,
},
.is_private = true,
.is_constructor = false };

NT::fr const args_hash = NT::fr::random_element();
NT::fr const constructor_vk_hash = NT::fr::random_element();
Expand Down
12 changes: 7 additions & 5 deletions circuits/cpp/src/aztec3/circuits/abis/function_data.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#pragma once

#include "aztec3/circuits/abis/function_selector.hpp"
#include "aztec3/constants.hpp"
#include "aztec3/utils/types/circuit_types.hpp"
#include "aztec3/utils/types/convert.hpp"
Expand All @@ -17,7 +18,7 @@ template <typename NCT> struct FunctionData {
using boolean = typename NCT::boolean;
using fr = typename NCT::fr;

uint32 function_selector; // e.g. 1st 4-bytes of abi-encoding of function.
FunctionSelector<NCT> function_selector;
boolean is_internal = false;
boolean is_private = false;
boolean is_constructor = false;
Expand All @@ -38,7 +39,7 @@ template <typename NCT> struct FunctionData {
auto to_ct = [&](auto& e) { return aztec3::utils::types::to_ct(builder, e); };

FunctionData<CircuitTypes<Builder>> function_data = {
to_ct(function_selector),
function_selector.to_circuit_type(builder),
to_ct(is_internal),
to_ct(is_private),
to_ct(is_constructor),
Expand All @@ -50,10 +51,11 @@ template <typename NCT> struct FunctionData {
template <typename Builder> FunctionData<NativeTypes> to_native_type() const
{
static_assert(std::is_same<CircuitTypes<Builder>, NCT>::value);
auto to_native_type = []<typename T>(T& e) { return e.template to_native_type<Builder>(); };
auto to_nt = [&](auto& e) { return aztec3::utils::types::to_nt<Builder>(e); };

FunctionData<NativeTypes> function_data = {
to_nt(function_selector),
to_native_type(function_selector),
to_nt(is_internal),
to_nt(is_private),
to_nt(is_constructor),
Expand All @@ -66,7 +68,7 @@ template <typename NCT> struct FunctionData {
{
static_assert(!(std::is_same<NativeTypes, NCT>::value));

fr(function_selector).set_public();
function_selector.set_public();
fr(is_internal).set_public();
fr(is_private).set_public();
fr(is_constructor).set_public();
Expand All @@ -76,7 +78,7 @@ template <typename NCT> struct FunctionData {
fr hash() const
{
std::vector<fr> const inputs = {
fr(function_selector),
fr(function_selector.value),
fr(is_internal),
fr(is_private),
fr(is_constructor),
Expand Down
14 changes: 10 additions & 4 deletions circuits/cpp/src/aztec3/circuits/abis/function_leaf_preimage.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#pragma once

#include "aztec3/circuits/abis/function_selector.hpp"
#include "aztec3/constants.hpp"
#include "aztec3/utils/types/circuit_types.hpp"
#include "aztec3/utils/types/convert.hpp"
Expand Down Expand Up @@ -31,7 +32,7 @@ template <typename NCT> struct FunctionLeafPreimage {
using fr = typename NCT::fr;
using uint32 = typename NCT::uint32;

uint32 function_selector = 0;
FunctionSelector<NCT> function_selector = {};
boolean is_internal = false;
boolean is_private = false;
fr vk_hash = 0;
Expand All @@ -54,7 +55,11 @@ template <typename NCT> struct FunctionLeafPreimage {
auto to_ct = [&](auto& e) { return aztec3::utils::types::to_ct(builder, e); };

FunctionLeafPreimage<CircuitTypes<Builder>> preimage = {
to_ct(function_selector), to_ct(is_internal), to_ct(is_private), to_ct(vk_hash), to_ct(acir_hash),
function_selector.to_circuit_type(builder),
to_ct(is_internal),
to_ct(is_private),
to_ct(vk_hash),
to_ct(acir_hash),
};

return preimage;
Expand All @@ -63,10 +68,11 @@ template <typename NCT> struct FunctionLeafPreimage {
template <typename Builder> FunctionLeafPreimage<NativeTypes> to_native_type() const
{
static_assert(std::is_same<CircuitTypes<Builder>, NCT>::value);
auto to_native_type = []<typename T>(T& e) { return e.template to_native_type<Builder>(); };
auto to_nt = [&](auto& e) { return aztec3::utils::types::to_nt<Builder>(e); };

FunctionLeafPreimage<NativeTypes> preimage = {
to_nt(function_selector), to_nt(is_internal), to_nt(is_private), to_nt(vk_hash), to_nt(acir_hash),
to_native_type(function_selector), to_nt(is_internal), to_nt(is_private), to_nt(vk_hash), to_nt(acir_hash),
};

return preimage;
Expand All @@ -86,7 +92,7 @@ template <typename NCT> struct FunctionLeafPreimage {
fr hash() const
{
std::vector<fr> const inputs = {
function_selector, fr(is_internal), fr(is_private), vk_hash, acir_hash,
function_selector.value, fr(is_internal), fr(is_private), vk_hash, acir_hash,
};
return NCT::compress(inputs, GeneratorIndex::FUNCTION_LEAF);
}
Expand Down
59 changes: 59 additions & 0 deletions circuits/cpp/src/aztec3/circuits/abis/function_selector.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#pragma once

#include "aztec3/utils/types/circuit_types.hpp"
#include "aztec3/utils/types/convert.hpp"
#include "aztec3/utils/types/native_types.hpp"

#include "barretenberg/serialize/msgpack.hpp"

namespace aztec3::circuits::abis {

using aztec3::utils::types::CircuitTypes;
using aztec3::utils::types::NativeTypes;

template <typename NCT> struct FunctionSelector {
using uint32 = typename NCT::uint32;
using boolean = typename NCT::boolean;
using fr = typename NCT::fr;

uint32 value; // e.g. 1st 4-bytes of abi-encoding of function.

MSGPACK_FIELDS(value);

boolean operator==(FunctionSelector<NCT> const& other) const { return value == other.value; };

template <typename Builder> FunctionSelector<CircuitTypes<Builder>> to_circuit_type(Builder& builder) const
{
static_assert((std::is_same<NativeTypes, NCT>::value));

// Capture the circuit builder:
auto to_ct = [&](auto& e) { return aztec3::utils::types::to_ct(builder, e); };

FunctionSelector<CircuitTypes<Builder>> function_selector = {
to_ct(value),
};

return function_selector;
};

template <typename Builder> FunctionSelector<NativeTypes> to_native_type() const
{
static_assert(std::is_same<CircuitTypes<Builder>, NCT>::value);
auto to_nt = [&](auto& e) { return aztec3::utils::types::to_nt<Builder>(e); };

FunctionSelector<NativeTypes> function_selector = {
to_nt(value),
};

return function_selector;
};

void set_public()
{
static_assert(!(std::is_same<NativeTypes, NCT>::value));

fr(value).set_public();
}
};

} // namespace aztec3::circuits::abis
5 changes: 4 additions & 1 deletion circuits/cpp/src/aztec3/circuits/apps/.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,10 @@ class state_var_tests : public ::testing::Test {
uint256_t(0x01071e9a23e0f7edULL, 0x5d77b35d1830fa3eULL, 0xc6ba3660bb1f0c0bULL, 0x2ef9f7f09867fd6eULL));

FunctionData<NT> const function_data{
.function_selector = 1, // TODO: deduce this from the contract, somehow.
.function_selector =
FunctionSelector<NT>{
.value = 1, // TODO: deduce this from the contract, somehow.
},
.is_private = true,
.is_constructor = false,
};
Expand Down
6 changes: 5 additions & 1 deletion circuits/cpp/src/aztec3/circuits/apps/contract.tpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ namespace aztec3::circuits::apps {

using NT = aztec3::utils::types::NativeTypes;
using aztec3::circuits::abis::FunctionData;
using aztec3::circuits::abis::FunctionSelector;

template <typename NCT> void Contract<NCT>::set_functions(std::vector<FunctionDeclaration<NCT>> const& functions)
{
Expand All @@ -22,7 +23,10 @@ template <typename NCT> void Contract<NCT>::set_functions(std::vector<FunctionDe
throw_or_abort("Name already exists");
}
function_datas[function.name] = FunctionData<NCT>{
.function_selector = static_cast<uint32>(i),
.function_selector =
FunctionSelector<NT>{
.value = static_cast<uint32>(i),
},
.is_private = function.is_private,
.is_constructor = function.is_constructor,
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,10 @@ template <typename Builder> class FunctionExecutionContext {

const FunctionData<CT> f_function_data_ct{
// Note: we MUST
.function_selector = f_encoding_ct,
.function_selector =
FunctionSelector<CT>{
.value = f_encoding_ct,
},
.is_private = true,
.is_constructor = false,
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@ class escrow_tests : public ::testing::Test {
uint256_t(0x01071e9a23e0f7edULL, 0x5d77b35d1830fa3eULL, 0xc6ba3660bb1f0c0bULL, 0x2ef9f7f09867fd6eULL));

FunctionData<NT> const function_data{
.function_selector = 1, // TODO: deduce this from the contract, somehow.
.function_selector =
FunctionSelector<NT>{
.value = 1, // TODO: deduce this from the contract, somehow.
},
.is_private = true,
.is_constructor = false,
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@ TEST(private_to_private_function_call_tests, circuit_private_to_private_function
uint256_t(0x01071e9a23e0f7edULL, 0x5d77b35d1830fa3eULL, 0xc6ba3660bb1f0c0bULL, 0x2ef9f7f09867fd6eULL);

const FunctionData<NT> function_data{
.function_selector = 1, // TODO: deduce this from the contract, somehow.
.function_selector =
FunctionSelector<NT>{
.value = 1, // TODO: deduce this from the contract, somehow.
},
.is_private = true,
.is_constructor = false,
};
Expand Down
4 changes: 3 additions & 1 deletion circuits/cpp/src/aztec3/circuits/hash.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include "aztec3/circuits/abis/function_data.hpp"
#include "aztec3/circuits/abis/function_leaf_preimage.hpp"
#include "aztec3/circuits/abis/function_selector.hpp"
#include "aztec3/circuits/abis/global_variables.hpp"
#include "aztec3/circuits/abis/new_contract_data.hpp"
#include "aztec3/circuits/abis/point.hpp"
Expand All @@ -16,6 +17,7 @@
namespace aztec3::circuits {

using abis::FunctionData;
using abis::FunctionSelector;
using abis::Point;
using aztec3::circuits::abis::ContractLeafPreimage;
using aztec3::circuits::abis::FunctionLeafPreimage;
Expand Down Expand Up @@ -303,7 +305,7 @@ void check_membership(Builder& builder,
* @return NCT::fr
*/
template <typename NCT> typename NCT::fr function_tree_root_from_siblings(
typename NCT::uint32 const& function_selector,
FunctionSelector<NCT> const& function_selector,
typename NCT::boolean const& is_internal,
typename NCT::boolean const& is_private,
typename NCT::fr const& vk_hash,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,9 @@ TEST_F(native_private_kernel_init_tests, contract_deployment_function_data_misma
auto private_inputs = do_private_call_get_kernel_inputs_init(true, constructor, standard_test_args());

// Modify the function selector in function data.
private_inputs.tx_request.function_data.function_selector = numeric::random::get_engine().get_random_uint32();
private_inputs.tx_request.function_data.function_selector = FunctionSelector<NT>{
.value = numeric::random::get_engine().get_random_uint32(),
};

// Invoke the native private kernel circuit
DummyBuilder builder = DummyBuilder("private_kernel_tests__contract_deployment_function_data_mismatch_fails");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,10 @@ std::pair<PrivateCallData<NT>, ContractDeploymentData<NT>> create_private_call_d
const Point<NT> msg_sender_pub_key = { .x = 123456789, .y = 123456789 };

FunctionData<NT> const function_data{
.function_selector = 1, // TODO(suyash): deduce this from the contract, somehow.
.function_selector =
FunctionSelector<NT>{
.value = 1, // TODO: deduce this from the contract, somehow.
},
.is_private = true,
.is_constructor = is_constructor,
};
Expand Down
14 changes: 11 additions & 3 deletions circuits/cpp/src/aztec3/circuits/kernel/public/.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,10 @@ PublicCallStackItem generate_call_stack_item(NT::fr contract_address,
{
NT::uint32 count = seed + 1;
FunctionData<NT> const function_data{
.function_selector = count,
.function_selector =
FunctionSelector<NT>{
.value = count,
},
.is_private = false,
.is_constructor = false,
};
Expand Down Expand Up @@ -264,7 +267,10 @@ PublicKernelInputs<NT> get_kernel_inputs_with_previous_kernel(NT::boolean privat
const NT::address msg_sender = NT::fr(1);

FunctionData<NT> const function_data{
.function_selector = 1,
.function_selector =
FunctionSelector<NT>{
.value = 1,
},
.is_private = false,
.is_constructor = false,
};
Expand Down Expand Up @@ -640,7 +646,9 @@ TEST(public_kernel_tests, function_selector_must_be_valid)
DummyBuilder dummyBuilder = DummyBuilder("public_kernel_tests__function_selector_must_be_valid");
PublicKernelInputs<NT> inputs = get_kernel_inputs_with_previous_kernel(true);

inputs.public_call.call_stack_item.function_data.function_selector = 0;
inputs.public_call.call_stack_item.function_data.function_selector = FunctionSelector<NT>{
.value = 0,
};
auto public_inputs = native_public_kernel_circuit_private_previous_kernel(dummyBuilder, inputs);
ASSERT_TRUE(dummyBuilder.failed());
ASSERT_EQ(dummyBuilder.get_first_failure().code, CircuitErrorCode::PUBLIC_KERNEL__FUNCTION_SIGNATURE_INVALID);
Expand Down
2 changes: 1 addition & 1 deletion circuits/cpp/src/aztec3/circuits/kernel/public/common.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ void common_validate_inputs(DummyBuilder& builder, KernelInput const& public_ker
builder.do_assert(this_call_stack_item.contract_address != 0,
"Contract address must be non-zero",
CircuitErrorCode::PUBLIC_KERNEL__CONTRACT_ADDRESS_INVALID);
builder.do_assert(this_call_stack_item.function_data.function_selector != 0,
builder.do_assert(this_call_stack_item.function_data.function_selector.value != 0,
"Function signature must be non-zero",
CircuitErrorCode::PUBLIC_KERNEL__FUNCTION_SIGNATURE_INVALID);
builder.do_assert(this_call_stack_item.function_data.is_constructor == false,
Expand Down
9 changes: 0 additions & 9 deletions yarn-project/acir-simulator/src/acvm/deserialize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,15 +57,6 @@ export function frToBoolean(fr: Fr): boolean {
return buf[buf.length - 1] !== 0;
}

/**
* Converts a field to a function selector.
* @param fr - The field to convert.
* @returns The function selector.
*/
export function frToSelector(fr: Fr): Buffer {
return fr.toBuffer().slice(-4);
}

/**
* Extracts the return fields of a given partial witness.
* @param acir - The bytecode of the function.
Expand Down
Loading

0 comments on commit 942f705

Please sign in to comment.