Skip to content

Commit

Permalink
refactor: computeContractAddress as computeCompleteAddress (#1876)
Browse files Browse the repository at this point in the history
Fixes #1873
  • Loading branch information
benesjan authored Sep 22, 2023
1 parent 2fe8f5e commit 4d95b44
Show file tree
Hide file tree
Showing 21 changed files with 274 additions and 280 deletions.
72 changes: 5 additions & 67 deletions circuits/cpp/src/aztec3/circuits/abis/c_bind.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "rollup/root/root_rollup_public_inputs.hpp"

#include "aztec3/circuits/abis/combined_accumulated_data.hpp"
#include "aztec3/circuits/abis/complete_address.hpp"
#include "aztec3/circuits/abis/final_accumulated_data.hpp"
#include "aztec3/circuits/abis/new_contract_data.hpp"
#include "aztec3/circuits/abis/packers.hpp"
Expand All @@ -33,9 +34,8 @@
namespace {

using aztec3::circuits::compute_constructor_hash;
using aztec3::circuits::compute_contract_address;
using aztec3::circuits::compute_partial_address;
using aztec3::circuits::abis::CallStackItem;
using aztec3::circuits::abis::CompleteAddress;
using aztec3::circuits::abis::ConstantsPacker;
using aztec3::circuits::abis::FunctionData;
using aztec3::circuits::abis::FunctionLeafPreimage;
Expand Down Expand Up @@ -289,39 +289,9 @@ WASM_EXPORT void abis__hash_constructor(uint8_t const* function_data_buf,
}

/**
* @brief Compute a contract address
* This is a WASM-export that can be called from Typescript.
*
* @details Computes a contract address by hashing the deployers public key along with the previously computed partial
* address Return the serialized results in the `output` buffer.
*
* @param point_data_buf point data struct as a buffer of bytes
* @param contract_address_salt_buf salt value for the contract address
* @param function_tree_root_buf root value of the contract's function tree
* @param constructor_hash_buf the hash of the contract constructor's verification key
* @param output buffer that will contain the output. The serialized contract address.
* @brief Compute a complete address.
*/
WASM_EXPORT void abis__compute_contract_address(uint8_t const* point_data_buf,
uint8_t const* contract_address_salt_buf,
uint8_t const* function_tree_root_buf,
uint8_t const* constructor_hash_buf,
uint8_t* output)
{
Point<NT> deployer_public_key;
NT::fr contract_address_salt;
NT::fr function_tree_root;
NT::fr constructor_hash;

serialize::read(point_data_buf, deployer_public_key);
read(contract_address_salt_buf, contract_address_salt);
read(function_tree_root_buf, function_tree_root);
read(constructor_hash_buf, constructor_hash);

NT::fr const contract_address =
compute_contract_address(deployer_public_key, contract_address_salt, function_tree_root, constructor_hash);

NT::fr::serialize_to_buffer(contract_address, output);
}
CBIND(abis__compute_complete_address, aztec3::circuits::abis::CompleteAddress<NT>::compute);

/**
* @brief Compute a contract address from deployer public key and partial address.
Expand Down Expand Up @@ -350,38 +320,6 @@ WASM_EXPORT void abis__compute_contract_address_from_partial(uint8_t const* poin
NT::fr::serialize_to_buffer(contract_address, output);
}

/**
* @brief Compute a partial address
* This is a WASM-export that can be called from Typescript.
*
* @details Computes a partial address by hashing the salt, function tree root and constructor hash
* Return the serialized results in the `output` buffer.
*
* @param contract_address_salt_buf salt value for the contract address
* @param function_tree_root_buf root value of the contract's function tree
* @param constructor_hash_buf the hash of the contract constructor's verification key
* @param output buffer that will contain the output. The serialized contract address.
* See the link bellow for more details:
* https://github.com/AztecProtocol/aztec-packages/blob/master/docs/docs/concepts/foundation/accounts/keys.md#addresses-partial-addresses-and-public-keys
*/
WASM_EXPORT void abis__compute_partial_address(uint8_t const* contract_address_salt_buf,
uint8_t const* function_tree_root_buf,
uint8_t const* constructor_hash_buf,
uint8_t* output)
{
NT::fr contract_address_salt;
NT::fr function_tree_root;
NT::fr constructor_hash;

read(contract_address_salt_buf, contract_address_salt);
read(function_tree_root_buf, function_tree_root);
read(constructor_hash_buf, constructor_hash);
NT::fr const partial_address =
compute_partial_address<NT>(contract_address_salt, function_tree_root, constructor_hash);

NT::fr::serialize_to_buffer(partial_address, output);
}

/**
* @brief Hash args for a function call.
*
Expand All @@ -400,7 +338,7 @@ WASM_EXPORT void abis__compute_var_args_hash(uint8_t const* args_buf, uint8_t* o
* @brief Generates a function tree leaf from its preimage.
* This is a WASM-export that can be called from Typescript.
*
* @details given a `uint8_t const*` buffer representing a function leaf's prieimage,
* @details given a `uint8_t const*` buffer representing a function leaf's preimage,
* construct a NewContractData instance, hash, and return the serialized results
* in the `output` buffer.
*
Expand Down
11 changes: 1 addition & 10 deletions circuits/cpp/src/aztec3/circuits/abis/c_bind.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,7 @@ WASM_EXPORT void abis__hash_constructor(uint8_t const* func_data_buf,
uint8_t const* constructor_vk_hash_buf,
uint8_t* output);

WASM_EXPORT void abis__compute_contract_address(uint8_t const* point_data_buf,
uint8_t const* contract_address_salt_buf,
uint8_t const* function_tree_root_buf,
uint8_t const* constructor_hash_buf,
uint8_t* output);

WASM_EXPORT void abis__compute_partial_address(uint8_t const* contract_address_salt_buf,
uint8_t const* function_tree_root_buf,
uint8_t const* constructor_hash_buf,
uint8_t* output);
CBIND_DECL(abis__compute_complete_address);

CBIND_DECL(abis__compute_commitment_nonce);
CBIND_DECL(abis__compute_unique_commitment);
Expand Down
51 changes: 1 addition & 50 deletions circuits/cpp/src/aztec3/circuits/abis/c_bind.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "function_leaf_preimage.hpp"
#include "tx_request.hpp"

#include "aztec3/circuits/abis/complete_address.hpp"
#include "aztec3/circuits/abis/new_contract_data.hpp"
#include "aztec3/circuits/abis/tx_request.hpp"
#include "aztec3/circuits/hash.hpp"
Expand Down Expand Up @@ -50,56 +51,6 @@ template <size_t NUM_BYTES> std::string bytes_to_hex_str(std::array<uint8_t, NUM

namespace aztec3::circuits::abis {

TEST(abi_tests, compute_partial_address)
{
auto const contract_address_salt = NT::fr(3);
auto const function_tree_root = NT::fr(4);
auto const constructor_hash = NT::fr(5);
NT::fr const expected = compute_partial_address<NT>(contract_address_salt, function_tree_root, constructor_hash);

std::array<uint8_t, sizeof(NT::fr)> output = { 0 };
std::vector<uint8_t> salt_buf;
std::vector<uint8_t> function_tree_root_buf;
std::vector<uint8_t> constructor_hash_buf;
write(salt_buf, contract_address_salt);
write(function_tree_root_buf, function_tree_root);
write(constructor_hash_buf, constructor_hash);
abis__compute_partial_address(
salt_buf.data(), function_tree_root_buf.data(), constructor_hash_buf.data(), output.data());

// Convert buffer to `fr` for comparison to in-test calculated hash
NT::fr const actual = NT::fr::serialize_from_buffer(output.data());
EXPECT_EQ(actual, expected);
}

TEST(abi_tests, compute_contract_address)
{
Point<NT> const point = { .x = 1, .y = 3 };
auto const contract_address_salt = NT::fr(5);
auto const function_tree_root = NT::fr(6);
auto const constructor_hash = NT::fr(7);
NT::fr const expected =
compute_contract_address(point, contract_address_salt, function_tree_root, constructor_hash);

std::array<uint8_t, sizeof(NT::fr)> output = { 0 };
std::vector<uint8_t> contract_address_salt_buf;
std::vector<uint8_t> function_tree_root_buf;
std::vector<uint8_t> constructor_hash_buf;
std::vector<uint8_t> point_buf;
write(contract_address_salt_buf, contract_address_salt);
write(function_tree_root_buf, function_tree_root);
write(constructor_hash_buf, constructor_hash);
serialize::write(point_buf, point);
abis__compute_contract_address(point_buf.data(),
contract_address_salt_buf.data(),
function_tree_root_buf.data(),
constructor_hash_buf.data(),
output.data());

// Convert buffer to `fr` for comparison to in-test calculated hash
NT::fr const actual = NT::fr::serialize_from_buffer(output.data());
EXPECT_EQ(actual, expected);
}
TEST(abi_tests, hash_tx_request)
{
// Construct TxRequest with some randomized fields
Expand Down
90 changes: 90 additions & 0 deletions circuits/cpp/src/aztec3/circuits/abis/complete_address.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
#pragma once
#include "aztec3/circuits/abis/coordinate.hpp"
#include "aztec3/circuits/abis/point.hpp"
#include "aztec3/circuits/hash.hpp"
#include "aztec3/utils/types/circuit_types.hpp"
#include "aztec3/utils/types/convert.hpp"
#include "aztec3/utils/types/native_types.hpp"

#include <barretenberg/barretenberg.hpp>

namespace aztec3::circuits::abis {

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

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

typename NCT::address address;
Point<NCT> public_key;
fr partial_address;

// for serialization, update with new fields
MSGPACK_FIELDS(address, public_key, partial_address);
bool operator==(CompleteAddress<NCT> const&) const = default;

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

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

CompleteAddress<CircuitTypes<Builder>> complete_address = { to_ct(address),
to_ct(public_key),
to_ct(partial_address) };

return complete_address;
};

template <typename Builder> CompleteAddress<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); };

CompleteAddress<NativeTypes> complete_address = { to_nt(address), to_nt(public_key), to_nt(partial_address) };

return complete_address;
};

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

address.set_public();
public_key.set_public();
partial_address.set_public();
}

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

address.assert_is_zero();
public_key.assert_is_zero();
partial_address.assert_is_zero();
}

static CompleteAddress<NCT> compute(Point<NCT> const& point,
typename NCT::fr const& contract_address_salt,
typename NCT::fr const& function_tree_root,
typename NCT::fr const& constructor_hash)
{
using fr = typename NCT::fr;

const fr partial_address =
compute_partial_address<NCT>(contract_address_salt, function_tree_root, constructor_hash);

CompleteAddress<NCT> complete_address;
complete_address.address = compute_contract_address_from_partial(point, partial_address);
complete_address.public_key = point;
complete_address.partial_address = partial_address;

return complete_address;
}
};

} // namespace aztec3::circuits::abis
13 changes: 0 additions & 13 deletions circuits/cpp/src/aztec3/circuits/hash.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,19 +72,6 @@ typename NCT::address compute_contract_address_from_partial(Point<NCT> const& po
return { NCT::hash(inputs, aztec3::GeneratorIndex::CONTRACT_ADDRESS) };
}

template <typename NCT> typename NCT::address compute_contract_address(Point<NCT> const& point,
typename NCT::fr const& contract_address_salt,
typename NCT::fr const& function_tree_root,
typename NCT::fr const& constructor_hash)
{
using fr = typename NCT::fr;

const fr partial_address =
compute_partial_address<NCT>(contract_address_salt, function_tree_root, constructor_hash);

return compute_contract_address_from_partial(point, partial_address);
}

template <typename NCT> typename NCT::fr compute_commitment_nonce(typename NCT::fr const& first_nullifier,
typename NCT::fr const& commitment_index)
{
Expand Down
10 changes: 6 additions & 4 deletions circuits/cpp/src/aztec3/circuits/kernel/private/common.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include "init.hpp"

#include "aztec3/circuits/abis/complete_address.hpp"
#include "aztec3/circuits/abis/contract_deployment_data.hpp"
#include "aztec3/circuits/abis/function_data.hpp"
#include "aztec3/circuits/abis/kernel_circuit_public_inputs.hpp"
Expand Down Expand Up @@ -288,10 +289,11 @@ void common_contract_logic(DummyBuilder& builder,
auto constructor_hash =
compute_constructor_hash(function_data, private_call_public_inputs.args_hash, private_call_vk_hash);

auto const new_contract_address = compute_contract_address<NT>(contract_dep_data.deployer_public_key,
contract_dep_data.contract_address_salt,
contract_dep_data.function_tree_root,
constructor_hash);
auto const new_contract_address = abis::CompleteAddress<NT>::compute(contract_dep_data.deployer_public_key,
contract_dep_data.contract_address_salt,
contract_dep_data.function_tree_root,
constructor_hash)
.address;

// Add new contract data if its a contract deployment function
NewContractData<NT> const native_new_contract_data{ new_contract_address,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "init.hpp"

#include "aztec3/circuits/abis/complete_address.hpp"
#include "aztec3/circuits/abis/kernel_circuit_public_inputs.hpp"
#include "aztec3/circuits/abis/new_contract_data.hpp"
#include "aztec3/circuits/abis/private_kernel/private_kernel_inputs_inner.hpp"
Expand All @@ -21,7 +22,6 @@ using plonk::stdlib::is_array_empty;
using plonk::stdlib::push_array_to_array;

using aztec3::circuits::compute_constructor_hash;
using aztec3::circuits::compute_contract_address;
using aztec3::circuits::silo_commitment;
using aztec3::circuits::silo_nullifier;

Expand Down Expand Up @@ -113,10 +113,11 @@ void update_end_values(PrivateKernelInputsInner<CT> const& private_inputs, Kerne
"constructor_vk_hash does not match private call vk hash");

// compute the contract address (only valid if this is a contract deployment)
auto contract_address = compute_contract_address<CT>(contract_deployment_data.deployer_public_key,
contract_deployment_data.contract_address_salt,
contract_deployment_data.function_tree_root,
constructor_hash);
auto const contract_address = abis::CompleteAddress<CT>::compute(contract_deployment_data.deployer_public_key,
contract_deployment_data.contract_address_salt,
contract_deployment_data.function_tree_root,
constructor_hash)
.address;

// must imply == derived address
is_contract_deployment.must_imply(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "aztec3/circuits/abis/call_stack_item.hpp"
#include "aztec3/circuits/abis/combined_accumulated_data.hpp"
#include "aztec3/circuits/abis/combined_constant_data.hpp"
#include "aztec3/circuits/abis/complete_address.hpp"
#include "aztec3/circuits/abis/contract_deployment_data.hpp"
#include "aztec3/circuits/abis/function_data.hpp"
#include "aztec3/circuits/abis/historic_block_data.hpp"
Expand Down Expand Up @@ -225,8 +226,11 @@ std::pair<PrivateCallData<NT>, ContractDeploymentData<NT>> create_private_call_d
auto constructor_hash = compute_constructor_hash<NT>(function_data, args_hash, private_circuit_vk_hash);

// Derive contract address so that it can be used inside the constructor itself
contract_address = compute_contract_address<NT>(
msg_sender_pub_key, contract_address_salt, contract_deployment_data.function_tree_root, constructor_hash);
contract_address = abis::CompleteAddress<NT>::compute(msg_sender_pub_key,
contract_address_salt,
contract_deployment_data.function_tree_root,
constructor_hash)
.address;
// update the contract address in the call context now that it is known
call_context.storage_contract_address = contract_address;
} else {
Expand Down Expand Up @@ -529,8 +533,10 @@ bool validate_deployed_contract_address(PrivateKernelInputsInit<NT> const& priva
auto expected_constructor_hash = compute_constructor_hash(
private_inputs.private_call.call_stack_item.function_data, tx_request.args_hash, private_circuit_vk_hash);

NT::fr const expected_contract_address = compute_contract_address(
cdd.deployer_public_key, cdd.contract_address_salt, cdd.function_tree_root, expected_constructor_hash);
NT::fr const expected_contract_address =
abis::CompleteAddress<NT>::compute(
cdd.deployer_public_key, cdd.contract_address_salt, cdd.function_tree_root, expected_constructor_hash)
.address;

return (public_inputs.end.new_contracts[0].contract_address.to_field() == expected_contract_address);
}
Expand Down
Loading

0 comments on commit 4d95b44

Please sign in to comment.