Skip to content

Commit

Permalink
feat: partial logic to check existence of vk in contract tree (missin…
Browse files Browse the repository at this point in the history
…g merkle tree membership calls)
  • Loading branch information
iAmMichaelConnor authored and dbanks12 committed Apr 6, 2023
1 parent 2d4873c commit 580540d
Show file tree
Hide file tree
Showing 3 changed files with 134 additions and 54 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -112,4 +112,6 @@ template <typename NCT> std::ostream& operator<<(std::ostream& os, NewContractDa
<< "function_tree_root: " << new_contract_data.function_tree_root << "\n";
}

template <typename NCT> using ContractLeafPreimage = NewContractData<NCT>;

} // namespace aztec3::circuits::abis::private_kernel
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ template <typename NCT> struct PrivateCallData {
MembershipWitness<NCT, CONTRACT_TREE_HEIGHT> contract_leaf_membership_witness;

fr portal_contract_address; // an ETH address
fr acir_hash;

boolean operator==(PrivateCallData<NCT> const& other) const
{
Expand All @@ -46,6 +47,7 @@ template <typename NCT> struct PrivateCallData {
function_leaf_membership_witness == other.function_leaf_membership_witness &&
contract_leaf_membership_witness == other.contract_leaf_membership_witness &&
portal_contract_address == other.portal_contract_address;
acir_hash == other.acir_hash;
};

// WARNING: the `proof` does NOT get converted! (because the current implementation of `verify_proof` takes a proof
Expand All @@ -72,6 +74,7 @@ template <typename NCT> struct PrivateCallData {
to_circuit_type(contract_leaf_membership_witness),

to_ct(portal_contract_address),
to_ct(acir_hash),
};

return data;
Expand All @@ -89,6 +92,7 @@ template <typename NCT> void read(uint8_t const*& it, PrivateCallData<NCT>& obj)
read(it, obj.function_leaf_membership_witness);
read(it, obj.contract_leaf_membership_witness);
read(it, obj.portal_contract_address);
read(it, obj.acir_hash);
};

template <typename NCT> void write(std::vector<uint8_t>& buf, PrivateCallData<NCT> const& obj)
Expand All @@ -102,6 +106,7 @@ template <typename NCT> void write(std::vector<uint8_t>& buf, PrivateCallData<NC
write(buf, obj.function_leaf_membership_witness);
write(buf, obj.contract_leaf_membership_witness);
write(buf, obj.portal_contract_address);
write(buf, obj.acir_hash);
};

template <typename NCT> std::ostream& operator<<(std::ostream& os, PrivateCallData<NCT> const& obj)
Expand All @@ -118,7 +123,8 @@ template <typename NCT> std::ostream& operator<<(std::ostream& os, PrivateCallDa
<< obj.function_leaf_membership_witness << "\n"
<< "contract_leaf_membership_witness:\n"
<< obj.contract_leaf_membership_witness << "\n"
<< "portal_contract_address: " << obj.portal_contract_address << "\n";
<< "portal_contract_address: " << obj.portal_contract_address << "\n"
<< "acir_hash: " << obj.acir_hash << "\n";
}

} // namespace aztec3::circuits::abis::private_kernel
178 changes: 125 additions & 53 deletions cpp/src/aztec3/circuits/kernel/private/native_private_kernel_circuit.cpp
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
#include "aztec3/constants.hpp"
#include "init.hpp"

#include "aztec3/circuits/abis/function_leaf_preimage.hpp"
#include <aztec3/circuits/abis/private_kernel/private_inputs.hpp>
#include <aztec3/circuits/abis/private_kernel/public_inputs.hpp>
#include <aztec3/circuits/abis/private_kernel/new_contract_data.hpp>

#include <aztec3/utils/array.hpp>
#include <aztec3/circuits/hash.hpp>
#include "aztec3/constants.hpp"

#include <barretenberg/stdlib/merkle_tree/membership.hpp>

