diff --git a/circuits/cpp/src/aztec3/circuits/abis/.test.cpp b/circuits/cpp/src/aztec3/circuits/abis/.test.cpp index a81da1e62b05..86492c81d63d 100644 --- a/circuits/cpp/src/aztec3/circuits/abis/.test.cpp +++ b/circuits/cpp/src/aztec3/circuits/abis/.test.cpp @@ -4,7 +4,7 @@ #include "index.hpp" #include -#include "private_kernel/previous_kernel_data.hpp" +#include "previous_kernel_data.hpp" #include "private_kernel/private_inputs.hpp" namespace aztec3::circuits::abis { diff --git a/circuits/cpp/src/aztec3/circuits/abis/c_bind.cpp b/circuits/cpp/src/aztec3/circuits/abis/c_bind.cpp index 58161210b13a..a26bb2e03c82 100644 --- a/circuits/cpp/src/aztec3/circuits/abis/c_bind.cpp +++ b/circuits/cpp/src/aztec3/circuits/abis/c_bind.cpp @@ -2,7 +2,7 @@ #include "barretenberg/srs/reference_string/mem_reference_string.hpp" #include "aztec3/circuits/abis/function_data.hpp" #include "aztec3/circuits/abis/function_leaf_preimage.hpp" -#include "aztec3/circuits/abis/private_kernel/new_contract_data.hpp" +#include "aztec3/circuits/abis/new_contract_data.hpp" #include "private_circuit_public_inputs.hpp" #include "tx_request.hpp" #include "tx_context.hpp" @@ -12,9 +12,9 @@ #include "rollup/base/base_or_merge_rollup_public_inputs.hpp" #include "rollup/root/root_rollup_public_inputs.hpp" #include "rollup/root/root_rollup_inputs.hpp" -#include "private_kernel/previous_kernel_data.hpp" +#include "previous_kernel_data.hpp" #include "private_kernel/private_inputs.hpp" -#include "private_kernel/public_inputs.hpp" +#include "kernel_circuit_public_inputs.hpp" #include #include @@ -31,9 +31,9 @@ using aztec3::circuits::compute_constructor_hash; using aztec3::circuits::compute_contract_address; using aztec3::circuits::abis::FunctionData; using aztec3::circuits::abis::FunctionLeafPreimage; +using aztec3::circuits::abis::NewContractData; using aztec3::circuits::abis::TxContext; using aztec3::circuits::abis::TxRequest; -using aztec3::circuits::abis::private_kernel::NewContractData; using NT = aztec3::utils::types::NativeTypes; // Cbind helper functions @@ -403,7 +403,7 @@ WASM_EXPORT const char* abis__test_roundtrip_serialize_base_rollup_inputs(uint8_ WASM_EXPORT const char* abis__test_roundtrip_serialize_previous_kernel_data(uint8_t const* kernel_data_buf, uint32_t* size) { - return as_string_output>(kernel_data_buf, size); + return as_string_output>(kernel_data_buf, size); } WASM_EXPORT const char* abis__test_roundtrip_serialize_base_or_merge_rollup_public_inputs( @@ -441,17 +441,16 @@ WASM_EXPORT const char* abis__test_roundtrip_serialize_private_kernel_inputs(uin return as_string_output>(input, size); } -WASM_EXPORT const char* abis__test_roundtrip_serialize_private_kernel_public_inputs(uint8_t const* input, +WASM_EXPORT const char* abis__test_roundtrip_serialize_kernel_circuit_public_inputs(uint8_t const* input, uint32_t* size) { - return as_string_output>(input, size); + return as_string_output>(input, size); } - -WASM_EXPORT const char* abis__test_roundtrip_serialize_function_leaf_preimage(uint8_t const* function_leaf_preimage_buf, uint32_t* size) +WASM_EXPORT const char* abis__test_roundtrip_serialize_function_leaf_preimage(uint8_t const* function_leaf_preimage_buf, + uint32_t* size) { return as_string_output>(function_leaf_preimage_buf, size); } - } // extern "C" 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 1ee832d871e3..a050e9d2c7fd 100644 --- a/circuits/cpp/src/aztec3/circuits/abis/c_bind.test.cpp +++ b/circuits/cpp/src/aztec3/circuits/abis/c_bind.test.cpp @@ -2,7 +2,7 @@ #include "tx_request.hpp" #include "function_leaf_preimage.hpp" -#include "aztec3/circuits/abis/private_kernel/new_contract_data.hpp" +#include "aztec3/circuits/abis/new_contract_data.hpp" #include #include @@ -13,7 +13,7 @@ namespace { using NT = aztec3::utils::types::NativeTypes; -using aztec3::circuits::abis::private_kernel::NewContractData; +using aztec3::circuits::abis::NewContractData; auto& engine = numeric::random::get_debug_engine(); diff --git a/circuits/cpp/src/aztec3/circuits/abis/call_stack_item.hpp b/circuits/cpp/src/aztec3/circuits/abis/call_stack_item.hpp index e1b77bd1eb5b..e87bfdeb2ae9 100644 --- a/circuits/cpp/src/aztec3/circuits/abis/call_stack_item.hpp +++ b/circuits/cpp/src/aztec3/circuits/abis/call_stack_item.hpp @@ -2,6 +2,7 @@ #include "function_data.hpp" #include "private_circuit_public_inputs.hpp" #include "public_circuit_public_inputs.hpp" +#include "kernel_circuit_public_inputs.hpp" #include #include @@ -15,20 +16,11 @@ using aztec3::utils::types::NativeTypes; using std::conditional; using std::is_same; -enum class CallType { - Public, - Private, -}; - -template struct CallStackItem { +template typename PrivatePublic> struct CallStackItem { typedef typename NCT::address address; typedef typename NCT::boolean boolean; typedef typename NCT::fr fr; - template - using PublicInputs = typename std:: - conditional, PrivateCircuitPublicInputs>::type; - // This is the _actual_ contract address relating to where this function's code resides in the // contract tree. Regardless of whether this is a call or delegatecall, this // `contract_address` _does not change_. Amongst other things, it's used as a lookup for @@ -36,7 +28,7 @@ template struct CallStackItem { // within a CallStackItem which varies depending on whether this is a call or delegatecall. address contract_address = 0; FunctionData function_data{}; - PublicInputs public_inputs{}; + typename PrivatePublic::AppCircuitPublicInputs public_inputs{}; boolean operator==(CallContext const& other) const { @@ -45,14 +37,14 @@ template struct CallStackItem { }; template - CallStackItem, call_type> to_circuit_type(Composer& composer) const + CallStackItem, PrivatePublic> to_circuit_type(Composer& composer) const { static_assert((std::is_same::value)); // Capture the composer: auto to_ct = [&](auto& e) { return aztec3::utils::types::to_ct(composer, e); }; - CallStackItem, call_type> call_stack_item = { + CallStackItem, PrivatePublic> call_stack_item = { to_ct(contract_address), function_data.to_circuit_type(composer), public_inputs.to_circuit_type(composer), @@ -75,8 +67,8 @@ template struct CallStackItem { } }; // namespace aztec3::circuits::abis -template -void read(uint8_t const*& it, CallStackItem& call_stack_item) +template typename PrivatePublic> +void read(uint8_t const*& it, CallStackItem& call_stack_item) { using serialize::read; @@ -85,8 +77,8 @@ void read(uint8_t const*& it, CallStackItem& call_stack_item) read(it, call_stack_item.public_inputs); }; -template -void write(std::vector& buf, CallStackItem const& call_stack_item) +template typename PrivatePublic> +void write(std::vector& buf, CallStackItem const& call_stack_item) { using serialize::write; @@ -95,8 +87,8 @@ void write(std::vector& buf, CallStackItem const& call_ write(buf, call_stack_item.public_inputs); }; -template -std::ostream& operator<<(std::ostream& os, CallStackItem const& call_stack_item) +template typename PrivatePublic> +std::ostream& operator<<(std::ostream& os, CallStackItem const& call_stack_item) { return os << "contract_address: " << call_stack_item.contract_address << "\n" << "function_data: " << call_stack_item.function_data << "\n" diff --git a/circuits/cpp/src/aztec3/circuits/abis/private_kernel/accumulated_data.hpp b/circuits/cpp/src/aztec3/circuits/abis/combined_accumulated_data.hpp similarity index 68% rename from circuits/cpp/src/aztec3/circuits/abis/private_kernel/accumulated_data.hpp rename to circuits/cpp/src/aztec3/circuits/abis/combined_accumulated_data.hpp index f089eb98cc8c..0493445bebd3 100644 --- a/circuits/cpp/src/aztec3/circuits/abis/private_kernel/accumulated_data.hpp +++ b/circuits/cpp/src/aztec3/circuits/abis/combined_accumulated_data.hpp @@ -1,6 +1,8 @@ #pragma once -#include "../optionally_revealed_data.hpp" -#include "aztec3/circuits/abis/private_kernel/new_contract_data.hpp" +#include "optionally_revealed_data.hpp" +#include "new_contract_data.hpp" +#include "state_transition.hpp" +#include "state_read.hpp" #include "aztec3/constants.hpp" #include #include @@ -10,14 +12,14 @@ #include #include -namespace aztec3::circuits::abis::private_kernel { +namespace aztec3::circuits::abis { using aztec3::utils::zero_array; using aztec3::utils::types::CircuitTypes; using aztec3::utils::types::NativeTypes; using std::is_same; -template struct AccumulatedData { +template struct CombinedAccumulatedData { typedef typename NCT::fr fr; typedef typename NCT::boolean boolean; typedef typename NCT::AggregationObject AggregationObject; @@ -25,6 +27,7 @@ template struct AccumulatedData { AggregationObject aggregation_object{}; fr private_call_count = 0; + fr public_call_count = 0; std::array new_commitments = zero_array(); std::array new_nullifiers = zero_array(); @@ -39,16 +42,21 @@ template struct AccumulatedData { std::array, KERNEL_OPTIONALLY_REVEALED_DATA_LENGTH> optionally_revealed_data{}; - boolean operator==(AccumulatedData const& other) const + std::array, STATE_TRANSITIONS_LENGTH> state_transitions{}; + std::array, STATE_READS_LENGTH> state_reads{}; + + boolean operator==(CombinedAccumulatedData const& other) const { return aggregation_object == other.aggregation_object && private_call_count == other.private_call_count && - new_commitments == other.new_commitments && new_nullifiers == other.new_nullifiers && - private_call_stack == other.private_call_stack && public_call_stack == other.public_call_stack && - l1_msg_stack == other.l1_msg_stack && new_contracts == other.new_contracts && - optionally_revealed_data == other.optionally_revealed_data; + public_call_count == other.public_call_count && new_commitments == other.new_commitments && + new_nullifiers == other.new_nullifiers && private_call_stack == other.private_call_stack && + public_call_stack == other.public_call_stack && l1_msg_stack == other.l1_msg_stack && + new_contracts == other.new_contracts && optionally_revealed_data == other.optionally_revealed_data && + state_transitions == other.state_transitions && state_reads == other.state_reads; }; - template AccumulatedData> to_circuit_type(Composer& composer) const + template + CombinedAccumulatedData> to_circuit_type(Composer& composer) const { typedef CircuitTypes CT; static_assert((std::is_same::value)); @@ -57,7 +65,7 @@ template struct AccumulatedData { auto to_ct = [&](auto& e) { return aztec3::utils::types::to_ct(composer, e); }; auto to_circuit_type = [&](auto& e) { return e.to_circuit_type(composer); }; - AccumulatedData acc_data = { + CombinedAccumulatedData acc_data = { typename CT::AggregationObject{ to_ct(aggregation_object.P0), to_ct(aggregation_object.P1), @@ -67,6 +75,7 @@ template struct AccumulatedData { }, to_ct(private_call_count), + to_ct(public_call_count), to_ct(new_commitments), to_ct(new_nullifiers), @@ -77,18 +86,20 @@ template struct AccumulatedData { map(new_contracts, to_circuit_type), map(optionally_revealed_data, to_circuit_type), + map(state_transitions, to_circuit_type), + map(state_reads, to_circuit_type), }; return acc_data; }; - template AccumulatedData to_native_type() const + template CombinedAccumulatedData to_native_type() const { static_assert(std::is_same, NCT>::value); auto to_nt = [&](auto& e) { return aztec3::utils::types::to_nt(e); }; auto to_native_type = [](T& e) { return e.template to_native_type(); }; - AccumulatedData acc_data = { + CombinedAccumulatedData acc_data = { typename NativeTypes::AggregationObject{ to_nt(aggregation_object.P0), to_nt(aggregation_object.P1), @@ -98,6 +109,7 @@ template struct AccumulatedData { }, to_nt(private_call_count), + to_nt(public_call_count), to_nt(new_commitments), to_nt(new_nullifiers), @@ -108,6 +120,8 @@ template struct AccumulatedData { map(new_contracts, to_native_type), map(optionally_revealed_data, to_native_type), + map(state_transitions, to_native_type), + map(state_reads, to_native_type), }; return acc_data; @@ -120,6 +134,7 @@ template struct AccumulatedData { aggregation_object.add_proof_outputs_as_public_inputs(); private_call_count.set_public(); + public_call_count.set_public(); set_array_public(new_commitments); set_array_public(new_nullifiers); @@ -130,6 +145,8 @@ template struct AccumulatedData { set_array_public(new_contracts); set_array_public(optionally_revealed_data); + set_array_public(state_transitions); + set_array_public(state_reads); } template void set_array_public(std::array& arr) @@ -155,14 +172,31 @@ template struct AccumulatedData { e.set_public(); } } + + template void set_array_public(std::array, SIZE>& arr) + { + static_assert(!(std::is_same::value)); + for (auto& e : arr) { + e.set_public(); + } + } + + template void set_array_public(std::array, SIZE>& arr) + { + static_assert(!(std::is_same::value)); + for (auto& e : arr) { + e.set_public(); + } + } }; -template void read(uint8_t const*& it, AccumulatedData& accum_data) +template void read(uint8_t const*& it, CombinedAccumulatedData& accum_data) { using serialize::read; read(it, accum_data.aggregation_object); read(it, accum_data.private_call_count); + read(it, accum_data.public_call_count); read(it, accum_data.new_commitments); read(it, accum_data.new_nullifiers); read(it, accum_data.private_call_stack); @@ -170,14 +204,17 @@ template void read(uint8_t const*& it, AccumulatedData& accu read(it, accum_data.l1_msg_stack); read(it, accum_data.new_contracts); read(it, accum_data.optionally_revealed_data); + read(it, accum_data.state_transitions); + read(it, accum_data.state_reads); }; -template void write(std::vector& buf, AccumulatedData const& accum_data) +template void write(std::vector& buf, CombinedAccumulatedData const& accum_data) { using serialize::write; write(buf, accum_data.aggregation_object); write(buf, accum_data.private_call_count); + write(buf, accum_data.public_call_count); write(buf, accum_data.new_commitments); write(buf, accum_data.new_nullifiers); write(buf, accum_data.private_call_stack); @@ -185,13 +222,16 @@ template void write(std::vector& buf, AccumulatedData std::ostream& operator<<(std::ostream& os, AccumulatedData const& accum_data) +template std::ostream& operator<<(std::ostream& os, CombinedAccumulatedData const& accum_data) { return os << "aggregation_object:\n" << accum_data.aggregation_object << "\n" << "private_call_count: " << accum_data.private_call_count << "\n" + << "public_call_count: " << accum_data.public_call_count << "\n" << "new_commitments:\n" << accum_data.new_commitments << "\n" << "new_nullifiers:\n" @@ -205,7 +245,11 @@ template std::ostream& operator<<(std::ostream& os, AccumulatedDa << "new_contracts:\n" << accum_data.new_contracts << "\n" << "optionally_revealed_data:\n" - << accum_data.optionally_revealed_data << "\n"; + << accum_data.optionally_revealed_data << "\n" + << "state_transitions:\n" + << accum_data.state_transitions << "\n" + << "state_reads:\n" + << accum_data.state_reads << "\n"; } -} // namespace aztec3::circuits::abis::private_kernel \ No newline at end of file +} // namespace aztec3::circuits::abis \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/abis/private_kernel/constant_data.hpp b/circuits/cpp/src/aztec3/circuits/abis/combined_constant_data.hpp similarity index 68% rename from circuits/cpp/src/aztec3/circuits/abis/private_kernel/constant_data.hpp rename to circuits/cpp/src/aztec3/circuits/abis/combined_constant_data.hpp index fbd748a50548..e4465ed49e57 100644 --- a/circuits/cpp/src/aztec3/circuits/abis/private_kernel/constant_data.hpp +++ b/circuits/cpp/src/aztec3/circuits/abis/combined_constant_data.hpp @@ -1,37 +1,37 @@ #pragma once -#include "historic_tree_roots.hpp" -#include "../tx_context.hpp" +#include "combined_historic_tree_roots.hpp" +#include "tx_context.hpp" #include #include #include #include -namespace aztec3::circuits::abis::private_kernel { +namespace aztec3::circuits::abis { using aztec3::utils::types::CircuitTypes; using aztec3::utils::types::NativeTypes; using plonk::stdlib::witness_t; using std::is_same; -template struct ConstantData { +template struct CombinedConstantData { typedef typename NCT::fr fr; typedef typename NCT::boolean boolean; - HistoricTreeRoots historic_tree_roots{}; + CombinedHistoricTreeRoots historic_tree_roots{}; TxContext tx_context{}; - boolean operator==(ConstantData const& other) const + boolean operator==(CombinedConstantData const& other) const { return historic_tree_roots == other.historic_tree_roots && tx_context == other.tx_context; }; - template ConstantData> to_circuit_type(Composer& composer) const + template CombinedConstantData> to_circuit_type(Composer& composer) const { static_assert((std::is_same::value)); - ConstantData> constant_data = { + CombinedConstantData> constant_data = { historic_tree_roots.to_circuit_type(composer), tx_context.to_circuit_type(composer), }; @@ -39,13 +39,13 @@ template struct ConstantData { return constant_data; }; - template ConstantData to_native_type() const + template CombinedConstantData to_native_type() const { static_assert(std::is_same, NCT>::value); auto to_native_type = [](T& e) { return e.template to_native_type(); }; - ConstantData constant_data = { + CombinedConstantData constant_data = { to_native_type(historic_tree_roots), to_native_type(tx_context), }; @@ -62,7 +62,7 @@ template struct ConstantData { } }; -template void read(uint8_t const*& it, ConstantData& constant_data) +template void read(uint8_t const*& it, CombinedConstantData& constant_data) { using serialize::read; @@ -70,7 +70,7 @@ template void read(uint8_t const*& it, ConstantData& constan read(it, constant_data.tx_context); }; -template void write(std::vector& buf, ConstantData const& constant_data) +template void write(std::vector& buf, CombinedConstantData const& constant_data) { using serialize::write; @@ -78,10 +78,10 @@ template void write(std::vector& buf, ConstantData write(buf, constant_data.tx_context); }; -template std::ostream& operator<<(std::ostream& os, ConstantData const& constant_data) +template std::ostream& operator<<(std::ostream& os, CombinedConstantData const& constant_data) { return os << "historic_tree_roots: " << constant_data.historic_tree_roots << "\n" << "tx_context: " << constant_data.tx_context << "\n"; } -} // namespace aztec3::circuits::abis::private_kernel \ No newline at end of file +} // namespace aztec3::circuits::abis \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/abis/combined_historic_tree_roots.hpp b/circuits/cpp/src/aztec3/circuits/abis/combined_historic_tree_roots.hpp new file mode 100644 index 000000000000..0218218e12e8 --- /dev/null +++ b/circuits/cpp/src/aztec3/circuits/abis/combined_historic_tree_roots.hpp @@ -0,0 +1,89 @@ +#pragma once +#include +#include +#include +#include +#include "private_historic_tree_roots.hpp" + +namespace aztec3::circuits::abis { + +using aztec3::utils::types::CircuitTypes; +using aztec3::utils::types::NativeTypes; +using plonk::stdlib::witness_t; +using std::is_same; + +template struct CombinedHistoricTreeRoots { + typedef typename NCT::fr fr; + typedef typename NCT::boolean boolean; + + PrivateHistoricTreeRoots private_historic_tree_roots; + fr public_data_tree_root = 0; + + boolean operator==(CombinedHistoricTreeRoots const& other) const + { + return private_historic_tree_roots == other.private_historic_tree_roots && + public_data_tree_root == other.public_data_tree_root; + }; + + template CombinedHistoricTreeRoots> to_circuit_type(Composer& composer) const + { + static_assert((std::is_same::value)); + + // Capture the composer: + auto to_ct = [&](auto& e) { return aztec3::utils::types::to_ct(composer, e); }; + auto to_circuit_type = [&](auto& e) { return e.to_circuit_type(composer); }; + + CombinedHistoricTreeRoots> data = { + to_circuit_type(private_historic_tree_roots), + to_ct(public_data_tree_root), + }; + + return data; + }; + + template CombinedHistoricTreeRoots to_native_type() const + { + static_assert(std::is_same, NCT>::value); + auto to_nt = [&](auto& e) { return aztec3::utils::types::to_nt(e); }; + auto to_native_type = [&](T& e) { return e.template to_native_type(); }; + + CombinedHistoricTreeRoots data = { + to_native_type(private_historic_tree_roots), + to_nt(public_data_tree_root), + }; + + return data; + }; + + void set_public() + { + static_assert(!(std::is_same::value)); + + private_historic_tree_roots.set_public(); + public_data_tree_root.set_public(); + } +}; + +template void read(uint8_t const*& it, CombinedHistoricTreeRoots& historic_tree_roots) +{ + using serialize::read; + + read(it, historic_tree_roots.private_historic_tree_roots); + read(it, historic_tree_roots.public_data_tree_root); +}; + +template void write(std::vector& buf, CombinedHistoricTreeRoots const& historic_tree_roots) +{ + using serialize::write; + + write(buf, historic_tree_roots.private_historic_tree_roots); + write(buf, historic_tree_roots.public_data_tree_root); +}; + +template std::ostream& operator<<(std::ostream& os, CombinedHistoricTreeRoots const& historic_tree_roots) +{ + return os << "private_historic_tree_roots: " << historic_tree_roots.private_historic_tree_roots << "\n" + << "public_data_tree_root: " << historic_tree_roots.public_data_tree_root << "\n"; +} + +} // namespace aztec3::circuits::abis \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/abis/private_kernel/public_inputs.hpp b/circuits/cpp/src/aztec3/circuits/abis/kernel_circuit_public_inputs.hpp similarity index 68% rename from circuits/cpp/src/aztec3/circuits/abis/private_kernel/public_inputs.hpp rename to circuits/cpp/src/aztec3/circuits/abis/kernel_circuit_public_inputs.hpp index 7006f493491c..043d89088428 100644 --- a/circuits/cpp/src/aztec3/circuits/abis/private_kernel/public_inputs.hpp +++ b/circuits/cpp/src/aztec3/circuits/abis/kernel_circuit_public_inputs.hpp @@ -1,40 +1,42 @@ #pragma once -#include "accumulated_data.hpp" -#include "constant_data.hpp" +#include "combined_accumulated_data.hpp" +#include "combined_constant_data.hpp" #include #include #include #include -namespace aztec3::circuits::abis::private_kernel { +namespace aztec3::circuits::abis { using aztec3::utils::types::CircuitTypes; using aztec3::utils::types::NativeTypes; using plonk::stdlib::witness_t; +using std::conditional; using std::is_same; -template struct PublicInputs { +template struct KernelCircuitPublicInputs { typedef typename NCT::fr fr; typedef typename NCT::boolean boolean; - AccumulatedData end{}; - ConstantData constants{}; + CombinedAccumulatedData end{}; + CombinedConstantData constants{}; boolean is_private = true; // TODO: might need to instantiate from witness! - boolean operator==(PublicInputs const& other) const + boolean operator==(KernelCircuitPublicInputs const& other) const { return end == other.end && constants == other.constants && is_private == other.is_private; }; - template PublicInputs> to_circuit_type(Composer& composer) const + template + KernelCircuitPublicInputs> to_circuit_type(Composer& composer) const { static_assert((std::is_same::value)); // Capture the composer: auto to_ct = [&](auto& e) { return aztec3::utils::types::to_ct(composer, e); }; - PublicInputs> private_inputs = { + KernelCircuitPublicInputs> private_inputs = { end.to_circuit_type(composer), constants.to_circuit_type(composer), @@ -44,13 +46,13 @@ template struct PublicInputs { return private_inputs; }; - template PublicInputs to_native_type() const + template KernelCircuitPublicInputs to_native_type() const { static_assert(std::is_same, NCT>::value); auto to_nt = [&](auto& e) { return aztec3::utils::types::to_nt(e); }; auto to_native_type = [](T& e) { return e.template to_native_type(); }; - PublicInputs pis = { + KernelCircuitPublicInputs pis = { to_native_type(end), to_native_type(constants), @@ -71,7 +73,7 @@ template struct PublicInputs { } }; -template void read(uint8_t const*& it, PublicInputs& public_inputs) +template void read(uint8_t const*& it, KernelCircuitPublicInputs& public_inputs) { using serialize::read; @@ -80,7 +82,7 @@ template void read(uint8_t const*& it, PublicInputs& public_ read(it, public_inputs.is_private); }; -template void write(std::vector& buf, PublicInputs const& public_inputs) +template void write(std::vector& buf, KernelCircuitPublicInputs const& public_inputs) { using serialize::write; @@ -89,7 +91,7 @@ template void write(std::vector& buf, PublicInputs write(buf, public_inputs.is_private); }; -template std::ostream& operator<<(std::ostream& os, PublicInputs const& public_inputs) +template std::ostream& operator<<(std::ostream& os, KernelCircuitPublicInputs const& public_inputs) { return os << "end:\n" << public_inputs.end << "\n" @@ -98,4 +100,4 @@ template std::ostream& operator<<(std::ostream& os, PublicInputs< << "is_private: " << public_inputs.is_private << "\n"; } -} // namespace aztec3::circuits::abis::private_kernel \ No newline at end of file +} // namespace aztec3::circuits::abis \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/abis/private_kernel/new_contract_data.hpp b/circuits/cpp/src/aztec3/circuits/abis/new_contract_data.hpp similarity index 97% rename from circuits/cpp/src/aztec3/circuits/abis/private_kernel/new_contract_data.hpp rename to circuits/cpp/src/aztec3/circuits/abis/new_contract_data.hpp index eb9ba995ce96..9790d6061233 100644 --- a/circuits/cpp/src/aztec3/circuits/abis/private_kernel/new_contract_data.hpp +++ b/circuits/cpp/src/aztec3/circuits/abis/new_contract_data.hpp @@ -4,7 +4,7 @@ #include "aztec3/utils/types/circuit_types.hpp" #include "aztec3/utils/types/convert.hpp" #include "barretenberg/stdlib/primitives/witness/witness.hpp" -namespace aztec3::circuits::abis::private_kernel { +namespace aztec3::circuits::abis { using aztec3::utils::types::CircuitTypes; using aztec3::utils::types::NativeTypes; @@ -114,4 +114,4 @@ template std::ostream& operator<<(std::ostream& os, NewContractDa template using ContractLeafPreimage = NewContractData; -} // namespace aztec3::circuits::abis::private_kernel \ No newline at end of file +} // namespace aztec3::circuits::abis \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/abis/private_kernel/previous_kernel_data.hpp b/circuits/cpp/src/aztec3/circuits/abis/previous_kernel_data.hpp similarity index 93% rename from circuits/cpp/src/aztec3/circuits/abis/private_kernel/previous_kernel_data.hpp rename to circuits/cpp/src/aztec3/circuits/abis/previous_kernel_data.hpp index 74fce6048f72..42f697bacdcf 100644 --- a/circuits/cpp/src/aztec3/circuits/abis/private_kernel/previous_kernel_data.hpp +++ b/circuits/cpp/src/aztec3/circuits/abis/previous_kernel_data.hpp @@ -1,5 +1,5 @@ #pragma once -#include "aztec3/circuits/abis/private_kernel/public_inputs.hpp" +#include "aztec3/circuits/abis/kernel_circuit_public_inputs.hpp" #include #include #include @@ -7,7 +7,7 @@ #include #include -namespace aztec3::circuits::abis::private_kernel { +namespace aztec3::circuits::abis { using aztec3::utils::types::CircuitTypes; using aztec3::utils::types::NativeTypes; @@ -20,7 +20,7 @@ template struct PreviousKernelData { typedef typename NCT::VK VK; typedef typename NCT::uint32 uint32; - PublicInputs public_inputs{}; // TODO: not needed as already contained in proof? + KernelCircuitPublicInputs public_inputs{}; // TODO: not needed as already contained in proof? NativeTypes::Proof proof{}; // TODO: how to express proof as native/circuit type when it gets used as a buffer? std::shared_ptr vk; @@ -103,4 +103,4 @@ template std::ostream& operator<<(std::ostream& os, PreviousKerne << "vk_path: " << kernel_data.vk_path << "\n"; } -} // namespace aztec3::circuits::abis::private_kernel \ No newline at end of file +} // namespace aztec3::circuits::abis \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/abis/private_kernel/historic_tree_roots.hpp b/circuits/cpp/src/aztec3/circuits/abis/private_historic_tree_roots.hpp similarity index 77% rename from circuits/cpp/src/aztec3/circuits/abis/private_kernel/historic_tree_roots.hpp rename to circuits/cpp/src/aztec3/circuits/abis/private_historic_tree_roots.hpp index dea1a37d9ae3..a509148ad988 100644 --- a/circuits/cpp/src/aztec3/circuits/abis/private_kernel/historic_tree_roots.hpp +++ b/circuits/cpp/src/aztec3/circuits/abis/private_historic_tree_roots.hpp @@ -4,14 +4,14 @@ #include #include -namespace aztec3::circuits::abis::private_kernel { +namespace aztec3::circuits::abis { using aztec3::utils::types::CircuitTypes; using aztec3::utils::types::NativeTypes; using plonk::stdlib::witness_t; using std::is_same; -template struct HistoricTreeRoots { +template struct PrivateHistoricTreeRoots { typedef typename NCT::fr fr; typedef typename NCT::boolean boolean; @@ -20,21 +20,21 @@ template struct HistoricTreeRoots { fr contract_tree_root = 0; fr private_kernel_vk_tree_root = 0; // TODO: future enhancement - boolean operator==(HistoricTreeRoots const& other) const + boolean operator==(PrivateHistoricTreeRoots const& other) const { return private_data_tree_root == other.private_data_tree_root && nullifier_tree_root == other.nullifier_tree_root && contract_tree_root == other.contract_tree_root && private_kernel_vk_tree_root == other.private_kernel_vk_tree_root; }; - template HistoricTreeRoots> to_circuit_type(Composer& composer) const + template PrivateHistoricTreeRoots> to_circuit_type(Composer& composer) const { static_assert((std::is_same::value)); // Capture the composer: auto to_ct = [&](auto& e) { return aztec3::utils::types::to_ct(composer, e); }; - HistoricTreeRoots> data = { + PrivateHistoricTreeRoots> data = { to_ct(private_data_tree_root), to_ct(nullifier_tree_root), to_ct(contract_tree_root), @@ -44,12 +44,12 @@ template struct HistoricTreeRoots { return data; }; - template HistoricTreeRoots to_native_type() const + template PrivateHistoricTreeRoots to_native_type() const { static_assert(std::is_same, NCT>::value); auto to_nt = [&](auto& e) { return aztec3::utils::types::to_nt(e); }; - HistoricTreeRoots data = { + PrivateHistoricTreeRoots data = { to_nt(private_data_tree_root), to_nt(nullifier_tree_root), to_nt(contract_tree_root), @@ -70,7 +70,7 @@ template struct HistoricTreeRoots { } }; -template void read(uint8_t const*& it, HistoricTreeRoots& historic_tree_roots) +template void read(uint8_t const*& it, PrivateHistoricTreeRoots& historic_tree_roots) { using serialize::read; @@ -80,7 +80,7 @@ template void read(uint8_t const*& it, HistoricTreeRoots& hi read(it, historic_tree_roots.private_kernel_vk_tree_root); }; -template void write(std::vector& buf, HistoricTreeRoots const& historic_tree_roots) +template void write(std::vector& buf, PrivateHistoricTreeRoots const& historic_tree_roots) { using serialize::write; @@ -90,7 +90,7 @@ template void write(std::vector& buf, HistoricTreeRoots< write(buf, historic_tree_roots.private_kernel_vk_tree_root); }; -template std::ostream& operator<<(std::ostream& os, HistoricTreeRoots const& historic_tree_roots) +template std::ostream& operator<<(std::ostream& os, PrivateHistoricTreeRoots const& historic_tree_roots) { return os << "private_data_tree_root: " << historic_tree_roots.private_data_tree_root << "\n" << "nullifier_tree_root: " << historic_tree_roots.nullifier_tree_root << "\n" @@ -98,4 +98,4 @@ template std::ostream& operator<<(std::ostream& os, HistoricTreeR << "private_kernel_vk_tree_root: " << historic_tree_roots.private_kernel_vk_tree_root << "\n"; } -} // namespace aztec3::circuits::abis::private_kernel \ No newline at end of file +} // namespace aztec3::circuits::abis \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/abis/private_kernel/private_call_data.hpp b/circuits/cpp/src/aztec3/circuits/abis/private_kernel/private_call_data.hpp index 37dcbe58a3e2..c37646d008ff 100644 --- a/circuits/cpp/src/aztec3/circuits/abis/private_kernel/private_call_data.hpp +++ b/circuits/cpp/src/aztec3/circuits/abis/private_kernel/private_call_data.hpp @@ -5,6 +5,7 @@ #include "call_context_reconciliation_data.hpp" #include "../call_stack_item.hpp" #include "../membership_witness.hpp" +#include "../types.hpp" #include #include @@ -25,9 +26,9 @@ template struct PrivateCallData { typedef typename NCT::boolean boolean; typedef typename NCT::VK VK; - CallStackItem call_stack_item{}; + CallStackItem call_stack_item{}; - std::array, PRIVATE_CALL_STACK_LENGTH> private_call_stack_preimages{}; + std::array, PRIVATE_CALL_STACK_LENGTH> private_call_stack_preimages{}; // std::array, PUBLIC_CALL_STACK_LENGTH> public_call_stack_preimages; @@ -62,7 +63,7 @@ template struct PrivateCallData { auto to_circuit_type = [&](auto& e) { return e.to_circuit_type(composer); }; PrivateCallData> data = { - call_stack_item.to_circuit_type(composer), + to_circuit_type(call_stack_item), map(private_call_stack_preimages, to_circuit_type), @@ -79,7 +80,7 @@ template struct PrivateCallData { return data; }; -}; +}; // namespace aztec3::circuits::abis::private_kernel template void read(uint8_t const*& it, PrivateCallData& obj) { diff --git a/circuits/cpp/src/aztec3/circuits/abis/private_kernel/private_inputs.hpp b/circuits/cpp/src/aztec3/circuits/abis/private_kernel/private_inputs.hpp index e5fa856686bd..f978830e1271 100644 --- a/circuits/cpp/src/aztec3/circuits/abis/private_kernel/private_inputs.hpp +++ b/circuits/cpp/src/aztec3/circuits/abis/private_kernel/private_inputs.hpp @@ -1,7 +1,7 @@ #pragma once -#include "accumulated_data.hpp" -#include "previous_kernel_data.hpp" +#include "../combined_accumulated_data.hpp" +#include "../previous_kernel_data.hpp" #include "private_call_data.hpp" #include "../signed_tx_request.hpp" @@ -24,7 +24,7 @@ template struct PrivateInputs { PreviousKernelData previous_kernel{}; PrivateCallData private_call{}; - boolean operator==(PublicInputs const& other) const + boolean operator==(PrivateInputs const& other) const { return signed_tx_request == other.signed_tx_request && previous_kernel == other.previous_kernel && private_call == other.private_call; diff --git a/circuits/cpp/src/aztec3/circuits/abis/public_circuit_public_inputs.hpp b/circuits/cpp/src/aztec3/circuits/abis/public_circuit_public_inputs.hpp index 0e58caca1529..e98985112cf2 100644 --- a/circuits/cpp/src/aztec3/circuits/abis/public_circuit_public_inputs.hpp +++ b/circuits/cpp/src/aztec3/circuits/abis/public_circuit_public_inputs.hpp @@ -35,7 +35,7 @@ template struct PublicCircuitPublicInputs { std::array public_call_stack = zero_array(); std::array l1_msg_stack = zero_array(); - fr historic_private_data_tree_root; + fr historic_public_data_tree_root; address prover_address; @@ -45,7 +45,7 @@ template struct PublicCircuitPublicInputs { emitted_events == other.emitted_events && state_transitions == other.state_transitions && state_reads == other.state_reads && public_call_stack == other.public_call_stack && l1_msg_stack == other.l1_msg_stack && - historic_private_data_tree_root == other.historic_private_data_tree_root && + historic_public_data_tree_root == other.historic_public_data_tree_root && prover_address == other.prover_address; }; @@ -72,7 +72,7 @@ template struct PublicCircuitPublicInputs { .public_call_stack = to_ct(public_call_stack), .l1_msg_stack = to_ct(l1_msg_stack), - .historic_private_data_tree_root = to_ct(historic_private_data_tree_root), + .historic_public_data_tree_root = to_ct(historic_public_data_tree_root), .prover_address = to_ct(prover_address), }; @@ -101,9 +101,9 @@ template struct PublicCircuitPublicInputs { spread_arr_into_vec(public_call_stack, inputs); spread_arr_into_vec(l1_msg_stack, inputs); - inputs.push_back(historic_private_data_tree_root); + inputs.push_back(historic_public_data_tree_root); - return NCT::compress(inputs, GeneratorIndex::PRIVATE_CIRCUIT_PUBLIC_INPUTS); + return NCT::compress(inputs, GeneratorIndex::PUBLIC_CIRCUIT_PUBLIC_INPUTS); } template void spread_arr_into_vec(std::array const& arr, std::vector& vec) const @@ -113,15 +113,15 @@ template struct PublicCircuitPublicInputs { } }; // namespace aztec3::circuits::abis -template void read(uint8_t const*& it, PublicCircuitPublicInputs& private_circuit_public_inputs) +template void read(uint8_t const*& it, PublicCircuitPublicInputs& public_circuit_public_inputs) { using serialize::read; - PublicCircuitPublicInputs& pis = private_circuit_public_inputs; + PublicCircuitPublicInputs& pis = public_circuit_public_inputs; + read(it, pis.call_context); read(it, pis.args); read(it, pis.return_values); read(it, pis.emitted_events); - read(it, pis.emitted_ouputs); read(it, pis.state_transitions); read(it, pis.state_reads); @@ -129,22 +129,22 @@ template void read(uint8_t const*& it, PublicCircuitPublicInputs< read(it, pis.public_call_stack); read(it, pis.l1_msg_stack); - read(it, pis.historic_private_data_tree_root); + read(it, pis.historic_public_data_tree_root); read(it, pis.prover_address); }; template -void write(std::vector& buf, PublicCircuitPublicInputs const& private_circuit_public_inputs) +void write(std::vector& buf, PublicCircuitPublicInputs const& public_circuit_public_inputs) { using serialize::write; - PublicCircuitPublicInputs const& pis = private_circuit_public_inputs; + PublicCircuitPublicInputs const& pis = public_circuit_public_inputs; + write(buf, pis.call_context); write(buf, pis.args); write(buf, pis.return_values); write(buf, pis.emitted_events); - write(buf, pis.emitted_ouputs); write(buf, pis.state_transitions); write(buf, pis.state_reads); @@ -152,17 +152,18 @@ void write(std::vector& buf, PublicCircuitPublicInputs const& priv write(buf, pis.public_call_stack); write(buf, pis.l1_msg_stack); - write(buf, pis.historic_private_data_tree_root); + write(buf, pis.historic_public_data_tree_root); write(buf, pis.prover_address); }; template -std::ostream& operator<<(std::ostream& os, PublicCircuitPublicInputs const& private_circuit_public_inputs) +std::ostream& operator<<(std::ostream& os, PublicCircuitPublicInputs const& public_circuit_public_inputs) { - PublicCircuitPublicInputs const& pis = private_circuit_public_inputs; - return os << "args: " << pis.args << "\n" + PublicCircuitPublicInputs const& pis = public_circuit_public_inputs; + return os << "call_context: " << pis.call_context << "\n" + << "args: " << pis.args << "\n" << "return_values: " << pis.return_values << "\n" << "emitted_events: " << pis.emitted_events << "\n" @@ -172,7 +173,7 @@ std::ostream& operator<<(std::ostream& os, PublicCircuitPublicInputs const& << "public_call_stack: " << pis.public_call_stack << "\n" << "l1_msg_stack: " << pis.l1_msg_stack << "\n" - << "historic_private_data_tree_root: " << pis.historic_private_data_tree_root << "\n" + << "historic_public_data_tree_root: " << pis.historic_public_data_tree_root << "\n" << "prover_address: " << pis.prover_address << "\n"; } diff --git a/circuits/cpp/src/aztec3/circuits/abis/public_kernel/public_call_data.hpp b/circuits/cpp/src/aztec3/circuits/abis/public_kernel/public_call_data.hpp new file mode 100644 index 000000000000..8dc2f28638f9 --- /dev/null +++ b/circuits/cpp/src/aztec3/circuits/abis/public_kernel/public_call_data.hpp @@ -0,0 +1,122 @@ +#pragma once + +#include "aztec3/constants.hpp" +#include "aztec3/utils/array.hpp" +#include "../call_stack_item.hpp" +#include "../types.hpp" + +#include +#include +#include +#include +#include + +namespace aztec3::circuits::abis::public_kernel { + +using aztec3::utils::types::CircuitTypes; +using aztec3::utils::types::NativeTypes; +using plonk::stdlib::witness_t; +using std::is_same; + +template struct PublicCallData { + typedef typename NCT::address address; + typedef typename NCT::fr fr; + typedef typename NCT::boolean boolean; + typedef typename NCT::VK VK; + + CallStackItem call_stack_item{}; + + std::array, PUBLIC_CALL_STACK_LENGTH> public_call_stack_preimages{}; + + NativeTypes::Proof proof{}; // TODO: how to express proof as native/circuit type when it gets used as a buffer? + + fr portal_contract_address = 0; // an ETH address + fr bytecode_hash = 0; + + boolean operator==(PublicCallData const& other) const + { + // WARNING: proof skipped! + return call_stack_item == other.call_stack_item && + public_call_stack_preimages == other.public_call_stack_preimages && + portal_contract_address == other.portal_contract_address && bytecode_hash == other.bytecode_hash; + }; + + // WARNING: the `proof` does NOT get converted! (because the current implementation of `verify_proof` takes a proof + // of native bytes; any conversion to circuit types happens within the `verify_proof` function) + template PublicCallData> to_circuit_type(Composer& composer) const + { + // typedef CircuitTypes CT; + static_assert((std::is_same::value)); + + // Capture the composer: + auto to_ct = [&](auto& e) { return aztec3::utils::types::to_ct(composer, e); }; + auto to_circuit_type = [&](auto& e) { return e.to_circuit_type(composer); }; + + PublicCallData> data = { + call_stack_item.to_circuit_type(composer), + + map(public_call_stack_preimages, to_circuit_type), + + proof, // Notice: not converted! Stays as native. This is because of how the verify_proof function + // currently works. + // CT::VK::from_witness(&composer, vk), + + // to_circuit_type(function_leaf_membership_witness), + // to_circuit_type(contract_leaf_membership_witness), + + to_ct(portal_contract_address), + to_ct(bytecode_hash), + }; + + return data; + }; +}; + +template void read(uint8_t const*& it, PublicCallData& obj) +{ + using serialize::read; + + read(it, obj.call_stack_item); + read(it, obj.private_call_stack_preimages); + read(it, obj.proof); + read(it, obj.vk); + 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 void write(std::vector& buf, PublicCallData const& obj) +{ + using serialize::write; + + write(buf, obj.call_stack_item); + write(buf, obj.private_call_stack_preimages); + write(buf, obj.proof); + write(buf, *obj.vk); + 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 std::ostream& operator<<(std::ostream& os, PublicCallData const& obj) +{ + return os << "call_stack_item:\n" + << obj.call_stack_item << "\n" + << "public_call_stack_preimages:\n" + << obj.public_call_stack_preimages << "\n" + << "proof:\n" + << obj.proof + << "\n" + //<< "vk:\n" + //<< *(obj.vk) << "\n" + //<< "function_leaf_membership_witness:\n" + //<< 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" + << "bytecode_hash: " << obj.bytecode_hash << "\n"; +} + +} // namespace aztec3::circuits::abis::public_kernel \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/abis/public_kernel/public_kernel_inputs.hpp b/circuits/cpp/src/aztec3/circuits/abis/public_kernel/public_kernel_inputs.hpp new file mode 100644 index 000000000000..c783de20d97e --- /dev/null +++ b/circuits/cpp/src/aztec3/circuits/abis/public_kernel/public_kernel_inputs.hpp @@ -0,0 +1,67 @@ +#pragma once + +#include "../previous_kernel_data.hpp" +#include "public_call_data.hpp" +#include "../signed_tx_request.hpp" + +#include +#include +#include +#include + +namespace aztec3::circuits::abis::public_kernel { + +using aztec3::utils::types::CircuitTypes; +using aztec3::utils::types::NativeTypes; +using std::is_same; + +template struct PublicKernelInputs { + typedef typename NCT::fr fr; + typedef typename NCT::boolean boolean; + + PreviousKernelData previous_kernel{}; + PublicCallData public_call{}; + + boolean operator==(PublicKernelInputs const& other) const + { + return previous_kernel == other.previous_kernel && public_call == other.public_call; + }; + + template PublicKernelInputs> to_circuit_type(Composer& composer) const + { + static_assert((std::is_same::value)); + + PublicKernelInputs> public_kernel_inputs = { + previous_kernel.to_circuit_type(composer), + public_call.to_circuit_type(composer), + }; + + return public_kernel_inputs; + }; +}; + +template void read(uint8_t const*& it, PublicKernelInputs& public_kernel_inputs) +{ + using serialize::read; + + read(it, public_kernel_inputs.previous_kernel); + read(it, public_kernel_inputs.public_call); +}; + +template void write(std::vector& buf, PublicKernelInputs const& public_kernel_inputs) +{ + using serialize::write; + + write(buf, public_kernel_inputs.previous_kernel); + write(buf, public_kernel_inputs.public_call); +}; + +template std::ostream& operator<<(std::ostream& os, PublicKernelInputs const& public_kernel_inputs) +{ + return os << "previous_kernel:\n" + << public_kernel_inputs.previous_kernel << "\n" + << "public_call:\n" + << public_kernel_inputs.public_call << "\n"; +} + +} // namespace aztec3::circuits::abis::public_kernel \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/abis/public_kernel/public_kernel_inputs_no_previous_kernel.hpp b/circuits/cpp/src/aztec3/circuits/abis/public_kernel/public_kernel_inputs_no_previous_kernel.hpp new file mode 100644 index 000000000000..eb0ce7c1d3c7 --- /dev/null +++ b/circuits/cpp/src/aztec3/circuits/abis/public_kernel/public_kernel_inputs_no_previous_kernel.hpp @@ -0,0 +1,71 @@ +#pragma once + +#include "../previous_kernel_data.hpp" +#include "public_call_data.hpp" +#include "witnessed_public_call_data.hpp" + +#include +#include +#include +#include + +namespace aztec3::circuits::abis::public_kernel { + +using aztec3::utils::types::CircuitTypes; +using aztec3::utils::types::NativeTypes; +using std::is_same; + +template struct PublicKernelInputsNoKernelInput { + typedef typename NCT::fr fr; + typedef typename NCT::boolean boolean; + + SignedTxRequest signed_tx_request{}; + WitnessedPublicCallData public_call{}; + + boolean operator==(PublicKernelInputsNoKernelInput const& other) const + { + return signed_tx_request == other.signed_tx_request && public_call == other.public_call; + }; + + template + PublicKernelInputsNoKernelInput> to_circuit_type(Composer& composer) const + { + static_assert((std::is_same::value)); + + PublicKernelInputsNoKernelInput> public_kernel_inputs = { + // TODO to_ct(signature), + signed_tx_request.to_circuit_type(composer), + public_call.to_circuit_type(composer), + }; + + return public_kernel_inputs; + }; +}; + +template void read(uint8_t const*& it, PublicKernelInputsNoKernelInput& public_kernel_inputs) +{ + using serialize::read; + + read(it, public_kernel_inputs.signed_tx_request); + read(it, public_kernel_inputs.public_call); +}; + +template +void write(std::vector& buf, PublicKernelInputsNoKernelInput const& public_kernel_inputs) +{ + using serialize::write; + + write(buf, public_kernel_inputs.signed_tx_request); + write(buf, public_kernel_inputs.public_call); +}; + +template +std::ostream& operator<<(std::ostream& os, PublicKernelInputsNoKernelInput const& public_kernel_inputs) +{ + return os << "signed_tx_request:\n" + << public_kernel_inputs.signed_tx_request << "\n" + << "public_call:\n" + << public_kernel_inputs.public_call << "\n"; +} + +} // namespace aztec3::circuits::abis::public_kernel \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/abis/public_kernel/witnessed_public_call_data.hpp b/circuits/cpp/src/aztec3/circuits/abis/public_kernel/witnessed_public_call_data.hpp new file mode 100644 index 000000000000..4be78a959b59 --- /dev/null +++ b/circuits/cpp/src/aztec3/circuits/abis/public_kernel/witnessed_public_call_data.hpp @@ -0,0 +1,86 @@ +#pragma once + +#include "../previous_kernel_data.hpp" +#include "public_call_data.hpp" +#include "../signed_tx_request.hpp" +#include "../membership_witness.hpp" + +#include +#include +#include +#include + +namespace aztec3::circuits::abis::public_kernel { + +using aztec3::utils::types::CircuitTypes; +using aztec3::utils::types::NativeTypes; +using std::is_same; + +template struct WitnessedPublicCallData { + typedef typename NCT::fr fr; + typedef typename NCT::boolean boolean; + + PublicCallData public_call_data; + std::array, STATE_TRANSITIONS_LENGTH> + state_transitions_sibling_paths; + std::array, STATE_READS_LENGTH> state_reads_sibling_paths; + fr public_data_tree_root; + + boolean operator==(WitnessedPublicCallData const& other) const + { + return public_call_data == other.public_call_data && + state_transitions_sibling_paths == other.state_transitions_sibling_paths && + state_reads_sibling_paths == other.state_reads_sibling_paths && + public_data_tree_root == other.public_data_tree_root; + }; + + template + WitnessedPublicCallData> to_circuit_type(Composer& composer) const + { + static_assert((std::is_same::value)); + + WitnessedPublicCallData> witnessed_call_data = { + // TODO to_ct(signature), + public_call_data.to_circuit_type(composer), + state_transitions_sibling_paths.to_circuit_type(composer), + state_reads_sibling_paths.to_circuit_type(composer), + public_data_tree_root.to_circuit_type(composer), + }; + + return witnessed_call_data; + }; +}; + +template void read(uint8_t const*& it, WitnessedPublicCallData& witnessed_call_data) +{ + using serialize::read; + + read(it, witnessed_call_data.public_call_data); + read(it, witnessed_call_data.state_transitions_sibling_paths); + read(it, witnessed_call_data.state_reads_sibling_paths); + read(it, witnessed_call_data.public_data_tree_root); +}; + +template void write(std::vector& buf, WitnessedPublicCallData& witnessed_call_data) +{ + using serialize::write; + + write(buf, witnessed_call_data.public_call_data); + write(buf, witnessed_call_data.state_transitions_sibling_paths); + write(buf, witnessed_call_data.state_reads_sibling_paths); + write(buf, witnessed_call_data.public_data_tree_root); +}; + +template std::ostream& operator<<(std::ostream& os, WitnessedPublicCallData& witnessed_call_data) +{ + return os << "public_call_data:\n" + << witnessed_call_data.public_call_data << "\n" + << "state_transitions_sibling_paths:\n" + << witnessed_call_data.state_transitions_sibling_paths << "\n" + << "state_reads_sibling_paths:\n" + << witnessed_call_data.state_reads_sibling_paths << "\n" + << "public_data_tree_root:\n" + << public_kernel_inputs.public_data_tree_root << "\n"; +} + +} // namespace aztec3::circuits::abis::public_kernel \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/abis/rollup/base/base_or_merge_rollup_public_inputs.hpp b/circuits/cpp/src/aztec3/circuits/abis/rollup/base/base_or_merge_rollup_public_inputs.hpp index 889236181112..c86ecc372737 100644 --- a/circuits/cpp/src/aztec3/circuits/abis/rollup/base/base_or_merge_rollup_public_inputs.hpp +++ b/circuits/cpp/src/aztec3/circuits/abis/rollup/base/base_or_merge_rollup_public_inputs.hpp @@ -37,6 +37,9 @@ template struct BaseOrMergeRollupPublicInputs { AppendOnlyTreeSnapshot start_contract_tree_snapshot; AppendOnlyTreeSnapshot end_contract_tree_snapshot; + AppendOnlyTreeSnapshot start_public_data_tree_snapshot; + AppendOnlyTreeSnapshot end_public_data_tree_snapshot; + // Hashes (probably sha256) to make public inputs constant-sized (to then be unpacked on-chain) // Needs to be two fields to accomodate all 256-bits of the hash std::array calldata_hash; @@ -58,6 +61,8 @@ template void read(uint8_t const*& it, BaseOrMergeRollupPublicInp read(it, obj.end_nullifier_tree_snapshot); read(it, obj.start_contract_tree_snapshot); read(it, obj.end_contract_tree_snapshot); + read(it, obj.start_public_data_tree_snapshot); + read(it, obj.end_public_data_tree_snapshot); read(it, obj.calldata_hash); }; @@ -75,6 +80,8 @@ template void write(std::vector& buf, BaseOrMergeRollupP write(buf, obj.end_nullifier_tree_snapshot); write(buf, obj.start_contract_tree_snapshot); write(buf, obj.end_contract_tree_snapshot); + write(buf, obj.start_public_data_tree_snapshot); + write(buf, obj.end_public_data_tree_snapshot); write(buf, obj.calldata_hash); }; @@ -107,6 +114,12 @@ template std::ostream& operator<<(std::ostream& os, BaseOrMergeRo << "\n" "end_contract_tree_snapshot:\n" << obj.end_contract_tree_snapshot + << "\n" + "start_public_data_tree_snapshot:\n" + << obj.start_public_data_tree_snapshot + << "\n" + "end_public_data_tree_snapshot:\n" + << obj.end_public_data_tree_snapshot << "\n" "calldata_hash: " << obj.calldata_hash << "\n"; diff --git a/circuits/cpp/src/aztec3/circuits/abis/rollup/base/base_rollup_inputs.hpp b/circuits/cpp/src/aztec3/circuits/abis/rollup/base/base_rollup_inputs.hpp index bdaf8e88ac66..93fbe8f7f438 100644 --- a/circuits/cpp/src/aztec3/circuits/abis/rollup/base/base_rollup_inputs.hpp +++ b/circuits/cpp/src/aztec3/circuits/abis/rollup/base/base_rollup_inputs.hpp @@ -1,6 +1,6 @@ #pragma once #include "../../append_only_tree_snapshot.hpp" -#include "../../private_kernel/previous_kernel_data.hpp" +#include "../../previous_kernel_data.hpp" #include "../../membership_witness.hpp" #include "../nullifier_leaf_preimage.hpp" #include "../constant_rollup_data.hpp" @@ -17,11 +17,12 @@ template struct BaseRollupInputs { typedef typename NCT::fr fr; - std::array, 2> kernel_data; + std::array, 2> kernel_data; AppendOnlyTreeSnapshot start_private_data_tree_snapshot; AppendOnlyTreeSnapshot start_nullifier_tree_snapshot; AppendOnlyTreeSnapshot start_contract_tree_snapshot; + AppendOnlyTreeSnapshot start_public_data_tree_snapshot; std::array, 2 * KERNEL_NEW_NULLIFIERS_LENGTH> low_nullifier_leaf_preimages; std::array, 2 * KERNEL_NEW_NULLIFIERS_LENGTH> @@ -32,6 +33,8 @@ template struct BaseRollupInputs { std::array new_commitments_subtree_sibling_path; std::array new_nullifiers_subtree_sibling_path; std::array new_contracts_subtree_sibling_path; + std::array, 2 * STATE_TRANSITIONS_LENGTH> + new_state_transitions_sibling_paths; std::array, 2> historic_private_data_tree_root_membership_witnesses; @@ -51,11 +54,13 @@ template void read(uint8_t const*& it, BaseRollupInputs& obj read(it, obj.start_private_data_tree_snapshot); read(it, obj.start_nullifier_tree_snapshot); read(it, obj.start_contract_tree_snapshot); + read(it, obj.start_public_data_tree_snapshot); read(it, obj.low_nullifier_leaf_preimages); read(it, obj.low_nullifier_membership_witness); read(it, obj.new_commitments_subtree_sibling_path); read(it, obj.new_nullifiers_subtree_sibling_path); read(it, obj.new_contracts_subtree_sibling_path); + read(it, obj.new_state_transitions_sibling_paths); read(it, obj.historic_private_data_tree_root_membership_witnesses); read(it, obj.historic_contract_tree_root_membership_witnesses); read(it, obj.constants); @@ -69,11 +74,13 @@ template void write(std::vector& buf, BaseRollupInputs std::ostream& operator<<(std::ostream& os, BaseRollupInp << obj.start_nullifier_tree_snapshot << "\n" << "start_contract_tree_snapshot:\n" << obj.start_contract_tree_snapshot << "\n" + << "start_public_data_tree_snapshot:\n" + << obj.start_public_data_tree_snapshot << "\n" << "low_nullifier_leaf_preimages:\n" << obj.low_nullifier_leaf_preimages << "\n" << "low_nullifier_membership_witness:\n" @@ -99,6 +108,8 @@ template std::ostream& operator<<(std::ostream& os, BaseRollupInp << obj.new_nullifiers_subtree_sibling_path << "\n" << "new_contracts_subtree_sibling_path:\n" << obj.new_contracts_subtree_sibling_path << "\n" + << "new_state_transitions_sibling_paths:\n" + << obj.new_state_transitions_sibling_paths << "\n" << "historic_private_data_tree_root_membership_witnesses:\n" << obj.historic_private_data_tree_root_membership_witnesses << "\n" << "historic_contract_tree_root_membership_witnesses:\n" diff --git a/circuits/cpp/src/aztec3/circuits/abis/state_read.hpp b/circuits/cpp/src/aztec3/circuits/abis/state_read.hpp index 8c9bd74b5d52..e512cc99f5cd 100644 --- a/circuits/cpp/src/aztec3/circuits/abis/state_read.hpp +++ b/circuits/cpp/src/aztec3/circuits/abis/state_read.hpp @@ -33,6 +33,20 @@ template struct StateRead { return state_read; }; + template StateRead to_native_type() const + { + static_assert((std::is_same, NCT>::value)); + + auto to_nt = [&](auto& e) { return aztec3::utils::types::to_nt(e); }; + + StateRead state_read = { + to_nt(storage_slot), + to_nt(current_value), + }; + + return state_read; + }; + fr hash() const { std::vector inputs = { @@ -42,13 +56,21 @@ template struct StateRead { return NCT::compress(inputs, GeneratorIndex::STATE_READ); } + + void set_public() + { + static_assert(!(std::is_same::value)); + + storage_slot.set_public(); + current_value.set_public(); + } }; template void read(uint8_t const*& it, StateRead& state_read) { using serialize::read; - read(it, state_read.l1_result_hash); + read(it, state_read.storage_slot); read(it, state_read.current_value); }; diff --git a/circuits/cpp/src/aztec3/circuits/abis/state_transition.hpp b/circuits/cpp/src/aztec3/circuits/abis/state_transition.hpp index 576fe719d3ef..29c72967c15c 100644 --- a/circuits/cpp/src/aztec3/circuits/abis/state_transition.hpp +++ b/circuits/cpp/src/aztec3/circuits/abis/state_transition.hpp @@ -35,6 +35,21 @@ template struct StateTransition { return state_transition; }; + template StateTransition to_native_type() const + { + static_assert((std::is_same, NCT>::value)); + + auto to_nt = [&](auto& e) { return aztec3::utils::types::to_nt(e); }; + + StateTransition state_transition = { + to_nt(storage_slot), + to_nt(old_value), + to_nt(new_value), + }; + + return state_transition; + }; + fr hash() const { std::vector inputs = { @@ -45,13 +60,22 @@ template struct StateTransition { return NCT::compress(inputs, GeneratorIndex::STATE_TRANSITION); } + + void set_public() + { + static_assert(!(std::is_same::value)); + + storage_slot.set_public(); + old_value.set_public(); + new_value.set_public(); + } }; template void read(uint8_t const*& it, StateTransition& state_transition) { using serialize::read; - read(it, state_transition.l1_result_hash); + read(it, state_transition.storage_slot); read(it, state_transition.old_value); read(it, state_transition.new_value); }; diff --git a/circuits/cpp/src/aztec3/circuits/abis/types.hpp b/circuits/cpp/src/aztec3/circuits/abis/types.hpp new file mode 100644 index 000000000000..c349f07dfa8d --- /dev/null +++ b/circuits/cpp/src/aztec3/circuits/abis/types.hpp @@ -0,0 +1,25 @@ +#pragma once +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "private_circuit_public_inputs.hpp" +#include "public_circuit_public_inputs.hpp" + +namespace aztec3::circuits::abis { + +template struct PrivateTypes { + typedef PrivateCircuitPublicInputs AppCircuitPublicInputs; +}; + +template struct PublicTypes { + typedef PublicCircuitPublicInputs AppCircuitPublicInputs; +}; +} // namespace aztec3::circuits::abis \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/apps/function_execution_context.hpp b/circuits/cpp/src/aztec3/circuits/apps/function_execution_context.hpp index 26413df1a190..7d28615ca32a 100644 --- a/circuits/cpp/src/aztec3/circuits/apps/function_execution_context.hpp +++ b/circuits/cpp/src/aztec3/circuits/apps/function_execution_context.hpp @@ -12,6 +12,7 @@ #include #include #include +#include #include @@ -22,10 +23,10 @@ namespace aztec3::circuits::apps { using aztec3::circuits::abis::CallStackItem; -using aztec3::circuits::abis::CallType; using aztec3::circuits::abis::FunctionData; using aztec3::circuits::abis::OptionalPrivateCircuitPublicInputs; using aztec3::circuits::abis::PrivateCircuitPublicInputs; +using aztec3::circuits::abis::PrivateTypes; using aztec3::circuits::apps::notes::NoteInterface; using aztec3::circuits::apps::opcodes::Opcodes; @@ -113,12 +114,12 @@ template class FunctionExecutionContext { /** * @brief Get the call_stack_item representing `this` exec_ctx's function call. */ - CallStackItem get_call_stack_item() + CallStackItem get_call_stack_item() { const NT::address& actual_contract_address = oracle.native_oracle.get_actual_contract_address(); const FunctionData& function_data = oracle.native_oracle.get_function_data(); - return CallStackItem{ + return CallStackItem{ .contract_address = actual_contract_address, .function_data = function_data, .public_inputs = get_final_private_circuit_public_inputs(), @@ -128,9 +129,9 @@ template class FunctionExecutionContext { /** * @brief Get the call_stack_items of any nested function calls made by this exec_ctx's function. */ - std::array, PRIVATE_CALL_STACK_LENGTH> get_private_call_stack_items() + std::array, PRIVATE_CALL_STACK_LENGTH> get_private_call_stack_items() { - std::array, PRIVATE_CALL_STACK_LENGTH> result; + std::array, PRIVATE_CALL_STACK_LENGTH> result; for (size_t i = 0; i < result.size(); ++i) { auto& nested_exec_ctx = nested_private_call_exec_ctxs[i]; @@ -139,7 +140,7 @@ template class FunctionExecutionContext { nested_exec_ctx->oracle.native_oracle.get_actual_contract_address(); const FunctionData& function_data = nested_exec_ctx->oracle.native_oracle.get_function_data(); - result[i] = CallStackItem{ + result[i] = CallStackItem{ .contract_address = actual_contract_address, .function_data = function_data, .public_inputs = nested_exec_ctx->get_final_private_circuit_public_inputs(), @@ -239,7 +240,7 @@ template class FunctionExecutionContext { args[i].assert_equal(f_public_inputs_ct.args[i]); } - CallStackItem f_call_stack_item_ct{ + CallStackItem f_call_stack_item_ct{ .contract_address = f_contract_address, .function_data = f_function_data_ct, .public_inputs = f_public_inputs_ct, diff --git a/circuits/cpp/src/aztec3/circuits/hash.hpp b/circuits/cpp/src/aztec3/circuits/hash.hpp index fcfde09f1745..08de69fd07ed 100644 --- a/circuits/cpp/src/aztec3/circuits/hash.hpp +++ b/circuits/cpp/src/aztec3/circuits/hash.hpp @@ -1,14 +1,14 @@ #include #include #include "aztec3/circuits/abis/function_leaf_preimage.hpp" -#include +#include #include namespace aztec3::circuits { using abis::FunctionData; +using aztec3::circuits::abis::ContractLeafPreimage; using aztec3::circuits::abis::FunctionLeafPreimage; -using aztec3::circuits::abis::private_kernel::ContractLeafPreimage; template typename NCT::fr compute_args_hash(std::array args) { diff --git a/circuits/cpp/src/aztec3/circuits/kernel/private/.test.cpp b/circuits/cpp/src/aztec3/circuits/kernel/private/.test.cpp index 05458edd504b..a08979f53e47 100644 --- a/circuits/cpp/src/aztec3/circuits/kernel/private/.test.cpp +++ b/circuits/cpp/src/aztec3/circuits/kernel/private/.test.cpp @@ -18,11 +18,12 @@ #include #include #include -#include -#include -#include -#include +#include +#include +#include +#include #include +#include #include "aztec3/circuits/kernel/private/utils.hpp" #include @@ -37,24 +38,25 @@ namespace { using aztec3::circuits::compute_empty_sibling_path; using aztec3::circuits::abis::CallContext; using aztec3::circuits::abis::CallStackItem; -using aztec3::circuits::abis::CallType; using aztec3::circuits::abis::ContractDeploymentData; using aztec3::circuits::abis::FunctionData; using aztec3::circuits::abis::FunctionLeafPreimage; +using aztec3::circuits::abis::NewContractData; using aztec3::circuits::abis::OptionalPrivateCircuitPublicInputs; using aztec3::circuits::abis::PrivateCircuitPublicInputs; +using aztec3::circuits::abis::PrivateTypes; using aztec3::circuits::abis::SignedTxRequest; using aztec3::circuits::abis::TxContext; using aztec3::circuits::abis::TxRequest; -using aztec3::circuits::abis::private_kernel::NewContractData; -using aztec3::circuits::abis::private_kernel::AccumulatedData; -using aztec3::circuits::abis::private_kernel::ConstantData; -using aztec3::circuits::abis::private_kernel::HistoricTreeRoots; -using aztec3::circuits::abis::private_kernel::PreviousKernelData; +using aztec3::circuits::abis::CombinedAccumulatedData; +using aztec3::circuits::abis::CombinedConstantData; +using aztec3::circuits::abis::CombinedHistoricTreeRoots; +using aztec3::circuits::abis::KernelCircuitPublicInputs; +using aztec3::circuits::abis::PreviousKernelData; +using aztec3::circuits::abis::PrivateHistoricTreeRoots; using aztec3::circuits::abis::private_kernel::PrivateCallData; using aztec3::circuits::abis::private_kernel::PrivateInputs; -using aztec3::circuits::abis::private_kernel::PublicInputs; using aztec3::circuits::apps::test_apps::basic_contract_deployment::constructor; using aztec3::circuits::apps::test_apps::escrow::deposit; @@ -322,7 +324,7 @@ PrivateInputs do_private_call_get_kernel_inputs(bool const is_constructor, // verify in the first round of recursion, OR, we have some fiddly conditional logic in the circuit to ignore // certain checks if we're handling the 'base case' of the recursion. // I've chosen the former, for now. - const CallStackItem call_stack_item{ + const CallStackItem call_stack_item{ .contract_address = tx_request.to, .function_data = tx_request.function_data, .public_inputs = private_circuit_public_inputs, @@ -335,13 +337,14 @@ PrivateInputs do_private_call_get_kernel_inputs(bool const is_constructor, auto mock_previous_kernel = utils::dummy_previous_kernel(real_kernel_circuit); // Fill in some important fields in public inputs mock_previous_kernel.public_inputs.end.private_call_stack = initial_kernel_private_call_stack; - mock_previous_kernel.public_inputs.constants = ConstantData{ + mock_previous_kernel.public_inputs.constants = CombinedConstantData{ .historic_tree_roots = - HistoricTreeRoots{ - .private_data_tree_root = private_circuit_public_inputs.historic_private_data_tree_root, - // .nullifier_tree_root = - .contract_tree_root = private_circuit_public_inputs.historic_contract_tree_root, - // .private_kernel_vk_tree_root = + CombinedHistoricTreeRoots { + .private_historic_tree_roots = + PrivateHistoricTreeRoots{ + .private_data_tree_root = private_circuit_public_inputs.historic_private_data_tree_root, + .contract_tree_root = private_circuit_public_inputs.historic_contract_tree_root, + }, }, .tx_context = tx_request.tx_context, }; @@ -389,7 +392,8 @@ PrivateInputs do_private_call_get_kernel_inputs(bool const is_constructor, * @param private_inputs to be used in manual computation * @param public_inputs that contain the expected new contract address */ -void validate_deployed_contract_address(PrivateInputs const& private_inputs, PublicInputs const& public_inputs) +void validate_deployed_contract_address(PrivateInputs const& private_inputs, + KernelCircuitPublicInputs const& public_inputs) { auto tx_request = private_inputs.signed_tx_request.tx_request; diff --git a/circuits/cpp/src/aztec3/circuits/kernel/private/c_bind.cpp b/circuits/cpp/src/aztec3/circuits/kernel/private/c_bind.cpp index 7db4b9d83cb3..fbbf2b90f7f3 100644 --- a/circuits/cpp/src/aztec3/circuits/kernel/private/c_bind.cpp +++ b/circuits/cpp/src/aztec3/circuits/kernel/private/c_bind.cpp @@ -9,7 +9,7 @@ #include "aztec3/circuits/abis/signed_tx_request.hpp" #include "aztec3/circuits/abis/private_kernel/private_call_data.hpp" #include -#include +#include #include "aztec3/circuits/kernel/private/utils.hpp" #include @@ -21,15 +21,15 @@ namespace { using NT = aztec3::utils::types::NativeTypes; using DummyComposer = aztec3::utils::DummyComposer; +using aztec3::circuits::abis::CombinedAccumulatedData; +using aztec3::circuits::abis::CombinedConstantData; +using aztec3::circuits::abis::CombinedHistoricTreeRoots; +using aztec3::circuits::abis::KernelCircuitPublicInputs; +using aztec3::circuits::abis::PreviousKernelData; using aztec3::circuits::abis::SignedTxRequest; using aztec3::circuits::abis::TxContext; -using aztec3::circuits::abis::private_kernel::AccumulatedData; -using aztec3::circuits::abis::private_kernel::ConstantData; -using aztec3::circuits::abis::private_kernel::HistoricTreeRoots; -using aztec3::circuits::abis::private_kernel::PreviousKernelData; using aztec3::circuits::abis::private_kernel::PrivateCallData; using aztec3::circuits::abis::private_kernel::PrivateInputs; -using aztec3::circuits::abis::private_kernel::PublicInputs; using aztec3::circuits::kernel::private_kernel::native_private_kernel_circuit; using aztec3::circuits::kernel::private_kernel::private_kernel_circuit; using aztec3::circuits::kernel::private_kernel::utils::dummy_previous_kernel; @@ -108,10 +108,10 @@ WASM_EXPORT size_t private_kernel__sim(uint8_t const* signed_tx_request_buf, previous_kernel = dummy_previous_kernel(); previous_kernel.public_inputs.end.private_call_stack[0] = private_call_data.call_stack_item.hash(); - previous_kernel.public_inputs.constants.historic_tree_roots.private_data_tree_root = + previous_kernel.public_inputs.constants.historic_tree_roots.private_historic_tree_roots.private_data_tree_root = private_call_data.call_stack_item.public_inputs.historic_private_data_tree_root; // previous_kernel.public_inputs.constants.historic_tree_roots.nullifier_tree_root = - previous_kernel.public_inputs.constants.historic_tree_roots.contract_tree_root = + previous_kernel.public_inputs.constants.historic_tree_roots.private_historic_tree_roots.contract_tree_root = private_call_data.call_stack_item.public_inputs.historic_contract_tree_root; // previous_kernel.public_inputs.constants.historic_tree_roots.private_kernel_vk_tree_root = previous_kernel.public_inputs.constants.tx_context = signed_tx_request.tx_request.tx_context; @@ -126,7 +126,7 @@ WASM_EXPORT size_t private_kernel__sim(uint8_t const* signed_tx_request_buf, .private_call = private_call_data, }; - PublicInputs public_inputs = native_private_kernel_circuit(composer, private_inputs); + KernelCircuitPublicInputs public_inputs = native_private_kernel_circuit(composer, private_inputs); // serialize public inputs to bytes vec std::vector public_inputs_vec; @@ -163,9 +163,9 @@ WASM_EXPORT size_t private_kernel__prove(uint8_t const* signed_tx_request_buf, previous_kernel = dummy_previous_kernel(true); previous_kernel.public_inputs.end.private_call_stack[0] = private_call_data.call_stack_item.hash(); - previous_kernel.public_inputs.constants.historic_tree_roots.private_data_tree_root = + previous_kernel.public_inputs.constants.historic_tree_roots.private_historic_tree_roots.private_data_tree_root = private_call_data.call_stack_item.public_inputs.historic_private_data_tree_root; - previous_kernel.public_inputs.constants.historic_tree_roots.contract_tree_root = + previous_kernel.public_inputs.constants.historic_tree_roots.private_historic_tree_roots.contract_tree_root = private_call_data.call_stack_item.public_inputs.historic_contract_tree_root; previous_kernel.public_inputs.constants.tx_context = signed_tx_request.tx_request.tx_context; previous_kernel.public_inputs.is_private = true; @@ -181,7 +181,7 @@ WASM_EXPORT size_t private_kernel__prove(uint8_t const* signed_tx_request_buf, Composer private_kernel_composer = Composer(crs_factory); plonk::stdlib::types::Prover private_kernel_prover = private_kernel_composer.create_prover(); - PublicInputs public_inputs; + KernelCircuitPublicInputs public_inputs; public_inputs = private_kernel_circuit(private_kernel_composer, private_inputs); NT::Proof private_kernel_proof; private_kernel_proof = private_kernel_prover.construct_proof(); diff --git a/circuits/cpp/src/aztec3/circuits/kernel/private/native_private_kernel_circuit.cpp b/circuits/cpp/src/aztec3/circuits/kernel/private/native_private_kernel_circuit.cpp index 5e5e1a68c7a8..a599dc474cdf 100644 --- a/circuits/cpp/src/aztec3/circuits/kernel/private/native_private_kernel_circuit.cpp +++ b/circuits/cpp/src/aztec3/circuits/kernel/private/native_private_kernel_circuit.cpp @@ -2,8 +2,8 @@ #include "aztec3/circuits/abis/function_leaf_preimage.hpp" #include -#include -#include +#include +#include #include #include @@ -14,10 +14,10 @@ namespace aztec3::circuits::kernel::private_kernel { -using aztec3::circuits::abis::private_kernel::ContractLeafPreimage; -using aztec3::circuits::abis::private_kernel::NewContractData; +using aztec3::circuits::abis::ContractLeafPreimage; +using aztec3::circuits::abis::KernelCircuitPublicInputs; +using aztec3::circuits::abis::NewContractData; using aztec3::circuits::abis::private_kernel::PrivateInputs; -using aztec3::circuits::abis::private_kernel::PublicInputs; using aztec3::utils::array_length; using aztec3::utils::array_pop; @@ -53,7 +53,7 @@ using aztec3::circuits::function_tree_root_from_siblings; // return aggregation_object; // } -void initialise_end_values(PrivateInputs const& private_inputs, PublicInputs& public_inputs) +void initialise_end_values(PrivateInputs const& private_inputs, KernelCircuitPublicInputs& public_inputs) { public_inputs.constants = private_inputs.previous_kernel.public_inputs.constants; @@ -72,7 +72,9 @@ void initialise_end_values(PrivateInputs const& private_inputs, PublicInputs end.optionally_revealed_data = start.optionally_revealed_data; } -void contract_logic(DummyComposer& composer, PrivateInputs const& private_inputs, PublicInputs& public_inputs) +void contract_logic(DummyComposer& composer, + PrivateInputs const& private_inputs, + KernelCircuitPublicInputs& public_inputs) { const auto private_call_public_inputs = private_inputs.private_call.call_stack_item.public_inputs; const auto& storage_contract_address = private_call_public_inputs.call_context.storage_contract_address; @@ -142,7 +144,7 @@ void contract_logic(DummyComposer& composer, PrivateInputs const& private_in auto const& purported_contract_tree_root = private_inputs.private_call.call_stack_item.public_inputs.historic_contract_tree_root; auto const& previous_kernel_contract_tree_root = - private_inputs.previous_kernel.public_inputs.constants.historic_tree_roots.contract_tree_root; + private_inputs.previous_kernel.public_inputs.constants.historic_tree_roots.private_historic_tree_roots.contract_tree_root; composer.do_assert(purported_contract_tree_root == previous_kernel_contract_tree_root, "purported_contract_tree_root doesn't match previous_kernel_contract_tree_root"); @@ -170,7 +172,7 @@ void contract_logic(DummyComposer& composer, PrivateInputs const& private_in void update_end_values(DummyComposer& composer, PrivateInputs const& private_inputs, - PublicInputs& public_inputs) + KernelCircuitPublicInputs& public_inputs) { const auto private_call_public_inputs = private_inputs.private_call.call_stack_item.public_inputs; @@ -325,10 +327,11 @@ void validate_inputs(DummyComposer& composer, PrivateInputs const& private_i // TODO: decide what to return. // TODO: is there a way to identify whether an input has not been used by ths circuit? This would help us more-safely // ensure we're constraining everything. -PublicInputs native_private_kernel_circuit(DummyComposer& composer, PrivateInputs const& private_inputs) +KernelCircuitPublicInputs native_private_kernel_circuit(DummyComposer& composer, + PrivateInputs const& private_inputs) { // We'll be pushing data to this during execution of this circuit. - PublicInputs public_inputs{}; + KernelCircuitPublicInputs public_inputs{}; // Do this before any functions can modify the inputs. initialise_end_values(private_inputs, public_inputs); diff --git a/circuits/cpp/src/aztec3/circuits/kernel/private/native_private_kernel_circuit.hpp b/circuits/cpp/src/aztec3/circuits/kernel/private/native_private_kernel_circuit.hpp index 819370ea8cb8..56c00ddcbc63 100644 --- a/circuits/cpp/src/aztec3/circuits/kernel/private/native_private_kernel_circuit.hpp +++ b/circuits/cpp/src/aztec3/circuits/kernel/private/native_private_kernel_circuit.hpp @@ -3,17 +3,18 @@ #include "init.hpp" #include -#include +#include #include namespace aztec3::circuits::kernel::private_kernel { +using aztec3::circuits::abis::KernelCircuitPublicInputs; using aztec3::circuits::abis::private_kernel::PrivateInputs; -using aztec3::circuits::abis::private_kernel::PublicInputs; // using abis::private_kernel::PublicInputs; using DummyComposer = aztec3::utils::DummyComposer; // TODO: decide what to return. -PublicInputs native_private_kernel_circuit(DummyComposer& composer, PrivateInputs const& _private_inputs); +KernelCircuitPublicInputs native_private_kernel_circuit(DummyComposer& composer, + PrivateInputs const& _private_inputs); } // namespace aztec3::circuits::kernel::private_kernel \ No newline at end of file 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 e17c4dbbcc67..a7148faad668 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 @@ -4,16 +4,16 @@ #include #include -#include -#include +#include +#include #include namespace aztec3::circuits::kernel::private_kernel { -using aztec3::circuits::abis::private_kernel::NewContractData; +using aztec3::circuits::abis::KernelCircuitPublicInputs; +using aztec3::circuits::abis::NewContractData; using aztec3::circuits::abis::private_kernel::PrivateInputs; -using aztec3::circuits::abis::private_kernel::PublicInputs; using plonk::stdlib::array_length; using plonk::stdlib::array_pop; @@ -56,7 +56,7 @@ CT::AggregationObject verify_proofs(Composer& composer, * as well as signed TX request and the private call information * @param public_inputs should be empty here since it is being initialized in this call */ -void initialise_end_values(PrivateInputs const& private_inputs, PublicInputs& public_inputs) +void initialise_end_values(PrivateInputs const& private_inputs, KernelCircuitPublicInputs& public_inputs) { // TODO: Ensure public inputs is empty here public_inputs.constants = private_inputs.previous_kernel.public_inputs.constants; @@ -90,7 +90,7 @@ void initialise_end_values(PrivateInputs const& private_inputs, PublicInputs * and update its running callstack with all items in the current private-circuit/function's * callstack. */ -void update_end_values(PrivateInputs const& private_inputs, PublicInputs& public_inputs) +void update_end_values(PrivateInputs const& private_inputs, KernelCircuitPublicInputs& public_inputs) { const auto private_call_public_inputs = private_inputs.private_call.call_stack_item.public_inputs; @@ -321,12 +321,12 @@ void validate_inputs(PrivateInputs const& private_inputs) // TODO: decide what to return. // TODO: is there a way to identify whether an input has not been used by ths circuit? This would help us more-safely // ensure we're constraining everything. -PublicInputs private_kernel_circuit(Composer& composer, PrivateInputs const& _private_inputs) +KernelCircuitPublicInputs private_kernel_circuit(Composer& composer, PrivateInputs const& _private_inputs) { const PrivateInputs private_inputs = _private_inputs.to_circuit_type(composer); // We'll be pushing data to this during execution of this circuit. - PublicInputs public_inputs = PublicInputs{}.to_circuit_type(composer); + KernelCircuitPublicInputs public_inputs = KernelCircuitPublicInputs{}.to_circuit_type(composer); // Do this before any functions can modify the inputs. initialise_end_values(private_inputs, public_inputs); diff --git a/circuits/cpp/src/aztec3/circuits/kernel/private/private_kernel_circuit.hpp b/circuits/cpp/src/aztec3/circuits/kernel/private/private_kernel_circuit.hpp index 6ebc21650d7c..80a33b300360 100644 --- a/circuits/cpp/src/aztec3/circuits/kernel/private/private_kernel_circuit.hpp +++ b/circuits/cpp/src/aztec3/circuits/kernel/private/private_kernel_circuit.hpp @@ -3,14 +3,14 @@ #include "init.hpp" #include -#include +#include namespace aztec3::circuits::kernel::private_kernel { +using aztec3::circuits::abis::KernelCircuitPublicInputs; using aztec3::circuits::abis::private_kernel::PrivateInputs; -using aztec3::circuits::abis::private_kernel::PublicInputs; -PublicInputs private_kernel_circuit(Composer& composer, PrivateInputs const& _private_inputs); -PublicInputs private_kernel_native(PrivateInputs const& private_inputs); +KernelCircuitPublicInputs private_kernel_circuit(Composer& composer, PrivateInputs const& _private_inputs); +KernelCircuitPublicInputs private_kernel_native(PrivateInputs const& private_inputs); } // namespace aztec3::circuits::kernel::private_kernel \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/kernel/private/utils.cpp b/circuits/cpp/src/aztec3/circuits/kernel/private/utils.cpp index a12a03913c29..41f06be4fa1b 100644 --- a/circuits/cpp/src/aztec3/circuits/kernel/private/utils.cpp +++ b/circuits/cpp/src/aztec3/circuits/kernel/private/utils.cpp @@ -3,12 +3,12 @@ #include "barretenberg/proof_system/types/composer_type.hpp" #include -#include "aztec3/circuits/abis/private_kernel/new_contract_data.hpp" +#include "aztec3/circuits/abis/new_contract_data.hpp" namespace { using NT = aztec3::utils::types::NativeTypes; using AggregationObject = aztec3::utils::types::NativeTypes::AggregationObject; -using aztec3::circuits::abis::private_kernel::PreviousKernelData; +using aztec3::circuits::abis::PreviousKernelData; using aztec3::circuits::mock::mock_kernel_circuit; } // namespace diff --git a/circuits/cpp/src/aztec3/circuits/kernel/private/utils.hpp b/circuits/cpp/src/aztec3/circuits/kernel/private/utils.hpp index 87733c013069..fed871f7873f 100644 --- a/circuits/cpp/src/aztec3/circuits/kernel/private/utils.hpp +++ b/circuits/cpp/src/aztec3/circuits/kernel/private/utils.hpp @@ -4,7 +4,7 @@ namespace { using NT = aztec3::utils::types::NativeTypes; -using aztec3::circuits::abis::private_kernel::PreviousKernelData; +using aztec3::circuits::abis::PreviousKernelData; } // namespace namespace aztec3::circuits::kernel::private_kernel::utils { diff --git a/circuits/cpp/src/aztec3/circuits/kernel/public/.test.cpp b/circuits/cpp/src/aztec3/circuits/kernel/public/.test.cpp new file mode 100644 index 000000000000..6fed95c37893 --- /dev/null +++ b/circuits/cpp/src/aztec3/circuits/kernel/public/.test.cpp @@ -0,0 +1,23 @@ +#include "init.hpp" +#include "native_public_kernel_circuit.hpp" +#include +#include +#include + +using DummyComposer = aztec3::utils::DummyComposer; +using aztec3::circuits::abis::public_kernel::PublicKernelInputs; +using NT = aztec3::utils::types::NativeTypes; + +namespace aztec3::circuits::kernel::public_kernel { +/** + * @brief Some private circuit proof (`constructor`, in this case) + */ +TEST(public_kernel_tests, end_values_are_initialised) +{ + DummyComposer dc; + PublicKernelInputs inputs; + auto public_inputs = native_public_kernel_circuit(dc, inputs); + + ASSERT_EQ(public_inputs.end, inputs.previous_kernel.public_inputs.end); +} +} // namespace aztec3::circuits::kernel::public_kernel \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/kernel/public/init.hpp b/circuits/cpp/src/aztec3/circuits/kernel/public/init.hpp new file mode 100644 index 000000000000..75604e97e449 --- /dev/null +++ b/circuits/cpp/src/aztec3/circuits/kernel/public/init.hpp @@ -0,0 +1,35 @@ +#pragma once +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include + +namespace aztec3::circuits::kernel::public_kernel { + +// Turbo specific, at the moment: +using Composer = plonk::stdlib::types::Composer; +using plonk::stdlib::types::Prover; + +using Aggregator = aztec3::circuits::recursion::Aggregator; + +// Generic: +using CT = aztec3::utils::types::CircuitTypes; +using NT = aztec3::utils::types::NativeTypes; +using aztec3::utils::types::to_ct; + +using DB = oracle::FakeDB; +using oracle::NativeOracle; +using OracleWrapper = aztec3::circuits::apps::OracleWrapperInterface; + +using FunctionExecutionContext = aztec3::circuits::apps::FunctionExecutionContext; + +} // namespace aztec3::circuits::kernel::public_kernel \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/kernel/public/native_public_kernel_circuit.cpp b/circuits/cpp/src/aztec3/circuits/kernel/public/native_public_kernel_circuit.cpp new file mode 100644 index 000000000000..47eaa060c551 --- /dev/null +++ b/circuits/cpp/src/aztec3/circuits/kernel/public/native_public_kernel_circuit.cpp @@ -0,0 +1,324 @@ +#include "init.hpp" + +#include +#include + +#include +#include +#include +#include "aztec3/constants.hpp" + +#include + +namespace aztec3::circuits::kernel::public_kernel { + +using aztec3::circuits::abis::KernelCircuitPublicInputs; +using aztec3::circuits::abis::public_kernel::PublicKernelInputs; +using aztec3::utils::array_length; + +using DummyComposer = aztec3::utils::DummyComposer; + +void initialise_end_values(PublicKernelInputs const& public_kernel_inputs, + KernelCircuitPublicInputs& public_inputs) +{ + public_inputs.constants = public_kernel_inputs.previous_kernel.public_inputs.constants; + + // Ensure the arrays are the same as previously, before we start pushing more data onto them in other functions + // within this circuit: + auto& end = public_inputs.end; + const auto& start = public_kernel_inputs.previous_kernel.public_inputs.end; + + end.public_call_stack = start.public_call_stack; + end.state_transitions = start.state_transitions; +} + +// void contract_logic(DummyComposer& composer, PrivateInputs const& private_inputs, PublicInputs& +// public_inputs) +// { +// const auto private_call_public_inputs = private_inputs.private_call.call_stack_item.public_inputs; +// 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; + +// auto private_call_vk_hash = stdlib::recursion::verification_key::compress_native( +// private_inputs.private_call.vk, GeneratorIndex::VK); + +// auto constructor_hash = compute_constructor_hash(private_inputs.signed_tx_request.tx_request.function_data, +// private_call_public_inputs.args, +// private_call_vk_hash); + +// if (is_contract_deployment) { +// composer.do_assert(contract_deployment_data.constructor_vk_hash == private_call_vk_hash, +// "constructor_vk_hash doesn't match private_call_vk_hash"); +// } + +// auto const new_contract_address = compute_contract_address(deployer_address, +// contract_deployment_data.contract_address_salt, +// contract_deployment_data.function_tree_root, +// constructor_hash); + +// if (is_contract_deployment) { +// // must imply == derived address +// composer.do_assert(storage_contract_address == new_contract_address, +// "contract address supplied doesn't match derived address"); +// } else { +// // non-contract deployments must specify contract address being interacted with +// composer.do_assert(storage_contract_address != 0, +// "contract address can't be 0 for non-contract deployment related transactions"); +// } + +// // 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()); + +// // 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 native_new_contract_data{ new_contract_address, +// portal_contract_address, +// contract_deployment_data.function_tree_root }; + +// array_push, 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 (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 contract_leaf with the contract_leaf's sibling_path to get the contract_tree_root +// */ + +// // ensure that historic/purported contract tree root matches the one in previous kernel +// auto const& purported_contract_tree_root = +// private_inputs.private_call.call_stack_item.public_inputs.historic_contract_tree_root; +// auto const& previous_kernel_contract_tree_root = +// private_inputs.previous_kernel.public_inputs.constants.historic_tree_roots.contract_tree_root; +// composer.do_assert(purported_contract_tree_root == previous_kernel_contract_tree_root, +// "purported_contract_tree_root doesn't match previous_kernel_contract_tree_root"); + +// // The logic below ensures that the contract exists in the contracts tree +// if (!is_contract_deployment) { +// auto const& computed_function_tree_root = function_tree_root_from_siblings( +// private_inputs.private_call.call_stack_item.function_data.function_selector, +// true, // is_private +// private_call_vk_hash, +// private_inputs.private_call.acir_hash, +// private_inputs.private_call.function_leaf_membership_witness.leaf_index, +// private_inputs.private_call.function_leaf_membership_witness.sibling_path); + +// auto const& computed_contract_tree_root = contract_tree_root_from_siblings( +// computed_function_tree_root, +// storage_contract_address, +// portal_contract_address, +// private_inputs.private_call.contract_leaf_membership_witness.leaf_index, +// private_inputs.private_call.contract_leaf_membership_witness.sibling_path); + +// composer.do_assert(computed_contract_tree_root == purported_contract_tree_root, +// "computed_contract_tree_root doesn't match purported_contract_tree_root"); +// } +// } + +// void update_end_values(DummyComposer& composer, +// PrivateInputs const& private_inputs, +// PublicInputs& 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: +// composer.do_assert(is_array_empty(new_commitments) == true, "new_commitments must be empty for static +// calls"); composer.do_assert(is_array_empty(new_nullifiers) == true, "new_nullifiers must be empty for static +// calls"); +// } + +// 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 +// // milestone. This must not be the way we derive nonce nullifiers in production. It can be front-run by other +// // users. It is not domain separated. Naughty. +// array_push(public_inputs.end.new_nullifiers, private_inputs.signed_tx_request.tx_request.nonce); +// } + +// { // commitments & nullifiers +// std::array siloed_new_commitments; +// for (size_t i = 0; i < new_commitments.size(); ++i) { +// siloed_new_commitments[i] = +// new_commitments[i] == 0 +// ? 0 +// : add_contract_address_to_commitment(storage_contract_address, new_commitments[i]); +// } + +// std::array siloed_new_nullifiers; +// for (size_t i = 0; i < new_nullifiers.size(); ++i) { +// siloed_new_nullifiers[i] = +// new_nullifiers[i] == 0 +// ? 0 +// : add_contract_address_to_nullifier(storage_contract_address, new_nullifiers[i]); +// } + +// push_array_to_array(siloed_new_commitments, public_inputs.end.new_commitments); +// push_array_to_array(siloed_new_nullifiers, public_inputs.end.new_nullifiers); +// } + +// { // call stacks +// auto& this_private_call_stack = private_call_public_inputs.private_call_stack; +// push_array_to_array(this_private_call_stack, public_inputs.end.private_call_stack); +// } + +// // const auto& portal_contract_address = private_inputs.private_call.portal_contract_address; + +// // { +// // const auto& l1_msg_stack = private_call_public_inputs.l1_msg_stack; +// // std::array l1_call_stack; + +// // for (size_t i = 0; i < l1_msg_stack.size(); ++i) { +// // l1_call_stack[i] = CT::fr::conditional_assign( +// // l1_msg_stack[i] == 0, +// // 0, +// // CT::compress({ portal_contract_address, l1_msg_stack[i] }, GeneratorIndex::L1_MSG_STACK_ITEM)); +// // } +// // } +// } + +// void validate_this_private_call_hash(DummyComposer& composer, PrivateInputs 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 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(); + +// composer.do_assert( +// popped_private_call_hash == calculated_this_private_call_hash, +// "calculated private_call_hash does not match provided private_call_hash at the top of the call stack"); +// }; + +// void validate_this_private_call_stack(DummyComposer& composer, PrivateInputs const& private_inputs) +// { +// auto& stack = private_inputs.private_call.call_stack_item.public_inputs.private_call_stack; +// auto& preimages = private_inputs.private_call.private_call_stack_preimages; +// for (size_t i = 0; i < stack.size(); ++i) { +// const auto& hash = stack[i]; +// const auto& preimage = preimages[i]; + +// // Note: this assumes it's computationally infeasible to have `0` as a valid call_stack_item_hash. +// // Assumes `hash == 0` means "this stack item is empty". +// const auto calculated_hash = hash == 0 ? 0 : preimage.hash(); +// composer.do_assert(hash != calculated_hash, +// format("private_call_stack[", i, "] = ", hash, "; does not reconcile")); +// } +// }; + +void validate_inputs(DummyComposer& composer, PublicKernelInputs const& public_kernel_inputs) +{ + const auto& this_call_stack_item = public_kernel_inputs.public_call.call_stack_item; + + composer.do_assert(this_call_stack_item.function_data.is_private == false, + "Cannot execute a private function with the public kernel circuit"); + + const auto& start = public_kernel_inputs.previous_kernel.public_inputs.end; + + const NT::boolean is_base_case = start.public_call_count == 0; + + // TODO: we might want to range-constrain the call_count to prevent some kind of overflow errors. Having said that, + // iterating 2^254 times isn't feasible. + + NT::fr start_public_call_stack_length = array_length(start.public_call_stack); + // NT::fr start_state_transitions_length = array_length(start.state_transitions); + + // Base Case + if (is_base_case) { + // TODO: change to allow 3 initial calls on the private call stack, so a fee can be paid and a gas + // rebate can be paid. + + composer.do_assert(start_public_call_stack_length == 1, "Public call stack must be length 1"); + + // composer.do_assert(start_state_transitions_length == 0, "State transition length must be 0"); + + composer.do_assert(this_call_stack_item.public_inputs.call_context.is_delegate_call == false, + "Users cannot make a delegatecall"); + composer.do_assert(this_call_stack_item.public_inputs.call_context.is_static_call == false, + "Users cannot make a static call"); + + // The below also prevents delegatecall/staticcall in the base case + composer.do_assert(this_call_stack_item.public_inputs.call_context.storage_contract_address == + this_call_stack_item.contract_address, + "Storage contract address must be that of the called contract"); + + composer.do_assert(public_kernel_inputs.previous_kernel.vk->contains_recursive_proof == false, + "Mock kernel proof must not contain a recursive proof"); + + // TODO: Assert that the previous kernel data is empty. (Or rather, the verify_proof() function needs a valid + // dummy proof and vk to complete execution, so actually what we want is for that mockvk to be + // hard-coded into the circuit and assert that that is the one which has been used in the base case). + } else { + // is_recursive_case + + composer.do_assert(public_kernel_inputs.previous_kernel.public_inputs.is_private == true, + "Cannot verify a non-private kernel snark in the private kernel circuit"); + composer.do_assert(this_call_stack_item.function_data.is_constructor == false, + "A constructor must be executed as the first tx in the recursion"); + composer.do_assert(start_public_call_stack_length != 0, + "Cannot execute public kernel circuit with an empty public call stack"); + } +} + +// NOTE: THIS IS A VERY UNFINISHED WORK IN PROGRESS. +// TODO: decide what to return. +// TODO: is there a way to identify whether an input has not been used by ths circuit? This would help us more-safely +// ensure we're constraining everything. +KernelCircuitPublicInputs native_public_kernel_circuit(DummyComposer& composer, + PublicKernelInputs const& public_kernel_inputs) +{ + // We'll be pushing data to this during execution of this circuit. + (void)composer; + KernelCircuitPublicInputs public_inputs{}; + + // Do this before any functions can modify the inputs. + initialise_end_values(public_kernel_inputs, public_inputs); + + // validate_inputs(composer, private_inputs); + + // validate_this_private_call_hash(composer, private_inputs); + + // validate_this_private_call_stack(composer, private_inputs); + + // update_end_values(composer, private_inputs, public_inputs); + + // contract_logic(composer, private_inputs, public_inputs); + + // We'll skip any verification in this native implementation, because for a Local Developer Testnet, there won't + // _be_ a valid proof to verify!!! auto aggregation_object = verify_proofs(composer, + // private_inputs, + // _private_inputs.private_call.vk->num_public_inputs, + // _private_inputs.previous_kernel.vk->num_public_inputs); + + // TODO: kernel vk membership check! + + // Note: given that we skipped the verify_proof function, the aggregation object we get at the end will just be the + // same as we had at the start. public_inputs.end.aggregation_object = aggregation_object; + public_inputs.end.aggregation_object = public_kernel_inputs.previous_kernel.public_inputs.end.aggregation_object; + + return public_inputs; +}; + +} // namespace aztec3::circuits::kernel::public_kernel \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/kernel/public/native_public_kernel_circuit.hpp b/circuits/cpp/src/aztec3/circuits/kernel/public/native_public_kernel_circuit.hpp new file mode 100644 index 000000000000..4e818d39937a --- /dev/null +++ b/circuits/cpp/src/aztec3/circuits/kernel/public/native_public_kernel_circuit.hpp @@ -0,0 +1,22 @@ +#pragma once + +#include "init.hpp" + +#include +#include +#include + +namespace aztec3::circuits::kernel::public_kernel { + +using aztec3::circuits::abis::KernelCircuitPublicInputs; +using aztec3::circuits::abis::public_kernel::PublicKernelInputs; +// using abis::private_kernel::PublicInputs; +using DummyComposer = aztec3::utils::DummyComposer; + +// TODO: decide what to return. +KernelCircuitPublicInputs native_public_kernel_circuit(DummyComposer& composer, + PublicKernelInputs const& _public_kernel_inputs); + +void validate_inputs(DummyComposer& composer, PublicKernelInputs const& public_kernel_inputs); + +} // namespace aztec3::circuits::kernel::public_kernel \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/mock/mock_kernel_circuit.hpp b/circuits/cpp/src/aztec3/circuits/mock/mock_kernel_circuit.hpp index 03ec3461ec40..6b1f68aef260 100644 --- a/circuits/cpp/src/aztec3/circuits/mock/mock_kernel_circuit.hpp +++ b/circuits/cpp/src/aztec3/circuits/mock/mock_kernel_circuit.hpp @@ -6,7 +6,7 @@ #include #include #include -#include +#include // #include namespace { @@ -15,14 +15,15 @@ auto& engine = numeric::random::get_debug_engine(); namespace aztec3::circuits::mock { -using aztec3::circuits::abis::private_kernel::PublicInputs; +using aztec3::circuits::abis::KernelCircuitPublicInputs; using NT = aztec3::utils::types::NativeTypes; using aztec3::utils::types::CircuitTypes; using plonk::stdlib::pedersen_commitment; using plonk::stdlib::witness_t; template -PublicInputs mock_kernel_circuit(Composer& composer, PublicInputs const& _public_inputs) +KernelCircuitPublicInputs mock_kernel_circuit(Composer& composer, + KernelCircuitPublicInputs const& _public_inputs) { typedef CircuitTypes CT; typedef typename CT::fr fr; diff --git a/circuits/cpp/src/aztec3/circuits/rollup/base/.test.cpp b/circuits/cpp/src/aztec3/circuits/rollup/base/.test.cpp index 9c16a565b914..145e2b0f159c 100644 --- a/circuits/cpp/src/aztec3/circuits/rollup/base/.test.cpp +++ b/circuits/cpp/src/aztec3/circuits/rollup/base/.test.cpp @@ -1,7 +1,7 @@ #include "aztec3/circuits/abis/append_only_tree_snapshot.hpp" #include "aztec3/circuits/abis/membership_witness.hpp" -#include "aztec3/circuits/abis/private_kernel/new_contract_data.hpp" -#include "aztec3/circuits/abis/private_kernel/previous_kernel_data.hpp" +#include "aztec3/circuits/abis/new_contract_data.hpp" +#include "aztec3/circuits/abis/previous_kernel_data.hpp" #include "aztec3/circuits/kernel/private/utils.hpp" #include "aztec3/circuits/abis/rollup/nullifier_leaf_preimage.hpp" #include "aztec3/constants.hpp" @@ -26,10 +26,11 @@ #include #include #include -#include -#include -#include -#include +#include +#include +#include +#include +#include #include #include @@ -57,7 +58,6 @@ namespace { using aztec3::circuits::abis::CallContext; using aztec3::circuits::abis::CallStackItem; -using aztec3::circuits::abis::CallType; using aztec3::circuits::abis::ContractDeploymentData; using aztec3::circuits::abis::FunctionData; using aztec3::circuits::abis::OptionalPrivateCircuitPublicInputs; @@ -66,14 +66,14 @@ using aztec3::circuits::abis::SignedTxRequest; using aztec3::circuits::abis::TxContext; using aztec3::circuits::abis::TxRequest; -using aztec3::circuits::abis::private_kernel::AccumulatedData; -using aztec3::circuits::abis::private_kernel::ConstantData; +using aztec3::circuits::abis::CombinedAccumulatedData; +using aztec3::circuits::abis::CombinedConstantData; +using aztec3::circuits::abis::CombinedHistoricTreeRoots; +using aztec3::circuits::abis::KernelCircuitPublicInputs; +using aztec3::circuits::abis::PreviousKernelData; using aztec3::circuits::abis::private_kernel::Globals; -using aztec3::circuits::abis::private_kernel::HistoricTreeRoots; -using aztec3::circuits::abis::private_kernel::PreviousKernelData; using aztec3::circuits::abis::private_kernel::PrivateCallData; using aztec3::circuits::abis::private_kernel::PrivateInputs; -using aztec3::circuits::abis::private_kernel::PublicInputs; using aztec3::circuits::apps::test_apps::basic_contract_deployment::constructor; using aztec3::circuits::apps::test_apps::escrow::deposit; @@ -94,8 +94,8 @@ using aztec3::circuits::rollup::native_base_rollup::ConstantRollupData; using aztec3::circuits::rollup::native_base_rollup::NT; using aztec3::circuits::abis::FunctionData; +using aztec3::circuits::abis::NewContractData; using aztec3::circuits::abis::OptionallyRevealedData; -using aztec3::circuits::abis::private_kernel::NewContractData; using DummyComposer = aztec3::utils::DummyComposer; } // namespace @@ -693,7 +693,7 @@ TEST_F(base_rollup_tests, native_compute_membership_historic_private_data) .root = tree.root(), .next_available_leaf_index = 0, }; - inputs.kernel_data[0].public_inputs.constants.historic_tree_roots.private_data_tree_root = fr(0); + inputs.kernel_data[0].public_inputs.constants.historic_tree_roots.private_historic_tree_roots.private_data_tree_root = fr(0); // fetch sibling path from hash path (only get the second half of the hash path) auto hash_path = tree.get_hash_path(0); diff --git a/circuits/cpp/src/aztec3/circuits/rollup/base/c_bind.cpp b/circuits/cpp/src/aztec3/circuits/rollup/base/c_bind.cpp index 4e502fa4d82e..ab9557ffee31 100644 --- a/circuits/cpp/src/aztec3/circuits/rollup/base/c_bind.cpp +++ b/circuits/cpp/src/aztec3/circuits/rollup/base/c_bind.cpp @@ -10,7 +10,7 @@ #include "aztec3/circuits/abis/signed_tx_request.hpp" #include "aztec3/circuits/abis/private_kernel/private_call_data.hpp" #include -#include +#include #include #include "barretenberg/srs/reference_string/env_reference_string.hpp" diff --git a/circuits/cpp/src/aztec3/circuits/rollup/base/native_base_rollup_circuit.cpp b/circuits/cpp/src/aztec3/circuits/rollup/base/native_base_rollup_circuit.cpp index b93e47eb16c6..ab4f77b84b40 100644 --- a/circuits/cpp/src/aztec3/circuits/rollup/base/native_base_rollup_circuit.cpp +++ b/circuits/cpp/src/aztec3/circuits/rollup/base/native_base_rollup_circuit.cpp @@ -201,7 +201,8 @@ void perform_historical_private_data_tree_membership_checks(DummyComposer& compo auto historic_root = baseRollupInputs.constants.start_tree_of_historic_private_data_tree_roots_snapshot.root; for (size_t i = 0; i < 2; i++) { - NT::fr leaf = baseRollupInputs.kernel_data[i].public_inputs.constants.historic_tree_roots.private_data_tree_root; + NT::fr leaf = baseRollupInputs.kernel_data[i] + .public_inputs.constants.historic_tree_roots.private_historic_tree_roots.private_data_tree_root; abis::MembershipWitness historic_root_witness = baseRollupInputs.historic_private_data_tree_root_membership_witnesses[i]; @@ -216,7 +217,8 @@ void perform_historical_contract_data_tree_membership_checks(DummyComposer& comp auto historic_root = baseRollupInputs.constants.start_tree_of_historic_contract_tree_roots_snapshot.root; for (size_t i = 0; i < 2; i++) { - NT::fr leaf = baseRollupInputs.kernel_data[i].public_inputs.constants.historic_tree_roots.contract_tree_root; + NT::fr leaf = baseRollupInputs.kernel_data[i] + .public_inputs.constants.historic_tree_roots.private_historic_tree_roots.contract_tree_root; abis::MembershipWitness historic_root_witness = baseRollupInputs.historic_contract_tree_root_membership_witnesses[i]; diff --git a/circuits/cpp/src/aztec3/circuits/rollup/base/utils.cpp b/circuits/cpp/src/aztec3/circuits/rollup/base/utils.cpp index 9c7a059a333b..4e6d69933677 100644 --- a/circuits/cpp/src/aztec3/circuits/rollup/base/utils.cpp +++ b/circuits/cpp/src/aztec3/circuits/rollup/base/utils.cpp @@ -6,7 +6,7 @@ #include #include -#include "aztec3/circuits/abis/private_kernel/new_contract_data.hpp" +#include "aztec3/circuits/abis/new_contract_data.hpp" namespace { using NT = aztec3::utils::types::NativeTypes; @@ -38,7 +38,7 @@ BaseRollupInputs dummy_base_rollup_inputs() // constantRollupData.tree_of_historic_l1_to_l2_msg_tree_roots_snapshot = // Kernels - std::array, 2> kernel_data; + std::array, 2> kernel_data; // grab mocked previous kernel (need a valid vk, proof, aggobj) kernel_data[0] = dummy_previous_kernel(); kernel_data[1] = dummy_previous_kernel(); diff --git a/circuits/cpp/src/aztec3/circuits/rollup/merge/utils.cpp b/circuits/cpp/src/aztec3/circuits/rollup/merge/utils.cpp index 5e30ce02b08e..fd9b6798a293 100644 --- a/circuits/cpp/src/aztec3/circuits/rollup/merge/utils.cpp +++ b/circuits/cpp/src/aztec3/circuits/rollup/merge/utils.cpp @@ -10,7 +10,7 @@ #include #include -#include "aztec3/circuits/abis/private_kernel/new_contract_data.hpp" +#include "aztec3/circuits/abis/new_contract_data.hpp" #include "aztec3/circuits/rollup/base/utils.hpp" // #include "aztec3/circuits/abis/rollup/base/previous_rollup_data.hpp" diff --git a/circuits/cpp/src/aztec3/circuits/rollup/root/.test.cpp b/circuits/cpp/src/aztec3/circuits/rollup/root/.test.cpp index 4f00f39b1b4b..c216f54322ee 100644 --- a/circuits/cpp/src/aztec3/circuits/rollup/root/.test.cpp +++ b/circuits/cpp/src/aztec3/circuits/rollup/root/.test.cpp @@ -1,7 +1,7 @@ #include "aztec3/circuits/abis/append_only_tree_snapshot.hpp" #include "aztec3/circuits/abis/membership_witness.hpp" -#include "aztec3/circuits/abis/private_kernel/new_contract_data.hpp" -#include "aztec3/circuits/abis/private_kernel/previous_kernel_data.hpp" +#include "aztec3/circuits/abis/new_contract_data.hpp" +#include "aztec3/circuits/abis/previous_kernel_data.hpp" #include "aztec3/circuits/abis/rollup/merge/previous_rollup_data.hpp" #include "aztec3/circuits/abis/rollup/nullifier_leaf_preimage.hpp" #include "aztec3/circuits/rollup/base/init.hpp" @@ -29,10 +29,11 @@ #include #include #include -#include -#include -#include -#include +#include +#include +#include +#include +#include #include #include @@ -51,7 +52,6 @@ namespace { using aztec3::circuits::abis::CallContext; using aztec3::circuits::abis::CallStackItem; -using aztec3::circuits::abis::CallType; using aztec3::circuits::abis::ContractDeploymentData; using aztec3::circuits::abis::FunctionData; using aztec3::circuits::abis::OptionalPrivateCircuitPublicInputs; @@ -60,14 +60,15 @@ using aztec3::circuits::abis::SignedTxRequest; using aztec3::circuits::abis::TxContext; using aztec3::circuits::abis::TxRequest; -using aztec3::circuits::abis::private_kernel::AccumulatedData; -using aztec3::circuits::abis::private_kernel::ConstantData; +using aztec3::circuits::abis::CombinedAccumulatedData; +using aztec3::circuits::abis::CombinedConstantData; +using aztec3::circuits::abis::CombinedHistoricTreeRoots; +using aztec3::circuits::abis::KernelCircuitPublicInputs; +using aztec3::circuits::abis::PreviousKernelData; +using aztec3::circuits::abis::PrivateHistoricTreeRoots; using aztec3::circuits::abis::private_kernel::Globals; -using aztec3::circuits::abis::private_kernel::HistoricTreeRoots; -using aztec3::circuits::abis::private_kernel::PreviousKernelData; using aztec3::circuits::abis::private_kernel::PrivateCallData; using aztec3::circuits::abis::private_kernel::PrivateInputs; -using aztec3::circuits::abis::private_kernel::PublicInputs; using aztec3::circuits::apps::test_apps::basic_contract_deployment::constructor; using aztec3::circuits::apps::test_apps::escrow::deposit; @@ -93,8 +94,8 @@ using aztec3::circuits::rollup::native_root_rollup::RootRollupInputs; using aztec3::circuits::rollup::native_root_rollup::RootRollupPublicInputs; using aztec3::circuits::abis::FunctionData; +using aztec3::circuits::abis::NewContractData; using aztec3::circuits::abis::OptionallyRevealedData; -using aztec3::circuits::abis::private_kernel::NewContractData; using MemoryTree = proof_system::plonk::stdlib::merkle_tree::MemoryTree; diff --git a/circuits/cpp/src/aztec3/circuits/rollup/root/c_bind.cpp b/circuits/cpp/src/aztec3/circuits/rollup/root/c_bind.cpp index 92114351c0cd..91a992fe9c33 100644 --- a/circuits/cpp/src/aztec3/circuits/rollup/root/c_bind.cpp +++ b/circuits/cpp/src/aztec3/circuits/rollup/root/c_bind.cpp @@ -7,7 +7,7 @@ #include "aztec3/circuits/abis/signed_tx_request.hpp" #include "aztec3/circuits/abis/private_kernel/private_call_data.hpp" #include -#include +#include #include #include "barretenberg/srs/reference_string/env_reference_string.hpp" diff --git a/circuits/cpp/src/aztec3/constants.hpp b/circuits/cpp/src/aztec3/constants.hpp index f07866f69dac..aa03741daa4a 100644 --- a/circuits/cpp/src/aztec3/constants.hpp +++ b/circuits/cpp/src/aztec3/constants.hpp @@ -31,6 +31,7 @@ constexpr size_t FUNCTION_TREE_HEIGHT = 4; constexpr size_t CONTRACT_TREE_HEIGHT = 4; constexpr size_t PRIVATE_DATA_TREE_HEIGHT = 8; constexpr size_t NULLIFIER_TREE_HEIGHT = 8; +constexpr size_t PUBLIC_DATA_TREE_HEIGHT = 32; constexpr size_t CONTRACT_SUBTREE_DEPTH = 1; constexpr size_t CONTRACT_SUBTREE_INCLUSION_CHECK_DEPTH = CONTRACT_TREE_HEIGHT - CONTRACT_SUBTREE_DEPTH; diff --git a/yarn-project/acir-simulator/src/acvm/serialize.ts b/yarn-project/acir-simulator/src/acvm/serialize.ts index 1a53d4f57c0e..bc46a2c885ee 100644 --- a/yarn-project/acir-simulator/src/acvm/serialize.ts +++ b/yarn-project/acir-simulator/src/acvm/serialize.ts @@ -4,7 +4,7 @@ import { CallContext, ContractDeploymentData, FunctionData, - HistoricTreeRoots, + PrivateHistoricTreeRoots, PrivateCallStackItem, PrivateCircuitPublicInputs, TxContext, @@ -89,7 +89,7 @@ export function writeInputs( args: Fr[], callContext: CallContext, txContext: TxContext, - historicRoots: HistoricTreeRoots, + historicRoots: PrivateHistoricTreeRoots, witnessStartIndex = 1, ) { const fields = [ diff --git a/yarn-project/acir-simulator/src/execution.ts b/yarn-project/acir-simulator/src/execution.ts index 4e4fae7d1835..df63804a662b 100644 --- a/yarn-project/acir-simulator/src/execution.ts +++ b/yarn-project/acir-simulator/src/execution.ts @@ -12,7 +12,7 @@ import { import { AztecAddress, EthAddress, Fr } from '@aztec/foundation'; import { CallContext, - HistoricTreeRoots, + PrivateHistoricTreeRoots, TxRequest, PrivateCallStackItem, FunctionData, @@ -58,7 +58,7 @@ export class Execution { // Global to the tx private db: DBOracle, private request: TxRequest, - private historicRoots: HistoricTreeRoots, + private historicRoots: PrivateHistoricTreeRoots, // Concrete to this execution private abi: FunctionAbi, private contractAddress: AztecAddress, diff --git a/yarn-project/acir-simulator/src/index.test.ts b/yarn-project/acir-simulator/src/index.test.ts index a5345d4908b2..8b93b926938c 100644 --- a/yarn-project/acir-simulator/src/index.test.ts +++ b/yarn-project/acir-simulator/src/index.test.ts @@ -5,7 +5,7 @@ import { ContractDeploymentData, FunctionData, NEW_COMMITMENTS_LENGTH, - HistoricTreeRoots, + PrivateHistoricTreeRoots, PRIVATE_DATA_TREE_HEIGHT, TxContext, TxRequest, @@ -39,7 +39,7 @@ describe('ACIR simulator', () => { }); describe('empty constructor', () => { - const historicRoots = new HistoricTreeRoots(new Fr(0n), new Fr(0n), new Fr(0n), new Fr(0n)); + const historicRoots = new PrivateHistoricTreeRoots(new Fr(0n), new Fr(0n), new Fr(0n), new Fr(0n)); const contractDeploymentData = new ContractDeploymentData(Fr.random(), Fr.random(), Fr.random(), EthAddress.ZERO); const txContext = new TxContext(false, false, true, contractDeploymentData); @@ -92,7 +92,7 @@ describe('ACIR simulator', () => { }); it('should a constructor with arguments that creates notes', async () => { - const historicRoots = new HistoricTreeRoots(new Fr(0n), new Fr(0n), new Fr(0n), new Fr(0n)); + const historicRoots = new PrivateHistoricTreeRoots(new Fr(0n), new Fr(0n), new Fr(0n), new Fr(0n)); const contractAddress = AztecAddress.random(); const abi = ZkTokenContractAbi.functions.find(f => f.name === 'constructor') as unknown as FunctionAbi; @@ -119,7 +119,7 @@ describe('ACIR simulator', () => { }); it('should run the mint function', async () => { - const historicRoots = new HistoricTreeRoots(new Fr(0n), new Fr(0n), new Fr(0n), new Fr(0n)); + const historicRoots = new PrivateHistoricTreeRoots(new Fr(0n), new Fr(0n), new Fr(0n), new Fr(0n)); const contractAddress = AztecAddress.random(); const abi = ZkTokenContractAbi.functions.find(f => f.name === 'mint') as unknown as FunctionAbi; @@ -158,7 +158,7 @@ describe('ACIR simulator', () => { // TODO for this we need that noir siloes the commitment the same way as the kernel does, to do merkle membership await tree.appendLeaves(preimages.map(preimage => acirSimulator.computeNoteHash(preimage, bbWasm))); - const historicRoots = new HistoricTreeRoots( + const historicRoots = new PrivateHistoricTreeRoots( Fr.fromBuffer(tree.getRoot(false)), new Fr(0n), new Fr(0n), @@ -229,7 +229,7 @@ describe('ACIR simulator', () => { // TODO for this we need that noir siloes the commitment the same way as the kernel does, to do merkle membership await tree.appendLeaves(preimages.map(preimage => acirSimulator.computeNoteHash(preimage, bbWasm))); - const historicRoots = new HistoricTreeRoots( + const historicRoots = new PrivateHistoricTreeRoots( Fr.fromBuffer(tree.getRoot(false)), new Fr(0n), new Fr(0n), @@ -273,7 +273,7 @@ describe('ACIR simulator', () => { }); describe('nested calls', () => { - const historicRoots = new HistoricTreeRoots(new Fr(0n), new Fr(0n), new Fr(0n), new Fr(0n)); + const historicRoots = new PrivateHistoricTreeRoots(new Fr(0n), new Fr(0n), new Fr(0n), new Fr(0n)); const contractDeploymentData = new ContractDeploymentData(Fr.random(), Fr.random(), Fr.random(), EthAddress.ZERO); const txContext = new TxContext(false, false, true, contractDeploymentData); diff --git a/yarn-project/acir-simulator/src/public/state_actions.ts b/yarn-project/acir-simulator/src/public/state_actions.ts index 33688fad9871..e6289d0bceb5 100644 --- a/yarn-project/acir-simulator/src/public/state_actions.ts +++ b/yarn-project/acir-simulator/src/public/state_actions.ts @@ -65,15 +65,19 @@ export class StateActionsCollector { * @returns all state read and transitions */ public collect(): [StateRead[], StateTransition[]] { - const reads = Array.from(this.stateReads.entries()).map(([slot, value]) => ({ - storageSlot: new Fr(slot), - ...value, - })); + const reads = Array.from(this.stateReads.entries()).map(([slot, value]) => + StateRead.from({ + storageSlot: new Fr(slot), + ...value, + }), + ); - const transitions = Array.from(this.stateTransitions.entries()).map(([slot, values]) => ({ - storageSlot: new Fr(slot), - ...values, - })); + const transitions = Array.from(this.stateTransitions.entries()).map(([slot, values]) => + StateTransition.from({ + storageSlot: new Fr(slot), + ...values, + }), + ); return [reads, transitions]; } diff --git a/yarn-project/acir-simulator/src/simulator.ts b/yarn-project/acir-simulator/src/simulator.ts index 79ac7851b3fd..db52bc2b95cc 100644 --- a/yarn-project/acir-simulator/src/simulator.ts +++ b/yarn-project/acir-simulator/src/simulator.ts @@ -1,5 +1,5 @@ import { AztecAddress, EthAddress, Fr } from '@aztec/foundation'; -import { CallContext, HistoricTreeRoots, TxRequest } from '@aztec/circuits.js'; +import { CallContext, PrivateHistoricTreeRoots, TxRequest } from '@aztec/circuits.js'; import { FunctionAbi } from '@aztec/noir-contracts'; import { DBOracle } from './db_oracle.js'; import { Execution, ExecutionResult } from './execution.js'; @@ -20,7 +20,7 @@ export class AcirSimulator { entryPointABI: FunctionAbi, contractAddress: AztecAddress, portalContractAddress: EthAddress, - historicRoots: HistoricTreeRoots, + historicRoots: PrivateHistoricTreeRoots, ): Promise { const callContext = new CallContext( request.from, diff --git a/yarn-project/aztec-rpc/src/account_state/account_state.ts b/yarn-project/aztec-rpc/src/account_state/account_state.ts index f944d0ed8b7b..5932c05d173c 100644 --- a/yarn-project/aztec-rpc/src/account_state/account_state.ts +++ b/yarn-project/aztec-rpc/src/account_state/account_state.ts @@ -1,7 +1,7 @@ import { AcirSimulator } from '@aztec/acir-simulator'; import { AztecNode } from '@aztec/aztec-node'; import { Grumpkin } from '@aztec/barretenberg.js/crypto'; -import { EcdsaSignature, KERNEL_NEW_COMMITMENTS_LENGTH, HistoricTreeRoots, TxRequest } from '@aztec/circuits.js'; +import { EcdsaSignature, KERNEL_NEW_COMMITMENTS_LENGTH, PrivateHistoricTreeRoots, TxRequest } from '@aztec/circuits.js'; import { AztecAddress, Fr, Point, createDebugLogger } from '@aztec/foundation'; import { KernelProver, OutputNoteData } from '@aztec/kernel-prover'; import { INITIAL_L2_BLOCK_NUM } from '@aztec/l1-contracts'; @@ -69,7 +69,7 @@ export class AccountState { txRequest.functionData.functionSelector, ); const portalContract = await contractDataOracle.getPortalContractAddress(contractAddress); - const historicRoots = new HistoricTreeRoots(Fr.ZERO, Fr.ZERO, Fr.ZERO, Fr.ZERO); // TODO - get old roots from the database/node + const historicRoots = new PrivateHistoricTreeRoots(Fr.ZERO, Fr.ZERO, Fr.ZERO, Fr.ZERO); // TODO - get old roots from the database/node const simulatorOracle = new SimulatorOracle(contractDataOracle, this.db, this.keyPair, this.node); const simulator = new AcirSimulator(simulatorOracle); diff --git a/yarn-project/aztec-rpc/src/contract_tree/contract_tree.ts b/yarn-project/aztec-rpc/src/contract_tree/contract_tree.ts index c09bed156cc6..cde2b9ebeb02 100644 --- a/yarn-project/aztec-rpc/src/contract_tree/contract_tree.ts +++ b/yarn-project/aztec-rpc/src/contract_tree/contract_tree.ts @@ -166,7 +166,7 @@ export class ContractTree { const targetFunctions = this.contract.functions.filter(isConstrained); const functionIndex = targetFunctions.findIndex(f => f.selector.equals(functionSelector)); if (functionIndex < 0) { - return MembershipWitness.makeEmpty(FUNCTION_TREE_HEIGHT, 0); + return MembershipWitness.empty(FUNCTION_TREE_HEIGHT, 0); } if (!this.functionTree) { diff --git a/yarn-project/circuits.js/src/kernel/kernel.ts b/yarn-project/circuits.js/src/kernel/kernel.ts index 72d1de317637..e8225f69991c 100644 --- a/yarn-project/circuits.js/src/kernel/kernel.ts +++ b/yarn-project/circuits.js/src/kernel/kernel.ts @@ -5,7 +5,7 @@ import { FUNCTION_TREE_HEIGHT, PreviousKernelData, PrivateCallData, - PrivateKernelPublicInputs, + KernelCircuitPublicInputs, SignedTxRequest, } from '../index.js'; import { boolToBuffer, serializeToBuffer, uint8ArrayToNum } from '../utils/serialize.js'; @@ -117,5 +117,5 @@ export async function privateKernelSim( const publicInputBuffer = Buffer.from(wasm.getMemorySlice(address, address + outputSize)); wasm.call('bbfree', publicInputOutputAddressPtr); wasm.call('bbfree', address); - return PrivateKernelPublicInputs.fromBuffer(publicInputBuffer); + return KernelCircuitPublicInputs.fromBuffer(publicInputBuffer); } diff --git a/yarn-project/circuits.js/src/structs/__snapshots__/tx.test.ts.snap b/yarn-project/circuits.js/src/structs/__snapshots__/tx_context.test.ts.snap similarity index 100% rename from yarn-project/circuits.js/src/structs/__snapshots__/tx.test.ts.snap rename to yarn-project/circuits.js/src/structs/__snapshots__/tx_context.test.ts.snap diff --git a/yarn-project/circuits.js/src/structs/aggregation_object.ts b/yarn-project/circuits.js/src/structs/aggregation_object.ts new file mode 100644 index 000000000000..7b24f17c0a95 --- /dev/null +++ b/yarn-project/circuits.js/src/structs/aggregation_object.ts @@ -0,0 +1,46 @@ +import { BufferReader } from '@aztec/foundation'; +import { Fq, Fr } from '@aztec/foundation/fields'; +import { serializeToBuffer } from '../utils/serialize.js'; +import times from 'lodash.times'; +import { Vector, UInt32, AffineElement } from './shared.js'; + +export class AggregationObject { + public publicInputs: Vector; + public proofWitnessIndices: Vector; + + constructor( + public p0: AffineElement, + public p1: AffineElement, + publicInputsData: Fr[], + proofWitnessIndicesData: UInt32[], + public hasData = false, + ) { + this.publicInputs = new Vector(publicInputsData); + this.proofWitnessIndices = new Vector(proofWitnessIndicesData); + } + + toBuffer() { + return serializeToBuffer(this.p0, this.p1, this.publicInputs, this.proofWitnessIndices, this.hasData); + } + + static fromBuffer(buffer: Buffer | BufferReader): AggregationObject { + const reader = BufferReader.asReader(buffer); + return new AggregationObject( + reader.readObject(AffineElement), + reader.readObject(AffineElement), + reader.readVector(Fr), + reader.readNumberVector(), + reader.readBoolean(), + ); + } + + static makeFake() { + return new AggregationObject( + new AffineElement(new Fq(1n), new Fq(2n)), + new AffineElement(new Fq(1n), new Fq(2n)), + [], + times(16, i => 3027 + i), + false, + ); + } +} diff --git a/yarn-project/circuits.js/src/structs/private_call_stack_item.ts b/yarn-project/circuits.js/src/structs/call_stack_item.ts similarity index 55% rename from yarn-project/circuits.js/src/structs/private_call_stack_item.ts rename to yarn-project/circuits.js/src/structs/call_stack_item.ts index 56f5b06f5fe2..252e834b1ede 100644 --- a/yarn-project/circuits.js/src/structs/private_call_stack_item.ts +++ b/yarn-project/circuits.js/src/structs/call_stack_item.ts @@ -2,6 +2,7 @@ import { AztecAddress } from '@aztec/foundation'; import { serializeToBuffer } from '../utils/serialize.js'; import { FunctionData } from './function_data.js'; import { PrivateCircuitPublicInputs } from './private_circuit_public_inputs.js'; +import { PublicCircuitPublicInputs } from './public_circuit_public_inputs.js'; /** * Call stack item on a private call. @@ -22,3 +23,23 @@ export class PrivateCallStackItem { return new PrivateCallStackItem(AztecAddress.ZERO, FunctionData.empty(), PrivateCircuitPublicInputs.empty()); } } + +/** + * Call stack item on a public call. + * @see cpp/src/aztec3/circuits/abis/call_stack_item.hpp. + */ +export class PublicCallStackItem { + constructor( + public contractAddress: AztecAddress, + public functionData: FunctionData, + public publicInputs: PublicCircuitPublicInputs, + ) {} + + toBuffer() { + return serializeToBuffer(this.contractAddress, this.functionData, this.publicInputs); + } + + public static empty() { + return new PublicCallStackItem(AztecAddress.ZERO, FunctionData.empty(), PublicCircuitPublicInputs.empty()); + } +} diff --git a/yarn-project/circuits.js/src/structs/index.ts b/yarn-project/circuits.js/src/structs/index.ts index e7dafe19a36f..58dbceea16fb 100644 --- a/yarn-project/circuits.js/src/structs/index.ts +++ b/yarn-project/circuits.js/src/structs/index.ts @@ -1,17 +1,27 @@ -export * from './base_rollup.js'; +export * from './rollup/base_rollup.js'; +export * from './rollup/merge_rollup.js'; +export * from './rollup/root_rollup.js'; +export * from './rollup/append_only_tree_snapshot.js'; +export * from './rollup/base_or_merge_rollup_public_inputs.js'; +export * from './rollup/previous_rollup_data.js'; export * from './call_context.js'; export * from './constants.js'; export * from './function_data.js'; -export * from './private_kernel.js'; -export * from './public_kernel.js'; -export * from './merge_rollup.js'; +export * from './kernel/private_kernel.js'; +export * from './kernel/public_kernel.js'; +export * from './kernel/combined_accumulated_data.js'; +export * from './kernel/combined_constant_data.js'; +export * from './kernel/previous_kernel_data.js'; +export * from './kernel/public_inputs.js'; export * from './private_circuit_public_inputs.js'; export * from './public_circuit_public_inputs.js'; -export * from './private_call_stack_item.js'; -export * from './root_rollup.js'; +export * from './call_stack_item.js'; export * from './shared.js'; -export * from './tx.js'; +export * from './tx_request.js'; +export * from './tx_context.js'; export * from './verification_key.js'; -export * from './private_call_stack_item.js'; +export * from './call_stack_item.js'; export * from './function_leaf_preimage.js'; +export * from './aggregation_object.js'; +export * from './membership_witness.js'; export { Fr, Fq, AztecAddress, EthAddress } from '@aztec/foundation'; diff --git a/yarn-project/circuits.js/src/structs/__snapshots__/private_kernel.test.ts.snap b/yarn-project/circuits.js/src/structs/kernel/__snapshots__/private_kernel.test.ts.snap similarity index 89% rename from yarn-project/circuits.js/src/structs/__snapshots__/private_kernel.test.ts.snap rename to yarn-project/circuits.js/src/structs/kernel/__snapshots__/private_kernel.test.ts.snap index 5a88b65611af..3e4857fad659 100644 --- a/yarn-project/circuits.js/src/structs/__snapshots__/private_kernel.test.ts.snap +++ b/yarn-project/circuits.js/src/structs/kernel/__snapshots__/private_kernel.test.ts.snap @@ -15,6 +15,7 @@ proof_witness_indices: [ 7 8 9 10 11 12 ] has_data: 0 private_call_count: 0xd +public_call_count: 0xe new_commitments: [ 0x101 0x102 0x103 0x104 ] new_nullifiers: @@ -88,13 +89,39 @@ pay_fee_from_public_l2: 0 called_from_l1: 1 called_from_public_l2: 0 ] +state_transitions: +[ storage_slot: 0x801 +old_value: 0x802 +new_value: 0x803 + storage_slot: 0x802 +old_value: 0x803 +new_value: 0x804 + storage_slot: 0x803 +old_value: 0x804 +new_value: 0x805 + storage_slot: 0x804 +old_value: 0x805 +new_value: 0x806 + ] +state_reads: +[ storage_slot: 0x901 +current_value: 0x902 + storage_slot: 0x902 +current_value: 0x903 + storage_slot: 0x903 +current_value: 0x904 + storage_slot: 0x904 +current_value: 0x905 + ] constants: -historic_tree_roots: private_data_tree_root: 0x101 +historic_tree_roots: private_historic_tree_roots: private_data_tree_root: 0x101 nullifier_tree_root: 0x102 contract_tree_root: 0x103 private_kernel_vk_tree_root: 0x104 +public_data_tree_root: 0x105 + tx_context: is_fee_payment_tx: 0 is_rebate_payment_tx: 0 is_contract_deployment_tx: 1 @@ -162,6 +189,7 @@ proof_witness_indices: [ 4103 4104 4105 4106 4107 4108 ] has_data: 0 private_call_count: 0x100d +public_call_count: 0x100e new_commitments: [ 0x1101 0x1102 0x1103 0x1104 ] new_nullifiers: @@ -235,13 +263,39 @@ pay_fee_from_public_l2: 0 called_from_l1: 1 called_from_public_l2: 0 ] +state_transitions: +[ storage_slot: 0x1801 +old_value: 0x1802 +new_value: 0x1803 + storage_slot: 0x1802 +old_value: 0x1803 +new_value: 0x1804 + storage_slot: 0x1803 +old_value: 0x1804 +new_value: 0x1805 + storage_slot: 0x1804 +old_value: 0x1805 +new_value: 0x1806 + ] +state_reads: +[ storage_slot: 0x1901 +current_value: 0x1902 + storage_slot: 0x1902 +current_value: 0x1903 + storage_slot: 0x1903 +current_value: 0x1904 + storage_slot: 0x1904 +current_value: 0x1905 + ] constants: -historic_tree_roots: private_data_tree_root: 0x1101 +historic_tree_roots: private_historic_tree_roots: private_data_tree_root: 0x1101 nullifier_tree_root: 0x1102 contract_tree_root: 0x1103 private_kernel_vk_tree_root: 0x1104 +public_data_tree_root: 0x1105 + tx_context: is_fee_payment_tx: 0 is_rebate_payment_tx: 0 is_contract_deployment_tx: 1 @@ -479,6 +533,7 @@ proof_witness_indices: [ 7 8 9 10 11 12 ] has_data: 0 private_call_count: 0xd +public_call_count: 0xe new_commitments: [ 0x101 0x102 0x103 0x104 ] new_nullifiers: @@ -552,13 +607,39 @@ pay_fee_from_public_l2: 0 called_from_l1: 1 called_from_public_l2: 0 ] +state_transitions: +[ storage_slot: 0x801 +old_value: 0x802 +new_value: 0x803 + storage_slot: 0x802 +old_value: 0x803 +new_value: 0x804 + storage_slot: 0x803 +old_value: 0x804 +new_value: 0x805 + storage_slot: 0x804 +old_value: 0x805 +new_value: 0x806 + ] +state_reads: +[ storage_slot: 0x901 +current_value: 0x902 + storage_slot: 0x902 +current_value: 0x903 + storage_slot: 0x903 +current_value: 0x904 + storage_slot: 0x904 +current_value: 0x905 + ] constants: -historic_tree_roots: private_data_tree_root: 0x101 +historic_tree_roots: private_historic_tree_roots: private_data_tree_root: 0x101 nullifier_tree_root: 0x102 contract_tree_root: 0x103 private_kernel_vk_tree_root: 0x104 +public_data_tree_root: 0x105 + tx_context: is_fee_payment_tx: 0 is_rebate_payment_tx: 0 is_contract_deployment_tx: 1 diff --git a/yarn-project/circuits.js/src/structs/kernel/combined_accumulated_data.ts b/yarn-project/circuits.js/src/structs/kernel/combined_accumulated_data.ts new file mode 100644 index 000000000000..946c1d771c23 --- /dev/null +++ b/yarn-project/circuits.js/src/structs/kernel/combined_accumulated_data.ts @@ -0,0 +1,198 @@ +import { AztecAddress, BufferReader, EthAddress, Fr } from '@aztec/foundation'; +import times from 'lodash.times'; +import { StateRead, StateTransition } from '../../index.js'; +import { assertLength } from '../../utils/jsUtils.js'; +import { serializeToBuffer } from '../../utils/serialize.js'; +import { AggregationObject } from '../aggregation_object.js'; +import { + EMITTED_EVENTS_LENGTH, + KERNEL_L1_MSG_STACK_LENGTH, + KERNEL_NEW_COMMITMENTS_LENGTH, + KERNEL_NEW_CONTRACTS_LENGTH, + KERNEL_NEW_NULLIFIERS_LENGTH, + KERNEL_OPTIONALLY_REVEALED_DATA_LENGTH, + KERNEL_PRIVATE_CALL_STACK_LENGTH, + KERNEL_PUBLIC_CALL_STACK_LENGTH, + STATE_READS_LENGTH, + STATE_TRANSITIONS_LENGTH, +} from '../constants.js'; +import { FunctionData } from '../function_data.js'; + +// Not to be confused with ContractDeploymentData (maybe think of better names) + +export class NewContractData { + constructor( + public contractAddress: AztecAddress, + public portalContractAddress: EthAddress, + public functionTreeRoot: Fr, + ) {} + + toBuffer() { + return serializeToBuffer(this.contractAddress, this.portalContractAddress, this.functionTreeRoot); + } + + /** + * Deserializes from a buffer or reader, corresponding to a write in cpp. + * @param buffer - Buffer to read from. + */ + static fromBuffer(buffer: Buffer | BufferReader): NewContractData { + const reader = BufferReader.asReader(buffer); + return new NewContractData(reader.readObject(AztecAddress), new EthAddress(reader.readBytes(32)), reader.readFr()); + } + + static empty() { + return new NewContractData(AztecAddress.ZERO, EthAddress.ZERO, Fr.ZERO); + } +} + +export class OptionallyRevealedData { + constructor( + public callStackItemHash: Fr, + public functionData: FunctionData, + public emittedEvents: Fr[], + public vkHash: Fr, + public portalContractAddress: EthAddress, + public payFeeFromL1: boolean, + public payFeeFromPublicL2: boolean, + public calledFromL1: boolean, + public calledFromPublicL2: boolean, + ) { + assertLength(this, 'emittedEvents', EMITTED_EVENTS_LENGTH); + } + + toBuffer() { + return serializeToBuffer( + this.callStackItemHash, + this.functionData, + this.emittedEvents, + this.vkHash, + this.portalContractAddress, + this.payFeeFromL1, + this.payFeeFromPublicL2, + this.calledFromL1, + this.calledFromPublicL2, + ); + } + + /** + * Deserializes from a buffer or reader, corresponding to a write in cpp. + * @param buffer - Buffer to read from. + */ + static fromBuffer(buffer: Buffer | BufferReader): OptionallyRevealedData { + const reader = BufferReader.asReader(buffer); + return new OptionallyRevealedData( + reader.readFr(), + reader.readObject(FunctionData), + reader.readArray(EMITTED_EVENTS_LENGTH, Fr), + reader.readFr(), + new EthAddress(reader.readBytes(32)), + reader.readBoolean(), + reader.readBoolean(), + reader.readBoolean(), + reader.readBoolean(), + ); + } + + static empty() { + return new OptionallyRevealedData( + Fr.ZERO, + FunctionData.empty(), + times(EMITTED_EVENTS_LENGTH, Fr.zero), + Fr.ZERO, + EthAddress.ZERO, + false, + false, + false, + false, + ); + } +} + +export class CombinedAccumulatedData { + constructor( + public aggregationObject: AggregationObject, + + public privateCallCount: Fr, + public publicCallCount: Fr, + + public newCommitments: Fr[], + public newNullifiers: Fr[], + + public privateCallStack: Fr[], + public publicCallStack: Fr[], + public l1MsgStack: Fr[], + + public newContracts: NewContractData[], + + public optionallyRevealedData: OptionallyRevealedData[], + + public stateTransitions: StateTransition[], + public stateReads: StateRead[], + ) { + assertLength(this, 'newCommitments', KERNEL_NEW_COMMITMENTS_LENGTH); + assertLength(this, 'newNullifiers', KERNEL_NEW_NULLIFIERS_LENGTH); + assertLength(this, 'privateCallStack', KERNEL_PRIVATE_CALL_STACK_LENGTH); + assertLength(this, 'publicCallStack', KERNEL_PUBLIC_CALL_STACK_LENGTH); + assertLength(this, 'l1MsgStack', KERNEL_L1_MSG_STACK_LENGTH); + assertLength(this, 'newContracts', KERNEL_NEW_CONTRACTS_LENGTH); + assertLength(this, 'optionallyRevealedData', KERNEL_OPTIONALLY_REVEALED_DATA_LENGTH); + assertLength(this, 'stateTransitions', STATE_TRANSITIONS_LENGTH); + assertLength(this, 'stateReads', STATE_READS_LENGTH); + } + + toBuffer() { + return serializeToBuffer( + this.aggregationObject, + this.privateCallCount, + this.publicCallCount, + this.newCommitments, + this.newNullifiers, + this.privateCallStack, + this.publicCallStack, + this.l1MsgStack, + this.newContracts, + this.optionallyRevealedData, + this.stateTransitions, + this.stateReads, + ); + } + + /** + * Deserializes from a buffer or reader, corresponding to a write in cpp. + * @param buffer - Buffer to read from. + */ + static fromBuffer(buffer: Buffer | BufferReader): CombinedAccumulatedData { + const reader = BufferReader.asReader(buffer); + return new CombinedAccumulatedData( + reader.readObject(AggregationObject), + reader.readFr(), + reader.readFr(), + reader.readArray(KERNEL_NEW_COMMITMENTS_LENGTH, Fr), + reader.readArray(KERNEL_NEW_NULLIFIERS_LENGTH, Fr), + reader.readArray(KERNEL_PRIVATE_CALL_STACK_LENGTH, Fr), + reader.readArray(KERNEL_PUBLIC_CALL_STACK_LENGTH, Fr), + reader.readArray(KERNEL_L1_MSG_STACK_LENGTH, Fr), + reader.readArray(KERNEL_NEW_CONTRACTS_LENGTH, NewContractData), + reader.readArray(KERNEL_OPTIONALLY_REVEALED_DATA_LENGTH, OptionallyRevealedData), + reader.readArray(STATE_TRANSITIONS_LENGTH, StateTransition), + reader.readArray(STATE_READS_LENGTH, StateRead), + ); + } + + static empty() { + return new CombinedAccumulatedData( + AggregationObject.makeFake(), + Fr.ZERO, + Fr.ZERO, + times(KERNEL_NEW_COMMITMENTS_LENGTH, Fr.zero), + times(KERNEL_NEW_NULLIFIERS_LENGTH, Fr.zero), + times(KERNEL_PRIVATE_CALL_STACK_LENGTH, Fr.zero), + times(KERNEL_PUBLIC_CALL_STACK_LENGTH, Fr.zero), + times(KERNEL_L1_MSG_STACK_LENGTH, Fr.zero), + times(KERNEL_NEW_CONTRACTS_LENGTH, NewContractData.empty), + times(KERNEL_OPTIONALLY_REVEALED_DATA_LENGTH, OptionallyRevealedData.empty), + times(STATE_TRANSITIONS_LENGTH, StateTransition.empty), + times(STATE_READS_LENGTH, StateRead.empty), + ); + } +} diff --git a/yarn-project/circuits.js/src/structs/kernel/combined_constant_data.ts b/yarn-project/circuits.js/src/structs/kernel/combined_constant_data.ts new file mode 100644 index 000000000000..a1b0e5b1116c --- /dev/null +++ b/yarn-project/circuits.js/src/structs/kernel/combined_constant_data.ts @@ -0,0 +1,75 @@ +import { BufferReader, Fr } from '@aztec/foundation'; +import { serializeToBuffer } from '../../utils/serialize.js'; +import { TxContext } from '../tx_context.js'; + +export class PrivateHistoricTreeRoots { + constructor( + public privateDataTreeRoot: Fr, + public nullifierTreeRoot: Fr, + public contractTreeRoot: Fr, + public privateKernelVkTreeRoot: Fr, // future enhancement + ) {} + + toBuffer() { + return serializeToBuffer( + this.privateDataTreeRoot, + this.nullifierTreeRoot, + this.contractTreeRoot, + this.privateKernelVkTreeRoot, + ); + } + + /** + * Deserializes from a buffer or reader, corresponding to a write in cpp. + * @param buffer - Buffer to read from. + */ + static fromBuffer(buffer: Buffer | BufferReader): PrivateHistoricTreeRoots { + const reader = BufferReader.asReader(buffer); + return new PrivateHistoricTreeRoots(reader.readFr(), reader.readFr(), reader.readFr(), reader.readFr()); + } + + static empty() { + return new PrivateHistoricTreeRoots(Fr.ZERO, Fr.ZERO, Fr.ZERO, Fr.ZERO); + } +} + +export class CombinedHistoricTreeRoots { + constructor( + public readonly privateHistoricTreeRoots: PrivateHistoricTreeRoots, + public readonly publicDataTreeRoot: Fr, + ) {} + + toBuffer() { + return serializeToBuffer(this.privateHistoricTreeRoots, this.publicDataTreeRoot); + } + + static fromBuffer(buffer: Buffer | BufferReader) { + const reader = BufferReader.asReader(buffer); + return new CombinedHistoricTreeRoots(reader.readObject(PrivateHistoricTreeRoots), reader.readFr()); + } + + static empty() { + return new CombinedHistoricTreeRoots(PrivateHistoricTreeRoots.empty(), Fr.ZERO); + } +} + +export class CombinedConstantData { + constructor(public historicTreeRoots: CombinedHistoricTreeRoots, public txContext: TxContext) {} + + toBuffer() { + return serializeToBuffer(this.historicTreeRoots, this.txContext); + } + + /** + * Deserializes from a buffer or reader, corresponding to a write in cpp. + * @param buffer - Buffer to read from. + */ + static fromBuffer(buffer: Buffer | BufferReader): CombinedConstantData { + const reader = BufferReader.asReader(buffer); + return new CombinedConstantData(reader.readObject(CombinedHistoricTreeRoots), reader.readObject(TxContext)); + } + + static empty() { + return new CombinedConstantData(CombinedHistoricTreeRoots.empty(), TxContext.empty()); + } +} diff --git a/yarn-project/circuits.js/src/structs/kernel/previous_kernel_data.ts b/yarn-project/circuits.js/src/structs/kernel/previous_kernel_data.ts new file mode 100644 index 000000000000..0f55e4427986 --- /dev/null +++ b/yarn-project/circuits.js/src/structs/kernel/previous_kernel_data.ts @@ -0,0 +1,77 @@ +import { BufferReader, Fr } from '@aztec/foundation'; +import times from 'lodash.times'; +import { CircuitsWasm, getDummyPreviousKernelData } from '../../index.js'; +import { assertLength } from '../../utils/jsUtils.js'; +import { serializeToBuffer } from '../../utils/serialize.js'; +import { VK_TREE_HEIGHT } from '../constants.js'; +import { UInt32, UInt8Vector } from '../shared.js'; +import { VerificationKey } from '../verification_key.js'; +import { KernelCircuitPublicInputs } from './public_inputs.js'; +import { makeEmptyProof } from './private_kernel.js'; + +export class PreviousKernelData { + constructor( + public publicInputs: KernelCircuitPublicInputs, + public proof: UInt8Vector, + public vk: VerificationKey, + public vkIndex: UInt32, + public vkSiblingPath: Fr[], + ) { + assertLength(this, 'vkSiblingPath', VK_TREE_HEIGHT); + } + + /** + * Serialize this as a buffer. + * @returns The buffer. + */ + toBuffer() { + return serializeToBuffer(this.publicInputs, this.proof, this.vk, this.vkIndex, this.vkSiblingPath); + } + + /** + * Deserializes from a buffer or reader, corresponding to a write in cpp. + * @param buffer - Buffer to read from. + */ + static fromBuffer(buffer: Buffer | BufferReader): PreviousKernelData { + const reader = BufferReader.asReader(buffer); + return new PreviousKernelData( + reader.readObject(KernelCircuitPublicInputs), + reader.readObject(UInt8Vector), + reader.readObject(VerificationKey), + reader.readNumber(), + reader.readArray(VK_TREE_HEIGHT, Fr), + ); + } + + /** + * Creates an empty instance, valid enough to be accepted by circuits + */ + static empty() { + return new PreviousKernelData( + KernelCircuitPublicInputs.empty(), + makeEmptyProof(), + VerificationKey.makeFake(), + 0, + times(VK_TREE_HEIGHT, Fr.zero), + ); + } +} + +export class DummyPreviousKernelData { + private static instance: DummyPreviousKernelData; + + private constructor(private data: PreviousKernelData) {} + + public static async getDummyPreviousKernelData(wasm: CircuitsWasm) { + if (!DummyPreviousKernelData.instance) { + const data = await getDummyPreviousKernelData(wasm); + DummyPreviousKernelData.instance = new DummyPreviousKernelData(data); + } + + return DummyPreviousKernelData.instance.getData(); + } + + public getData() { + return this.data; + } +} diff --git a/yarn-project/circuits.js/src/structs/private_kernel.test.ts b/yarn-project/circuits.js/src/structs/kernel/private_kernel.test.ts similarity index 70% rename from yarn-project/circuits.js/src/structs/private_kernel.test.ts rename to yarn-project/circuits.js/src/structs/kernel/private_kernel.test.ts index d1082873a8da..1fe00e29fe80 100644 --- a/yarn-project/circuits.js/src/structs/private_kernel.test.ts +++ b/yarn-project/circuits.js/src/structs/kernel/private_kernel.test.ts @@ -1,5 +1,5 @@ -import { expectSerializeToMatchSnapshot } from '../tests/expectSerialize.js'; -import { makePreviousKernelData, makePrivateKernelInputs, makePrivateKernelPublicInputs } from '../tests/factories.js'; +import { expectSerializeToMatchSnapshot } from '../../tests/expectSerialize.js'; +import { makePreviousKernelData, makePrivateKernelInputs, makeKernelPublicInputs } from '../../tests/factories.js'; describe('structs/kernel', () => { it(`serializes and prints previous_kernel_data`, async () => { @@ -19,10 +19,10 @@ describe('structs/kernel', () => { }); it(`serializes and prints private_kernel_public_inputs`, async () => { - const kernelInputs = makePrivateKernelPublicInputs(); + const kernelInputs = makeKernelPublicInputs(); await expectSerializeToMatchSnapshot( kernelInputs.toBuffer(), - 'abis__test_roundtrip_serialize_private_kernel_public_inputs', + 'abis__test_roundtrip_serialize_kernel_circuit_public_inputs', ); }); }); diff --git a/yarn-project/circuits.js/src/structs/kernel/private_kernel.ts b/yarn-project/circuits.js/src/structs/kernel/private_kernel.ts new file mode 100644 index 000000000000..b4f7ed6fded7 --- /dev/null +++ b/yarn-project/circuits.js/src/structs/kernel/private_kernel.ts @@ -0,0 +1,83 @@ +import { EthAddress, Fr } from '@aztec/foundation'; +import { FieldsOf, assertLength } from '../../utils/jsUtils.js'; +import { serializeToBuffer } from '../../utils/serialize.js'; +import { PrivateCallStackItem } from '../call_stack_item.js'; +import { CONTRACT_TREE_HEIGHT, FUNCTION_TREE_HEIGHT, PRIVATE_CALL_STACK_LENGTH } from '../constants.js'; +import { MembershipWitness } from '../membership_witness.js'; +import { UInt8Vector } from '../shared.js'; +import { SignedTxRequest } from '../tx_request.js'; +import { VerificationKey } from '../verification_key.js'; +import { PreviousKernelData } from './previous_kernel_data.js'; + +/** + * Private call data. + * @see circuits/cpp/src/aztec3/circuits/abis/call_stack_item.hpp + */ +export class PrivateCallData { + constructor( + public callStackItem: PrivateCallStackItem, + public privateCallStackPreimages: PrivateCallStackItem[], + public proof: UInt8Vector, + public vk: VerificationKey, + public functionLeafMembershipWitness: MembershipWitness, + public contractLeafMembershipWitness: MembershipWitness, + public portalContractAddress: EthAddress, + public acirHash: Fr, + ) { + assertLength(this, 'privateCallStackPreimages', PRIVATE_CALL_STACK_LENGTH); + } + + /** + * Serialize into a field array. Low-level utility. + * @param fields - Object with fields. + * @returns The array. + */ + static getFields(fields: FieldsOf) { + return [ + // NOTE: Must have same order as CPP. + fields.callStackItem, + fields.privateCallStackPreimages, + fields.proof, + fields.vk, + fields.functionLeafMembershipWitness, + fields.contractLeafMembershipWitness, + fields.portalContractAddress, + fields.acirHash, + ] as const; + } + + static from(fields: FieldsOf): PrivateCallData { + return new PrivateCallData(...PrivateCallData.getFields(fields)); + } + + /** + * Serialize this as a buffer. + * @returns The buffer. + */ + toBuffer(): Buffer { + return serializeToBuffer(...PrivateCallData.getFields(this)); + } +} + +/** + * Input to the private kernel circuit. + */ +export class PrivateKernelInputs { + constructor( + public signedTxRequest: SignedTxRequest, + public previousKernel: PreviousKernelData, + public privateCall: PrivateCallData, + ) {} + + /** + * Serialize this as a buffer. + * @returns The buffer. + */ + toBuffer() { + return serializeToBuffer(this.signedTxRequest, this.previousKernel, this.privateCall); + } +} + +export function makeEmptyProof() { + return new UInt8Vector(Buffer.alloc(0)); +} diff --git a/yarn-project/circuits.js/src/structs/kernel/public_inputs.ts b/yarn-project/circuits.js/src/structs/kernel/public_inputs.ts new file mode 100644 index 000000000000..20f32f52e21c --- /dev/null +++ b/yarn-project/circuits.js/src/structs/kernel/public_inputs.ts @@ -0,0 +1,38 @@ +import { BufferReader } from '@aztec/foundation'; +import { serializeToBuffer } from '../../utils/serialize.js'; +import { CombinedAccumulatedData } from './combined_accumulated_data.js'; +import { CombinedConstantData } from './combined_constant_data.js'; + +/** + * Public inputs of the public and private kernel circuits. + * @see circuits/cpp/src/aztec3/circuits/abis/kernel_circuit_public_inputs.hpp + */ + +export class KernelCircuitPublicInputs { + constructor( + public end: CombinedAccumulatedData, + public constants: CombinedConstantData, + public isPrivateKernel: boolean, + ) {} + + toBuffer() { + return serializeToBuffer(this.end, this.constants, this.isPrivateKernel); + } + + /** + * Deserializes from a buffer or reader, corresponding to a write in cpp. + * @param buffer - Buffer to read from. + */ + static fromBuffer(buffer: Buffer | BufferReader): KernelCircuitPublicInputs { + const reader = BufferReader.asReader(buffer); + return new KernelCircuitPublicInputs( + reader.readObject(CombinedAccumulatedData), + reader.readObject(CombinedConstantData), + reader.readBoolean(), + ); + } + + static empty() { + return new KernelCircuitPublicInputs(CombinedAccumulatedData.empty(), CombinedConstantData.empty(), true); + } +} diff --git a/yarn-project/circuits.js/src/structs/public_kernel.ts b/yarn-project/circuits.js/src/structs/kernel/public_kernel.ts similarity index 70% rename from yarn-project/circuits.js/src/structs/public_kernel.ts rename to yarn-project/circuits.js/src/structs/kernel/public_kernel.ts index 900f0d0bbc75..3a6969519489 100644 --- a/yarn-project/circuits.js/src/structs/public_kernel.ts +++ b/yarn-project/circuits.js/src/structs/kernel/public_kernel.ts @@ -1,17 +1,19 @@ -import { AztecAddress, Fr } from '@aztec/foundation'; -import { PreviousKernelData as PreviousPrivateKernelData } from './private_kernel.js'; -import { MembershipWitness, UInt8Vector } from './shared.js'; -import { SignedTxRequest } from './tx.js'; -import { VerificationKey } from './verification_key.js'; +import { Fr } from '@aztec/foundation'; +import { assertLength } from '../../utils/jsUtils.js'; +import { PublicCallStackItem } from '../call_stack_item.js'; import { PUBLIC_CALL_STACK_LENGTH, PUBLIC_DATA_TREE_HEIGHT, STATE_READS_LENGTH, STATE_TRANSITIONS_LENGTH, -} from './constants.js'; -import { assertLength } from '../utils/jsUtils.js'; -import { FunctionData } from './function_data.js'; -import { PublicCircuitPublicInputs } from './public_circuit_public_inputs.js'; +} from '../constants.js'; +import { PreviousKernelData as PreviousPrivateKernelData } from './previous_kernel_data.js'; +import { CombinedConstantData } from './combined_constant_data.js'; +import { CombinedAccumulatedData } from './combined_accumulated_data.js'; +import { UInt8Vector } from '../shared.js'; +import { MembershipWitness } from '../membership_witness.js'; +import { SignedTxRequest } from '../tx_request.js'; +import { VerificationKey } from '../verification_key.js'; export type PublicKernelInputs = | PublicKernelInputsNonFirstIteration @@ -70,18 +72,6 @@ export class PublicCallData { } } -export class PublicCallStackItem { - constructor( - public readonly contractAddress: AztecAddress, - public readonly functionSignature: FunctionData, - public readonly publicInputs: PublicCircuitPublicInputs, - ) {} - - static empty() { - return new this(AztecAddress.ZERO, FunctionData.empty(), PublicCircuitPublicInputs.empty()); - } -} - export class PreviousPublicKernelData { constructor( public readonly publicInputs: PublicKernelPublicInputs, @@ -95,18 +85,6 @@ export class PublicKernelPublicInputs { constructor(public readonly end: CombinedAccumulatedData, public readonly constants: CombinedConstantData) {} static empty() { - return new this(CombinedAccumulatedData.empty(), CombinedConstantData.empty()); - } -} - -class CombinedAccumulatedData { - static empty() { - return new this(); - } -} - -class CombinedConstantData { - static empty() { - return new this(); + return new PublicKernelPublicInputs(CombinedAccumulatedData.empty(), CombinedConstantData.empty()); } } diff --git a/yarn-project/circuits.js/src/structs/membership_witness.ts b/yarn-project/circuits.js/src/structs/membership_witness.ts new file mode 100644 index 000000000000..43dc1dcda36b --- /dev/null +++ b/yarn-project/circuits.js/src/structs/membership_witness.ts @@ -0,0 +1,47 @@ +import { Fr } from '@aztec/foundation/fields'; +import { assertLength, range } from '../utils/jsUtils.js'; +import { serializeToBuffer } from '../utils/serialize.js'; +import { UInt32 } from './shared.js'; + +export class MembershipWitness { + constructor(pathSize: N, public leafIndex: UInt32, public siblingPath: Fr[]) { + assertLength(this, 'siblingPath', pathSize); + } + + toBuffer() { + return serializeToBuffer(this.leafIndex, ...this.siblingPath); + } + + static mock(size: number, start: number) { + return new MembershipWitness( + size, + start, + range(size, start).map(x => new Fr(BigInt(x))), + ); + } + + public static random(pathSize: N) { + return new MembershipWitness( + pathSize, + 0, + Array(pathSize) + .fill(0) + .map(() => Fr.random()), + ); + } + + public static empty(pathSize: N, leafIndex: UInt32) { + const arr = Array(pathSize) + .fill(0) + .map(() => Fr.ZERO); + return new MembershipWitness(pathSize, leafIndex, arr); + } + + static fromBufferArray(leafIndex: number, siblingPath: Buffer[]) { + return new MembershipWitness( + siblingPath.length, + leafIndex, + siblingPath.map(x => Fr.fromBuffer(x)), + ); + } +} diff --git a/yarn-project/circuits.js/src/structs/merge_rollup.ts b/yarn-project/circuits.js/src/structs/merge_rollup.ts deleted file mode 100644 index 01f1ec4b009e..000000000000 --- a/yarn-project/circuits.js/src/structs/merge_rollup.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { serializeToBuffer } from '../utils/serialize.js'; -import { BaseOrMergeRollupPublicInputs } from './base_rollup.js'; -import { ROLLUP_VK_TREE_HEIGHT } from './constants.js'; -import { MembershipWitness, UInt32, UInt8Vector } from './shared.js'; -import { VerificationKey } from './verification_key.js'; - -export class PreviousRollupData { - constructor( - public publicInputs: BaseOrMergeRollupPublicInputs, - public proof: UInt8Vector, - public vk: VerificationKey, - /** - * The index of the rollup circuit's vk in a big tree of rollup circuit vks. - */ - public vkIndex: UInt32, - public vkSiblingPath: MembershipWitness, - ) {} - - toBuffer() { - return serializeToBuffer(this.publicInputs, this.proof, this.vk, this.vkIndex, this.vkSiblingPath); - } -} - -export class MergeRollupInputs { - constructor(public previousRollupData: [PreviousRollupData, PreviousRollupData]) {} - - toBuffer() { - return serializeToBuffer(this.previousRollupData); - } -} diff --git a/yarn-project/circuits.js/src/structs/private_circuit_public_inputs.ts b/yarn-project/circuits.js/src/structs/private_circuit_public_inputs.ts index ff76fe67a1c7..a8acd64909fd 100644 --- a/yarn-project/circuits.js/src/structs/private_circuit_public_inputs.ts +++ b/yarn-project/circuits.js/src/structs/private_circuit_public_inputs.ts @@ -12,7 +12,7 @@ import { PUBLIC_CALL_STACK_LENGTH, RETURN_VALUES_LENGTH, } from './constants.js'; -import { ContractDeploymentData } from './tx.js'; +import { ContractDeploymentData } from './tx_context.js'; /** * Public inputs to a private circuit. diff --git a/yarn-project/circuits.js/src/structs/private_kernel.ts b/yarn-project/circuits.js/src/structs/private_kernel.ts deleted file mode 100644 index 8b44688abf84..000000000000 --- a/yarn-project/circuits.js/src/structs/private_kernel.ts +++ /dev/null @@ -1,416 +0,0 @@ -import { CircuitsWasm, getDummyPreviousKernelData } from '../index.js'; -import { assertLength, FieldsOf } from '../utils/jsUtils.js'; -import { serializeToBuffer } from '../utils/serialize.js'; -import { - CONTRACT_TREE_HEIGHT, - EMITTED_EVENTS_LENGTH, - FUNCTION_TREE_HEIGHT, - KERNEL_L1_MSG_STACK_LENGTH, - KERNEL_NEW_COMMITMENTS_LENGTH, - KERNEL_NEW_CONTRACTS_LENGTH, - KERNEL_NEW_NULLIFIERS_LENGTH, - KERNEL_OPTIONALLY_REVEALED_DATA_LENGTH, - KERNEL_PRIVATE_CALL_STACK_LENGTH, - KERNEL_PUBLIC_CALL_STACK_LENGTH, - PRIVATE_CALL_STACK_LENGTH, - VK_TREE_HEIGHT, -} from './constants.js'; -import { FunctionData } from './function_data.js'; -import { PrivateCallStackItem } from './private_call_stack_item.js'; -import { AggregationObject, MembershipWitness, UInt32, UInt8Vector } from './shared.js'; -import { ContractDeploymentData, SignedTxRequest, TxContext } from './tx.js'; -import { VerificationKey } from './verification_key.js'; -import { AztecAddress, EthAddress, Fr, BufferReader } from '@aztec/foundation'; -import times from 'lodash.times'; - -export class HistoricTreeRoots { - constructor( - public privateDataTreeRoot: Fr, - public nullifierTreeRoot: Fr, - public contractTreeRoot: Fr, - public privateKernelVkTreeRoot: Fr, // future enhancement - ) {} - - toBuffer() { - return serializeToBuffer( - this.privateDataTreeRoot, - this.nullifierTreeRoot, - this.contractTreeRoot, - this.privateKernelVkTreeRoot, - ); - } - - /** - * Deserializes from a buffer or reader, corresponding to a write in cpp. - * @param buffer - Buffer to read from. - */ - static fromBuffer(buffer: Buffer | BufferReader): HistoricTreeRoots { - const reader = BufferReader.asReader(buffer); - return new HistoricTreeRoots(reader.readFr(), reader.readFr(), reader.readFr(), reader.readFr()); - } -} - -export class ConstantData { - constructor(public historicTreeRoots: HistoricTreeRoots, public txContext: TxContext) {} - - toBuffer() { - return serializeToBuffer(this.historicTreeRoots, this.txContext); - } - - /** - * Deserializes from a buffer or reader, corresponding to a write in cpp. - * @param buffer - Buffer to read from. - */ - static fromBuffer(buffer: Buffer | BufferReader): ConstantData { - const reader = BufferReader.asReader(buffer); - return new ConstantData(reader.readObject(HistoricTreeRoots), reader.readObject(TxContext)); - } -} - -// Not to be confused with ContractDeploymentData (maybe think of better names) -export class NewContractData { - constructor( - public contractAddress: AztecAddress, - public portalContractAddress: EthAddress, - public functionTreeRoot: Fr, - ) {} - - toBuffer() { - return serializeToBuffer(this.contractAddress, this.portalContractAddress, this.functionTreeRoot); - } - - /** - * Deserializes from a buffer or reader, corresponding to a write in cpp. - * @param buffer - Buffer to read from. - */ - static fromBuffer(buffer: Buffer | BufferReader): NewContractData { - const reader = BufferReader.asReader(buffer); - return new NewContractData(reader.readObject(AztecAddress), new EthAddress(reader.readBytes(32)), reader.readFr()); - } -} - -export class OptionallyRevealedData { - constructor( - public callStackItemHash: Fr, - public functionData: FunctionData, - public emittedEvents: Fr[], - public vkHash: Fr, - public portalContractAddress: EthAddress, - public payFeeFromL1: boolean, - public payFeeFromPublicL2: boolean, - public calledFromL1: boolean, - public calledFromPublicL2: boolean, - ) { - assertLength(this, 'emittedEvents', EMITTED_EVENTS_LENGTH); - } - - toBuffer() { - return serializeToBuffer( - this.callStackItemHash, - this.functionData, - this.emittedEvents, - this.vkHash, - this.portalContractAddress, - this.payFeeFromL1, - this.payFeeFromPublicL2, - this.calledFromL1, - this.calledFromPublicL2, - ); - } - - /** - * Deserializes from a buffer or reader, corresponding to a write in cpp. - * @param buffer - Buffer to read from. - */ - static fromBuffer(buffer: Buffer | BufferReader): OptionallyRevealedData { - const reader = BufferReader.asReader(buffer); - return new OptionallyRevealedData( - reader.readFr(), - reader.readObject(FunctionData), - reader.readArray(EMITTED_EVENTS_LENGTH, Fr), - reader.readFr(), - new EthAddress(reader.readBytes(32)), - reader.readBoolean(), - reader.readBoolean(), - reader.readBoolean(), - reader.readBoolean(), - ); - } -} - -export class AccumulatedData { - constructor( - public aggregationObject: AggregationObject, // Contains the aggregated proof of all previous kernel iterations - - public privateCallCount: Fr, - - public newCommitments: Fr[], - public newNullifiers: Fr[], - - public privateCallStack: Fr[], - public publicCallStack: Fr[], - public l1MsgStack: Fr[], - - public newContracts: NewContractData[], - - public optionallyRevealedData: OptionallyRevealedData[], - ) { - assertLength(this, 'newCommitments', KERNEL_NEW_COMMITMENTS_LENGTH); - assertLength(this, 'newNullifiers', KERNEL_NEW_NULLIFIERS_LENGTH); - assertLength(this, 'privateCallStack', KERNEL_PRIVATE_CALL_STACK_LENGTH); - assertLength(this, 'publicCallStack', KERNEL_PUBLIC_CALL_STACK_LENGTH); - assertLength(this, 'l1MsgStack', KERNEL_L1_MSG_STACK_LENGTH); - assertLength(this, 'newContracts', KERNEL_NEW_CONTRACTS_LENGTH); - assertLength(this, 'optionallyRevealedData', KERNEL_OPTIONALLY_REVEALED_DATA_LENGTH); - } - - toBuffer() { - return serializeToBuffer( - this.aggregationObject, - this.privateCallCount, - this.newCommitments, - this.newNullifiers, - this.privateCallStack, - this.publicCallStack, - this.l1MsgStack, - this.newContracts, - this.optionallyRevealedData, - ); - } - - /** - * Deserializes from a buffer or reader, corresponding to a write in cpp. - * @param buffer - Buffer to read from. - */ - static fromBuffer(buffer: Buffer | BufferReader): AccumulatedData { - const reader = BufferReader.asReader(buffer); - return new AccumulatedData( - reader.readObject(AggregationObject), - reader.readFr(), - reader.readArray(KERNEL_NEW_COMMITMENTS_LENGTH, Fr), - reader.readArray(KERNEL_NEW_NULLIFIERS_LENGTH, Fr), - reader.readArray(KERNEL_PRIVATE_CALL_STACK_LENGTH, Fr), - reader.readArray(KERNEL_PUBLIC_CALL_STACK_LENGTH, Fr), - reader.readArray(KERNEL_L1_MSG_STACK_LENGTH, Fr), - reader.readArray(KERNEL_NEW_CONTRACTS_LENGTH, NewContractData), - reader.readArray(KERNEL_OPTIONALLY_REVEALED_DATA_LENGTH, OptionallyRevealedData), - ); - } -} - -export class PrivateKernelPublicInputs { - constructor(public end: AccumulatedData, public constants: ConstantData, public isPrivateKernel: true) {} - - toBuffer() { - return serializeToBuffer(this.end, this.constants, this.isPrivateKernel); - } - - /** - * Deserializes from a buffer or reader, corresponding to a write in cpp. - * @param buffer - Buffer to read from. - */ - static fromBuffer(buffer: Buffer | BufferReader): PrivateKernelPublicInputs { - const reader = BufferReader.asReader(buffer); - return new PrivateKernelPublicInputs(reader.readObject(AccumulatedData), reader.readObject(ConstantData), true); - } - - static makeEmpty() { - return new PrivateKernelPublicInputs(makeEmptyAccumulatedData(), makeEmptyConstantData(), true); - } -} - -export class PreviousKernelData { - constructor( - public publicInputs: PrivateKernelPublicInputs, - public proof: UInt8Vector, - public vk: VerificationKey, - public vkIndex: UInt32, // the index of the kernel circuit's vk in a big tree of kernel circuit vks - public vkSiblingPath: Fr[], - ) { - assertLength(this, 'vkSiblingPath', VK_TREE_HEIGHT); - } - - /** - * Serialize this as a buffer. - * @returns The buffer. - */ - toBuffer() { - return serializeToBuffer(this.publicInputs, this.proof, this.vk, this.vkIndex, this.vkSiblingPath); - } - - /** - * Deserializes from a buffer or reader, corresponding to a write in cpp. - * @param buffer - Buffer to read from. - */ - static fromBuffer(buffer: Buffer | BufferReader): PreviousKernelData { - const reader = BufferReader.asReader(buffer); - return new PreviousKernelData( - reader.readObject(PrivateKernelPublicInputs), - reader.readObject(UInt8Vector), - reader.readObject(VerificationKey), - reader.readNumber(), - reader.readArray(VK_TREE_HEIGHT, Fr), - ); - } - - /** - * Creates an empty instance, valid enough to be accepted by circuits - */ - static makeEmpty() { - return new PreviousKernelData( - PrivateKernelPublicInputs.makeEmpty(), - makeEmptyProof(), - VerificationKey.makeFake(), - 0, - Array(VK_TREE_HEIGHT).fill(frZero()), - ); - } -} - -export class DummyPreviousKernelData { - private static instance: DummyPreviousKernelData; - - private constructor(private data: PreviousKernelData) {} - - public static async getDummyPreviousKernelData(wasm: CircuitsWasm) { - if (!DummyPreviousKernelData.instance) { - const data = await getDummyPreviousKernelData(wasm); - DummyPreviousKernelData.instance = new DummyPreviousKernelData(data); - } - - return DummyPreviousKernelData.instance.getData(); - } - - public getData() { - return this.data; - } -} - -/** - * Private call data. - * @see cpp/src/aztec3/circuits/abis/call_stack_item.hpp. - */ -export class PrivateCallData { - constructor( - public callStackItem: PrivateCallStackItem, - public privateCallStackPreimages: PrivateCallStackItem[], - public proof: UInt8Vector, - public vk: VerificationKey, - public functionLeafMembershipWitness: MembershipWitness, - public contractLeafMembershipWitness: MembershipWitness, - public portalContractAddress: EthAddress, - public acirHash: Fr, - ) { - assertLength(this, 'privateCallStackPreimages', PRIVATE_CALL_STACK_LENGTH); - } - - /** - * Serialize into a field array. Low-level utility. - * @param fields - Object with fields. - * @returns The array. - */ - static getFields(fields: FieldsOf) { - return [ - // NOTE: Must have same order as CPP. - fields.callStackItem, - fields.privateCallStackPreimages, - fields.proof, - fields.vk, - fields.functionLeafMembershipWitness, - fields.contractLeafMembershipWitness, - fields.portalContractAddress, - fields.acirHash, - ] as const; - } - - static from(fields: FieldsOf): PrivateCallData { - return new PrivateCallData(...PrivateCallData.getFields(fields)); - } - - /** - * Serialize this as a buffer. - * @returns The buffer. - */ - toBuffer(): Buffer { - return serializeToBuffer(...PrivateCallData.getFields(this)); - } -} - -/** - * Input to the private kernel circuit. - */ -export class PrivateKernelInputs { - constructor( - public signedTxRequest: SignedTxRequest, - public previousKernel: PreviousKernelData, - public privateCall: PrivateCallData, - ) {} - - /** - * Serialize this as a buffer. - * @returns The buffer. - */ - toBuffer() { - return serializeToBuffer(this.signedTxRequest, this.previousKernel, this.privateCall); - } -} - -// Helper functions for making empty structs (delete them eventually to use real data or factories instances) -// or move them somewhere generic, or within each struct - -function frZero() { - return Fr.fromBuffer(Buffer.alloc(32, 0)); -} - -function makeEmptyEthAddress() { - return new EthAddress(Buffer.alloc(20, 0)); -} - -function makeEmptyNewContractData(): NewContractData { - return new NewContractData(AztecAddress.ZERO, makeEmptyEthAddress(), frZero()); -} - -function makeEmptyTxContext(): TxContext { - const deploymentData = new ContractDeploymentData(frZero(), frZero(), frZero(), makeEmptyEthAddress()); - return new TxContext(false, false, true, deploymentData); -} - -function makeEmptyHistoricTreeRoots(): HistoricTreeRoots { - return new HistoricTreeRoots(frZero(), frZero(), frZero(), frZero()); -} - -function makeEmptyConstantData(): ConstantData { - return new ConstantData(makeEmptyHistoricTreeRoots(), makeEmptyTxContext()); -} - -function makeEmptyOptionallyRevealedData(): OptionallyRevealedData { - return new OptionallyRevealedData( - frZero(), - new FunctionData(Buffer.alloc(4), true, true), - times(EMITTED_EVENTS_LENGTH, frZero), - frZero(), - makeEmptyEthAddress(), - false, - false, - false, - false, - ); -} - -function makeEmptyAccumulatedData(): AccumulatedData { - return new AccumulatedData( - AggregationObject.makeFake(), - frZero(), - times(KERNEL_NEW_COMMITMENTS_LENGTH, frZero), - times(KERNEL_NEW_NULLIFIERS_LENGTH, frZero), - times(KERNEL_PRIVATE_CALL_STACK_LENGTH, frZero), - times(KERNEL_PUBLIC_CALL_STACK_LENGTH, frZero), - times(KERNEL_L1_MSG_STACK_LENGTH, frZero), - times(KERNEL_NEW_CONTRACTS_LENGTH, makeEmptyNewContractData), - times(KERNEL_OPTIONALLY_REVEALED_DATA_LENGTH, makeEmptyOptionallyRevealedData), - ); -} - -export function makeEmptyProof() { - return new UInt8Vector(Buffer.alloc(0)); -} diff --git a/yarn-project/circuits.js/src/structs/public_circuit_public_inputs.ts b/yarn-project/circuits.js/src/structs/public_circuit_public_inputs.ts index 83e86cda7799..e227de5dea6b 100644 --- a/yarn-project/circuits.js/src/structs/public_circuit_public_inputs.ts +++ b/yarn-project/circuits.js/src/structs/public_circuit_public_inputs.ts @@ -1,4 +1,4 @@ -import { AztecAddress, Fr } from '@aztec/foundation'; +import { AztecAddress, BufferReader, Fr } from '@aztec/foundation'; import times from 'lodash.times'; import { FieldsOf, assertLength } from '../utils/jsUtils.js'; import { CallContext } from './call_context.js'; @@ -11,22 +11,54 @@ import { STATE_READS_LENGTH, STATE_TRANSITIONS_LENGTH, } from './constants.js'; +import { serializeToBuffer } from '../utils/serialize.js'; /** * Read operations from the public state tree. */ -export interface StateRead { - storageSlot: Fr; - value: Fr; +export class StateRead { + constructor(public readonly storageSlot: Fr, public readonly value: Fr) {} + + static from(args: { storageSlot: Fr; value: Fr }) { + return new StateRead(args.storageSlot, args.value); + } + + toBuffer() { + return serializeToBuffer(this.storageSlot, this.value); + } + + static fromBuffer(buffer: Buffer | BufferReader) { + const reader = BufferReader.asReader(buffer); + return new StateRead(reader.readFr(), reader.readFr()); + } + + static empty() { + return new StateRead(Fr.ZERO, Fr.ZERO); + } } /** * Write operations on the public state tree. */ -export interface StateTransition { - storageSlot: Fr; - oldValue: Fr; - newValue: Fr; +export class StateTransition { + constructor(public readonly storageSlot: Fr, public readonly oldValue: Fr, public readonly newValue: Fr) {} + + static from(args: { storageSlot: Fr; oldValue: Fr; newValue: Fr }) { + return new StateTransition(args.storageSlot, args.oldValue, args.newValue); + } + + toBuffer() { + return serializeToBuffer(this.storageSlot, this.oldValue, this.newValue); + } + + static fromBuffer(buffer: Buffer | BufferReader) { + const reader = BufferReader.asReader(buffer); + return new StateTransition(reader.readFr(), reader.readFr(), reader.readFr()); + } + + static empty() { + return new StateTransition(Fr.ZERO, Fr.ZERO, Fr.ZERO); + } } /** @@ -38,10 +70,11 @@ export class PublicCircuitPublicInputs { public args: Fr[], public returnValues: Fr[], public emittedEvents: Fr[], - public publicCallStack: Fr[], - public l1MsgStack: Fr[], public stateTransitions: StateTransition[], public stateReads: StateRead[], + public publicCallStack: Fr[], + public l1MsgStack: Fr[], + public historicPublicDataTreeRoot: Fr, public proverAddress: AztecAddress, ) { assertLength(this, 'args', ARGS_LENGTH); @@ -52,6 +85,7 @@ export class PublicCircuitPublicInputs { assertLength(this, 'stateTransitions', STATE_TRANSITIONS_LENGTH); assertLength(this, 'stateReads', STATE_READS_LENGTH); } + /** * Create PublicCircuitPublicInputs from a fields dictionary. * @param fields - The dictionary. @@ -72,10 +106,11 @@ export class PublicCircuitPublicInputs { frArray(ARGS_LENGTH), frArray(RETURN_VALUES_LENGTH), frArray(EMITTED_EVENTS_LENGTH), + times(STATE_TRANSITIONS_LENGTH, StateTransition.empty), + times(STATE_READS_LENGTH, StateRead.empty), frArray(PUBLIC_CALL_STACK_LENGTH), frArray(L1_MSG_STACK_LENGTH), - times(STATE_TRANSITIONS_LENGTH, () => ({ storageSlot: Fr.ZERO, oldValue: Fr.ZERO, newValue: Fr.ZERO })), - times(STATE_READS_LENGTH, () => ({ storageSlot: Fr.ZERO, value: Fr.ZERO })), + Fr.ZERO, AztecAddress.ZERO, ); } @@ -90,11 +125,20 @@ export class PublicCircuitPublicInputs { fields.args, fields.returnValues, fields.emittedEvents, - fields.publicCallStack, - fields.l1MsgStack, fields.stateTransitions, fields.stateReads, + fields.publicCallStack, + fields.l1MsgStack, + fields.historicPublicDataTreeRoot, fields.proverAddress, ] as const; } + + /** + * Serialize this as a buffer. + * @returns The buffer. + */ + toBuffer(): Buffer { + return serializeToBuffer(...PublicCircuitPublicInputs.getFields(this)); + } } diff --git a/yarn-project/circuits.js/src/structs/__snapshots__/base_rollup.test.ts.snap b/yarn-project/circuits.js/src/structs/rollup/__snapshots__/base_rollup.test.ts.snap similarity index 72% rename from yarn-project/circuits.js/src/structs/__snapshots__/base_rollup.test.ts.snap rename to yarn-project/circuits.js/src/structs/rollup/__snapshots__/base_rollup.test.ts.snap index 19347cc3e14c..21e12d43f56f 100644 --- a/yarn-project/circuits.js/src/structs/__snapshots__/base_rollup.test.ts.snap +++ b/yarn-project/circuits.js/src/structs/rollup/__snapshots__/base_rollup.test.ts.snap @@ -16,6 +16,7 @@ proof_witness_indices: [ 106 107 108 109 10a 10b ] has_data: 0 private_call_count: 0x10c +public_call_count: 0x10d new_commitments: [ 0x200 0x201 0x202 0x203 ] new_nullifiers: @@ -89,13 +90,39 @@ pay_fee_from_public_l2: 0 called_from_l1: 1 called_from_public_l2: 0 ] +state_transitions: +[ storage_slot: 0x900 +old_value: 0x901 +new_value: 0x902 + storage_slot: 0x901 +old_value: 0x902 +new_value: 0x903 + storage_slot: 0x902 +old_value: 0x903 +new_value: 0x904 + storage_slot: 0x903 +old_value: 0x904 +new_value: 0x905 + ] +state_reads: +[ storage_slot: 0xa00 +current_value: 0xa01 + storage_slot: 0xa01 +current_value: 0xa02 + storage_slot: 0xa02 +current_value: 0xa03 + storage_slot: 0xa03 +current_value: 0xa04 + ] constants: -historic_tree_roots: private_data_tree_root: 0x200 +historic_tree_roots: private_historic_tree_roots: private_data_tree_root: 0x200 nullifier_tree_root: 0x201 contract_tree_root: 0x202 private_kernel_vk_tree_root: 0x203 +public_data_tree_root: 0x204 + tx_context: is_fee_payment_tx: 0 is_rebate_payment_tx: 0 is_contract_deployment_tx: 1 @@ -135,6 +162,7 @@ proof_witness_indices: [ 206 207 208 209 20a 20b ] has_data: 0 private_call_count: 0x20c +public_call_count: 0x20d new_commitments: [ 0x300 0x301 0x302 0x303 ] new_nullifiers: @@ -208,13 +236,39 @@ pay_fee_from_public_l2: 0 called_from_l1: 1 called_from_public_l2: 0 ] +state_transitions: +[ storage_slot: 0xa00 +old_value: 0xa01 +new_value: 0xa02 + storage_slot: 0xa01 +old_value: 0xa02 +new_value: 0xa03 + storage_slot: 0xa02 +old_value: 0xa03 +new_value: 0xa04 + storage_slot: 0xa03 +old_value: 0xa04 +new_value: 0xa05 + ] +state_reads: +[ storage_slot: 0xb00 +current_value: 0xb01 + storage_slot: 0xb01 +current_value: 0xb02 + storage_slot: 0xb02 +current_value: 0xb03 + storage_slot: 0xb03 +current_value: 0xb04 + ] constants: -historic_tree_roots: private_data_tree_root: 0x300 +historic_tree_roots: private_historic_tree_roots: private_data_tree_root: 0x300 nullifier_tree_root: 0x301 contract_tree_root: 0x302 private_kernel_vk_tree_root: 0x303 +public_data_tree_root: 0x304 + tx_context: is_fee_payment_tx: 0 is_rebate_payment_tx: 0 is_contract_deployment_tx: 1 @@ -253,6 +307,10 @@ start_contract_tree_snapshot: root: 0x300 next_available_leaf_index: 768 +start_public_data_tree_snapshot: +root: 0x400 +next_available_leaf_index: 1024 + low_nullifier_leaf_preimages: [ leaf_value: 0x1000 next_value: 0x1100 @@ -303,6 +361,24 @@ new_nullifiers_subtree_sibling_path: [ 0x4000 0x4001 0x4002 0x4003 0x4004 ] new_contracts_subtree_sibling_path: [ 0x5000 0x5001 0x5002 ] +new_state_transitions_sibling_paths: +[ leaf_index: 6000 +sibling_path: [ 0x6000 0x6001 0x6002 0x6003 0x6004 0x6005 0x6006 0x6007 0x6008 0x6009 0x600a 0x600b 0x600c 0x600d 0x600e 0x600f 0x6010 0x6011 0x6012 0x6013 0x6014 0x6015 0x6016 0x6017 0x6018 0x6019 0x601a 0x601b 0x601c 0x601d 0x601e 0x601f ] + leaf_index: 6001 +sibling_path: [ 0x6001 0x6002 0x6003 0x6004 0x6005 0x6006 0x6007 0x6008 0x6009 0x600a 0x600b 0x600c 0x600d 0x600e 0x600f 0x6010 0x6011 0x6012 0x6013 0x6014 0x6015 0x6016 0x6017 0x6018 0x6019 0x601a 0x601b 0x601c 0x601d 0x601e 0x601f 0x6020 ] + leaf_index: 6002 +sibling_path: [ 0x6002 0x6003 0x6004 0x6005 0x6006 0x6007 0x6008 0x6009 0x600a 0x600b 0x600c 0x600d 0x600e 0x600f 0x6010 0x6011 0x6012 0x6013 0x6014 0x6015 0x6016 0x6017 0x6018 0x6019 0x601a 0x601b 0x601c 0x601d 0x601e 0x601f 0x6020 0x6021 ] + leaf_index: 6003 +sibling_path: [ 0x6003 0x6004 0x6005 0x6006 0x6007 0x6008 0x6009 0x600a 0x600b 0x600c 0x600d 0x600e 0x600f 0x6010 0x6011 0x6012 0x6013 0x6014 0x6015 0x6016 0x6017 0x6018 0x6019 0x601a 0x601b 0x601c 0x601d 0x601e 0x601f 0x6020 0x6021 0x6022 ] + leaf_index: 6004 +sibling_path: [ 0x6004 0x6005 0x6006 0x6007 0x6008 0x6009 0x600a 0x600b 0x600c 0x600d 0x600e 0x600f 0x6010 0x6011 0x6012 0x6013 0x6014 0x6015 0x6016 0x6017 0x6018 0x6019 0x601a 0x601b 0x601c 0x601d 0x601e 0x601f 0x6020 0x6021 0x6022 0x6023 ] + leaf_index: 6005 +sibling_path: [ 0x6005 0x6006 0x6007 0x6008 0x6009 0x600a 0x600b 0x600c 0x600d 0x600e 0x600f 0x6010 0x6011 0x6012 0x6013 0x6014 0x6015 0x6016 0x6017 0x6018 0x6019 0x601a 0x601b 0x601c 0x601d 0x601e 0x601f 0x6020 0x6021 0x6022 0x6023 0x6024 ] + leaf_index: 6006 +sibling_path: [ 0x6006 0x6007 0x6008 0x6009 0x600a 0x600b 0x600c 0x600d 0x600e 0x600f 0x6010 0x6011 0x6012 0x6013 0x6014 0x6015 0x6016 0x6017 0x6018 0x6019 0x601a 0x601b 0x601c 0x601d 0x601e 0x601f 0x6020 0x6021 0x6022 0x6023 0x6024 0x6025 ] + leaf_index: 6007 +sibling_path: [ 0x6007 0x6008 0x6009 0x600a 0x600b 0x600c 0x600d 0x600e 0x600f 0x6010 0x6011 0x6012 0x6013 0x6014 0x6015 0x6016 0x6017 0x6018 0x6019 0x601a 0x601b 0x601c 0x601d 0x601e 0x601f 0x6020 0x6021 0x6022 0x6023 0x6024 0x6025 0x6026 ] + ] historic_private_data_tree_root_membership_witnesses: [ leaf_index: 6000 sibling_path: [ 0x6000 0x6001 0x6002 0x6003 0x6004 0x6005 0x6006 0x6007 ] @@ -395,6 +471,14 @@ end_contract_tree_snapshot: root: 0x800 next_available_leaf_index: 2048 +start_public_data_tree_snapshot: +root: 0x900 +next_available_leaf_index: 2304 + +end_public_data_tree_snapshot: +root: 0x1000 +next_available_leaf_index: 4096 + calldata_hash: [ 0x901 0x902 ] " `; diff --git a/yarn-project/circuits.js/src/structs/__snapshots__/root_rollup.test.ts.snap b/yarn-project/circuits.js/src/structs/rollup/__snapshots__/root_rollup.test.ts.snap similarity index 93% rename from yarn-project/circuits.js/src/structs/__snapshots__/root_rollup.test.ts.snap rename to yarn-project/circuits.js/src/structs/rollup/__snapshots__/root_rollup.test.ts.snap index 062996f05b0c..03cc84369b1b 100644 --- a/yarn-project/circuits.js/src/structs/__snapshots__/root_rollup.test.ts.snap +++ b/yarn-project/circuits.js/src/structs/rollup/__snapshots__/root_rollup.test.ts.snap @@ -59,6 +59,14 @@ end_contract_tree_snapshot: root: 0x800 next_available_leaf_index: 800 +start_public_data_tree_snapshot: +root: 0x900 +next_available_leaf_index: 900 + +end_public_data_tree_snapshot: +root: 0x1000 +next_available_leaf_index: 1000 + calldata_hash: [ 0x901 0x902 ] proof: [ 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 ] @@ -133,6 +141,14 @@ end_contract_tree_snapshot: root: 0x1800 next_available_leaf_index: 1800 +start_public_data_tree_snapshot: +root: 0x1900 +next_available_leaf_index: 1900 + +end_public_data_tree_snapshot: +root: 0x2000 +next_available_leaf_index: 2000 + calldata_hash: [ 0x1901 0x1902 ] proof: [ 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 ] diff --git a/yarn-project/circuits.js/src/structs/rollup/append_only_tree_snapshot.ts b/yarn-project/circuits.js/src/structs/rollup/append_only_tree_snapshot.ts new file mode 100644 index 000000000000..78c64f35e317 --- /dev/null +++ b/yarn-project/circuits.js/src/structs/rollup/append_only_tree_snapshot.ts @@ -0,0 +1,20 @@ +import { BufferReader, Fr } from '@aztec/foundation'; +import { serializeToBuffer } from '../../utils/serialize.js'; +import { UInt32 } from '../shared.js'; + +export class AppendOnlyTreeSnapshot { + constructor(public root: Fr, public nextAvailableLeafIndex: UInt32) {} + + toBuffer() { + return serializeToBuffer(this.root, this.nextAvailableLeafIndex); + } + + static fromBuffer(buffer: Buffer | BufferReader): AppendOnlyTreeSnapshot { + const reader = BufferReader.asReader(buffer); + return new AppendOnlyTreeSnapshot(reader.readFr(), reader.readNumber()); + } + + static empty() { + return new AppendOnlyTreeSnapshot(Fr.ZERO, 0); + } +} diff --git a/yarn-project/circuits.js/src/structs/rollup/base_or_merge_rollup_public_inputs.ts b/yarn-project/circuits.js/src/structs/rollup/base_or_merge_rollup_public_inputs.ts new file mode 100644 index 000000000000..4304f43b4469 --- /dev/null +++ b/yarn-project/circuits.js/src/structs/rollup/base_or_merge_rollup_public_inputs.ts @@ -0,0 +1,84 @@ +import { BufferReader, Fr } from '@aztec/foundation'; +import { serializeToBuffer } from '../../utils/serialize.js'; +import { RollupTypes } from '../shared.js'; +import { AggregationObject } from '../aggregation_object.js'; +import { AppendOnlyTreeSnapshot } from './append_only_tree_snapshot.js'; +import { ConstantBaseRollupData } from './base_rollup.js'; + +/** + * Output of the base rollup circuit + */ + +export class BaseOrMergeRollupPublicInputs { + constructor( + public rollupType: RollupTypes, + public rollupSubTreeHeight: Fr, + public endAggregationObject: AggregationObject, + public constants: ConstantBaseRollupData, + + public startPrivateDataTreeSnapshot: AppendOnlyTreeSnapshot, + public endPrivateDataTreeSnapshot: AppendOnlyTreeSnapshot, + + public startNullifierTreeSnapshot: AppendOnlyTreeSnapshot, + public endNullifierTreeSnapshot: AppendOnlyTreeSnapshot, + + public startContractTreeSnapshot: AppendOnlyTreeSnapshot, + public endContractTreeSnapshot: AppendOnlyTreeSnapshot, + + public startPublicDataTreeTreeSnapshot: AppendOnlyTreeSnapshot, + public endPublicDataTreeTreeSnapshot: AppendOnlyTreeSnapshot, + + // Hashes (sha256), to make public inputs constant-sized (to then be unpacked on-chain). Length 2 for high and low + public calldataHash: [Fr, Fr], + ) {} + + /** + * Deserializes from a buffer or reader, corresponding to a write in cpp. + * @param bufferReader - Buffer to read from. + */ + static fromBuffer(buffer: Buffer | BufferReader): BaseOrMergeRollupPublicInputs { + const reader = BufferReader.asReader(buffer); + return new BaseOrMergeRollupPublicInputs( + reader.readNumber(), + reader.readFr(), + reader.readObject(AggregationObject), + reader.readObject(ConstantBaseRollupData), + reader.readObject(AppendOnlyTreeSnapshot), + reader.readObject(AppendOnlyTreeSnapshot), + reader.readObject(AppendOnlyTreeSnapshot), + reader.readObject(AppendOnlyTreeSnapshot), + reader.readObject(AppendOnlyTreeSnapshot), + reader.readObject(AppendOnlyTreeSnapshot), + reader.readObject(AppendOnlyTreeSnapshot), + reader.readObject(AppendOnlyTreeSnapshot), + reader.readArray(2, Fr) as [Fr, Fr], + ); + } + + /** + * Serialize this as a buffer. + * @returns The buffer. + */ + toBuffer() { + return serializeToBuffer( + this.rollupType, + this.rollupSubTreeHeight, + this.endAggregationObject, + this.constants, + + this.startPrivateDataTreeSnapshot, + this.endPrivateDataTreeSnapshot, + + this.startNullifierTreeSnapshot, + this.endNullifierTreeSnapshot, + + this.startContractTreeSnapshot, + this.endContractTreeSnapshot, + + this.startPublicDataTreeTreeSnapshot, + this.endPublicDataTreeTreeSnapshot, + + this.calldataHash, + ); + } +} diff --git a/yarn-project/circuits.js/src/structs/base_rollup.test.ts b/yarn-project/circuits.js/src/structs/rollup/base_rollup.test.ts similarity index 86% rename from yarn-project/circuits.js/src/structs/base_rollup.test.ts rename to yarn-project/circuits.js/src/structs/rollup/base_rollup.test.ts index 1b41c07071b0..3ea37664bcb7 100644 --- a/yarn-project/circuits.js/src/structs/base_rollup.test.ts +++ b/yarn-project/circuits.js/src/structs/rollup/base_rollup.test.ts @@ -1,6 +1,6 @@ -import { expectReserializeToMatchObject, expectSerializeToMatchSnapshot } from '../tests/expectSerialize.js'; -import { makeBaseRollupInputs, makeBaseRollupPublicInputs } from '../tests/factories.js'; -import { BaseOrMergeRollupPublicInputs } from './base_rollup.js'; +import { expectReserializeToMatchObject, expectSerializeToMatchSnapshot } from '../../tests/expectSerialize.js'; +import { makeBaseRollupInputs, makeBaseRollupPublicInputs } from '../../tests/factories.js'; +import { BaseOrMergeRollupPublicInputs } from './base_or_merge_rollup_public_inputs.js'; describe('structs/base_rollup', () => { it(`serializes and prints BaseRollupInputs`, async () => { diff --git a/yarn-project/circuits.js/src/structs/base_rollup.ts b/yarn-project/circuits.js/src/structs/rollup/base_rollup.ts similarity index 64% rename from yarn-project/circuits.js/src/structs/base_rollup.ts rename to yarn-project/circuits.js/src/structs/rollup/base_rollup.ts index 9ddde8a7a8a7..eda5f3d32148 100644 --- a/yarn-project/circuits.js/src/structs/base_rollup.ts +++ b/yarn-project/circuits.js/src/structs/rollup/base_rollup.ts @@ -1,6 +1,6 @@ import { BufferReader, Fr } from '@aztec/foundation'; -import { assertLength, FieldsOf } from '../utils/jsUtils.js'; -import { serializeToBuffer } from '../utils/serialize.js'; +import { assertLength, FieldsOf } from '../../utils/jsUtils.js'; +import { serializeToBuffer } from '../../utils/serialize.js'; import { CONTRACT_TREE_HEIGHT, CONTRACT_TREE_ROOTS_TREE_HEIGHT, @@ -10,9 +10,13 @@ import { NULLIFIER_TREE_HEIGHT, PRIVATE_DATA_TREE_HEIGHT, PRIVATE_DATA_TREE_ROOTS_TREE_HEIGHT, -} from './constants.js'; -import { PreviousKernelData } from './private_kernel.js'; -import { AggregationObject, MembershipWitness, RollupTypes, UInt32 } from './shared.js'; + PUBLIC_DATA_TREE_HEIGHT, + STATE_TRANSITIONS_LENGTH, +} from '../constants.js'; +import { PreviousKernelData } from '../kernel/previous_kernel_data.js'; +import { UInt32 } from '../shared.js'; +import { MembershipWitness } from '../membership_witness.js'; +import { AppendOnlyTreeSnapshot } from './append_only_tree_snapshot.js'; export class NullifierLeafPreimage { constructor(public leafValue: Fr, public nextValue: Fr, public nextIndex: UInt32) {} @@ -26,19 +30,6 @@ export class NullifierLeafPreimage { } } -export class AppendOnlyTreeSnapshot { - constructor(public root: Fr, public nextAvailableLeafIndex: UInt32) {} - - toBuffer() { - return serializeToBuffer(this.root, this.nextAvailableLeafIndex); - } - - static fromBuffer(buffer: Buffer | BufferReader): AppendOnlyTreeSnapshot { - const reader = BufferReader.asReader(buffer); - return new AppendOnlyTreeSnapshot(reader.readFr(), reader.readNumber()); - } -} - export class ConstantBaseRollupData { constructor( // The very latest roots as at the very beginning of the entire rollup: @@ -101,6 +92,7 @@ export class BaseRollupInputs { public startPrivateDataTreeSnapshot: AppendOnlyTreeSnapshot, public startNullifierTreeSnapshot: AppendOnlyTreeSnapshot, public startContractTreeSnapshot: AppendOnlyTreeSnapshot, + public startPublicDataTreeSnapshot: AppendOnlyTreeSnapshot, public lowNullifierLeafPreimages: NullifierLeafPreimage[], public lowNullifierMembershipWitness: MembershipWitness[], @@ -108,6 +100,7 @@ export class BaseRollupInputs { public newCommitmentsSubtreeSiblingPath: Fr[], public newNullifiersSubtreeSiblingPath: Fr[], public newContractsSubtreeSiblingPath: Fr[], + public newStateTransitionsSiblingPath: MembershipWitness[], public historicPrivateDataTreeRootMembershipWitnesses: [ MembershipWitness, @@ -137,6 +130,7 @@ export class BaseRollupInputs { 'newContractsSubtreeSiblingPath', CONTRACT_TREE_HEIGHT - BaseRollupInputs.CONTRACT_SUBTREE_HEIGHT, ); + assertLength(this, 'newStateTransitionsSiblingPath', 2 * STATE_TRANSITIONS_LENGTH); } static from(fields: FieldsOf): BaseRollupInputs { @@ -149,11 +143,13 @@ export class BaseRollupInputs { fields.startPrivateDataTreeSnapshot, fields.startNullifierTreeSnapshot, fields.startContractTreeSnapshot, + fields.startPublicDataTreeSnapshot, fields.lowNullifierLeafPreimages, fields.lowNullifierMembershipWitness, fields.newCommitmentsSubtreeSiblingPath, fields.newNullifiersSubtreeSiblingPath, fields.newContractsSubtreeSiblingPath, + fields.newStateTransitionsSiblingPath, fields.historicPrivateDataTreeRootMembershipWitnesses, fields.historicContractsTreeRootMembershipWitnesses, fields.constants, @@ -164,72 +160,3 @@ export class BaseRollupInputs { return serializeToBuffer(...BaseRollupInputs.getFields(this)); } } - -/** - * Output of the base rollup circuit - */ -export class BaseOrMergeRollupPublicInputs { - constructor( - public rollupType: RollupTypes, - public rollupSubTreeHeight: Fr, - public endAggregationObject: AggregationObject, - public constants: ConstantBaseRollupData, - - public startPrivateDataTreeSnapshot: AppendOnlyTreeSnapshot, - public endPrivateDataTreeSnapshot: AppendOnlyTreeSnapshot, - - public startNullifierTreeSnapshot: AppendOnlyTreeSnapshot, - public endNullifierTreeSnapshot: AppendOnlyTreeSnapshot, - - public startContractTreeSnapshot: AppendOnlyTreeSnapshot, - public endContractTreeSnapshot: AppendOnlyTreeSnapshot, - - // Hashes (sha256), to make public inputs constant-sized (to then be unpacked on-chain). Length 2 for high and low - public calldataHash: [Fr, Fr], - ) {} - - /** - * Deserializes from a buffer or reader, corresponding to a write in cpp. - * @param bufferReader - Buffer to read from. - */ - static fromBuffer(buffer: Buffer | BufferReader): BaseOrMergeRollupPublicInputs { - const reader = BufferReader.asReader(buffer); - return new BaseOrMergeRollupPublicInputs( - reader.readNumber(), - reader.readFr(), - reader.readObject(AggregationObject), - reader.readObject(ConstantBaseRollupData), - reader.readObject(AppendOnlyTreeSnapshot), - reader.readObject(AppendOnlyTreeSnapshot), - reader.readObject(AppendOnlyTreeSnapshot), - reader.readObject(AppendOnlyTreeSnapshot), - reader.readObject(AppendOnlyTreeSnapshot), - reader.readObject(AppendOnlyTreeSnapshot), - reader.readArray(2, Fr) as [Fr, Fr], - ); - } - - /** - * Serialize this as a buffer. - * @returns The buffer. - */ - toBuffer() { - return serializeToBuffer( - this.rollupType, - this.rollupSubTreeHeight, - this.endAggregationObject, - this.constants, - - this.startPrivateDataTreeSnapshot, - this.endPrivateDataTreeSnapshot, - - this.startNullifierTreeSnapshot, - this.endNullifierTreeSnapshot, - - this.startContractTreeSnapshot, - this.endContractTreeSnapshot, - - this.calldataHash, - ); - } -} diff --git a/yarn-project/circuits.js/src/structs/rollup/merge_rollup.ts b/yarn-project/circuits.js/src/structs/rollup/merge_rollup.ts new file mode 100644 index 000000000000..a4e32abe719f --- /dev/null +++ b/yarn-project/circuits.js/src/structs/rollup/merge_rollup.ts @@ -0,0 +1,10 @@ +import { serializeToBuffer } from '../../utils/serialize.js'; +import { PreviousRollupData } from './previous_rollup_data.js'; + +export class MergeRollupInputs { + constructor(public previousRollupData: [PreviousRollupData, PreviousRollupData]) {} + + toBuffer() { + return serializeToBuffer(this.previousRollupData); + } +} diff --git a/yarn-project/circuits.js/src/structs/rollup/previous_rollup_data.ts b/yarn-project/circuits.js/src/structs/rollup/previous_rollup_data.ts new file mode 100644 index 000000000000..ed88f0bc9530 --- /dev/null +++ b/yarn-project/circuits.js/src/structs/rollup/previous_rollup_data.ts @@ -0,0 +1,23 @@ +import { serializeToBuffer } from '../../utils/serialize.js'; +import { BaseOrMergeRollupPublicInputs } from './base_or_merge_rollup_public_inputs.js'; +import { ROLLUP_VK_TREE_HEIGHT } from '../constants.js'; +import { UInt32, UInt8Vector } from '../shared.js'; +import { MembershipWitness } from '../membership_witness.js'; +import { VerificationKey } from '../verification_key.js'; + +export class PreviousRollupData { + constructor( + public publicInputs: BaseOrMergeRollupPublicInputs, + public proof: UInt8Vector, + public vk: VerificationKey, + /** + * The index of the rollup circuit's vk in a big tree of rollup circuit vks. + */ + public vkIndex: UInt32, + public vkSiblingPath: MembershipWitness, + ) {} + + toBuffer() { + return serializeToBuffer(this.publicInputs, this.proof, this.vk, this.vkIndex, this.vkSiblingPath); + } +} diff --git a/yarn-project/circuits.js/src/structs/root_rollup.test.ts b/yarn-project/circuits.js/src/structs/rollup/root_rollup.test.ts similarity index 92% rename from yarn-project/circuits.js/src/structs/root_rollup.test.ts rename to yarn-project/circuits.js/src/structs/rollup/root_rollup.test.ts index 7e1102e19506..bb99f7fba60a 100644 --- a/yarn-project/circuits.js/src/structs/root_rollup.test.ts +++ b/yarn-project/circuits.js/src/structs/rollup/root_rollup.test.ts @@ -1,5 +1,5 @@ -import { expectReserializeToMatchObject, expectSerializeToMatchSnapshot } from '../tests/expectSerialize.js'; -import { makeRootRollupInputs, makeRootRollupPublicInputs } from '../tests/factories.js'; +import { expectReserializeToMatchObject, expectSerializeToMatchSnapshot } from '../../tests/expectSerialize.js'; +import { makeRootRollupInputs, makeRootRollupPublicInputs } from '../../tests/factories.js'; import { RootRollupPublicInputs } from './root_rollup.js'; describe('structs/root_rollup', () => { diff --git a/yarn-project/circuits.js/src/structs/root_rollup.ts b/yarn-project/circuits.js/src/structs/rollup/root_rollup.ts similarity index 91% rename from yarn-project/circuits.js/src/structs/root_rollup.ts rename to yarn-project/circuits.js/src/structs/rollup/root_rollup.ts index 3af96eef1bd9..9f826e17b403 100644 --- a/yarn-project/circuits.js/src/structs/root_rollup.ts +++ b/yarn-project/circuits.js/src/structs/rollup/root_rollup.ts @@ -1,10 +1,10 @@ import { BufferReader, Fr } from '@aztec/foundation'; -import { assertLength, FieldsOf } from '../utils/jsUtils.js'; -import { serializeToBuffer } from '../utils/serialize.js'; -import { AppendOnlyTreeSnapshot } from './base_rollup.js'; -import { CONTRACT_TREE_ROOTS_TREE_HEIGHT, PRIVATE_DATA_TREE_ROOTS_TREE_HEIGHT } from './constants.js'; -import { PreviousRollupData } from './merge_rollup.js'; -import { AggregationObject } from './shared.js'; +import { assertLength, FieldsOf } from '../../utils/jsUtils.js'; +import { serializeToBuffer } from '../../utils/serialize.js'; +import { AppendOnlyTreeSnapshot } from './append_only_tree_snapshot.js'; +import { CONTRACT_TREE_ROOTS_TREE_HEIGHT, PRIVATE_DATA_TREE_ROOTS_TREE_HEIGHT } from '../constants.js'; +import { PreviousRollupData } from './previous_rollup_data.js'; +import { AggregationObject } from '../aggregation_object.js'; export class RootRollupInputs { constructor( diff --git a/yarn-project/circuits.js/src/structs/shared.ts b/yarn-project/circuits.js/src/structs/shared.ts index 8f28b8f5ed88..d753bb179c67 100644 --- a/yarn-project/circuits.js/src/structs/shared.ts +++ b/yarn-project/circuits.js/src/structs/shared.ts @@ -1,92 +1,7 @@ import { BufferReader, randomBytes } from '@aztec/foundation'; -import { Fq, Fr } from '@aztec/foundation/fields'; -import { assertLength, range } from '../utils/jsUtils.js'; +import { Fq } from '@aztec/foundation/fields'; +import { assertLength } from '../utils/jsUtils.js'; import { Bufferable, serializeToBuffer } from '../utils/serialize.js'; -import times from 'lodash.times'; - -export class MembershipWitness { - constructor(pathSize: N, public leafIndex: UInt32, public siblingPath: Fr[]) { - assertLength(this, 'siblingPath', pathSize); - } - - toBuffer() { - return serializeToBuffer(this.leafIndex, ...this.siblingPath); - } - - static mock(size: number, start: number) { - return new MembershipWitness( - size, - start, - range(size, start).map(x => new Fr(BigInt(x))), - ); - } - - public static random(pathSize: N) { - return new MembershipWitness( - pathSize, - 0, - Array(pathSize) - .fill(0) - .map(() => Fr.random()), - ); - } - - public static makeEmpty(pathSize: N, leafIndex: UInt32) { - const arr = Array(pathSize) - .fill(0) - .map(() => Fr.ZERO); - return new MembershipWitness(pathSize, leafIndex, arr); - } - - static fromBufferArray(leafIndex: number, siblingPath: Buffer[]) { - return new MembershipWitness( - siblingPath.length, - leafIndex, - siblingPath.map(x => Fr.fromBuffer(x)), - ); - } -} - -export class AggregationObject { - public publicInputs: Vector; - public proofWitnessIndices: Vector; - - constructor( - public p0: AffineElement, - public p1: AffineElement, - publicInputsData: Fr[], - proofWitnessIndicesData: UInt32[], - public hasData = false, - ) { - this.publicInputs = new Vector(publicInputsData); - this.proofWitnessIndices = new Vector(proofWitnessIndicesData); - } - - toBuffer() { - return serializeToBuffer(this.p0, this.p1, this.publicInputs, this.proofWitnessIndices, this.hasData); - } - - static fromBuffer(buffer: Buffer | BufferReader): AggregationObject { - const reader = BufferReader.asReader(buffer); - return new AggregationObject( - reader.readObject(AffineElement), - reader.readObject(AffineElement), - reader.readVector(Fr), - reader.readNumberVector(), - reader.readBoolean(), - ); - } - - static makeFake() { - return new AggregationObject( - new AffineElement(new Fq(1n), new Fq(2n)), - new AffineElement(new Fq(1n), new Fq(2n)), - [], - times(16, i => 3027 + i), - false, - ); - } -} export class Vector { constructor(public items: T[]) {} diff --git a/yarn-project/circuits.js/src/structs/tx.test.ts b/yarn-project/circuits.js/src/structs/tx_context.test.ts similarity index 100% rename from yarn-project/circuits.js/src/structs/tx.test.ts rename to yarn-project/circuits.js/src/structs/tx_context.test.ts diff --git a/yarn-project/circuits.js/src/structs/tx.ts b/yarn-project/circuits.js/src/structs/tx_context.ts similarity index 59% rename from yarn-project/circuits.js/src/structs/tx.ts rename to yarn-project/circuits.js/src/structs/tx_context.ts index 8ba40b87caaa..9a16148da0e6 100644 --- a/yarn-project/circuits.js/src/structs/tx.ts +++ b/yarn-project/circuits.js/src/structs/tx_context.ts @@ -1,8 +1,5 @@ -import { AztecAddress, BufferReader, EthAddress, Fr } from '@aztec/foundation'; -import { FieldsOf } from '../utils/jsUtils.js'; +import { BufferReader, EthAddress, Fr } from '@aztec/foundation'; import { serializeToBuffer } from '../utils/serialize.js'; -import { FunctionData } from './function_data.js'; -import { EcdsaSignature } from './shared.js'; /** * Contract deployment data in a TxContext @@ -81,60 +78,8 @@ export class TxContext { reader.readObject(ContractDeploymentData), ); } -} - -/** - * Signed transaction request. - * @see cpp/src/aztec3/circuits/abis/signed_tx_request.hpp. - */ -export class SignedTxRequest { - constructor(public txRequest: TxRequest, public signature: EcdsaSignature) {} - - /** - * Serialize as a buffer. - * @returns The buffer. - */ - toBuffer() { - return serializeToBuffer(this.txRequest, this.signature); - } -} - -/** - * Transaction request. - * @see cpp/src/aztec3/circuits/abis/tx_request.hpp. - */ -export class TxRequest { - constructor( - public from: AztecAddress, - public to: AztecAddress, - public functionData: FunctionData, - public args: Fr[], - public nonce: Fr, - public txContext: TxContext, - public chainId: Fr, - ) {} - static getFields(fields: FieldsOf) { - return [ - fields.from, - fields.to, - fields.functionData, - fields.args, - fields.nonce, - fields.txContext, - fields.chainId, - ] as const; - } - - static from(fields: FieldsOf): TxRequest { - return new TxRequest(...TxRequest.getFields(fields)); - } - - /** - * Serialize as a buffer. - * @returns The buffer. - */ - toBuffer() { - return serializeToBuffer(...TxRequest.getFields(this)); + static empty() { + return new TxContext(false, false, true, ContractDeploymentData.empty()); } } diff --git a/yarn-project/circuits.js/src/structs/tx_request.ts b/yarn-project/circuits.js/src/structs/tx_request.ts new file mode 100644 index 000000000000..3434bf672dde --- /dev/null +++ b/yarn-project/circuits.js/src/structs/tx_request.ts @@ -0,0 +1,62 @@ +import { AztecAddress, Fr } from '@aztec/foundation'; +import { FieldsOf } from '../utils/jsUtils.js'; +import { serializeToBuffer } from '../utils/serialize.js'; +import { FunctionData } from './function_data.js'; +import { EcdsaSignature } from './shared.js'; +import { TxContext } from './tx_context.js'; + +/** + * Signed transaction request. + * @see cpp/src/aztec3/circuits/abis/signed_tx_request.hpp. + */ +export class SignedTxRequest { + constructor(public txRequest: TxRequest, public signature: EcdsaSignature) {} + + /** + * Serialize as a buffer. + * @returns The buffer. + */ + toBuffer() { + return serializeToBuffer(this.txRequest, this.signature); + } +} + +/** + * Transaction request. + * @see cpp/src/aztec3/circuits/abis/tx_request.hpp. + */ +export class TxRequest { + constructor( + public from: AztecAddress, + public to: AztecAddress, + public functionData: FunctionData, + public args: Fr[], + public nonce: Fr, + public txContext: TxContext, + public chainId: Fr, + ) {} + + static getFields(fields: FieldsOf) { + return [ + fields.from, + fields.to, + fields.functionData, + fields.args, + fields.nonce, + fields.txContext, + fields.chainId, + ] as const; + } + + static from(fields: FieldsOf): TxRequest { + return new TxRequest(...TxRequest.getFields(fields)); + } + + /** + * Serialize as a buffer. + * @returns The buffer. + */ + toBuffer() { + return serializeToBuffer(...TxRequest.getFields(this)); + } +} diff --git a/yarn-project/circuits.js/src/tests/factories.ts b/yarn-project/circuits.js/src/tests/factories.ts index 24db7212d242..a1840d61ca71 100644 --- a/yarn-project/circuits.js/src/tests/factories.ts +++ b/yarn-project/circuits.js/src/tests/factories.ts @@ -1,19 +1,30 @@ import { AztecAddress, EthAddress, Fq, Fr } from '@aztec/foundation'; import { + BaseOrMergeRollupPublicInputs, + BaseRollupInputs, CallContext, + CombinedAccumulatedData, + CombinedConstantData, + CombinedHistoricTreeRoots, + ConstantBaseRollupData, + KernelCircuitPublicInputs, MergeRollupInputs, + NewContractData, + NullifierLeafPreimage, + OptionallyRevealedData, + PreviousKernelData, PreviousRollupData, + PrivateCallData, PrivateCircuitPublicInputs, + PrivateKernelInputs, + PrivateHistoricTreeRoots, RootRollupInputs, RootRollupPublicInputs, + StateRead, + StateTransition, } from '../index.js'; -import { - AppendOnlyTreeSnapshot, - BaseRollupInputs, - BaseOrMergeRollupPublicInputs, - ConstantBaseRollupData, - NullifierLeafPreimage, -} from '../structs/base_rollup.js'; +import { AggregationObject } from '../structs/aggregation_object.js'; +import { PrivateCallStackItem } from '../structs/call_stack_item.js'; import { ARGS_LENGTH, CONTRACT_TREE_HEIGHT, @@ -35,33 +46,19 @@ import { PRIVATE_DATA_TREE_HEIGHT, PRIVATE_DATA_TREE_ROOTS_TREE_HEIGHT, PUBLIC_CALL_STACK_LENGTH, + PUBLIC_DATA_TREE_HEIGHT, RETURN_VALUES_LENGTH, ROLLUP_VK_TREE_HEIGHT, + STATE_READS_LENGTH, + STATE_TRANSITIONS_LENGTH, VK_TREE_HEIGHT, } from '../structs/constants.js'; import { FunctionData } from '../structs/function_data.js'; -import { - AccumulatedData, - ConstantData, - NewContractData, - HistoricTreeRoots, - OptionallyRevealedData, - PreviousKernelData, - PrivateCallData, - PrivateKernelInputs, - PrivateKernelPublicInputs, -} from '../structs/private_kernel.js'; -import { PrivateCallStackItem } from '../structs/private_call_stack_item.js'; -import { - AffineElement, - AggregationObject, - ComposerType, - EcdsaSignature, - MembershipWitness, - RollupTypes, - UInt8Vector, -} from '../structs/shared.js'; -import { ContractDeploymentData, SignedTxRequest, TxContext, TxRequest } from '../structs/tx.js'; +import { MembershipWitness } from '../structs/membership_witness.js'; +import { AppendOnlyTreeSnapshot } from '../structs/rollup/append_only_tree_snapshot.js'; +import { AffineElement, ComposerType, EcdsaSignature, RollupTypes, UInt8Vector } from '../structs/shared.js'; +import { ContractDeploymentData, TxContext } from '../structs/tx_context.js'; +import { SignedTxRequest, TxRequest } from '../structs/tx_request.js'; import { CommitmentMap, G1AffineElement, VerificationKey } from '../structs/verification_key.js'; import { range } from '../utils/jsUtils.js'; import { numToUInt32BE } from '../utils/serialize.js'; @@ -71,12 +68,16 @@ export function makeTxContext(seed: number): TxContext { return new TxContext(false, false, true, deploymentData); } -export function makeHistoricTreeRoots(seed: number): HistoricTreeRoots { - return new HistoricTreeRoots(fr(seed), fr(seed + 1), fr(seed + 2), fr(seed + 3)); +export function makePrivateHistoricTreeRoots(seed: number): PrivateHistoricTreeRoots { + return new PrivateHistoricTreeRoots(fr(seed), fr(seed + 1), fr(seed + 2), fr(seed + 3)); +} + +export function makeCombinedHistoricTreeRoots(seed: number): CombinedHistoricTreeRoots { + return new CombinedHistoricTreeRoots(makePrivateHistoricTreeRoots(seed), fr(seed + 4)); } -export function makeConstantData(seed = 1): ConstantData { - return new ConstantData(makeHistoricTreeRoots(seed), makeTxContext(seed + 4)); +export function makeConstantData(seed = 1): CombinedConstantData { + return new CombinedConstantData(makeCombinedHistoricTreeRoots(seed), makeTxContext(seed + 4)); } export function makeSelector(seed: number) { @@ -85,10 +86,19 @@ export function makeSelector(seed: number) { return buffer; } -export function makeAccumulatedData(seed = 1): AccumulatedData { - return new AccumulatedData( +export function makeStateTransition(seed = 1) { + return new StateTransition(fr(seed), fr(seed + 1), fr(seed + 2)); +} + +export function makeStateRead(seed = 1) { + return new StateRead(fr(seed), fr(seed + 1)); +} + +export function makeAccumulatedData(seed = 1): CombinedAccumulatedData { + return new CombinedAccumulatedData( makeAggregationObject(seed), fr(seed + 12), + fr(seed + 13), range(KERNEL_NEW_COMMITMENTS_LENGTH, seed + 0x100).map(fr), range(KERNEL_NEW_NULLIFIERS_LENGTH, seed + 0x200).map(fr), range(KERNEL_PRIVATE_CALL_STACK_LENGTH, seed + 0x300).map(fr), @@ -96,6 +106,8 @@ export function makeAccumulatedData(seed = 1): AccumulatedData { range(KERNEL_L1_MSG_STACK_LENGTH, seed + 0x500).map(fr), range(KERNEL_NEW_CONTRACTS_LENGTH, seed + 0x600).map(makeNewContractData), range(KERNEL_OPTIONALLY_REVEALED_DATA_LENGTH, seed + 0x700).map(makeOptionallyRevealedData), + range(STATE_TRANSITIONS_LENGTH, seed + 0x800).map(makeStateTransition), + range(STATE_READS_LENGTH, seed + 0x900).map(makeStateRead), ); } @@ -126,8 +138,8 @@ export function makeAggregationObject(seed = 1): AggregationObject { ); } -export function makePrivateKernelPublicInputs(seed = 1): PrivateKernelPublicInputs { - return new PrivateKernelPublicInputs(makeAccumulatedData(seed), makeConstantData(seed + 0x100), true); +export function makeKernelPublicInputs(seed = 1): KernelCircuitPublicInputs { + return new KernelCircuitPublicInputs(makeAccumulatedData(seed), makeConstantData(seed + 0x100), true); } export function makeDynamicSizeBuffer(size: number, fill: number) { @@ -150,9 +162,10 @@ export function makeVerificationKey(): VerificationKey { range(5, 400), ); } + export function makePreviousKernelData(seed = 1): PreviousKernelData { return new PreviousKernelData( - makePrivateKernelPublicInputs(seed), + makeKernelPublicInputs(seed), makeDynamicSizeBuffer(16, seed + 0x80), makeVerificationKey(), 0x42, @@ -278,6 +291,8 @@ export function makeBaseRollupPublicInputs(seed = 0) { makeAppendOnlyTreeSnapshot(seed + 0x600), makeAppendOnlyTreeSnapshot(seed + 0x700), makeAppendOnlyTreeSnapshot(seed + 0x800), + makeAppendOnlyTreeSnapshot(seed + 0x900), + makeAppendOnlyTreeSnapshot(seed + 0x1000), [fr(seed + 0x901), fr(seed + 0x902)], ); } @@ -330,6 +345,7 @@ export function makeBaseRollupInputs(seed = 0) { const startPrivateDataTreeSnapshot = makeAppendOnlyTreeSnapshot(seed + 0x100); const startNullifierTreeSnapshot = makeAppendOnlyTreeSnapshot(seed + 0x200); const startContractTreeSnapshot = makeAppendOnlyTreeSnapshot(seed + 0x300); + const startPublicDataTreeSnapshot = makeAppendOnlyTreeSnapshot(seed + 0x400); const lowNullifierLeafPreimages = range(2 * KERNEL_NEW_NULLIFIERS_LENGTH, seed + 0x1000).map( x => new NullifierLeafPreimage(fr(x), fr(x + 0x100), x + 0x200), @@ -354,6 +370,10 @@ export function makeBaseRollupInputs(seed = 0) { seed + 0x5000, ).map(x => fr(x)); + const newStateTransitionsSiblingPath = range(2 * STATE_TRANSITIONS_LENGTH, seed + 0x6000).map(x => + makeMembershipWitness(PUBLIC_DATA_TREE_HEIGHT, x), + ); + const historicPrivateDataTreeRootMembershipWitnesses: BaseRollupInputs['historicPrivateDataTreeRootMembershipWitnesses'] = [ makeMembershipWitness(PRIVATE_DATA_TREE_ROOTS_TREE_HEIGHT, seed + 0x6000), @@ -373,11 +393,13 @@ export function makeBaseRollupInputs(seed = 0) { startPrivateDataTreeSnapshot, startNullifierTreeSnapshot, startContractTreeSnapshot, + startPublicDataTreeSnapshot, lowNullifierLeafPreimages, lowNullifierMembershipWitness, newCommitmentsSubtreeSiblingPath, newNullifiersSubtreeSiblingPath, newContractsSubtreeSiblingPath, + newStateTransitionsSiblingPath, historicPrivateDataTreeRootMembershipWitnesses, historicContractsTreeRootMembershipWitnesses, constants, diff --git a/yarn-project/foundation/src/fields/fields.ts b/yarn-project/foundation/src/fields/fields.ts index e41db257de14..25fc74c6e648 100644 --- a/yarn-project/foundation/src/fields/fields.ts +++ b/yarn-project/foundation/src/fields/fields.ts @@ -39,6 +39,14 @@ export class Fr { return new Fr(r); } + /** + * Returns a new zero-value field. + * @returns A new zero-value field. + */ + static zero() { + return new Fr(0n); + } + /** * Create an instance of the corresponding class (Fr or Fq) from a Buffer or a BufferReader. * Reads 'SIZE_IN_BYTES' bytes from the given Buffer or BufferReader and constructs an instance with the decoded value. diff --git a/yarn-project/kernel-prover/src/kernel_prover.test.ts b/yarn-project/kernel-prover/src/kernel_prover.test.ts index 16284b816e56..4c022f1261a2 100644 --- a/yarn-project/kernel-prover/src/kernel_prover.test.ts +++ b/yarn-project/kernel-prover/src/kernel_prover.test.ts @@ -5,7 +5,7 @@ import { PRIVATE_CALL_STACK_LENGTH, PrivateCallStackItem, PrivateCircuitPublicInputs, - PrivateKernelPublicInputs, + KernelCircuitPublicInputs, TxRequest, VK_TREE_HEIGHT, VerificationKey, @@ -53,7 +53,7 @@ describe('Kernel Prover', () => { }; const createProofOutput = (newNoteIndices: number[]) => { - const publicInputs = PrivateKernelPublicInputs.makeEmpty(); + const publicInputs = KernelCircuitPublicInputs.empty(); publicInputs.end.newCommitments = newNoteIndices.map(idx => generateFakeSiloedCommitment(notes[idx])); return { publicInputs, diff --git a/yarn-project/kernel-prover/src/kernel_prover.ts b/yarn-project/kernel-prover/src/kernel_prover.ts index 5a253e175a7b..e6d89b31b8d6 100644 --- a/yarn-project/kernel-prover/src/kernel_prover.ts +++ b/yarn-project/kernel-prover/src/kernel_prover.ts @@ -7,7 +7,7 @@ import { PreviousKernelData, PrivateCallData, PrivateCallStackItem, - PrivateKernelPublicInputs, + KernelCircuitPublicInputs, SignedTxRequest, TxRequest, VK_TREE_HEIGHT, @@ -42,7 +42,7 @@ export class KernelProver { let firstIteration = true; let previousVerificationKey = VerificationKey.makeFake(); let output: ProofOutput = { - publicInputs: PrivateKernelPublicInputs.makeEmpty(), + publicInputs: KernelCircuitPublicInputs.empty(), proof: makeEmptyProof(), }; while (executionStack.length) { diff --git a/yarn-project/kernel-prover/src/proof_creator.ts b/yarn-project/kernel-prover/src/proof_creator.ts index afb05c64c438..abec47054ddb 100644 --- a/yarn-project/kernel-prover/src/proof_creator.ts +++ b/yarn-project/kernel-prover/src/proof_creator.ts @@ -5,7 +5,7 @@ import { PreviousKernelData, PrivateCallData, PrivateCircuitPublicInputs, - PrivateKernelPublicInputs, + KernelCircuitPublicInputs, SignedTxRequest, UInt8Vector, makeEmptyProof, @@ -15,7 +15,7 @@ import { Fr } from '@aztec/foundation'; import { createDebugLogger } from '@aztec/foundation/log'; export interface ProofOutput { - publicInputs: PrivateKernelPublicInputs; + publicInputs: KernelCircuitPublicInputs; proof: UInt8Vector; } diff --git a/yarn-project/p2p/src/client/mocks.ts b/yarn-project/p2p/src/client/mocks.ts index 97990a29b4d7..e3799f383b87 100644 --- a/yarn-project/p2p/src/client/mocks.ts +++ b/yarn-project/p2p/src/client/mocks.ts @@ -1,12 +1,12 @@ import { UInt8Vector } from '@aztec/circuits.js'; -import { makePrivateKernelPublicInputs } from '@aztec/circuits.js/factories'; +import { makeKernelPublicInputs } from '@aztec/circuits.js/factories'; import { AztecAddress } from '@aztec/foundation'; import { ContractData, L2Block, L2BlockSource } from '@aztec/types'; import { Tx } from '@aztec/types'; import { UnverifiedData } from '@aztec/types'; export const MockTx = () => { - return Tx.createPrivate(makePrivateKernelPublicInputs(), new UInt8Vector(Buffer.alloc(0)), UnverifiedData.random(8)); + return Tx.createPrivate(makeKernelPublicInputs(), new UInt8Vector(Buffer.alloc(0)), UnverifiedData.random(8)); }; export class MockBlockSource implements L2BlockSource { diff --git a/yarn-project/sequencer-client/src/block_builder/circuit_block_builder.test.ts b/yarn-project/sequencer-client/src/block_builder/circuit_block_builder.test.ts index d54812c1d200..10e3d8e0e76f 100644 --- a/yarn-project/sequencer-client/src/block_builder/circuit_block_builder.test.ts +++ b/yarn-project/sequencer-client/src/block_builder/circuit_block_builder.test.ts @@ -10,7 +10,7 @@ import { import { makeBaseRollupPublicInputs, makeNewContractData, - makePrivateKernelPublicInputs, + makeKernelPublicInputs, makeRootRollupPublicInputs, } from '@aztec/circuits.js/factories'; import { PrivateTx, Tx } from '@aztec/types'; @@ -114,7 +114,9 @@ describe('sequencer/circuit_block_builder', () => { ['contractTreeRoot', MerkleTreeId.CONTRACT_TREE], ['nullifierTreeRoot', MerkleTreeId.NULLIFIER_TREE], ] as const) { - tx.data.constants.historicTreeRoots[name] = Fr.fromBuffer((await builderDb.getTreeInfo(id)).root); + tx.data.constants.historicTreeRoots.privateHistoricTreeRoots[name] = Fr.fromBuffer( + (await builderDb.getTreeInfo(id)).root, + ); } }; @@ -125,7 +127,7 @@ describe('sequencer/circuit_block_builder', () => { await builder.updateRootTrees(); // Assemble a fake transaction, we'll tweak some fields below - const tx = Tx.createPrivate(makePrivateKernelPublicInputs(), emptyProof, makeEmptyUnverifiedData()); + const tx = Tx.createPrivate(makeKernelPublicInputs(), emptyProof, makeEmptyUnverifiedData()); const txsLeft = [tx, makeEmptyPrivateTx()]; const txsRight = [makeEmptyPrivateTx(), makeEmptyPrivateTx()]; diff --git a/yarn-project/sequencer-client/src/block_builder/circuit_block_builder.ts b/yarn-project/sequencer-client/src/block_builder/circuit_block_builder.ts index 8eb3f00d89e3..ec3b448e7227 100644 --- a/yarn-project/sequencer-client/src/block_builder/circuit_block_builder.ts +++ b/yarn-project/sequencer-client/src/block_builder/circuit_block_builder.ts @@ -10,12 +10,14 @@ import { NULLIFIER_TREE_HEIGHT, NullifierLeafPreimage, PRIVATE_DATA_TREE_ROOTS_TREE_HEIGHT, + PUBLIC_DATA_TREE_HEIGHT, PreviousKernelData, PreviousRollupData, ROLLUP_VK_TREE_HEIGHT, RollupTypes, RootRollupInputs, RootRollupPublicInputs, + STATE_TRANSITIONS_LENGTH, UInt8Vector, VK_TREE_HEIGHT, VerificationKey, @@ -391,7 +393,7 @@ export class CircuitBlockBuilder implements BlockBuilder { protected getContractMembershipWitnessFor(tx: PrivateTx) { return this.getMembershipWitnessFor( - tx.data.constants.historicTreeRoots.contractTreeRoot, + tx.data.constants.historicTreeRoots.privateHistoricTreeRoots.contractTreeRoot, MerkleTreeId.CONTRACT_TREE_ROOTS_TREE, CONTRACT_TREE_ROOTS_TREE_HEIGHT, ); @@ -399,7 +401,7 @@ export class CircuitBlockBuilder implements BlockBuilder { protected getDataMembershipWitnessFor(tx: PrivateTx) { return this.getMembershipWitnessFor( - tx.data.constants.historicTreeRoots.privateDataTreeRoot, + tx.data.constants.historicTreeRoots.privateHistoricTreeRoots.privateDataTreeRoot, MerkleTreeId.PRIVATE_DATA_TREE_ROOTS_TREE, PRIVATE_DATA_TREE_ROOTS_TREE_HEIGHT, ); @@ -691,6 +693,10 @@ export class CircuitBlockBuilder implements BlockBuilder { const startContractTreeSnapshot = await this.getTreeSnapshot(MerkleTreeId.CONTRACT_TREE); const startPrivateDataTreeSnapshot = await this.getTreeSnapshot(MerkleTreeId.PRIVATE_DATA_TREE); + // TODO: Uncomment once the public data tree gets merged + // const startPublicDataTreeSnapshot = await this.getTreeSnapshot(MerkleTreeId.PUBLIC_DATA_TREE); + const startPublicDataTreeSnapshot = AppendOnlyTreeSnapshot.empty(); + // Update the contract and data trees with the new items being inserted to get the new roots // that will be used by the next iteration of the base rollup circuit, skipping the empty ones const wasm = await CircuitsWasm.get(); @@ -729,14 +735,21 @@ export class CircuitBlockBuilder implements BlockBuilder { BaseRollupInputs.NULLIFIER_SUBTREE_HEIGHT, ); + // TODO: Implement based on public tx data + const newStateTransitionsSiblingPath = times(2 * STATE_TRANSITIONS_LENGTH, () => + MembershipWitness.empty(PUBLIC_DATA_TREE_HEIGHT, 0), + ); + return BaseRollupInputs.from({ constants, startNullifierTreeSnapshot, startContractTreeSnapshot, startPrivateDataTreeSnapshot, + startPublicDataTreeSnapshot, newCommitmentsSubtreeSiblingPath, newContractsSubtreeSiblingPath, newNullifiersSubtreeSiblingPath, + newStateTransitionsSiblingPath, lowNullifierLeafPreimages: nullifierWitnesses.map((w: LowNullifierWitnessData) => w.preimage), lowNullifierMembershipWitness: lowNullifierMembershipWitnesses, kernelData: [this.getKernelDataFor(tx1), this.getKernelDataFor(tx2)], @@ -748,7 +761,7 @@ export class CircuitBlockBuilder implements BlockBuilder { await this.getDataMembershipWitnessFor(tx1), await this.getDataMembershipWitnessFor(tx2), ], - } as BaseRollupInputs); + }); } protected makeEmptyMembershipWitness(height: N) { diff --git a/yarn-project/sequencer-client/src/mocks/tx.ts b/yarn-project/sequencer-client/src/mocks/tx.ts index fdd92ccf5a39..6678b15bea82 100644 --- a/yarn-project/sequencer-client/src/mocks/tx.ts +++ b/yarn-project/sequencer-client/src/mocks/tx.ts @@ -1,5 +1,5 @@ -import { PrivateKernelPublicInputs, UInt8Vector } from '@aztec/circuits.js'; -import { makePrivateKernelPublicInputs } from '@aztec/circuits.js/factories'; +import { KernelCircuitPublicInputs, UInt8Vector } from '@aztec/circuits.js'; +import { makeKernelPublicInputs } from '@aztec/circuits.js/factories'; import { PrivateTx, Tx, UnverifiedData } from '@aztec/types'; function makeEmptyProof() { @@ -12,9 +12,9 @@ export function makeEmptyUnverifiedData(): UnverifiedData { } export function makeEmptyPrivateTx(): PrivateTx { - return Tx.createPrivate(PrivateKernelPublicInputs.makeEmpty(), makeEmptyProof(), makeEmptyUnverifiedData()); + return Tx.createPrivate(KernelCircuitPublicInputs.empty(), makeEmptyProof(), makeEmptyUnverifiedData()); } export function makePrivateTx(seed = 0): PrivateTx { - return Tx.createPrivate(makePrivateKernelPublicInputs(seed), makeEmptyProof(), UnverifiedData.random(2)); + return Tx.createPrivate(makeKernelPublicInputs(seed), makeEmptyProof(), UnverifiedData.random(2)); } diff --git a/yarn-project/sequencer-client/src/simulator/fake_public.ts b/yarn-project/sequencer-client/src/simulator/fake_public.ts index 18b1a2370079..9bdde663203c 100644 --- a/yarn-project/sequencer-client/src/simulator/fake_public.ts +++ b/yarn-project/sequencer-client/src/simulator/fake_public.ts @@ -8,14 +8,17 @@ import { PublicCircuitSimulator } from './index.js'; export class FakePublicCircuitSimulator implements PublicCircuitSimulator { public readonly db: WorldStatePublicDB; - constructor(merkleTree: MerkleTreeOperations) { - this.db = new WorldStatePublicDB(merkleTree); + constructor(private readonly merkleTree: MerkleTreeOperations) { + this.db = new WorldStatePublicDB(this.merkleTree); } public async publicCircuit(tx: TxRequest): Promise { const functionAbi: FunctionAbi = undefined as any; const portalAddress: EthAddress = undefined as any; + const publicDataTreeInfo = await this.merkleTree.getTreeInfo(MerkleTreeId.PUBLIC_DATA_TREE); + const historicPublicDataTreeRoot = Fr.fromBuffer(publicDataTreeInfo.root); + const execution = PublicExecution.fromTransactionRequest(this.db, tx, functionAbi, portalAddress); const result = await execution.run(); return PublicCircuitPublicInputs.from({ @@ -28,6 +31,7 @@ export class FakePublicCircuitSimulator implements PublicCircuitSimulator { returnValues: result.returnValues, stateReads: result.stateReads, stateTransitions: result.stateTransitions, + historicPublicDataTreeRoot, }); } } diff --git a/yarn-project/types/src/tx.ts b/yarn-project/types/src/tx.ts index bf6e977fd93e..f03f55075c55 100644 --- a/yarn-project/types/src/tx.ts +++ b/yarn-project/types/src/tx.ts @@ -1,4 +1,4 @@ -import { CircuitsWasm, PrivateKernelPublicInputs, SignedTxRequest, UInt8Vector } from '@aztec/circuits.js'; +import { CircuitsWasm, KernelCircuitPublicInputs, SignedTxRequest, UInt8Vector } from '@aztec/circuits.js'; import { computeContractLeaf } from '@aztec/circuits.js/abis'; import { createTxHash } from './create_tx_hash.js'; import { TxHash } from './tx_hash.js'; @@ -23,7 +23,7 @@ export class Tx { private hashPromise?: Promise; public static createPrivate( - data: PrivateKernelPublicInputs, + data: KernelCircuitPublicInputs, proof: UInt8Vector, unverifiedData: UnverifiedData, ): PrivateTx { @@ -35,7 +35,7 @@ export class Tx { } public static createPrivatePublic( - data: PrivateKernelPublicInputs, + data: KernelCircuitPublicInputs, proof: UInt8Vector, unverifiedData: UnverifiedData, txRequest: SignedTxRequest, @@ -44,7 +44,7 @@ export class Tx { } public static create( - data?: PrivateKernelPublicInputs, + data?: KernelCircuitPublicInputs, proof?: UInt8Vector, unverifiedData?: UnverifiedData, txRequest?: SignedTxRequest, @@ -72,7 +72,7 @@ export class Tx { * @param txRequest - Signed public function call data. */ protected constructor( - public readonly data?: PrivateKernelPublicInputs, + public readonly data?: KernelCircuitPublicInputs, public readonly proof?: UInt8Vector, public readonly unverifiedData?: UnverifiedData, public readonly txRequest?: SignedTxRequest,