From 4d95b4420e5a2bf9b5af121a3029d9b3e8a41fa0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Bene=C5=A1?= Date: Fri, 22 Sep 2023 21:58:53 +0200 Subject: [PATCH] refactor: `computeContractAddress` as `computeCompleteAddress` (#1876) Fixes #1873 --- .../cpp/src/aztec3/circuits/abis/c_bind.cpp | 72 +----------- .../cpp/src/aztec3/circuits/abis/c_bind.h | 11 +- .../src/aztec3/circuits/abis/c_bind.test.cpp | 51 +------- .../aztec3/circuits/abis/complete_address.hpp | 90 +++++++++++++++ circuits/cpp/src/aztec3/circuits/hash.hpp | 13 --- .../aztec3/circuits/kernel/private/common.cpp | 10 +- .../kernel/private/private_kernel_circuit.cpp | 11 +- .../kernel/private/testing_harness.cpp | 14 ++- .../aztec-rpc/src/contract_tree/index.ts | 11 +- .../src/abis/__snapshots__/abis.test.ts.snap | 90 +++++++++------ .../circuits.js/src/abis/abis.test.ts | 6 +- yarn-project/circuits.js/src/abis/abis.ts | 42 ++----- .../circuits.js/src/cbind/circuits.gen.ts | 109 +++++++++++++----- yarn-project/circuits.js/src/cbind/types.ts | 1 + .../src/contract/contract_deployment_info.ts | 12 +- .../complete_address.test.ts | 0 .../{types => structs}/complete_address.ts | 4 +- yarn-project/circuits.js/src/structs/index.ts | 1 + yarn-project/circuits.js/src/types/index.ts | 1 - .../src/e2e_sandbox_example.test.ts | 4 +- yarn-project/types/src/index.ts | 1 + 21 files changed, 274 insertions(+), 280 deletions(-) create mode 100644 circuits/cpp/src/aztec3/circuits/abis/complete_address.hpp rename yarn-project/circuits.js/src/{types => structs}/complete_address.test.ts (100%) rename yarn-project/circuits.js/src/{types => structs}/complete_address.ts (97%) diff --git a/circuits/cpp/src/aztec3/circuits/abis/c_bind.cpp b/circuits/cpp/src/aztec3/circuits/abis/c_bind.cpp index 15d5156dec5..75834fa5749 100644 --- a/circuits/cpp/src/aztec3/circuits/abis/c_bind.cpp +++ b/circuits/cpp/src/aztec3/circuits/abis/c_bind.cpp @@ -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" @@ -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; @@ -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 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::compute); /** * @brief Compute a contract address from deployer public key and partial address. @@ -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(contract_address_salt, function_tree_root, constructor_hash); - - NT::fr::serialize_to_buffer(partial_address, output); -} - /** * @brief Hash args for a function call. * @@ -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. * diff --git a/circuits/cpp/src/aztec3/circuits/abis/c_bind.h b/circuits/cpp/src/aztec3/circuits/abis/c_bind.h index 285aa0298a9..49ebe515418 100644 --- a/circuits/cpp/src/aztec3/circuits/abis/c_bind.h +++ b/circuits/cpp/src/aztec3/circuits/abis/c_bind.h @@ -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); diff --git a/circuits/cpp/src/aztec3/circuits/abis/c_bind.test.cpp b/circuits/cpp/src/aztec3/circuits/abis/c_bind.test.cpp index 7b822e777b6..8ff5270f123 100644 --- a/circuits/cpp/src/aztec3/circuits/abis/c_bind.test.cpp +++ b/circuits/cpp/src/aztec3/circuits/abis/c_bind.test.cpp @@ -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" @@ -50,56 +51,6 @@ template std::string bytes_to_hex_str(std::array(contract_address_salt, function_tree_root, constructor_hash); - - std::array output = { 0 }; - std::vector salt_buf; - std::vector function_tree_root_buf; - std::vector 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 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 output = { 0 }; - std::vector contract_address_salt_buf; - std::vector function_tree_root_buf; - std::vector constructor_hash_buf; - std::vector 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 diff --git a/circuits/cpp/src/aztec3/circuits/abis/complete_address.hpp b/circuits/cpp/src/aztec3/circuits/abis/complete_address.hpp new file mode 100644 index 00000000000..e8bc16eb76e --- /dev/null +++ b/circuits/cpp/src/aztec3/circuits/abis/complete_address.hpp @@ -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 + +namespace aztec3::circuits::abis { + +using aztec3::circuits::compute_partial_address; +using aztec3::utils::types::CircuitTypes; +using aztec3::utils::types::NativeTypes; + +template struct CompleteAddress { + using fr = typename NCT::fr; + using boolean = typename NCT::boolean; + + typename NCT::address address; + Point public_key; + fr partial_address; + + // for serialization, update with new fields + MSGPACK_FIELDS(address, public_key, partial_address); + bool operator==(CompleteAddress const&) const = default; + + template CompleteAddress> to_circuit_type(Builder& builder) const + { + static_assert((std::is_same::value)); + + auto to_ct = [&](auto& e) { return aztec3::utils::types::to_ct(builder, e); }; + + CompleteAddress> complete_address = { to_ct(address), + to_ct(public_key), + to_ct(partial_address) }; + + return complete_address; + }; + + template CompleteAddress to_native_type() const + { + static_assert((std::is_same, NCT>::value)); + + auto to_nt = [&](auto& e) { return aztec3::utils::types::to_nt(e); }; + + CompleteAddress complete_address = { to_nt(address), to_nt(public_key), to_nt(partial_address) }; + + return complete_address; + }; + + void set_public() + { + static_assert(!(std::is_same::value)); + + address.set_public(); + public_key.set_public(); + partial_address.set_public(); + } + + void assert_is_zero() + { + static_assert(!(std::is_same::value)); + + address.assert_is_zero(); + public_key.assert_is_zero(); + partial_address.assert_is_zero(); + } + + static CompleteAddress compute(Point 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(contract_address_salt, function_tree_root, constructor_hash); + + CompleteAddress 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 diff --git a/circuits/cpp/src/aztec3/circuits/hash.hpp b/circuits/cpp/src/aztec3/circuits/hash.hpp index 4c5141ddf91..e29810bce0f 100644 --- a/circuits/cpp/src/aztec3/circuits/hash.hpp +++ b/circuits/cpp/src/aztec3/circuits/hash.hpp @@ -72,19 +72,6 @@ typename NCT::address compute_contract_address_from_partial(Point const& po return { NCT::hash(inputs, aztec3::GeneratorIndex::CONTRACT_ADDRESS) }; } -template typename NCT::address compute_contract_address(Point 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(contract_address_salt, function_tree_root, constructor_hash); - - return compute_contract_address_from_partial(point, partial_address); -} - template typename NCT::fr compute_commitment_nonce(typename NCT::fr const& first_nullifier, typename NCT::fr const& commitment_index) { diff --git a/circuits/cpp/src/aztec3/circuits/kernel/private/common.cpp b/circuits/cpp/src/aztec3/circuits/kernel/private/common.cpp index 97b92d1f8c7..27e1f2ffddb 100644 --- a/circuits/cpp/src/aztec3/circuits/kernel/private/common.cpp +++ b/circuits/cpp/src/aztec3/circuits/kernel/private/common.cpp @@ -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" @@ -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(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::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 const native_new_contract_data{ new_contract_address, diff --git a/circuits/cpp/src/aztec3/circuits/kernel/private/private_kernel_circuit.cpp b/circuits/cpp/src/aztec3/circuits/kernel/private/private_kernel_circuit.cpp index 77a6f9549a6..6c40768c127 100644 --- a/circuits/cpp/src/aztec3/circuits/kernel/private/private_kernel_circuit.cpp +++ b/circuits/cpp/src/aztec3/circuits/kernel/private/private_kernel_circuit.cpp @@ -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" @@ -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; @@ -113,10 +113,11 @@ void update_end_values(PrivateKernelInputsInner 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(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::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( diff --git a/circuits/cpp/src/aztec3/circuits/kernel/private/testing_harness.cpp b/circuits/cpp/src/aztec3/circuits/kernel/private/testing_harness.cpp index fb3f08202ab..66ed5e2774e 100644 --- a/circuits/cpp/src/aztec3/circuits/kernel/private/testing_harness.cpp +++ b/circuits/cpp/src/aztec3/circuits/kernel/private/testing_harness.cpp @@ -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" @@ -225,8 +226,11 @@ std::pair, ContractDeploymentData> create_private_call_d auto constructor_hash = compute_constructor_hash(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( - msg_sender_pub_key, contract_address_salt, contract_deployment_data.function_tree_root, constructor_hash); + contract_address = abis::CompleteAddress::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 { @@ -529,8 +533,10 @@ bool validate_deployed_contract_address(PrivateKernelInputsInit 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::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); } diff --git a/yarn-project/aztec-rpc/src/contract_tree/index.ts b/yarn-project/aztec-rpc/src/contract_tree/index.ts index ad717de98a5..45b2bcc95d7 100644 --- a/yarn-project/aztec-rpc/src/contract_tree/index.ts +++ b/yarn-project/aztec-rpc/src/contract_tree/index.ts @@ -1,7 +1,6 @@ import { CONTRACT_TREE_HEIGHT, CircuitsWasm, - CompleteAddress, EthAddress, FUNCTION_TREE_HEIGHT, Fr, @@ -17,10 +16,9 @@ import { isConstructor, } from '@aztec/circuits.js'; import { - computeContractAddress, + computeCompleteAddress, computeContractLeaf, computeFunctionTreeRoot, - computePartialAddress, computeVarArgsHash, hashConstructor, } from '@aztec/circuits.js/abis'; @@ -95,11 +93,8 @@ export class ContractTree { const vkHash = hashVKStr(constructorAbi.verificationKey, wasm); const argsHash = await computeVarArgsHash(wasm, args); const constructorHash = hashConstructor(wasm, functionData, argsHash, vkHash); - // TODO(benesjan) https://github.com/AztecProtocol/aztec-packages/issues/1873: create computeCompleteAddress - // function --> The following is wasteful as it computes partial address twice - const partialAddress = computePartialAddress(wasm, contractAddressSalt, root, constructorHash); - const address = computeContractAddress(wasm, from, contractAddressSalt, root, constructorHash); - const completeAddress = await CompleteAddress.create(address, from, partialAddress); + + const completeAddress = computeCompleteAddress(wasm, from, contractAddressSalt, root, constructorHash); const contractDao: ContractDao = { ...abi, diff --git a/yarn-project/circuits.js/src/abis/__snapshots__/abis.test.ts.snap b/yarn-project/circuits.js/src/abis/__snapshots__/abis.test.ts.snap index b27325aa391..2146c33a650 100644 --- a/yarn-project/circuits.js/src/abis/__snapshots__/abis.test.ts.snap +++ b/yarn-project/circuits.js/src/abis/__snapshots__/abis.test.ts.snap @@ -1,43 +1,57 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`abis wasm bindings computes a contract address 1`] = ` -AztecAddress { - "buffer": { - "data": [ - 17, - 160, - 201, - 96, - 127, - 185, - 91, - 146, - 4, - 147, - 169, - 211, - 33, - 226, - 156, - 174, - 240, - 174, - 157, - 149, - 81, - 249, - 149, - 226, - 160, - 18, - 239, - 108, - 218, - 140, - 217, - 137, - ], - "type": "Buffer", +exports[`abis wasm bindings computes a complete address 1`] = ` +CompleteAddress { + "address": AztecAddress { + "buffer": { + "data": [ + 17, + 160, + 201, + 96, + 127, + 185, + 91, + 146, + 4, + 147, + 169, + 211, + 33, + 226, + 156, + 174, + 240, + 174, + 157, + 149, + 81, + 249, + 149, + 226, + 160, + 18, + 239, + 108, + 218, + 140, + 217, + 137, + ], + "type": "Buffer", + }, + }, + "partialAddress": Fr { + "value": 14273840083696241216436261500085649155281267590119694711623393161813305965081n, + }, + "publicKey": Point { + "kind": "point", + "x": Fr { + "value": 1n, + }, + "y": Fr { + "value": 2n, + }, }, } `; diff --git a/yarn-project/circuits.js/src/abis/abis.test.ts b/yarn-project/circuits.js/src/abis/abis.test.ts index 564777d086d..b630b7b5047 100644 --- a/yarn-project/circuits.js/src/abis/abis.test.ts +++ b/yarn-project/circuits.js/src/abis/abis.test.ts @@ -5,7 +5,7 @@ import { makeAztecAddress, makeEthAddress, makePoint, makeTxRequest, makeVerific import { CircuitsWasm } from '../wasm/circuits_wasm.js'; import { computeCommitmentNonce, - computeContractAddress, + computeCompleteAddress, computeContractLeaf, computeFunctionLeaf, computeFunctionSelector, @@ -62,12 +62,12 @@ describe('abis wasm bindings', () => { expect(res).toMatchSnapshot(); }); - it('computes a contract address', () => { + it('computes a complete address', () => { const deployerPubKey = makePoint(); const contractAddrSalt = new Fr(2n); const treeRoot = new Fr(3n); const constructorHash = new Fr(4n); - const res = computeContractAddress(wasm, deployerPubKey, contractAddrSalt, treeRoot, constructorHash); + const res = computeCompleteAddress(wasm, deployerPubKey, contractAddrSalt, treeRoot, constructorHash); expect(res).toMatchSnapshot(); }); diff --git a/yarn-project/circuits.js/src/abis/abis.ts b/yarn-project/circuits.js/src/abis/abis.ts index 887efe1289a..f24e6c54471 100644 --- a/yarn-project/circuits.js/src/abis/abis.ts +++ b/yarn-project/circuits.js/src/abis/abis.ts @@ -8,6 +8,7 @@ import { abisComputeBlockHash, abisComputeBlockHashWithGlobals, abisComputeCommitmentNonce, + abisComputeCompleteAddress, abisComputeGlobalsHash, abisComputePublicDataTreeIndex, abisComputePublicDataTreeValue, @@ -17,6 +18,7 @@ import { } from '../cbind/circuits.gen.js'; import { AztecAddress, + CompleteAddress, FUNCTION_SELECTOR_NUM_BYTES, Fr, FunctionData, @@ -182,53 +184,23 @@ export function hashConstructor( } /** - * Computes a contract address. + * Computes a complete address. * @param wasm - A module providing low-level wasm access. * @param deployerPubKey - The pubkey of the contract deployer. * @param contractAddrSalt - The salt used as one of the inputs of the contract address computation. * @param fnTreeRoot - The function tree root of the contract being deployed. * @param constructorHash - The hash of the constructor. - * @returns The contract address. + * @returns The complete address. */ -export function computeContractAddress( +export function computeCompleteAddress( wasm: IWasmModule, deployerPubKey: PublicKey, contractAddrSalt: Fr, fnTreeRoot: Fr, constructorHash: Fr, -): AztecAddress { - wasm.call('pedersen__init'); - const result = inputBuffersToOutputBuffer( - wasm, - 'abis__compute_contract_address', - [deployerPubKey.toBuffer(), contractAddrSalt.toBuffer(), fnTreeRoot.toBuffer(), constructorHash.toBuffer()], - 32, - ); - return new AztecAddress(result); -} - -/** - * Computes a partial address. Consists of all contract address components except the deployer public key. - * @param wasm - A module providing low-level wasm access. - * @param contractAddrSalt - The salt used as one of the inputs of the contract address computation. - * @param fnTreeRoot - The function tree root of the contract being deployed. - * @param constructorHash - The hash of the constructor. - * @returns The partially constructed contract address. - */ -export function computePartialAddress( - wasm: IWasmModule, - contractAddrSalt: Fr, - fnTreeRoot: Fr, - constructorHash: Fr, -): Fr { +): CompleteAddress { wasm.call('pedersen__init'); - const result = inputBuffersToOutputBuffer( - wasm, - 'abis__compute_partial_address', - [contractAddrSalt.toBuffer(), fnTreeRoot.toBuffer(), constructorHash.toBuffer()], - 32, - ); - return Fr.fromBuffer(result); + return abisComputeCompleteAddress(wasm, deployerPubKey, contractAddrSalt, fnTreeRoot, constructorHash); } /** diff --git a/yarn-project/circuits.js/src/cbind/circuits.gen.ts b/yarn-project/circuits.js/src/cbind/circuits.gen.ts index 5dabbdef88f..73a0f908492 100644 --- a/yarn-project/circuits.js/src/cbind/circuits.gen.ts +++ b/yarn-project/circuits.js/src/cbind/circuits.gen.ts @@ -16,6 +16,7 @@ import { CircuitError, CombinedAccumulatedData, CombinedConstantData, + CompleteAddress, ConstantRollupData, ContractDeploymentData, ContractStorageRead, @@ -64,6 +65,70 @@ import { toBuffer, } from './types.js'; +interface MsgpackPoint { + x: Buffer; + y: Buffer; +} + +export function toPoint(o: MsgpackPoint): Point { + if (o.x === undefined) { + throw new Error('Expected x in Point deserialization'); + } + if (o.y === undefined) { + throw new Error('Expected y in Point deserialization'); + } + return new Point(Fr.fromBuffer(o.x), Fr.fromBuffer(o.y)); +} + +export function fromPoint(o: Point): MsgpackPoint { + if (o.x === undefined) { + throw new Error('Expected x in Point serialization'); + } + if (o.y === undefined) { + throw new Error('Expected y in Point serialization'); + } + return { + x: toBuffer(o.x), + y: toBuffer(o.y), + }; +} + +interface MsgpackCompleteAddress { + address: Buffer; + public_key: MsgpackPoint; + partial_address: Buffer; +} + +export function toCompleteAddress(o: MsgpackCompleteAddress): CompleteAddress { + if (o.address === undefined) { + throw new Error('Expected address in CompleteAddress deserialization'); + } + if (o.public_key === undefined) { + throw new Error('Expected public_key in CompleteAddress deserialization'); + } + if (o.partial_address === undefined) { + throw new Error('Expected partial_address in CompleteAddress deserialization'); + } + return new CompleteAddress(Address.fromBuffer(o.address), toPoint(o.public_key), Fr.fromBuffer(o.partial_address)); +} + +export function fromCompleteAddress(o: CompleteAddress): MsgpackCompleteAddress { + if (o.address === undefined) { + throw new Error('Expected address in CompleteAddress serialization'); + } + if (o.publicKey === undefined) { + throw new Error('Expected publicKey in CompleteAddress serialization'); + } + if (o.partialAddress === undefined) { + throw new Error('Expected partialAddress in CompleteAddress serialization'); + } + return { + address: toBuffer(o.address), + public_key: fromPoint(o.publicKey), + partial_address: toBuffer(o.partialAddress), + }; +} + interface MsgpackGlobalVariables { chain_id: Buffer; version: Buffer; @@ -702,34 +767,6 @@ export function fromHistoricBlockData(o: HistoricBlockData): MsgpackHistoricBloc }; } -interface MsgpackPoint { - x: Buffer; - y: Buffer; -} - -export function toPoint(o: MsgpackPoint): Point { - if (o.x === undefined) { - throw new Error('Expected x in Point deserialization'); - } - if (o.y === undefined) { - throw new Error('Expected y in Point deserialization'); - } - return new Point(Fr.fromBuffer(o.x), Fr.fromBuffer(o.y)); -} - -export function fromPoint(o: Point): MsgpackPoint { - if (o.x === undefined) { - throw new Error('Expected x in Point serialization'); - } - if (o.y === undefined) { - throw new Error('Expected y in Point serialization'); - } - return { - x: toBuffer(o.x), - y: toBuffer(o.y), - }; -} - interface MsgpackContractDeploymentData { deployer_public_key: MsgpackPoint; constructor_vk_hash: Buffer; @@ -3088,6 +3125,22 @@ export function fromRootRollupPublicInputs(o: RootRollupPublicInputs): MsgpackRo }; } +export function abisComputeCompleteAddress( + wasm: IWasmModule, + arg0: Point, + arg1: Fr, + arg2: Fr, + arg3: Fr, +): CompleteAddress { + return toCompleteAddress( + callCbind(wasm, 'abis__compute_complete_address', [ + fromPoint(arg0), + toBuffer(arg1), + toBuffer(arg2), + toBuffer(arg3), + ]), + ); +} export function abisComputeCommitmentNonce(wasm: IWasmModule, arg0: Fr, arg1: Fr): Fr { return Fr.fromBuffer(callCbind(wasm, 'abis__compute_commitment_nonce', [toBuffer(arg0), toBuffer(arg1)])); } diff --git a/yarn-project/circuits.js/src/cbind/types.ts b/yarn-project/circuits.js/src/cbind/types.ts index 5c2d7c9f8b5..e30ef43cc1f 100644 --- a/yarn-project/circuits.js/src/cbind/types.ts +++ b/yarn-project/circuits.js/src/cbind/types.ts @@ -95,6 +95,7 @@ export { ContractDeploymentData, TxContext, CombinedConstantData, + CompleteAddress, KernelCircuitPublicInputs, KernelCircuitPublicInputsFinal, Proof, diff --git a/yarn-project/circuits.js/src/contract/contract_deployment_info.ts b/yarn-project/circuits.js/src/contract/contract_deployment_info.ts index 1f3d3ed9e93..dc6914eaf10 100644 --- a/yarn-project/circuits.js/src/contract/contract_deployment_info.ts +++ b/yarn-project/circuits.js/src/contract/contract_deployment_info.ts @@ -1,13 +1,12 @@ import { - computeContractAddress, + computeCompleteAddress, computeFunctionTreeRoot, - computePartialAddress, computeVarArgsHash, hashConstructor, } from '@aztec/circuits.js/abis'; import { ContractAbi, FunctionSelector, encodeArguments } from '@aztec/foundation/abi'; -import { CircuitsWasm, CompleteAddress, DeploymentInfo, Fr, FunctionData, PublicKey } from '../index.js'; +import { CircuitsWasm, DeploymentInfo, Fr, FunctionData, PublicKey } from '../index.js'; import { generateFunctionLeaves, hashVKStr, isConstructor } from './contract_tree/contract_tree.js'; /** @@ -46,10 +45,7 @@ export async function getContractDeploymentInfo( const argsHash = await computeVarArgsHash(wasm, flatArgs); const constructorHash = hashConstructor(wasm, functionData, argsHash, constructorVkHash.toBuffer()); - // TODO(benesjan) https://github.com/AztecProtocol/aztec-packages/issues/1873: create computeCompleteAddress - // function --> The following is wasteful as it computes partial address twice - const partialAddress = computePartialAddress(wasm, contractAddressSalt, functionTreeRoot, constructorHash); - const contractAddress = computeContractAddress( + const completeAddress = computeCompleteAddress( wasm, publicKey, contractAddressSalt, @@ -57,8 +53,6 @@ export async function getContractDeploymentInfo( constructorHash, ); - const completeAddress = await CompleteAddress.create(contractAddress, publicKey, partialAddress); - return { completeAddress, constructorHash: constructorVkHash, diff --git a/yarn-project/circuits.js/src/types/complete_address.test.ts b/yarn-project/circuits.js/src/structs/complete_address.test.ts similarity index 100% rename from yarn-project/circuits.js/src/types/complete_address.test.ts rename to yarn-project/circuits.js/src/structs/complete_address.test.ts diff --git a/yarn-project/circuits.js/src/types/complete_address.ts b/yarn-project/circuits.js/src/structs/complete_address.ts similarity index 97% rename from yarn-project/circuits.js/src/types/complete_address.ts rename to yarn-project/circuits.js/src/structs/complete_address.ts index 77dfa19d159..21db16b9a2a 100644 --- a/yarn-project/circuits.js/src/types/complete_address.ts +++ b/yarn-project/circuits.js/src/structs/complete_address.ts @@ -3,9 +3,7 @@ import { BufferReader } from '@aztec/foundation/serialize'; import { computeContractAddressFromPartial } from '../abis/abis.js'; import { Grumpkin } from '../barretenberg/index.js'; -import { CircuitsWasm, Fr, GrumpkinPrivateKey, Point } from '../index.js'; -import { PartialAddress } from './partial_address.js'; -import { PublicKey } from './public_key.js'; +import { CircuitsWasm, Fr, GrumpkinPrivateKey, PartialAddress, Point, PublicKey } from '../index.js'; /** * A complete address is a combination of an Aztec address, a public key and a partial address. diff --git a/yarn-project/circuits.js/src/structs/index.ts b/yarn-project/circuits.js/src/structs/index.ts index 7e31d2957b4..da643b14915 100644 --- a/yarn-project/circuits.js/src/structs/index.ts +++ b/yarn-project/circuits.js/src/structs/index.ts @@ -29,6 +29,7 @@ export * from './aggregation_object.js'; export * from './membership_witness.js'; export * from './read_request_membership_witness.js'; export * from './public_call_request.js'; +export * from './complete_address.js'; export * from '@aztec/foundation/eth-address'; export * from '@aztec/foundation/fields'; diff --git a/yarn-project/circuits.js/src/types/index.ts b/yarn-project/circuits.js/src/types/index.ts index b244de25e3b..12a0bb40a85 100644 --- a/yarn-project/circuits.js/src/types/index.ts +++ b/yarn-project/circuits.js/src/types/index.ts @@ -1,5 +1,4 @@ export * from './contract_function_dao.js'; -export * from './complete_address.js'; export * from './deployment_info.js'; export * from './partial_address.js'; export * from './grumpkin_private_key.js'; diff --git a/yarn-project/end-to-end/src/e2e_sandbox_example.test.ts b/yarn-project/end-to-end/src/e2e_sandbox_example.test.ts index 0cf0115d8b8..7f0b77d7aa9 100644 --- a/yarn-project/end-to-end/src/e2e_sandbox_example.test.ts +++ b/yarn-project/end-to-end/src/e2e_sandbox_example.test.ts @@ -5,8 +5,8 @@ import { computeMessageSecretHash, createAztecRpcClient, createDebugLogger, - getSchnorrAccount, getSandboxAccountsWallets, + getSchnorrAccount, waitForSandbox, } from '@aztec/aztec.js'; import { GrumpkinScalar } from '@aztec/circuits.js'; @@ -47,7 +47,7 @@ describe('e2e_sandbox_example', () => { logger(`Loaded alice's account at ${alice.toShortString()}`); logger(`Loaded bob's account at ${bob.toShortString()}`); // docs:end:load_accounts - + // docs:start:Deployment ////////////// DEPLOY OUR TOKEN CONTRACT ////////////// diff --git a/yarn-project/types/src/index.ts b/yarn-project/types/src/index.ts index d064651f5ce..c9714153628 100644 --- a/yarn-project/types/src/index.ts +++ b/yarn-project/types/src/index.ts @@ -23,3 +23,4 @@ export * from './interfaces/index.js'; export * from './sibling_path.js'; export * from './auth_witness.js'; export * from '@aztec/circuits.js/types'; +export { CompleteAddress } from '@aztec/circuits.js';