namespace aztec3::circuits::kernel::private_kernel {

using aztec3::circuits::abis::FunctionLeafPreimage;
using aztec3::circuits::abis::private_kernel::ContractLeafPreimage;
using aztec3::circuits::abis::private_kernel::NewContractData;
using aztec3::circuits::abis::private_kernel::PrivateInputs;
using aztec3::circuits::abis::private_kernel::PublicInputs;
Expand All @@ -23,6 +28,8 @@ using aztec3::utils::push_array_to_array;
using aztec3::circuits::compute_constructor_hash;
using aztec3::circuits::compute_contract_address;

// using plonk::stdlib::merkle_tree::

// // TODO: NEED TO RECONCILE THE `proof`'s public inputs (which are uint8's) with the
// // private_call.call_stack_item.public_inputs!
// CT::AggregationObject verify_proofs(Composer& composer,
Expand Down Expand Up @@ -62,73 +69,138 @@ void initialise_end_values(PrivateInputs<NT> const& private_inputs, PublicInputs
end.optionally_revealed_data = start.optionally_revealed_data;
}

void update_end_values(PrivateInputs<NT> const& private_inputs, PublicInputs<NT>& public_inputs)
void contract_logic(PrivateInputs<NT> const& private_inputs, PublicInputs<NT>& public_inputs)
{
const auto private_call_public_inputs = private_inputs.private_call.call_stack_item.public_inputs;

const auto& new_commitments = private_call_public_inputs.new_commitments;
const auto& new_nullifiers = private_call_public_inputs.new_nullifiers;

const auto& is_static_call = private_call_public_inputs.call_context.is_static_call;

if (is_static_call) {
// No state changes are allowed for static calls:
ASSERT(is_array_empty(new_commitments) == true);
ASSERT(is_array_empty(new_nullifiers) == true);
}

const auto& storage_contract_address = private_call_public_inputs.call_context.storage_contract_address;
const auto& portal_contract_address = private_inputs.private_call.portal_contract_address;
const auto& deployer_address = private_call_public_inputs.call_context.msg_sender;
const auto& contract_deployment_data =
private_inputs.signed_tx_request.tx_request.tx_context.contract_deployment_data;

{ // contract deployment
// input storage contract address must be 0 if its a constructor call and non-zero otherwise
auto is_contract_deployment = public_inputs.constants.tx_context.is_contract_deployment_tx;
// contract deployment

auto private_call_vk_hash = stdlib::recursion::verification_key<CT::bn254>::compress_native(
private_inputs.private_call.vk, GeneratorIndex::VK);
// input storage contract address must be 0 if its a constructor call and non-zero otherwise
auto is_contract_deployment = public_inputs.constants.tx_context.is_contract_deployment_tx;

auto constructor_hash = compute_constructor_hash(private_inputs.signed_tx_request.tx_request.function_data,
private_call_public_inputs.args,
private_call_vk_hash);
auto private_call_vk_hash = stdlib::recursion::verification_key<CT::bn254>::compress_native(
private_inputs.private_call.vk, GeneratorIndex::VK);

if (is_contract_deployment) {
ASSERT(contract_deployment_data.constructor_vk_hash == private_call_vk_hash);
}
auto constructor_hash = compute_constructor_hash(private_inputs.signed_tx_request.tx_request.function_data,
private_call_public_inputs.args,
private_call_vk_hash);

auto contract_address = compute_contract_address<NT>(deployer_address,
contract_deployment_data.contract_address_salt,
contract_deployment_data.function_tree_root,
constructor_hash);

if (is_contract_deployment) {
// must imply == derived address
ASSERT(storage_contract_address == contract_address);
} else {
// non-contract deployments must specify contract address being interacted with
ASSERT(storage_contract_address != 0);
}
if (is_contract_deployment) {
ASSERT(contract_deployment_data.constructor_vk_hash == private_call_vk_hash);
}

// compute contract address nullifier
auto blake_input = contract_address.to_field().to_buffer();
auto contract_address_nullifier = NT::fr::serialize_from_buffer(NT::blake3s(blake_input).data());
auto const new_contract_address = compute_contract_address<NT>(deployer_address,
contract_deployment_data.contract_address_salt,
contract_deployment_data.function_tree_root,
constructor_hash);

// push the contract address nullifier to nullifier vector
if (is_contract_deployment) {
array_push(public_inputs.end.new_nullifiers, contract_address_nullifier);
}
if (is_contract_deployment) {
// must imply == derived address
ASSERT(storage_contract_address == new_contract_address);
} else {
// non-contract deployments must specify contract address being interacted with
ASSERT(storage_contract_address != 0);
}

// Add new contract data if its a contract deployment function
auto native_new_contract_data = NewContractData<NT>{ contract_address,
portal_contract_address,
contract_deployment_data.function_tree_root };
// compute contract address nullifier
auto const blake_input = new_contract_address.to_field().to_buffer();
auto const new_contract_address_nullifier = NT::fr::serialize_from_buffer(NT::blake3s(blake_input).data());

array_push<NewContractData<NT>, KERNEL_NEW_CONTRACTS_LENGTH>(public_inputs.end.new_contracts,
native_new_contract_data);
// push the contract address nullifier to nullifier vector
if (is_contract_deployment) {
array_push(public_inputs.end.new_nullifiers, new_contract_address_nullifier);
}

// Add new contract data if its a contract deployment function
NewContractData<NT> native_new_contract_data{ new_contract_address,
portal_contract_address,
contract_deployment_data.function_tree_root };

array_push<NewContractData<NT>, KERNEL_NEW_CONTRACTS_LENGTH>(public_inputs.end.new_contracts,
native_new_contract_data);

// We need to compute the root of the contract tree, starting from the function's VK:

// Compute the vk_hash (already done above)
//
// Compute the function_leaf: hash(function_selector, is_private, vk_hash, acir_hash)
//
// Hash the function_leaf with the function_leaf's sibling_path to get the function_tree_root
//
// Compute the contract_leaf: hash(contract_address, portal_contract_address, function_tree_root)
//
// Hash the function_leaf with the contract_leaf's sibling_path to get the contract_tree_root

const auto function_leaf_preimage = FunctionLeafPreimage<NT>{
.function_selector = private_inputs.private_call.call_stack_item.function_data.function_selector,
.is_private = true,
.vk_hash = private_call_vk_hash,
.acir_hash = private_inputs.private_call.acir_hash,
};

const auto function_leaf = function_leaf_preimage.hash();

// TODO: compute function_tree_root using:
// the function_leaf,
auto& function_leaf_index = private_inputs.private_call.function_leaf_membership_witness.leaf_index;
auto& function_leaf_sibling_path = private_inputs.private_call.function_leaf_membership_witness.sibling_path;

const auto function_tree_root = 1; // TODO: compute the root properly!!!

const ContractLeafPreimage<NT> contract_leaf_preimage{
storage_contract_address,
portal_contract_address,
function_tree_root,
};

const auto contract_leaf = contract_leaf_preimage.hash();

// TODO: compute the contract_tree_root using:
// the contract_leaf,
auto& contract_leaf_index = private_inputs.private_call.contract_leaf_membership_witness.leaf_index;
auto& contract_leaf_sibling_path = private_inputs.private_call.contract_leaf_membership_witness.sibling_path;

// TODO remove prints
info("function_leaf: ", function_leaf);
info("function_leaf_index: ", function_leaf_index);
info("function_leaf_sibling_path: ", function_leaf_sibling_path);
info("contract_leaf: ", contract_leaf);
info("contract_leaf_index: ", contract_leaf_index);
info("contract_leaf_sibling_path: ", contract_leaf_sibling_path);

const auto computed_contract_tree_root = 2; // TODO: compute the root properly!!!

auto& purported_contract_tree_root =
private_inputs.private_call.call_stack_item.public_inputs.historic_contract_tree_root;
ASSERT(computed_contract_tree_root == purported_contract_tree_root);

auto& previous_kernel_contract_tree_root =
private_inputs.previous_kernel.public_inputs.constants.old_tree_roots.contract_tree_root;
ASSERT(purported_contract_tree_root == previous_kernel_contract_tree_root);
}

void update_end_values(PrivateInputs<NT> const& private_inputs, PublicInputs<NT>& public_inputs)
{
const auto private_call_public_inputs = private_inputs.private_call.call_stack_item.public_inputs;

const auto& new_commitments = private_call_public_inputs.new_commitments;
const auto& new_nullifiers = private_call_public_inputs.new_nullifiers;

const auto& is_static_call = private_call_public_inputs.call_context.is_static_call;

if (is_static_call) {
// No state changes are allowed for static calls:
ASSERT(is_array_empty(new_commitments) == true);
ASSERT(is_array_empty(new_nullifiers) == true);
}

const auto& storage_contract_address = private_call_public_inputs.call_context.storage_contract_address;

{
// Nonce nullifier
// DANGER: This is terrible. This should not be part of the protocol. This is an intentional bodge to reach a
Expand Down Expand Up @@ -183,11 +255,11 @@ void validate_this_private_call_hash(PrivateInputs<NT> const& private_inputs)
const auto& start = private_inputs.previous_kernel.public_inputs.end;
// TODO: this logic might need to change to accommodate the weird edge 3 initial txs (the 'main' tx, the 'fee' tx,
// and the 'gas rebate' tx).
const auto this_private_call_hash = array_pop(start.private_call_stack);
const auto popped_private_call_hash = array_pop(start.private_call_stack);
const auto calculated_this_private_call_hash = private_inputs.private_call.call_stack_item.hash();

ASSERT(this_private_call_hash ==
calculated_this_private_call_hash); // "this private_call_hash does not reconcile");
ASSERT(popped_private_call_hash ==
calculated_this_private_call_hash); // "this private_call_hash does not reconcile";
};

void validate_this_private_call_stack(PrivateInputs<NT> const& private_inputs)
Expand Down

0 comments on commit 580540d

Please sign in to comment.