diff --git a/circuits/README.md b/circuits/README.md index fc66f6b0c0dc..4d879148b57e 100644 --- a/circuits/README.md +++ b/circuits/README.md @@ -70,6 +70,10 @@ You can choose which tests will run via a gtest filter. This one below runs only ./scripts/run_tests_local wasm aztec3_circuits_abis_tests -*.circuit* ``` +> _Note:_ To log wasm output from within TS that uses them, you can use before running your `yarn test` +``` +export DEBUG='wasm' +``` --- Here's a list of the tests currently available (conveniently combined with the command to build, then execute them on `x86_64`, for easy copy-pasta): diff --git a/circuits/cpp/src/aztec3/circuits/abis/combined_accumulated_data.hpp b/circuits/cpp/src/aztec3/circuits/abis/combined_accumulated_data.hpp index 083dd054fb92..2751f63db339 100644 --- a/circuits/cpp/src/aztec3/circuits/abis/combined_accumulated_data.hpp +++ b/circuits/cpp/src/aztec3/circuits/abis/combined_accumulated_data.hpp @@ -36,7 +36,8 @@ template struct CombinedAccumulatedData { zero_array(); std::array public_call_stack = zero_array(); - std::array l1_msg_stack = zero_array(); + std::array new_l2_to_l1_msgs = + zero_array(); std::array, KERNEL_NEW_CONTRACTS_LENGTH> new_contracts{}; @@ -50,7 +51,7 @@ template struct CombinedAccumulatedData { return aggregation_object == other.aggregation_object && private_call_count == other.private_call_count && 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 && + public_call_stack == other.public_call_stack && new_l2_to_l1_msgs == other.new_l2_to_l1_msgs && new_contracts == other.new_contracts && optionally_revealed_data == other.optionally_revealed_data && state_transitions == other.state_transitions && state_reads == other.state_reads; }; @@ -82,7 +83,7 @@ template struct CombinedAccumulatedData { to_ct(private_call_stack), to_ct(public_call_stack), - to_ct(l1_msg_stack), + to_ct(new_l2_to_l1_msgs), map(new_contracts, to_circuit_type), map(optionally_revealed_data, to_circuit_type), @@ -116,7 +117,7 @@ template struct CombinedAccumulatedData { to_nt(private_call_stack), to_nt(public_call_stack), - to_nt(l1_msg_stack), + to_nt(new_l2_to_l1_msgs), map(new_contracts, to_native_type), map(optionally_revealed_data, to_native_type), @@ -140,7 +141,7 @@ template struct CombinedAccumulatedData { set_array_public(private_call_stack); set_array_public(public_call_stack); - set_array_public(l1_msg_stack); + set_array_public(new_l2_to_l1_msgs); set_array_public(new_contracts); set_array_public(optionally_revealed_data); @@ -200,7 +201,7 @@ template void read(uint8_t const*& it, CombinedAccumulatedData void write(std::vector& buf, CombinedAccumulate write(buf, accum_data.new_nullifiers); write(buf, accum_data.private_call_stack); write(buf, accum_data.public_call_stack); - write(buf, accum_data.l1_msg_stack); + write(buf, accum_data.new_l2_to_l1_msgs); write(buf, accum_data.new_contracts); write(buf, accum_data.optionally_revealed_data); write(buf, accum_data.state_transitions); @@ -239,8 +240,8 @@ template std::ostream& operator<<(std::ostream& os, CombinedAccum << accum_data.private_call_stack << "\n" << "public_call_stack:\n" << accum_data.public_call_stack << "\n" - << "l1_msg_stack:\n" - << accum_data.l1_msg_stack << "\n" + << "new_l2_to_l1_msgs:\n" + << accum_data.new_l2_to_l1_msgs << "\n" << "new_contracts:\n" << accum_data.new_contracts << "\n" << "optionally_revealed_data:\n" diff --git a/circuits/cpp/src/aztec3/circuits/abis/private_circuit_public_inputs.hpp b/circuits/cpp/src/aztec3/circuits/abis/private_circuit_public_inputs.hpp index 1c3e287bc4ef..e6b0d89d5be8 100644 --- a/circuits/cpp/src/aztec3/circuits/abis/private_circuit_public_inputs.hpp +++ b/circuits/cpp/src/aztec3/circuits/abis/private_circuit_public_inputs.hpp @@ -36,7 +36,7 @@ template class PrivateCircuitPublicInputs { std::array private_call_stack = zero_array(); std::array public_call_stack = zero_array(); - std::array l1_msg_stack = zero_array(); + std::array new_l2_to_l1_msgs = zero_array(); fr historic_private_data_tree_root = 0; fr historic_nullifier_tree_root = 0; @@ -49,7 +49,7 @@ template class PrivateCircuitPublicInputs { return call_context == other.call_context && args == other.args && return_values == other.return_values && emitted_events == other.emitted_events && 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 && + public_call_stack == other.public_call_stack && new_l2_to_l1_msgs == other.new_l2_to_l1_msgs && historic_private_data_tree_root == other.historic_private_data_tree_root && historic_nullifier_tree_root == other.historic_nullifier_tree_root && historic_contract_tree_root == other.historic_contract_tree_root && @@ -78,7 +78,7 @@ template class PrivateCircuitPublicInputs { to_ct(private_call_stack), to_ct(public_call_stack), - to_ct(l1_msg_stack), + to_ct(new_l2_to_l1_msgs), to_ct(historic_private_data_tree_root), to_ct(historic_nullifier_tree_root), @@ -109,7 +109,7 @@ template class PrivateCircuitPublicInputs { to_nt(private_call_stack), to_nt(public_call_stack), - to_nt(l1_msg_stack), + to_nt(new_l2_to_l1_msgs), to_nt(historic_private_data_tree_root), to_nt(historic_nullifier_tree_root), @@ -139,7 +139,7 @@ template class PrivateCircuitPublicInputs { spread_arr_into_vec(private_call_stack, inputs); spread_arr_into_vec(public_call_stack, inputs); - spread_arr_into_vec(l1_msg_stack, inputs); + spread_arr_into_vec(new_l2_to_l1_msgs, inputs); inputs.push_back(historic_private_data_tree_root); inputs.push_back(historic_nullifier_tree_root); @@ -170,7 +170,7 @@ template void read(uint8_t const*& it, PrivateCircuitPublicInputs read(it, pis.new_nullifiers); read(it, pis.private_call_stack); read(it, pis.public_call_stack); - read(it, pis.l1_msg_stack); + read(it, pis.new_l2_to_l1_msgs); read(it, pis.historic_private_data_tree_root); read(it, pis.historic_nullifier_tree_root); read(it, pis.historic_contract_tree_root); @@ -192,7 +192,7 @@ void write(std::vector& buf, PrivateCircuitPublicInputs const& pri write(buf, pis.new_nullifiers); write(buf, pis.private_call_stack); write(buf, pis.public_call_stack); - write(buf, pis.l1_msg_stack); + write(buf, pis.new_l2_to_l1_msgs); write(buf, pis.historic_private_data_tree_root); write(buf, pis.historic_nullifier_tree_root); write(buf, pis.historic_contract_tree_root); @@ -213,7 +213,7 @@ std::ostream& operator<<(std::ostream& os, PrivateCircuitPublicInputs const << "new_nullifiers: " << pis.new_nullifiers << "\n" << "private_call_stack: " << pis.private_call_stack << "\n" << "public_call_stack: " << pis.public_call_stack << "\n" - << "l1_msg_stack: " << pis.l1_msg_stack << "\n" + << "new_l2_to_l1_msgs: " << pis.new_l2_to_l1_msgs << "\n" << "historic_private_data_tree_root: " << pis.historic_private_data_tree_root << "\n" << "historic_nullifier_tree_root: " << pis.historic_nullifier_tree_root << "\n" << "contract_deployment_data: " << pis.contract_deployment_data << "\n" @@ -241,7 +241,7 @@ template class OptionalPrivateCircuitPublicInputs { std::array private_call_stack; std::array public_call_stack; - std::array l1_msg_stack; + std::array new_l2_to_l1_msgs; opt_fr historic_private_data_tree_root; opt_fr historic_nullifier_tree_root; @@ -263,7 +263,7 @@ template class OptionalPrivateCircuitPublicInputs { std::array const& private_call_stack, std::array const& public_call_stack, - std::array const& l1_msg_stack, + std::array const& new_l2_to_l1_msgs, opt_fr const& historic_private_data_tree_root, opt_fr const& historic_nullifier_tree_root, @@ -278,7 +278,7 @@ template class OptionalPrivateCircuitPublicInputs { , new_nullifiers(new_nullifiers) , private_call_stack(private_call_stack) , public_call_stack(public_call_stack) - , l1_msg_stack(l1_msg_stack) + , new_l2_to_l1_msgs(new_l2_to_l1_msgs) , historic_private_data_tree_root(historic_private_data_tree_root) , historic_nullifier_tree_root(historic_nullifier_tree_root) , historic_contract_tree_root(historic_contract_tree_root) @@ -303,7 +303,7 @@ template class OptionalPrivateCircuitPublicInputs { new_inputs.private_call_stack.fill(std::nullopt); new_inputs.public_call_stack.fill(std::nullopt); - new_inputs.l1_msg_stack.fill(std::nullopt); + new_inputs.new_l2_to_l1_msgs.fill(std::nullopt); new_inputs.historic_private_data_tree_root = std::nullopt; new_inputs.historic_nullifier_tree_root = std::nullopt; @@ -350,7 +350,7 @@ template class OptionalPrivateCircuitPublicInputs { make_unused_array_elements_zero(composer, private_call_stack); make_unused_array_elements_zero(composer, public_call_stack); - make_unused_array_elements_zero(composer, l1_msg_stack); + make_unused_array_elements_zero(composer, new_l2_to_l1_msgs); make_unused_element_zero(composer, historic_private_data_tree_root); make_unused_element_zero(composer, historic_nullifier_tree_root); @@ -381,7 +381,7 @@ template class OptionalPrivateCircuitPublicInputs { set_array_public(private_call_stack); set_array_public(public_call_stack); - set_array_public(l1_msg_stack); + set_array_public(new_l2_to_l1_msgs); (*historic_private_data_tree_root).set_public(); (*historic_nullifier_tree_root).set_public(); @@ -414,7 +414,7 @@ template class OptionalPrivateCircuitPublicInputs { to_ct(private_call_stack), to_ct(public_call_stack), - to_ct(l1_msg_stack), + to_ct(new_l2_to_l1_msgs), to_ct(historic_private_data_tree_root), to_ct(historic_nullifier_tree_root), @@ -448,7 +448,7 @@ template class OptionalPrivateCircuitPublicInputs { to_nt(private_call_stack), to_nt(public_call_stack), - to_nt(l1_msg_stack), + to_nt(new_l2_to_l1_msgs), to_nt(historic_private_data_tree_root), to_nt(historic_nullifier_tree_root), @@ -483,7 +483,7 @@ template class OptionalPrivateCircuitPublicInputs { spread_arr_opt_into_vec(private_call_stack, inputs); spread_arr_opt_into_vec(public_call_stack, inputs); - spread_arr_opt_into_vec(l1_msg_stack, inputs); + spread_arr_opt_into_vec(new_l2_to_l1_msgs, inputs); inputs.push_back(*historic_private_data_tree_root); inputs.push_back(*historic_nullifier_tree_root); @@ -512,7 +512,7 @@ template class OptionalPrivateCircuitPublicInputs { .private_call_stack = map(private_call_stack, get_value), .public_call_stack = map(public_call_stack, get_value), - .l1_msg_stack = map(l1_msg_stack, get_value), + .new_l2_to_l1_msgs = map(new_l2_to_l1_msgs, get_value), .historic_private_data_tree_root = historic_private_data_tree_root.value(), .historic_nullifier_tree_root = historic_nullifier_tree_root.value(), @@ -604,7 +604,7 @@ void read(uint8_t const*& it, OptionalPrivateCircuitPublicInputs& private_c read(it, pis.new_nullifiers); read(it, pis.private_call_stack); read(it, pis.public_call_stack); - read(it, pis.l1_msg_stack); + read(it, pis.new_l2_to_l1_msgs); read(it, pis.historic_private_data_tree_root); read(it, pis.historic_nullifier_tree_root); read(it, pis.historic_contract_tree_root); @@ -626,7 +626,7 @@ void write(std::vector& buf, OptionalPrivateCircuitPublicInputs co write(buf, pis.new_nullifiers); write(buf, pis.private_call_stack); write(buf, pis.public_call_stack); - write(buf, pis.l1_msg_stack); + write(buf, pis.new_l2_to_l1_msgs); write(buf, pis.historic_private_data_tree_root); write(buf, pis.historic_nullifier_tree_root); write(buf, pis.historic_contract_tree_root); @@ -646,7 +646,7 @@ std::ostream& operator<<(std::ostream& os, OptionalPrivateCircuitPublicInputs contract_deployment_call_stack; -// std::array, L1_MSG_STACK_LENGTH> l1_call_contexts; -// std::array l1_counterparts; // TODO: this is probably wrong. +// std::array, NEW_L2_TO_L1_MSGS_LENGTH> l1_call_contexts; +// std::array l1_counterparts; // TODO: this is probably wrong. // template // CallContextReconciliationData> to_circuit_type(Composer& composer) const 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 9e90e80db6d5..a5169aae2e3a 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 @@ -33,7 +33,7 @@ template struct PublicCircuitPublicInputs { std::array, STATE_READS_LENGTH> state_reads{}; std::array public_call_stack = zero_array(); - std::array l1_msg_stack = zero_array(); + std::array new_l2_to_l1_msgs = zero_array(); fr historic_public_data_tree_root = 0; @@ -44,7 +44,7 @@ template struct PublicCircuitPublicInputs { return call_context == other.call_context && args == other.args && return_values == other.return_values && 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 && + new_l2_to_l1_msgs == other.new_l2_to_l1_msgs && historic_public_data_tree_root == other.historic_public_data_tree_root && prover_address == other.prover_address; }; @@ -70,7 +70,7 @@ template struct PublicCircuitPublicInputs { .state_reads = map(state_reads, to_circuit_type), .public_call_stack = to_ct(public_call_stack), - .l1_msg_stack = to_ct(l1_msg_stack), + .new_l2_to_l1_msgs = to_ct(new_l2_to_l1_msgs), .historic_public_data_tree_root = to_ct(historic_public_data_tree_root), @@ -99,7 +99,7 @@ template struct PublicCircuitPublicInputs { spread_arr_into_vec(map(state_reads, to_hashes), inputs); spread_arr_into_vec(public_call_stack, inputs); - spread_arr_into_vec(l1_msg_stack, inputs); + spread_arr_into_vec(new_l2_to_l1_msgs, inputs); inputs.push_back(historic_public_data_tree_root); @@ -127,7 +127,7 @@ template void read(uint8_t const*& it, PublicCircuitPublicInputs< read(it, pis.state_reads); read(it, pis.public_call_stack); - read(it, pis.l1_msg_stack); + read(it, pis.new_l2_to_l1_msgs); read(it, pis.historic_public_data_tree_root); @@ -150,7 +150,7 @@ void write(std::vector& buf, PublicCircuitPublicInputs const& publ write(buf, pis.state_reads); write(buf, pis.public_call_stack); - write(buf, pis.l1_msg_stack); + write(buf, pis.new_l2_to_l1_msgs); write(buf, pis.historic_public_data_tree_root); @@ -171,7 +171,7 @@ std::ostream& operator<<(std::ostream& os, PublicCircuitPublicInputs const& << "state_reads: " << pis.state_reads << "\n" << "public_call_stack: " << pis.public_call_stack << "\n" - << "l1_msg_stack: " << pis.l1_msg_stack << "\n" + << "new_l2_to_l1_msgs: " << pis.new_l2_to_l1_msgs << "\n" << "historic_public_data_tree_root: " << pis.historic_public_data_tree_root << "\n" diff --git a/circuits/cpp/src/aztec3/circuits/abis/rollup/root/root_rollup_inputs.hpp b/circuits/cpp/src/aztec3/circuits/abis/rollup/root/root_rollup_inputs.hpp index f93c3fcbaaaa..0f2ba96f71fc 100644 --- a/circuits/cpp/src/aztec3/circuits/abis/rollup/root/root_rollup_inputs.hpp +++ b/circuits/cpp/src/aztec3/circuits/abis/rollup/root/root_rollup_inputs.hpp @@ -50,9 +50,10 @@ template void write(std::vector& buf, RootRollupInputs std::ostream& operator<<(std::ostream& os, RootRollupInputs const& obj) { return os << "previous_rollup_data: " << obj.previous_rollup_data << "\n" - << "new_historic_private_data_tree_roots: " << obj.new_historic_private_data_tree_root_sibling_path - << "\n" - << "new_historic_contract_tree_roots: " << obj.new_historic_contract_tree_root_sibling_path << "\n"; + << "new_historic_private_data_tree_root_sibling_path: " + << obj.new_historic_private_data_tree_root_sibling_path << "\n" + << "new_historic_contract_tree_root_sibling_path: " << obj.new_historic_contract_tree_root_sibling_path + << "\n"; } } // namespace aztec3::circuits::abis \ No newline at end of file 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 52a54e154bbb..b9f276730760 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 @@ -68,7 +68,7 @@ void initialise_end_values(PrivateInputs const& private_inputs, KernelCircui end.private_call_stack = start.private_call_stack; end.public_call_stack = start.public_call_stack; - end.l1_msg_stack = start.l1_msg_stack; + end.new_l2_to_l1_msgs = start.new_l2_to_l1_msgs; end.optionally_revealed_data = start.optionally_revealed_data; } @@ -239,14 +239,14 @@ void update_end_values(DummyComposer& composer, // 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; + // const auto& new_l2_to_l1_msgs = private_call_public_inputs.new_l2_to_l1_msgs; + // std::array l1_call_stack; - // for (size_t i = 0; i < l1_msg_stack.size(); ++i) { + // for (size_t i = 0; i < new_l2_to_l1_msgs.size(); ++i) { // l1_call_stack[i] = CT::fr::conditional_assign( - // l1_msg_stack[i] == 0, + // new_l2_to_l1_msgs[i] == 0, // 0, - // CT::compress({ portal_contract_address, l1_msg_stack[i] }, GeneratorIndex::L1_MSG_STACK_ITEM)); + // CT::compress({ portal_contract_address, new_l2_to_l1_msgs[i] }, GeneratorIndex::L1_MSG_STACK_ITEM)); // } // } } @@ -299,7 +299,7 @@ void validate_inputs(DummyComposer& composer, PrivateInputs const& private_i NT::fr start_private_call_stack_length = array_length(start.private_call_stack); NT::fr start_public_call_stack_length = array_length(start.public_call_stack); - NT::fr start_l1_msg_stack_length = array_length(start.l1_msg_stack); + NT::fr start_new_l2_to_l1_msgs = array_length(start.new_l2_to_l1_msgs); // Base Case if (is_base_case) { @@ -313,7 +313,7 @@ void validate_inputs(DummyComposer& composer, PrivateInputs const& private_i composer.do_assert(start_public_call_stack_length == 0, "Public call stack must be empty", CircuitErrorCode::PRIVATE_KERNEL__UNSUPPORTED_OP); - composer.do_assert(start_l1_msg_stack_length == 0, + composer.do_assert(start_new_l2_to_l1_msgs == 0, "L1 msg stack must be empty", CircuitErrorCode::PRIVATE_KERNEL__UNSUPPORTED_OP); 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 a7148faad668..3dc7259d7979 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 @@ -77,7 +77,7 @@ void initialise_end_values(PrivateInputs const& private_inputs, KernelCircui end.private_call_stack = start.private_call_stack; end.public_call_stack = start.public_call_stack; - end.l1_msg_stack = start.l1_msg_stack; + end.new_l2_to_l1_msgs = start.new_l2_to_l1_msgs; // TODO end.new_contracts = start.new_contracts; @@ -187,14 +187,14 @@ void update_end_values(PrivateInputs const& private_inputs, KernelCircuitPub } // { - // const auto& l1_msg_stack = private_call_public_inputs.l1_msg_stack; - // std::array l1_call_stack; + // const auto& new_l2_to_l1_msgs = private_call_public_inputs.new_l2_to_l1_msgs; + // std::array l1_call_stack; - // for (size_t i = 0; i < l1_msg_stack.size(); ++i) { + // for (size_t i = 0; i < new_l2_to_l1_msgs.size(); ++i) { // l1_call_stack[i] = CT::fr::conditional_assign( - // l1_msg_stack[i] == 0, + // new_l2_to_l1_msgs[i] == 0, // 0, - // CT::compress({ portal_contract_address, l1_msg_stack[i] }, GeneratorIndex::L1_MSG_STACK_ITEM)); + // CT::compress({ portal_contract_address, new_l2_to_l1_msgs[i] }, GeneratorIndex::L1_MSG_STACK_ITEM)); // } // } } @@ -260,7 +260,7 @@ void validate_inputs(PrivateInputs const& private_inputs) // but we want to know "length" in terms of how many nonzero entries have been inserted CT::fr start_private_call_stack_length = array_length(start.private_call_stack); CT::fr start_public_call_stack_length = array_length(start.public_call_stack); - CT::fr start_l1_msg_stack_length = array_length(start.l1_msg_stack); + CT::fr start_new_l2_to_l1_msgs = array_length(start.new_l2_to_l1_msgs); // Recall: we can't do traditional `if` statements in a circuit; all code paths are always executed. The below is // some syntactic sugar, which seeks readability similar to an `if` statement. @@ -271,7 +271,7 @@ void validate_inputs(PrivateInputs const& private_inputs) // rebate can be paid. { start_private_call_stack_length == 1, "Private call stack must be length 1" }, { start_public_call_stack_length == 0, "Public call stack must be empty" }, - { start_l1_msg_stack_length == 0, "L1 msg stack must be empty" }, + { start_new_l2_to_l1_msgs == 0, "L1 msg stack must be empty" }, { this_call_stack_item.public_inputs.call_context.is_delegate_call == false, "Users cannot make a delegatecall" }, diff --git a/circuits/cpp/src/aztec3/circuits/kernel/public/.test.cpp b/circuits/cpp/src/aztec3/circuits/kernel/public/.test.cpp index d0984dbeb941..c862a970fdf1 100644 --- a/circuits/cpp/src/aztec3/circuits/kernel/public/.test.cpp +++ b/circuits/cpp/src/aztec3/circuits/kernel/public/.test.cpp @@ -101,7 +101,7 @@ PublicCallStackItem generate_call_stack_item(NT::fr contract_address, NT::fr msg std::array return_values = array_of_values(count); std::array emitted_events = array_of_values(count); std::array public_call_stack = array_of_values(count); - std::array l1_msg_stack = array_of_values(count); + std::array new_l2_to_l1_msgs = array_of_values(count); std::array, STATE_READS_LENGTH> reads = generate_state_reads(count); std::array, STATE_TRANSITIONS_LENGTH> transitions = generate_state_transitions(count); @@ -114,7 +114,7 @@ PublicCallStackItem generate_call_stack_item(NT::fr contract_address, NT::fr msg .state_transitions = transitions, .state_reads = reads, .public_call_stack = public_call_stack, - .l1_msg_stack = l1_msg_stack, + .new_l2_to_l1_msgs = new_l2_to_l1_msgs, }; PublicCallStackItem call_stack_item = PublicCallStackItem{ @@ -204,7 +204,7 @@ PublicKernelInputsNoPreviousKernel do_public_call_get_kernel_inputs_no_previ std::array emitted_events = array_of_values(seed); std::array, STATE_TRANSITIONS_LENGTH> state_transitions = generate_state_transitions(seed); std::array, STATE_READS_LENGTH> state_reads = generate_state_reads(seed); - std::array l1_msg_stack = array_of_values(seed); + std::array new_l2_to_l1_msgs = array_of_values(seed); fr historic_public_data_tree_root = ++seed; // create the public circuit public inputs @@ -216,7 +216,7 @@ PublicKernelInputsNoPreviousKernel do_public_call_get_kernel_inputs_no_previ .state_transitions = state_transitions, .state_reads = state_reads, .public_call_stack = call_stack_hashes, - .l1_msg_stack = l1_msg_stack, + .new_l2_to_l1_msgs = new_l2_to_l1_msgs, .historic_public_data_tree_root = historic_public_data_tree_root, }; diff --git a/circuits/cpp/src/aztec3/circuits/kernel/public/common.cpp b/circuits/cpp/src/aztec3/circuits/kernel/public/common.cpp index e1b37cde111c..e28269d80f4a 100644 --- a/circuits/cpp/src/aztec3/circuits/kernel/public/common.cpp +++ b/circuits/cpp/src/aztec3/circuits/kernel/public/common.cpp @@ -19,7 +19,7 @@ void common_initialise_end_values(PublicKernelInputs const& public_kernel_in end.private_call_stack = start.private_call_stack; end.public_call_stack = start.public_call_stack; - end.l1_msg_stack = start.l1_msg_stack; + end.new_l2_to_l1_msgs = start.new_l2_to_l1_msgs; end.optionally_revealed_data = start.optionally_revealed_data; diff --git a/circuits/cpp/src/aztec3/circuits/rollup/base/.test.cpp b/circuits/cpp/src/aztec3/circuits/rollup/base/.test.cpp index 07a205324139..147a7f9eb678 100644 --- a/circuits/cpp/src/aztec3/circuits/rollup/base/.test.cpp +++ b/circuits/cpp/src/aztec3/circuits/rollup/base/.test.cpp @@ -575,8 +575,8 @@ TEST_F(base_rollup_tests, native_new_nullifier_tree_double_spend) TEST_F(base_rollup_tests, native_empty_block_calldata_hash) { DummyComposer composer = DummyComposer(); - // calldata_hash should be computed from leafs of 704 0 bytes. (0x00) - std::vector zero_bytes_vec(704, 0); + // calldata_hash should be computed from leafs of 832 0 bytes. (0x00) + std::vector zero_bytes_vec(832, 0); auto hash = sha256::sha256(zero_bytes_vec); BaseRollupInputs inputs = base_rollup_inputs_from_kernels({ get_empty_kernel(), get_empty_kernel() }); BaseOrMergeRollupPublicInputs outputs = @@ -603,48 +603,61 @@ TEST_F(base_rollup_tests, native_calldata_hash) // Execute the base rollup circuit with nullifiers, commitments and a contract deployment. Then check the calldata // hash against the expected value. std::array, 2> kernel_data = { get_empty_kernel(), get_empty_kernel() }; - std::vector input_data(704, 0); - - // Kernel 1 - // NOTE: nullifier insertions start from 8 as the generate_nullifier_tree_testing_values will populate the every - // nullifier leaf - for (uint8_t i = 0; i < 4; ++i) { - // nullifiers - input_data[i * 32 + 31] = i + 8; // 8 - kernel_data[0].public_inputs.end.new_nullifiers[i] = fr(i + 8); - - // commitments - input_data[8 * 32 + i * 32 + 31] = i + 1; // 1 - kernel_data[0].public_inputs.end.new_commitments[i] = fr(i + 1); - } - // Kernel 2 - for (uint8_t i = 0; i < 4; ++i) { - // nullifiers - input_data[(i + 4) * 32 + 31] = i + 12; // 1 - kernel_data[1].public_inputs.end.new_nullifiers[i] = fr(i + 12); - - // commitments - input_data[8 * 32 + (i + 4) * 32 + 31] = i + 4 + 1; // 1 - kernel_data[1].public_inputs.end.new_commitments[i] = fr(i + 4 + 1); - } + std::vector input_data(832, 0); - // Add a contract deployment - NewContractData new_contract = { - .contract_address = fr(1), - .portal_contract_address = fr(3), - .function_tree_root = fr(2), - }; - auto contract_leaf = crypto::pedersen_commitment::compress_native( - { new_contract.contract_address, new_contract.portal_contract_address, new_contract.function_tree_root }, - GeneratorIndex::CONTRACT_LEAF); - kernel_data[0].public_inputs.end.new_contracts[0] = new_contract; - auto contract_leaf_buffer = contract_leaf.to_buffer(); - auto contract_address_buffer = new_contract.contract_address.to_field().to_buffer(); - auto portal_address_buffer = new_contract.portal_contract_address.to_field().to_buffer(); - for (uint8_t i = 0; i < 32; ++i) { - input_data[16 * 32 + i] = contract_leaf_buffer[i]; - input_data[18 * 32 + i] = contract_address_buffer[i]; - input_data[20 * 32 + i] = portal_address_buffer[i]; + // @note Should we simply do this outside based on the kernels? + for (uint8_t kernel_i = 0; kernel_i < 2; kernel_i++) { + + uint32_t offset = 0; + // Nullifiers + for (uint8_t j = 0; j < KERNEL_NEW_NULLIFIERS_LENGTH; j++) { + uint8_t nullifier = (kernel_i * 4) + j + 16; + uint32_t dst = (kernel_i * 4 * 32) + (j * 32) + 31; // only inserting one byte + input_data[dst] = nullifier; + kernel_data[kernel_i].public_inputs.end.new_nullifiers[j] = nullifier; + } + offset += KERNEL_NEW_NULLIFIERS_LENGTH * 2 * 32; + + // Commitments + for (uint8_t j = 0; j < KERNEL_NEW_COMMITMENTS_LENGTH; j++) { + uint8_t commitment = (kernel_i * 4) + j + 32; + uint32_t dst = offset + (kernel_i * 4 * 32) + (j * 32) + 31; // only inserting one byte + input_data[dst] = commitment; + kernel_data[kernel_i].public_inputs.end.new_commitments[j] = commitment; + } + offset += KERNEL_NEW_COMMITMENTS_LENGTH * 2 * 32; + + // L2 to L1 Messages + for (uint8_t j = 0; j < KERNEL_NEW_L2_TO_L1_MSGS_LENGTH; j++) { + uint8_t l2_to_l1_message = (kernel_i * 2) + j + 48; + uint32_t dst = offset + (kernel_i * 2 * 32) + (j * 32) + 31; // only inserting one byte + input_data[dst] = l2_to_l1_message; + kernel_data[kernel_i].public_inputs.end.new_l2_to_l1_msgs[j] = l2_to_l1_message; + } + offset += KERNEL_NEW_L2_TO_L1_MSGS_LENGTH * 2 * 32; + + // Contracts + if (kernel_i == 0) { + // Contracts + NewContractData new_contract = { + .contract_address = fr(1), + .portal_contract_address = fr(3), + .function_tree_root = fr(2), + }; + auto contract_leaf = crypto::pedersen_commitment::compress_native({ new_contract.contract_address, + new_contract.portal_contract_address, + new_contract.function_tree_root }, + GeneratorIndex::CONTRACT_LEAF); + auto contract_leaf_buffer = contract_leaf.to_buffer(); + auto contract_address_buffer = new_contract.contract_address.to_field().to_buffer(); + auto portal_address_buffer = new_contract.portal_contract_address.to_field().to_buffer(); + for (uint8_t i = 0; i < 32; ++i) { + input_data[offset + kernel_i * 32 + i] = contract_leaf_buffer[i]; + input_data[offset + kernel_i * 2 * 32 + 2 * 32 + i] = contract_address_buffer[i]; + input_data[offset + kernel_i * 2 * 32 + 3 * 32 + i] = portal_address_buffer[i]; + } + kernel_data[kernel_i].public_inputs.end.new_contracts[0] = new_contract; + } } auto hash = sha256::sha256(input_data); 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 10ba6ad70af3..e29591f20436 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 @@ -75,25 +75,13 @@ std::vector calculate_contract_leaves(BaseRollupInputs const& baseRollup for (size_t i = 0; i < 2; i++) { - auto new_contacts = baseRollupInputs.kernel_data[i].public_inputs.end.new_contracts; + auto new_contracts = baseRollupInputs.kernel_data[i].public_inputs.end.new_contracts; // loop over the new contracts // TODO: NOTE: we are currently assuming that there is only going to be one - for (size_t j = 0; j < new_contacts.size(); j++) { - - NT::address contract_address = new_contacts[j].contract_address; - NT::address portal_contract_address = new_contacts[j].portal_contract_address; - NT::fr function_tree_root = new_contacts[j].function_tree_root; - - // Pedersen hash of the 3 fields (contract_address, portal_contract_address, function_tree_root) - auto contract_leaf = crypto::pedersen_commitment::compress_native( - { contract_address, portal_contract_address, function_tree_root }, GeneratorIndex::CONTRACT_LEAF); - - // When there is no contract deployment, we should insert a zero leaf into the tree and ignore the - // member-ship check. This is to ensure that we don't hit "already deployed" errors when we are not - // deploying contracts. e.g., when we are only calling functions on existing contracts. - auto to_push = contract_address == NT::address(0) ? NT::fr(0) : contract_leaf; - + for (size_t j = 0; j < new_contracts.size(); j++) { + auto leaf_preimage = new_contracts[j]; + auto to_push = leaf_preimage.contract_address == NT::address(0) ? NT::fr(0) : leaf_preimage.hash(); contract_leaves.push_back(to_push); } } @@ -142,35 +130,64 @@ NT::fr calculate_commitments_subtree(DummyComposer& composer, BaseRollupInputs c std::array calculate_calldata_hash(BaseRollupInputs const& baseRollupInputs, std::vector const& contract_leaves) { + + /** + * @brief Calculate the calldata hash for the base rollup (2 kernels) + * Note that the return value is two fields, as the sha256 is 32 bytes and we are using 254 bit field elements. + * Essentially, we are computing the hash of the following struct: + * Leaf_i = ( + * newNullifiersKernel1, + * newNullifiersKernel2, + * newCommitmentsKernel1, + * newCommitmentsKernel2, + * newL2ToL1MsgsKernel1, + * newL2ToL1MsgsKernel2, + * newContractLeafKernel1, + * newContractLeafKernel2, + * newContractDataKernel1.aztecAddress, + * newContractDataKernel1.ethAddress (padded to 32 bytes) + * newContractDataKernel2.aztecAddress, + * newContractDataKernel2.ethAddress (padded to 32 bytes) + * ); + */ // Compute calldata hashes - // 22 = (4 + 4 + 1 + 2) * 2 (2 kernels, 4 nullifiers per kernel, 4 commitments per kernel, 1 contract - // deployments, 2 contracts data fields (size 2 for each) ) - std::array calldata_hash_inputs; + // 26 = (4 + 4 + 2 + 1 + 2) * 2 (2 kernels, 4 nullifiers per kernel, 4 commitments per kernel, 2 l2 to l1_msgs per + // kernel, 1 contract deployments, 2 contracts data fields (size 2 for each) ) + std::array calldata_hash_inputs; for (size_t i = 0; i < 2; i++) { // Nullifiers auto new_nullifiers = baseRollupInputs.kernel_data[i].public_inputs.end.new_nullifiers; auto new_commitments = baseRollupInputs.kernel_data[i].public_inputs.end.new_commitments; + auto new_l2_to_l1_msgs = baseRollupInputs.kernel_data[i].public_inputs.end.new_l2_to_l1_msgs; + + size_t offset = 0; + + for (size_t j = 0; j < KERNEL_NEW_NULLIFIERS_LENGTH; j++) { + calldata_hash_inputs[offset + i * KERNEL_NEW_COMMITMENTS_LENGTH + j] = new_nullifiers[j]; + } + offset += KERNEL_NEW_NULLIFIERS_LENGTH * 2; + for (size_t j = 0; j < KERNEL_NEW_COMMITMENTS_LENGTH; j++) { - calldata_hash_inputs[i * KERNEL_NEW_COMMITMENTS_LENGTH + j] = new_nullifiers[j]; - calldata_hash_inputs[(KERNEL_NEW_NULLIFIERS_LENGTH * 2) + i * KERNEL_NEW_NULLIFIERS_LENGTH + j] = - new_commitments[j]; + calldata_hash_inputs[offset + i * KERNEL_NEW_NULLIFIERS_LENGTH + j] = new_commitments[j]; } + offset += KERNEL_NEW_COMMITMENTS_LENGTH * 2; - // yuck - TODO: is contract_leaves fixed size? - calldata_hash_inputs[16 + i] = contract_leaves[i]; + for (size_t j = 0; j < KERNEL_NEW_L2_TO_L1_MSGS_LENGTH; j++) { + calldata_hash_inputs[offset + i * KERNEL_NEW_L2_TO_L1_MSGS_LENGTH + j] = new_l2_to_l1_msgs[j]; + } + offset += KERNEL_NEW_L2_TO_L1_MSGS_LENGTH * 2; - auto new_contracts = baseRollupInputs.kernel_data[i].public_inputs.end.new_contracts; + calldata_hash_inputs[offset + i] = contract_leaves[i]; + offset += KERNEL_NEW_CONTRACTS_LENGTH * 2; - // TODO: this assumes that there is only one contract deployment - calldata_hash_inputs[18 + i] = new_contracts[0].contract_address; - calldata_hash_inputs[20 + i] = new_contracts[0].portal_contract_address; + auto new_contracts = baseRollupInputs.kernel_data[i].public_inputs.end.new_contracts; + calldata_hash_inputs[offset + i * 2] = new_contracts[0].contract_address; + calldata_hash_inputs[offset + i * 2 + 1] = new_contracts[0].portal_contract_address; } - // FIXME - // Calculate sha256 hash of calldata; TODO: work out typing here - // 22 * 32 = 22 fields, each 32 bytes - std::array calldata_hash_inputs_bytes; + // 26 * 32 = 26 fields, each 32 bytes + std::array calldata_hash_inputs_bytes; // Convert all into a buffer, then copy into the array, then hash for (size_t i = 0; i < calldata_hash_inputs.size(); i++) { auto as_bytes = calldata_hash_inputs[i].to_buffer(); @@ -178,7 +195,7 @@ std::array calculate_calldata_hash(BaseRollupInputs const& baseRollup auto offset = i * 32; std::copy(as_bytes.begin(), as_bytes.end(), calldata_hash_inputs_bytes.begin() + offset); } - // TODO: double check this gpt code + std::vector calldata_hash_inputs_bytes_vec(calldata_hash_inputs_bytes.begin(), calldata_hash_inputs_bytes.end()); diff --git a/circuits/cpp/src/aztec3/circuits/rollup/merge/.test.cpp b/circuits/cpp/src/aztec3/circuits/rollup/merge/.test.cpp index 8a3fa7a42082..288d26dc8416 100644 --- a/circuits/cpp/src/aztec3/circuits/rollup/merge/.test.cpp +++ b/circuits/cpp/src/aztec3/circuits/rollup/merge/.test.cpp @@ -215,7 +215,7 @@ TEST_F(merge_rollup_tests, native_start_and_end_snapshots) TEST_F(merge_rollup_tests, native_calldata_hash) { DummyComposer composer = DummyComposer(); - std::vector zero_bytes_vec(704, 0); + std::vector zero_bytes_vec(832, 0); auto call_data_hash_inner = sha256::sha256(zero_bytes_vec); std::array hash_input; diff --git a/circuits/cpp/src/aztec3/circuits/rollup/root/.test.cpp b/circuits/cpp/src/aztec3/circuits/rollup/root/.test.cpp index 7f0f3eaaa98f..f2f3a8ce7955 100644 --- a/circuits/cpp/src/aztec3/circuits/rollup/root/.test.cpp +++ b/circuits/cpp/src/aztec3/circuits/rollup/root/.test.cpp @@ -77,8 +77,10 @@ using aztec3::circuits::apps::test_apps::escrow::deposit; using aztec3::circuits::kernel::private_kernel::utils::dummy_previous_kernel; using aztec3::circuits::mock::mock_kernel_circuit; using aztec3::circuits::rollup::test_utils::utils::get_empty_kernel; +using aztec3::circuits::rollup::test_utils::utils::get_initial_nullifier_tree; using aztec3::circuits::rollup::test_utils::utils::get_root_rollup_inputs; using aztec3::circuits::rollup::test_utils::utils::set_kernel_commitments; +using aztec3::circuits::rollup::test_utils::utils::set_kernel_l2_to_l1_msgs; using aztec3::circuits::rollup::test_utils::utils::set_kernel_nullifiers; // using aztec3::circuits::mock::mock_kernel_inputs; @@ -166,7 +168,7 @@ class root_rollup_tests : public ::testing::Test { TEST_F(root_rollup_tests, native_calldata_hash_empty_blocks) { - std::vector zero_bytes_vec(704, 0); + std::vector zero_bytes_vec(832, 0); auto call_data_hash_inner = sha256::sha256(zero_bytes_vec); std::array hash_input; @@ -201,7 +203,8 @@ TEST_F(root_rollup_tests, native_calldata_hash_empty_blocks) EXPECT_FALSE(composer.failed()); // Expected hash of public inputs for an empty L2 block. Also used in the contract tests. - fr expected_hash = uint256_t("0013b2202a3e48b039cda7eef0976060d86e610d77fc9bb8cd5b0f1b561df48c"); + // Can be computed using the typescript l2_block's helper functions (see circuit_block_builder.test.ts) + fr expected_hash = uint256_t("2b9b56549c50cad1f6329a594979cf9a1d71f87f24c2a1bf33fe7743faabaaeb"); ASSERT_EQ(outputs.hash(), expected_hash); run_cbind(inputs, outputs, true); @@ -209,6 +212,7 @@ TEST_F(root_rollup_tests, native_calldata_hash_empty_blocks) TEST_F(root_rollup_tests, native_root_missing_nullifier_logic) { + // Creates the same block as we have for solidity tests and in typescript. utils::DummyComposer composer = utils::DummyComposer(); MemoryTree data_tree = MemoryTree(PRIVATE_DATA_TREE_HEIGHT); @@ -224,36 +228,44 @@ TEST_F(root_rollup_tests, native_root_missing_nullifier_logic) get_empty_kernel(), get_empty_kernel(), get_empty_kernel(), get_empty_kernel() }; - // Create commitments - for (uint8_t kernel_j = 0; kernel_j < 4; kernel_j++) { - std::array new_commitments; - for (uint8_t commitment_k = 0; commitment_k < KERNEL_NEW_COMMITMENTS_LENGTH; commitment_k++) { - auto val = fr(kernel_j * KERNEL_NEW_COMMITMENTS_LENGTH + commitment_k + 1); - new_commitments[commitment_k] = val; - data_tree.update_element(kernel_j * KERNEL_NEW_COMMITMENTS_LENGTH + commitment_k, val); - } - set_kernel_commitments(kernels[kernel_j], new_commitments); + set_kernel_commitments(kernels[0], { 257, 258, 259, 260 }); + for (size_t i = 0; i < 4; i++) { + data_tree.update_element(i, 257 + i); + } + + set_kernel_nullifiers(kernels[0], { 513, 514, 515, 516 }); + auto nullifier_tree = get_initial_nullifier_tree({ 1, 2, 3, 4, 5, 6, 7 }); + for (size_t i = 0; i < 4; i++) { + nullifier_tree.update_element(513 + i); } - // TODO: Add nullifiers + set_kernel_l2_to_l1_msgs(kernels[0], { 1281, 1282 }); + + /*std::vector buffer = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x03 }; + // Initialize a pointer to the start of the buffer + uint8_t const* it = buffer.data(); + // Initialize a ContractData object + NewContractData new_contract_data; + // Read data from the buffer into the ContractData object + read(it, new_contract_data); + info(new_contract_data, " -> ", new_contract_data.hash());*/ - // Contract tree NewContractData new_contract = { - .contract_address = fr(1), - .portal_contract_address = fr(3), - .function_tree_root = fr(2), + .contract_address = fr(1537), + .portal_contract_address = uint256_t("0000000000000000000000000202020202020202020202020202020202020202"), + .function_tree_root = fr(1539), }; - auto contract_leaf = crypto::pedersen_commitment::compress_native( - { - new_contract.contract_address, - new_contract.portal_contract_address, - new_contract.function_tree_root, - }, - GeneratorIndex::CONTRACT_LEAF); - - // Update contract tree - contract_tree.update_element(2, contract_leaf); - kernels[2].public_inputs.end.new_contracts[0] = new_contract; + + // todo: Something is not right down here. I'm getting different hashes on same leaf preimage + info("contract: ", new_contract.hash()); + + contract_tree.update_element(0, new_contract.hash()); + kernels[0].public_inputs.end.new_contracts[0] = new_contract; // The start historic data snapshot AppendOnlyTreeSnapshot start_historic_data_tree_snapshot = { .root = historic_data_tree.root(), @@ -275,6 +287,10 @@ TEST_F(root_rollup_tests, native_root_missing_nullifier_logic) RootRollupPublicInputs outputs = aztec3::circuits::rollup::native_root_rollup::root_rollup_circuit(composer, rootRollupInputs); + // info(outputs); + info("public output hash: ", outputs.hash()); + info("root: ", contract_tree.root()); + // Check data trees ASSERT_EQ( outputs.start_private_data_tree_snapshot, @@ -286,6 +302,9 @@ TEST_F(root_rollup_tests, native_root_missing_nullifier_logic) .next_available_leaf_index = 16 }; ASSERT_EQ(outputs.end_private_data_tree_snapshot, expected_data_tree_snapshot); + // Something wrong with contract tree? 0xf0c1d03ac280b15abbdfa91faa6137b216b9c29d83d30c1c9ce925ad4379fa6 + // Why are we getting things that is so different from typescript? + // check contract trees ASSERT_EQ(outputs.start_contract_tree_snapshot, rootRollupInputs.previous_rollup_data[0].base_or_merge_rollup_public_inputs.start_contract_tree_snapshot); @@ -305,6 +324,9 @@ TEST_F(root_rollup_tests, native_root_missing_nullifier_logic) ASSERT_EQ(outputs.start_tree_of_historic_contract_tree_roots_snapshot, start_historic_contract_tree_snapshot); ASSERT_EQ(outputs.end_tree_of_historic_contract_tree_roots_snapshot, end_historic_contract_tree_snapshot); + fr expected = uint256_t("20638cd5e03d287dbd356af6e16fd852337f535b12d06f7266599c035696098d"); + ASSERT_EQ(outputs.hash(), expected); + EXPECT_FALSE(composer.failed()); } diff --git a/circuits/cpp/src/aztec3/circuits/rollup/test_utils/utils.cpp b/circuits/cpp/src/aztec3/circuits/rollup/test_utils/utils.cpp index 693184d71992..8cf7316f063b 100644 --- a/circuits/cpp/src/aztec3/circuits/rollup/test_utils/utils.cpp +++ b/circuits/cpp/src/aztec3/circuits/rollup/test_utils/utils.cpp @@ -67,6 +67,15 @@ void set_kernel_commitments(KernelData& kernel_data, std::array new_l2_to_l1_msgs) +{ + for (size_t i = 0; i < KERNEL_NEW_L2_TO_L1_MSGS_LENGTH; i++) { + kernel_data.public_inputs.end.new_l2_to_l1_msgs[i] = new_l2_to_l1_msgs[i]; + } +} + + BaseRollupInputs base_rollup_inputs_from_kernels(std::array kernel_data, MerkleTree& private_data_tree, MerkleTree& contract_tree, @@ -242,10 +251,9 @@ std::array, 2> get_previous_rollup_data(DummyComposer& co kernel_data[i].public_inputs.end.new_commitments[j]); } auto contract_data = kernel_data[i].public_inputs.end.new_contracts[0]; - auto contract_leaf = crypto::pedersen_commitment::compress_native( - { contract_data.contract_address, contract_data.portal_contract_address, contract_data.function_tree_root }, - GeneratorIndex::CONTRACT_LEAF); - contract_tree.update_element(i, contract_leaf); + if (contract_data.contract_address != 0) { + contract_tree.update_element(i, contract_data.hash()); + } for (size_t j = 0; j < KERNEL_NEW_NULLIFIERS_LENGTH; j++) { initial_values.push_back(kernel_data[i].public_inputs.end.new_nullifiers[j]); nullifiers[i * KERNEL_NEW_NULLIFIERS_LENGTH + j] = kernel_data[2 + i].public_inputs.end.new_nullifiers[j]; @@ -263,7 +271,7 @@ std::array, 2> get_previous_rollup_data(DummyComposer& co // @todo Need an additional tests to check that these below are correct. // Changing the index in private tree still pass tests etc (16). base_rollup_input_2.new_contracts_subtree_sibling_path = - get_sibling_path(contract_tree, 1, CONTRACT_SUBTREE_DEPTH); + get_sibling_path(contract_tree, 2, CONTRACT_SUBTREE_DEPTH); base_rollup_input_2.new_commitments_subtree_sibling_path = get_sibling_path(private_data_tree, 8, PRIVATE_DATA_SUBTREE_DEPTH); diff --git a/circuits/cpp/src/aztec3/circuits/rollup/test_utils/utils.hpp b/circuits/cpp/src/aztec3/circuits/rollup/test_utils/utils.hpp index b1a237487522..baaa42799e60 100644 --- a/circuits/cpp/src/aztec3/circuits/rollup/test_utils/utils.hpp +++ b/circuits/cpp/src/aztec3/circuits/rollup/test_utils/utils.hpp @@ -48,15 +48,11 @@ template std::array get_sibling_path(MerkleTree& tree, size_t leafIndex, size_t const& subtree_depth_to_skip) { std::array siblingPath; - auto path = tree.get_hash_path(leafIndex); + auto path = tree.get_sibling_path(leafIndex); // slice out the skip leafIndex = leafIndex >> (subtree_depth_to_skip); for (size_t i = 0; i < N; i++) { - if (leafIndex & (1 << i)) { - siblingPath[i] = path[subtree_depth_to_skip + i].first; - } else { - siblingPath[i] = path[subtree_depth_to_skip + i].second; - } + siblingPath[i] = path[subtree_depth_to_skip + i]; } return siblingPath; } @@ -99,6 +95,9 @@ void set_kernel_commitments(KernelData& kernel_data, std::array new_nullifiers); +void set_kernel_l2_to_l1_msgs(KernelData& kernel_data, + std::array new_l2_to_l1_msgs); + MergeRollupInputs get_merge_rollup_inputs(utils::DummyComposer& composer, std::array kernel_data); inline abis::PublicDataWrite make_public_write(fr leaf_index, fr old_value, fr new_value) diff --git a/circuits/cpp/src/aztec3/constants.hpp b/circuits/cpp/src/aztec3/constants.hpp index b961b50eeab4..e010eae9c8dc 100644 --- a/circuits/cpp/src/aztec3/constants.hpp +++ b/circuits/cpp/src/aztec3/constants.hpp @@ -10,20 +10,20 @@ constexpr size_t EMITTED_EVENTS_LENGTH = 4; constexpr size_t NEW_COMMITMENTS_LENGTH = 4; constexpr size_t NEW_NULLIFIERS_LENGTH = 4; +constexpr size_t NEW_L2_TO_L1_MSGS_LENGTH = 2; constexpr size_t STATE_TRANSITIONS_LENGTH = 4; constexpr size_t STATE_READS_LENGTH = 4; constexpr size_t PRIVATE_CALL_STACK_LENGTH = 4; constexpr size_t PUBLIC_CALL_STACK_LENGTH = 4; -constexpr size_t L1_MSG_STACK_LENGTH = 2; constexpr size_t KERNEL_NEW_COMMITMENTS_LENGTH = 4; constexpr size_t KERNEL_NEW_NULLIFIERS_LENGTH = 4; +constexpr size_t KERNEL_NEW_L2_TO_L1_MSGS_LENGTH = 2; constexpr size_t KERNEL_NEW_CONTRACTS_LENGTH = 1; constexpr size_t KERNEL_PRIVATE_CALL_STACK_LENGTH = 8; constexpr size_t KERNEL_PUBLIC_CALL_STACK_LENGTH = 8; -constexpr size_t KERNEL_L1_MSG_STACK_LENGTH = 4; constexpr size_t KERNEL_OPTIONALLY_REVEALED_DATA_LENGTH = 4; constexpr size_t VK_TREE_HEIGHT = 3; diff --git a/l1-contracts/src/core/Decoder.sol b/l1-contracts/src/core/Decoder.sol index 9ee67b693dce..a025cc163f75 100644 --- a/l1-contracts/src/core/Decoder.sol +++ b/l1-contracts/src/core/Decoder.sol @@ -40,15 +40,19 @@ pragma solidity >=0.8.18; * | 0x170 | x | newCommits * | 0x170 + x | 0x04 | len(newNullifiers) denoted y * | 0x174 + x | y | newNullifiers - * | 0x174 + x + y | 0x04 | len(newContracts) denoted z - * | 0x178 + x + y | z | newContracts - * | 0x178 + x + y + z | z | newContractData + * | 0x174 + x + y | 0x04 | len(newL2ToL1msgs) denoted z + * | 0x178 + x + y | z | newL2ToL1msgs + * | 0x178 + x + y + z | 0x04 | len(newContracts) denoted v + * | 0x17c + x + y + z | v | newContracts + * | 0x17c + x + y + z + v | v | newContractData * |--- |--- | --- - * + * TODO: Actually the byte start are not with x,y,z,v but multiplied by the size... of the types most are 32 bytes + * but newContractData is 52 bytes. */ contract Decoder { uint256 internal constant COMMITMENTS_PER_KERNEL = 4; uint256 internal constant NULLIFIERS_PER_KERNEL = 4; + uint256 internal constant L2_TO_L1_MSGS_PER_KERNEL = 2; // Prime field order uint256 internal constant P = @@ -58,8 +62,8 @@ contract Decoder { * @notice Decodes the inputs and computes values to check state against * @param _l2Block - The L2 block calldata. * @return l2BlockNumber - The L2 block number. - * @return oldStateHash - The state hash expected prior the execution. - * @return newStateHash - The state hash expected after the execution. + * @return startStateHash - The state hash expected prior the execution. + * @return endStateHash - The state hash expected after the execution. * @return publicInputHash - The hash of the public inputs */ function _decode(bytes calldata _l2Block) @@ -67,16 +71,16 @@ contract Decoder { pure returns ( uint256 l2BlockNumber, - bytes32 oldStateHash, - bytes32 newStateHash, + bytes32 startStateHash, + bytes32 endStateHash, bytes32 publicInputHash ) { l2BlockNumber = _getL2BlockNumber(_l2Block); - // Note, for oldStateHash to match the storage, the l2 block number must be new - 1. + // Note, for startStateHash to match the storage, the l2 block number must be new - 1. // Only jumping 1 block at a time. - oldStateHash = _computeStateHash(l2BlockNumber - 1, 0x4, _l2Block); - newStateHash = _computeStateHash(l2BlockNumber, 0xb8, _l2Block); + startStateHash = _computeStateHash(l2BlockNumber - 1, 0x4, _l2Block); + endStateHash = _computeStateHash(l2BlockNumber, 0xb8, _l2Block); publicInputHash = _computePublicInputsHash(_l2Block); } @@ -142,6 +146,8 @@ contract Decoder { struct Vars { uint256 commitmentCount; + uint256 nullifierCount; + uint256 l2ToL1msgCount; uint256 kernelCount; uint256 contractCount; } @@ -155,19 +161,37 @@ contract Decoder { Vars memory vars; { uint256 commitmentCount; + uint256 nullifierCount; + uint256 l2ToL1msgCount; assembly { commitmentCount := and(shr(224, calldataload(add(_l2Block.offset, 0x16c))), 0xffffffff) + nullifierCount := + and( + shr(224, calldataload(add(_l2Block.offset, add(0x170, mul(commitmentCount, 0x20))))), + 0xffffffff + ) + l2ToL1msgCount := + and( + shr( + 224, + calldataload( + add(_l2Block.offset, add(0x174, mul(add(nullifierCount, commitmentCount), 0x20))) + ) + ), + 0xffffffff + ) } vars.commitmentCount = commitmentCount; + vars.nullifierCount = nullifierCount; + vars.l2ToL1msgCount = l2ToL1msgCount; vars.kernelCount = commitmentCount / COMMITMENTS_PER_KERNEL; uint256 contractCountOffset = - vars.kernelCount * (COMMITMENTS_PER_KERNEL + NULLIFIERS_PER_KERNEL) * 0x20; - + (vars.commitmentCount + vars.nullifierCount + vars.l2ToL1msgCount) * 0x20; uint256 newContractCount; assembly { newContractCount := and( - shr(224, calldataload(add(_l2Block.offset, add(0x174, contractCountOffset)))), 0xffffffff + shr(224, calldataload(add(_l2Block.offset, add(0x178, contractCountOffset)))), 0xffffffff ) } vars.contractCount = newContractCount; @@ -175,13 +199,10 @@ contract Decoder { bytes32[] memory baseLeafs = new bytes32[](vars.kernelCount / 2); - uint256 dstCommitmentOffset = COMMITMENTS_PER_KERNEL * 0x20 * 0x2; - uint256 dstContractOffset = dstCommitmentOffset + NULLIFIERS_PER_KERNEL * 0x20 * 0x2; - uint256 srcCommitmentOffset = 0x170; - uint256 srcNullifierOffset = 0x174 + vars.commitmentCount * 0x20; - uint256 srcContractOffset = - 0x178 + (baseLeafs.length * 2 * (NULLIFIERS_PER_KERNEL + COMMITMENTS_PER_KERNEL) * 0x20); + uint256 srcNullifierOffset = srcCommitmentOffset + 0x4 + vars.commitmentCount * 0x20; + uint256 srcL2ToL1msgOffset = srcNullifierOffset + 0x4 + vars.nullifierCount * 0x20; + uint256 srcContractOffset = srcL2ToL1msgOffset + 0x4 + vars.l2ToL1msgCount * 0x20; uint256 srcContractDataOffset = srcContractOffset + vars.contractCount * 0x20; for (uint256 i = 0; i < baseLeafs.length; i++) { @@ -192,6 +213,8 @@ contract Decoder { * newNullifiersKernel2, * newCommitmentsKernel1, * newCommitmentsKernel2, + * newL2ToL1MsgsKernel1, + * newL2ToL1MsgsKernel2, * newContractLeafKernel1, * newContractLeafKernel2, * newContractDataKernel1.aztecAddress, @@ -202,47 +225,66 @@ contract Decoder { * Note that we always read data, the l2Block (atm) must therefore include dummy or zero-notes for * Zero values. */ - bytes memory baseLeaf = new bytes(0x2c0); + bytes memory baseLeaf = new bytes(0x340); assembly { // Adding new nullifiers calldatacopy(add(baseLeaf, 0x20), add(_l2Block.offset, srcNullifierOffset), mul(0x08, 0x20)) // Adding new commitments + let dstCommitmentOffset := mul(0x20, 0x08) calldatacopy( add(baseLeaf, add(0x20, dstCommitmentOffset)), add(_l2Block.offset, srcCommitmentOffset), mul(0x08, 0x20) ) + // Adding new L2ToL1Msgs + let dstL2ToL1msgOffset := add(dstCommitmentOffset, mul(0x20, 0x8)) + calldatacopy( + add(baseLeaf, add(0x20, dstL2ToL1msgOffset)), + add(_l2Block.offset, srcL2ToL1msgOffset), + mul(0x04, 0x20) + ) + // Adding Contract Leafs + let dstContractOffset := add(dstL2ToL1msgOffset, mul(0x20, 0x4)) calldatacopy( add(baseLeaf, add(0x20, dstContractOffset)), add(_l2Block.offset, srcContractOffset), mul(2, 0x20) ) + dstContractOffset := add(dstContractOffset, 0x40) // Kernel1.contract.aztecaddress calldatacopy( - add(baseLeaf, add(0x20, add(dstContractOffset, 0x40))), + add(baseLeaf, add(0x20, dstContractOffset)), add(_l2Block.offset, srcContractDataOffset), 0x20 ) + dstContractOffset := add(dstContractOffset, 0x20) + // Kernel1.contract.ethAddress padded to 32 bytes + dstContractOffset := add(dstContractOffset, 0xc) calldatacopy( - add(baseLeaf, add(0x20, add(dstContractOffset, 0x6c))), + add(baseLeaf, add(0x20, dstContractOffset)), add(_l2Block.offset, add(srcContractDataOffset, 0x20)), 0x14 ) + dstContractOffset := add(dstContractOffset, 0x20) + // Kernel2.contract.aztecaddress calldatacopy( - add(baseLeaf, add(0x20, add(dstContractOffset, 0x80))), + add(baseLeaf, add(0x20, dstContractOffset)), add(_l2Block.offset, add(srcContractDataOffset, 0x34)), 0x20 ) + dstContractOffset := add(dstContractOffset, 0x20) + // Kernel2.contract.ethAddress padded to 32 bytes + dstContractOffset := add(dstContractOffset, 0xc) calldatacopy( - add(baseLeaf, add(0x20, add(dstContractOffset, 0xac))), + add(baseLeaf, add(0x20, dstContractOffset)), add(_l2Block.offset, add(srcContractDataOffset, 0x54)), 0x14 ) @@ -250,6 +292,7 @@ contract Decoder { srcCommitmentOffset += 2 * COMMITMENTS_PER_KERNEL * 0x20; srcNullifierOffset += 2 * NULLIFIERS_PER_KERNEL * 0x20; + srcL2ToL1msgOffset += 2 * L2_TO_L1_MSGS_PER_KERNEL * 0x20; srcContractOffset += 2 * 0x20; srcContractDataOffset += 2 * 0x34; diff --git a/l1-contracts/src/core/Rollup.sol b/l1-contracts/src/core/Rollup.sol index 4b1653020546..e09b66b98c2c 100644 --- a/l1-contracts/src/core/Rollup.sol +++ b/l1-contracts/src/core/Rollup.sol @@ -31,12 +31,12 @@ contract Rollup is Decoder { * @param _l2Block - The L2Block data, formatted as outlined in `Decoder.sol` */ function process(bytes memory _proof, bytes calldata _l2Block) external { - (uint256 l2BlockNumber, bytes32 oldStateHash, bytes32 newStateHash, bytes32 publicInputHash) = + (uint256 l2BlockNumber, bytes32 startStateHash, bytes32 endStateHash, bytes32 publicInputHash) = _decode(_l2Block); // @todo Proper genesis state. If the state is empty, we allow anything for now. - if (rollupStateHash != bytes32(0) && rollupStateHash != oldStateHash) { - revert InvalidStateHash(rollupStateHash, oldStateHash); + if (rollupStateHash != bytes32(0) && rollupStateHash != startStateHash) { + revert InvalidStateHash(rollupStateHash, startStateHash); } bytes32[] memory publicInputs = new bytes32[](1); @@ -46,7 +46,7 @@ contract Rollup is Decoder { revert InvalidProof(); } - rollupStateHash = newStateHash; + rollupStateHash = endStateHash; emit L2BlockProcessed(l2BlockNumber); } diff --git a/l1-contracts/src/periphery/UnverifiedDataEmitter.sol b/l1-contracts/src/periphery/UnverifiedDataEmitter.sol index 8933f1157d6e..c0285c221ada 100644 --- a/l1-contracts/src/periphery/UnverifiedDataEmitter.sol +++ b/l1-contracts/src/periphery/UnverifiedDataEmitter.sol @@ -13,7 +13,12 @@ contract UnverifiedDataEmitter { * @param portalAddress - The address of the L1 counterparty * @param acir - The acir bytecode of the L2 contract */ - event ContractDeployment(uint256 indexed l2BlockNum, bytes32 indexed aztecAddress, address indexed portalAddress, bytes acir); + event ContractDeployment( + uint256 indexed l2BlockNum, + bytes32 indexed aztecAddress, + address indexed portalAddress, + bytes acir + ); /** * @notice Used to share data which are not required to advance the state but are needed for other purposes diff --git a/l1-contracts/test/Decoder.t.sol b/l1-contracts/test/Decoder.t.sol index 5efef377203d..c0582e5d27c8 100644 --- a/l1-contracts/test/Decoder.t.sol +++ b/l1-contracts/test/Decoder.t.sol @@ -20,45 +20,176 @@ contract DecodeHelper is Decoder { } } -// Blocks generated with https://gist.github.com/LHerskind/dccc762ee539b7b0984bf51af6f51dbb +// Blocks generated using `circuit_block_builder.test.ts` contract DecoderTest is Test { Rollup internal rollup; DecodeHelper internal helper; bytes block_1 = - hex"0000000100000000026d27850fe7ca39749085f2a0dbde5776a38f37c982f024c4faec2cd51256a60000000092fda1d4e2f4d04645a5afab97c83831498573057c6274f975881bb93b16b0d60000000090e5ba6910314bb2d7175be5ab6cdd176bde431d3d9cc7ce2672c468ca57aab6000000008071532a7f22610b60a373b954208a01dc1058934e174c241a4825e1b04a59040000000055bcd75383e3c233124ca4b26857cf9d8474c78a063ceedd507726a7bc13254400000020496c61142f126c578fa762940fce65490ecb9dbb408a66b9275601725b16b827000000207728207bac279dbf8b7b5652b8b8c3619f65d007a7534015d0daf0a960e1550d00000008a71730065c0684ba4aa476b4ab3494db58b08ef8813cd0d4a456553ac046bf7a0000000172c52733e1b74bb841e89cfb2f9f6f08956d7d6c685073326442792d88e9cd1b000000019deecf3cb56703b46813472708f3085f00df5371fc20312b815063fa93ac55240000002004cf027a8ea6e124d01b5254a7c75f10aa2c849c016d3c7178f2f5b1b179c9e8830ffba67f219f3effa813a4669c84dec9b19c59c7dbbdc90a2b9ff701ff5045c7f12f133011953b37eb73a884c81b38d9b2ace4b224f81e6999a24b2f482e6a051742efabc5bf8b8649c6ca15ae9ae240483e6e64618ce2754c26d9a2bf2c5c780c2a3ff698bc4c750d5ff8fa74036e5562e8d89890c2dacb6d700f6b12f7dacfecafccd86a18d427d84d4bb8e0719feddd0bd4c248cff5889bb7e475e568784bdb542193a2752c78984436e8033e27030f1367819db683f004942872d3ef1c64dcd775fd8941913a85c0793160540be74e880dcf0649e3811d41d8eddaf1c3f8e487b4111d92ef95b7dd49fdc1591d17a9e5cc18eb547b318b09423c4a84131350f4b91f3c164aff80fe8e90c0a5e42d238fbddc22c0d89a510c1fea0839fedd1823ea7ec85c12461455881532f0fadc1786575ac924cfcc4edc44b4f8cd33ae54270c59b8d76198cc830453034e3a51dc30f6f5628b61c2467670de2dba1768a36430479247742a2238159cfb6328c3f27406d06d196319a993121ac74a89278d21b6e5cc1630f8929f5459a7038378814113a4d28712c670241ec3f76b85ac52e31dc9e22d55d290076829d9562c4e14ffccbeb9368c3ddc9eabf502b8e151a174b3bdbc202f98e4159b5be14fd57bc794523e9b305a284efaff9d06b5507829918a5292f07d2af3786ea18b46783b214ce79d8aaf3f25f05769cbae80bd7d211e94158f08a82cc1e745998074434360473dfa3145c368b08099578f356ea1b726e45ffda553180cd8f867c1656cdee5bd93513a745e7f4db6c78be52463088865aca180f5a5b241883c799d080d9af89cc7255b22ca9e007c54120e6b2d167bb9aa784941eeaea077e688f78c57c8460a2de65a5d6c0e18c751f301a691f1ede68c63593015ac2bc4867438a9082f4eed9778735ba5efe4f40b88af2b874951c60f1e1c89308684a3ef513589ff4f167e8471fbefa9eecc22de2d575625e87f8afb4fc5725780971dc16714d799c6563a7e8f603152aec76143efda4e7a8d72c82aa1a086e4545839636489815beeed36a17d744adc90ff20600691af9f74b64f3d5e83bb78bfbcbb31f969d01ba4e248737839afdc448ad3596fb2c464189b25c23038e1212710bd0667b3ef8ce232ffdeeeb1333d34d96f4c0713e39393e7d4bc660ec93c1c6d7fee494b10116f0380296c91d044b4d2ecb15294b520b8df116d106a42d9a460b6689f56fe8cac679e784ba7c8e64cc954b1ddfc8d811d2a45db2b3ef41269853dfc835fc2cab2d57e90494bf8250c6b90ed87477b1de6f28418e5c7a820aae2b4a1ce80c3f2807f1134e516371c997a414b790a65987e43ad32ab2182a0bc5772f9e42fad34319695e3857152040ab8c0bd64f18f33000000201ce5a42ecad03ede45ee270fd83aaab4bcb5bb11650a3f3cbb0a5b3266e676badba6aed51f14f10aacdaa9969745085353c0daf62dcd0cdaf56b7d8fac4a6a875c014e536d128d30cc6e184f7e4c88c6653aeb98732d82eb04eb9776b798707c461d8fb1bbcc44fe3db8d3845edb9ed468e0ea360b71c3354335d740069f4ec9764291034a710d6ee9845cd37d283153e70d4c85c6ecb202d5b76c5d9885afbcb8daf4c354e7772bbd880e86c3caaf527c9e37d80136285d05c4918d0e469b9a1e8d389d91cf64978d20175de676635e2915c619367e5093b6bd4aed7de6368ed77715c112d9b47d0e3597e1cf250a7e9ccc7c2919c584f62ad3499c6ed42d243c32ef99a2033d3bcaa5014188ca3a93376c1e08e47b48e1a6fc5a27c5e5dd7bbd7dbdd5020f29b66cd21d05a589cd704dbb1d4cf220fda802308472b786acd9346ce2999ffc43ebee8b46e40eef7aa41f88effe0a45c1d45245ac4109ef429cf0a59be7d0784d55cd25a4165a53f741d96a96b4358684d0280fbb8af43cf6afd59522e2f7ff1896296a560b1ed4e9532b41cc8d83c1e62b8b9d8e5d92561a66c9c9b661d27edf5b93931b95abb047650f3ab9d169d5c145d0325c4e913903987f3342cf3761bbcf58724fc13761114c97eaeabdc6d578c8ee39493377e6ae50bd6441f7334b57a96d9a0a6fce410de5d2aea385ee8c82788d3f3901278d49e101ed81d2ae4578d949a0fcf400ec9357c1e7d957c214b9e0b248aef8fdfd4ca50a039b493d87e5b41dde5f2ae56faa39547c924877f00ef56eb0b322c3f52bc1d47dcd12baafabab9f32311f355674550d0fbe51cb47c3ebbdfb9ef02713476f6aec98d64d596126146a4944fd6277065c692c726d6da6eefbd99852dc81765f278af17b49440a2b2730b76ea84cfaaf08a62de1124668551f6f3cc2a33d5d12796883693224bd43e70a979b900e88cc2c24d3db53bdcd82aa17a047674a5eb45a874a95186df03a4eac54a434b7b87943e5acd9561c9e09513f1bb60d96c0472faba31dc35d73affd2ae0757f07cfc23dc6c9e2c4dff4945d46f9d52e8bd9c74aca381af2e59f41640b14898a8f75adf7cfbc6c105844b580fcbc59a4c1f5e315beda39680ff392963fa4551a62e87feda484215a804ea4af55c52c6d7f77c3876615dc42e6476fd974e405fd2d16c086856fc1ad9420a581b770e9cbb807e6f171a2e3c491ac66de2b1adbc0ee3fd18277737340aa9b310342db71f344ac4f10b63cb23d5dd6de4a3566f1e948cddbed83538a7e3450c4870cd26da87e23c0bf66a5f5aa22fbd56984776ecbefbfbe276143d1fdabc2be4893c4cf438c8fea24dca9bcc03a076c56da333cc05213aa27c0f2aeea7583d499e62dbb84eabf6113e8a444dd3c3a04b09263bfe3248780c97ef8c5a6654a7f7c20729fb1a6c82e00000008fc7168914fb3f34b544b555c3079e18f0716b2e43062e1950d3a172dd2cc4e096d91f2f077802f217a1ba3f1b0c58bdb043914986e2ab375c2b2fc9cc069d09ec7b9f210134fce1e78b70e9f9f2a2ac4514bab668e99f0d0106006a62dbbf708fb5175774909691ff8fefd94a11bb37c3818ceb9e3335d7085bcbeb0cc8bf656985fcb53efd11f7e8808aacd0c7c5f244271aeb342f0f12656659960090926f31a61aef1c654db3b36b53d03453288fd92bcb30aefd36460330be3b9814669645e9344aa54e1deda1016d4ef3b3ae6c9da8c0ad19db46ad28bac03d34d7166b6fe280594b84df03effd72731c2f5d92dd2bae2b06ce45832bb3b7e9ae0041166d2a4c0c019fb4c3c865803a447b3895a18d456c66abfab8899db9c3d38b9af457feeae39874c79a99a998a31c0accf85edb4b8e9810f843ac6b8f7200760e95b2d5e0e34105fb39c2a7066865523132cdd40d0cd2f6aef3948e85259513b383a7a6db167d1804d93c99eb78c317288b4ebae14854b841b9825923812f9293d3d85e3942835f3cab7170a5c61bcb021b1cf773e1fe652381fad61f4cb4a43465b630212ca6e0223c2d20f30bc374e78fc79ec8d4fbeb4eae6d431ec0d306ccca543d0ab9ea6fe1724e1cef669e9254c8e036e0d856e241521e33bde0551e84260a5dd29fec18c1716f9a5e7bbc74eabc4dcee065c3770aa78bcb8404408e1b436f23cc3451811f331e0f75c607710a0838a42a373a690dc352d06dd4f5d21388de63678f61b6d02d8f3e9fe7e8a1e64c1a441df94a83295d6f6609580871767d29294e57e943895bf3b85a8b6ea33932379943e80e689b80455026dfe6a5d2f0544c25ee0f11d89d1bef2832080d95c4d39f6048b7e0db6d771154a321d2979ed36bcc70a9ea2fb3583844ff30a11a80197225cf7d1a7e8e4cef24f443c13ff08"; + hex"000000010668938c4a4167faa2b5031e427d74d6e38638d2eef68834b70480c5a93f8e15000000002d39729fd006096882acfbd350c91fd61883578b4fe35b63cdce3c1993a497ea000000082f8dc86ba80d8fcf491fb7a255f4163e4f9601d022ba0be35f13297531073fd80000000019c36f7bc2e4116d082865cc0b4ac8e16e9efa00ace9fb2222dd1dfd719cb671000000012b36b22912aa963f143c490227bd21e7a44338026b2f6a389cb98e82167c3718000000010283622796e1a2fa4718e254eb46d3f4287b05a5aaee35af02a54f2af8362f97000000101f99db4b9ffa5ab637607ad50c7d10ea3352a53478e14354355a02b6a87a7ab1000000181ba22861f1a04d910c399ce20125a7ef53c3a47e0f51fe1d2c179ea83b8da34e0000000415db3dd5c4e4589c0b7a5942f81c11548dda500600adefeb8c49d13481a88e24000000022309e4044d29f2906c728a7d19672aa7d80f3fbc289d4dd6fcab93f1e197b727000000020000001000000000000000000000000000000000000000000000000000000000000001010000000000000000000000000000000000000000000000000000000000000102000000000000000000000000000000000000000000000000000000000000010300000000000000000000000000000000000000000000000000000000000001040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002010000000000000000000000000000000000000000000000000000000000000202000000000000000000000000000000000000000000000000000000000000020300000000000000000000000000000000000000000000000000000000000002040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000005010000000000000000000000000000000000000000000000000000000000000502000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041b024f6e2e258ac4fa7b3a0d03f9fa242eee6d884ec85d0efd4beca26a88da2100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006010202020202020202020202020202020202020202000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; bytes block_2 = - hex"0000000200000020496c61142f126c578fa762940fce65490ecb9dbb408a66b9275601725b16b827000000207728207bac279dbf8b7b5652b8b8c3619f65d007a7534015d0daf0a960e1550d00000008a71730065c0684ba4aa476b4ab3494db58b08ef8813cd0d4a456553ac046bf7a0000000172c52733e1b74bb841e89cfb2f9f6f08956d7d6c685073326442792d88e9cd1b000000019deecf3cb56703b46813472708f3085f00df5371fc20312b815063fa93ac552400000020496c61142f126c578fa762940fce65490ecb9dbb408a66b9275601725b16b827000000207728207bac279dbf8b7b5652b8b8c3619f65d007a7534015d0daf0a960e1550d00000008a71730065c0684ba4aa476b4ab3494db58b08ef8813cd0d4a456553ac046bf7a000000022165eb4c24ae6094baac7030a5c34975363d08dffee879e7a977245dc4329755000000024cd0efa11cdedc2f673b57e9b016717b1111854fa17b6cb4385c09eab4f676fe000000000000000000000000"; + hex"000000020283622796e1a2fa4718e254eb46d3f4287b05a5aaee35af02a54f2af8362f97000000101f99db4b9ffa5ab637607ad50c7d10ea3352a53478e14354355a02b6a87a7ab1000000181ba22861f1a04d910c399ce20125a7ef53c3a47e0f51fe1d2c179ea83b8da34e0000000415db3dd5c4e4589c0b7a5942f81c11548dda500600adefeb8c49d13481a88e24000000022309e4044d29f2906c728a7d19672aa7d80f3fbc289d4dd6fcab93f1e197b72700000002013ffea42e60a3be0af304384d83ad4411df13f66213997a7f0b7551e242f19d0000002001872181b5fe2c7ea15e1e72f5672bc777d61c807771ff7ae40c9b2aa816323500000028063d7b42d552599d3f3ff8fbc93e55484d49fc20dcc41940e3ebeaac4483a8ba0000000803b6339133ac1ca21463e1e3370ca136862bac1be49bdc6e1e69f73068a22ebe0000000316204b8532027613f551ad0530dc70c1c3be36fb7828a3a6539a100c57d25034000000030000001000000000000000000000000000000000000000000000000000000000000001020000000000000000000000000000000000000000000000000000000000000103000000000000000000000000000000000000000000000000000000000000010400000000000000000000000000000000000000000000000000000000000001050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002020000000000000000000000000000000000000000000000000000000000000203000000000000000000000000000000000000000000000000000000000000020400000000000000000000000000000000000000000000000000000000000002050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000005020000000000000000000000000000000000000000000000000000000000000503000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000042ddfdac63df2e340ea582ed2b6c9d23bf04f6e98c281c25c6dd7e87251185b3500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006020303030303030303030303030303030303030303000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; - bytes block_empty = - hex"000000010dab4f2c5004966607528e2de5e46abc49d68ac863a6f3ad3e3d98332ca8989d000000000d4ee51c2e3c7b242113e4cdc73af511db2393fcc96e2916ad77b07d4dd2ee96000000082c21cd9d652b1d55ae6437893ec4189d5cc48db60f44ecd0ce272e3a0fef45360000000011418b0f96de397c0bdec2dda6dc049c9f9715fa62420e5a6e08f3dd0b68fd36000000012ccf6631cb5d548aa25e0c51b9398c89af35fb00b321d40db6cb8f13f44cce2f000000010dab4f2c5004966607528e2de5e46abc49d68ac863a6f3ad3e3d98332ca8989d000000100d4ee51c2e3c7b242113e4cdc73af511db2393fcc96e2916ad77b07d4dd2ee96000000182c21cd9d652b1d55ae6437893ec4189d5cc48db60f44ecd0ce272e3a0fef4536000000042fe07d4d766850fb0c5f289cb6d71334e2f662146dd7e9693351795a6233b2d00000000211fcecd075e7e86da01708dedfc9671475fe7a879e076d6fe67bf432347eb0300000000200000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; + bytes block_empty_1 = + hex"000000010668938c4a4167faa2b5031e427d74d6e38638d2eef68834b70480c5a93f8e15000000002d39729fd006096882acfbd350c91fd61883578b4fe35b63cdce3c1993a497ea000000082f8dc86ba80d8fcf491fb7a255f4163e4f9601d022ba0be35f13297531073fd80000000019c36f7bc2e4116d082865cc0b4ac8e16e9efa00ace9fb2222dd1dfd719cb671000000012b36b22912aa963f143c490227bd21e7a44338026b2f6a389cb98e82167c3718000000010668938c4a4167faa2b5031e427d74d6e38638d2eef68834b70480c5a93f8e15000000102d39729fd006096882acfbd350c91fd61883578b4fe35b63cdce3c1993a497ea000000182f8dc86ba80d8fcf491fb7a255f4163e4f9601d022ba0be35f13297531073fd800000004238b20b7bc1d5190f8e928eb2aa2094412588f9cad6c7862f69c09a9b246d6ed0000000225d4ca531bca7d097a93bc47d7aa2c4dbcc8d0d5ecf4138849104e363eb52c0300000002000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; + + bytes block_empty_2 = + hex"000000020668938c4a4167faa2b5031e427d74d6e38638d2eef68834b70480c5a93f8e15000000102d39729fd006096882acfbd350c91fd61883578b4fe35b63cdce3c1993a497ea000000182f8dc86ba80d8fcf491fb7a255f4163e4f9601d022ba0be35f13297531073fd800000004238b20b7bc1d5190f8e928eb2aa2094412588f9cad6c7862f69c09a9b246d6ed0000000225d4ca531bca7d097a93bc47d7aa2c4dbcc8d0d5ecf4138849104e363eb52c03000000020668938c4a4167faa2b5031e427d74d6e38638d2eef68834b70480c5a93f8e15000000202d39729fd006096882acfbd350c91fd61883578b4fe35b63cdce3c1993a497ea000000282f8dc86ba80d8fcf491fb7a255f4163e4f9601d022ba0be35f13297531073fd800000008236394e84a01824e286653b542a923474253251e86c118f02978d5714538236c000000030aaa66ea64a4b9493d7237d092f8276e31eb3f8b14ae5c5e0a91fa5627745a8300000003000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; function setUp() public { rollup = new Rollup(); helper = new DecodeHelper(); } - function testDecoderDiffRoot() public { - bytes32 diffRoot = helper.computeDiffRoot(block_1); - assertEq( - 0x260777a20fee44e43d74c60350ebb7a631dabe0a8a1c27ee9a8264b2f5c24c2d, - diffRoot, - "Invalid diff root" - ); - } + function testEmptyBlocks() public { + { + bytes32 diffRoot = helper.computeDiffRoot(block_empty_1); + assertEq( + 0x5064e7b73cbb2cf66cecd9ee874d30cc654bda2fba26ad1c75f0c9db437b261b, + diffRoot, + "Invalid diff root" + ); + + ( + uint256 l2BlockNumber, + bytes32 startStateHash, + bytes32 endStateHash, + bytes32 publicInputsHash + ) = helper.decode(block_empty_1); + + assertEq(l2BlockNumber, 1, "Invalid block number"); + assertEq( + startStateHash, + 0xd3f7645c4b49d31bca62aca09aa26740d7e47d264f3021e2de2db40562944745, + "Invalid start state hash" + ); + assertEq( + endStateHash, + 0x285c26b176e983e6a9101b2c9cb103771b0aedae57df63600631fed28ea7461d, + "Invalid end state hash" + ); + assertEq( + publicInputsHash, + 0x2b9b56549c50cad1f6329a594979cf9a1d71f87f24c2a1bf33fe7743faabaaeb, + "Invalid public input hash" + ); + + rollup.process(bytes(""), block_empty_1); + + assertEq(rollup.rollupStateHash(), endStateHash, "Invalid rollup state hash"); + } + + { + bytes32 diffRoot = helper.computeDiffRoot(block_empty_2); + assertEq( + 0x5064e7b73cbb2cf66cecd9ee874d30cc654bda2fba26ad1c75f0c9db437b261b, + diffRoot, + "Invalid diff root" + ); + + ( + uint256 l2BlockNumber, + bytes32 startStateHash, + bytes32 endStateHash, + bytes32 publicInputsHash + ) = helper.decode(block_empty_2); + + assertEq(l2BlockNumber, 2, "Invalid block number"); + assertEq( + startStateHash, + 0x285c26b176e983e6a9101b2c9cb103771b0aedae57df63600631fed28ea7461d, + "Invalid start state hash" + ); + assertEq( + endStateHash, + 0xa98e86cafb947da8469576e685c76b7b7451f72e8ff6c0e72c67d5bac6942b21, + "Invalid end state hash" + ); + assertEq( + publicInputsHash, + 0x0fb6d019d1da49d67732e9ca797f83777f09e50777cb4d08f46865b01be85881, + "Invalid public input hash" + ); + + rollup.process(bytes(""), block_empty_2); - function testDecoder() public { - rollup.process(bytes(""), block_1); - rollup.process(bytes(""), block_2); + assertEq(rollup.rollupStateHash(), endStateHash, "Invalid rollup state hash"); + } } - function testPublicInputHash() public { - (uint256 l2BlockNumber, bytes32 oldStateHash, bytes32 newStateHash, bytes32 publicInputsHash) = - helper.decode(block_empty); - assertEq( - publicInputsHash, - 0x0013b2202a3e48b039cda7eef0976060d86e610d77fc9bb8cd5b0f1b561df48c, - "Invalid public input hash" - ); + function testNonEmptyBlocks() public { + { + bytes32 diffRoot = helper.computeDiffRoot(block_1); + assertEq( + 0x9f1a00d7220a2b51a9c2591c2f85e089f03d06b01138586ea5e3656435d5e749, + diffRoot, + "Invalid diff root block 1" + ); + + ( + uint256 l2BlockNumber, + bytes32 startStateHash, + bytes32 endStateHash, + bytes32 publicInputsHash + ) = helper.decode(block_1); + + assertEq(l2BlockNumber, 1, "Invalid block number"); + assertEq( + startStateHash, + 0xd3f7645c4b49d31bca62aca09aa26740d7e47d264f3021e2de2db40562944745, + "Invalid start state hash block 1" + ); + assertEq( + endStateHash, + 0xe3b20add23469bcbf25157ff75b81665564b089aa95083f8e095a3bb77062831, + "Invalid end state hash block 1" + ); + assertEq( + publicInputsHash, + 0x20638cd5e03d287dbd356af6e16fd852337f535b12d06f7266599c035696098d, + "Invalid public input hash block 1" + ); + + rollup.process(bytes(""), block_1); + + assertEq(rollup.rollupStateHash(), endStateHash, "Invalid rollup state hash block 1"); + } + + { + bytes32 diffRoot = helper.computeDiffRoot(block_2); + assertEq( + 0x50f2f2dc986fc4022b8fdde8f2d610c82ee36776b282ca3514c12726dd9081ef, + diffRoot, + "Invalid diff root block 2" + ); + + ( + uint256 l2BlockNumber, + bytes32 startStateHash, + bytes32 endStateHash, + bytes32 publicInputsHash + ) = helper.decode(block_2); + + assertEq(l2BlockNumber, 2, "Invalid block number"); + assertEq( + startStateHash, + 0xe3b20add23469bcbf25157ff75b81665564b089aa95083f8e095a3bb77062831, + "Invalid start state hash block 2" + ); + assertEq( + endStateHash, + 0xdc4f85374d479c6388a9bed0ddea9880422b515c88de0a76fd96b5c93c809b21, + "Invalid end state hash block 2" + ); + assertEq( + publicInputsHash, + 0x12e84ea31aa75fab86269181c8c09dbb8486e518e5db9ce4dad204068fc0a925, + "Invalid public input hash block 2" + ); + + rollup.process(bytes(""), block_2); + + assertEq(rollup.rollupStateHash(), endStateHash, "Invalid rollup state hash"); + } } } diff --git a/yarn-project/acir-simulator/src/acvm/deserialize.ts b/yarn-project/acir-simulator/src/acvm/deserialize.ts index db614d24236c..e1aa90e98bde 100644 --- a/yarn-project/acir-simulator/src/acvm/deserialize.ts +++ b/yarn-project/acir-simulator/src/acvm/deserialize.ts @@ -5,7 +5,7 @@ import { CallContext, ContractDeploymentData, EMITTED_EVENTS_LENGTH, - L1_MSG_STACK_LENGTH, + NEW_L2_TO_L1_MSGS_LENGTH, NEW_COMMITMENTS_LENGTH, NEW_NULLIFIERS_LENGTH, PrivateCircuitPublicInputs, @@ -80,7 +80,7 @@ export function extractPublicInputs(partialWitness: ACVMWitness, acir: Buffer): const newNullifiers = witnessReader.readFieldArray(NEW_NULLIFIERS_LENGTH); const privateCallStack = witnessReader.readFieldArray(PRIVATE_CALL_STACK_LENGTH); const publicCallStack = witnessReader.readFieldArray(PUBLIC_CALL_STACK_LENGTH); - const l1MsgStack = witnessReader.readFieldArray(L1_MSG_STACK_LENGTH); + const newL2ToL1Msgs = witnessReader.readFieldArray(NEW_L2_TO_L1_MSGS_LENGTH); const privateDataTreeRoot = witnessReader.readField(); const nullifierTreeRoot = witnessReader.readField(); @@ -102,7 +102,7 @@ export function extractPublicInputs(partialWitness: ACVMWitness, acir: Buffer): newNullifiers, privateCallStack, publicCallStack, - l1MsgStack, + newL2ToL1Msgs, privateDataTreeRoot, nullifierTreeRoot, contractTreeRoot, diff --git a/yarn-project/acir-simulator/src/acvm/serialize.ts b/yarn-project/acir-simulator/src/acvm/serialize.ts index 5b2b13958a12..7505f753851a 100644 --- a/yarn-project/acir-simulator/src/acvm/serialize.ts +++ b/yarn-project/acir-simulator/src/acvm/serialize.ts @@ -51,7 +51,7 @@ export function toACVMPublicInputs(publicInputs: PrivateCircuitPublicInputs): AC ...publicInputs.newNullifiers.map(toACVMField), ...publicInputs.privateCallStack.map(toACVMField), ...publicInputs.publicCallStack.map(toACVMField), - ...publicInputs.l1MsgStack.map(toACVMField), + ...publicInputs.newL2ToL1Msgs.map(toACVMField), toACVMField(publicInputs.historicPrivateDataTreeRoot), toACVMField(publicInputs.historicPrivateNullifierTreeRoot), diff --git a/yarn-project/circuits.js/src/structs/__snapshots__/private_circuit_public_inputs.test.ts.snap b/yarn-project/circuits.js/src/structs/__snapshots__/private_circuit_public_inputs.test.ts.snap index 7b79b0716a92..933310b2f98f 100644 --- a/yarn-project/circuits.js/src/structs/__snapshots__/private_circuit_public_inputs.test.ts.snap +++ b/yarn-project/circuits.js/src/structs/__snapshots__/private_circuit_public_inputs.test.ts.snap @@ -15,7 +15,7 @@ new_commitments: [ 0x400 0x401 0x402 0x403 ] new_nullifiers: [ 0x500 0x501 0x502 0x503 ] private_call_stack: [ 0x600 0x601 0x602 0x603 ] public_call_stack: [ 0x700 0x701 0x702 0x703 ] -l1_msg_stack: [ 0x800 0x801 ] +new_l2_to_l1_msgs: [ 0x800 0x801 ] historic_private_data_tree_root: 0x1000 historic_nullifier_tree_root: 0x1100 contract_deployment_data: constructor_vk_hash: 0x1 diff --git a/yarn-project/circuits.js/src/structs/constants.ts b/yarn-project/circuits.js/src/structs/constants.ts index be28df64a271..5e247345c57d 100644 --- a/yarn-project/circuits.js/src/structs/constants.ts +++ b/yarn-project/circuits.js/src/structs/constants.ts @@ -7,20 +7,20 @@ export const EMITTED_EVENTS_LENGTH = 4; export const NEW_COMMITMENTS_LENGTH = 4; export const NEW_NULLIFIERS_LENGTH = 4; +export const NEW_L2_TO_L1_MSGS_LENGTH = 2; export const STATE_TRANSITIONS_LENGTH = 4; export const STATE_READS_LENGTH = 4; export const PRIVATE_CALL_STACK_LENGTH = 4; export const PUBLIC_CALL_STACK_LENGTH = 4; -export const L1_MSG_STACK_LENGTH = 2; export const KERNEL_NEW_COMMITMENTS_LENGTH = 4; export const KERNEL_NEW_NULLIFIERS_LENGTH = 4; export const KERNEL_NEW_CONTRACTS_LENGTH = 1; export const KERNEL_PRIVATE_CALL_STACK_LENGTH = 8; export const KERNEL_PUBLIC_CALL_STACK_LENGTH = 8; -export const KERNEL_L1_MSG_STACK_LENGTH = 4; +export const KERNEL_NEW_L2_TO_L1_MSGS_LENGTH = 2; export const KERNEL_OPTIONALLY_REVEALED_DATA_LENGTH = 4; export const VK_TREE_HEIGHT = 3; diff --git a/yarn-project/circuits.js/src/structs/kernel/__snapshots__/index.test.ts.snap b/yarn-project/circuits.js/src/structs/kernel/__snapshots__/index.test.ts.snap index ddff9f823fa4..377f4b15cd90 100644 --- a/yarn-project/circuits.js/src/structs/kernel/__snapshots__/index.test.ts.snap +++ b/yarn-project/circuits.js/src/structs/kernel/__snapshots__/index.test.ts.snap @@ -24,8 +24,8 @@ private_call_stack: [ 0x301 0x302 0x303 0x304 0x305 0x306 0x307 0x308 ] public_call_stack: [ 0x401 0x402 0x403 0x404 0x405 0x406 0x407 0x408 ] -l1_msg_stack: -[ 0x501 0x502 0x503 0x504 ] +new_l2_to_l1_msgs: +[ 0x501 0x502 ] new_contracts: [ contract_address: 0x601 portal_contract_address: 0x202020202020202020202020202020202020202 @@ -197,8 +197,8 @@ private_call_stack: [ 0x1301 0x1302 0x1303 0x1304 0x1305 0x1306 0x1307 0x1308 ] public_call_stack: [ 0x1401 0x1402 0x1403 0x1404 0x1405 0x1406 0x1407 0x1408 ] -l1_msg_stack: -[ 0x1501 0x1502 0x1503 0x1504 ] +new_l2_to_l1_msgs: +[ 0x1501 0x1502 ] new_contracts: [ contract_address: 0x1601 portal_contract_address: 0x202020202020202020202020202020202020202 @@ -341,7 +341,7 @@ new_commitments: [ 0x2411 0x2412 0x2413 0x2414 ] new_nullifiers: [ 0x2511 0x2512 0x2513 0x2514 ] private_call_stack: [ 0x2611 0x2612 0x2613 0x2614 ] public_call_stack: [ 0x2711 0x2712 0x2713 0x2714 ] -l1_msg_stack: [ 0x2811 0x2812 ] +new_l2_to_l1_msgs: [ 0x2811 0x2812 ] historic_private_data_tree_root: 0x3011 historic_nullifier_tree_root: 0x3111 contract_deployment_data: constructor_vk_hash: 0x1 @@ -376,7 +376,7 @@ new_commitments: [ 0x2421 0x2422 0x2423 0x2424 ] new_nullifiers: [ 0x2521 0x2522 0x2523 0x2524 ] private_call_stack: [ 0x2621 0x2622 0x2623 0x2624 ] public_call_stack: [ 0x2721 0x2722 0x2723 0x2724 ] -l1_msg_stack: [ 0x2821 0x2822 ] +new_l2_to_l1_msgs: [ 0x2821 0x2822 ] historic_private_data_tree_root: 0x3021 historic_nullifier_tree_root: 0x3121 contract_deployment_data: constructor_vk_hash: 0x1 @@ -409,7 +409,7 @@ new_commitments: [ 0x2422 0x2423 0x2424 0x2425 ] new_nullifiers: [ 0x2522 0x2523 0x2524 0x2525 ] private_call_stack: [ 0x2622 0x2623 0x2624 0x2625 ] public_call_stack: [ 0x2722 0x2723 0x2724 0x2725 ] -l1_msg_stack: [ 0x2822 0x2823 ] +new_l2_to_l1_msgs: [ 0x2822 0x2823 ] historic_private_data_tree_root: 0x3022 historic_nullifier_tree_root: 0x3122 contract_deployment_data: constructor_vk_hash: 0x1 @@ -442,7 +442,7 @@ new_commitments: [ 0x2423 0x2424 0x2425 0x2426 ] new_nullifiers: [ 0x2523 0x2524 0x2525 0x2526 ] private_call_stack: [ 0x2623 0x2624 0x2625 0x2626 ] public_call_stack: [ 0x2723 0x2724 0x2725 0x2726 ] -l1_msg_stack: [ 0x2823 0x2824 ] +new_l2_to_l1_msgs: [ 0x2823 0x2824 ] historic_private_data_tree_root: 0x3023 historic_nullifier_tree_root: 0x3123 contract_deployment_data: constructor_vk_hash: 0x1 @@ -475,7 +475,7 @@ new_commitments: [ 0x2424 0x2425 0x2426 0x2427 ] new_nullifiers: [ 0x2524 0x2525 0x2526 0x2527 ] private_call_stack: [ 0x2624 0x2625 0x2626 0x2627 ] public_call_stack: [ 0x2724 0x2725 0x2726 0x2727 ] -l1_msg_stack: [ 0x2824 0x2825 ] +new_l2_to_l1_msgs: [ 0x2824 0x2825 ] historic_private_data_tree_root: 0x3024 historic_nullifier_tree_root: 0x3124 contract_deployment_data: constructor_vk_hash: 0x1 @@ -540,8 +540,8 @@ private_call_stack: [ 0x301 0x302 0x303 0x304 0x305 0x306 0x307 0x308 ] public_call_stack: [ 0x401 0x402 0x403 0x404 0x405 0x406 0x407 0x408 ] -l1_msg_stack: -[ 0x501 0x502 0x503 0x504 ] +new_l2_to_l1_msgs: +[ 0x501 0x502 ] new_contracts: [ contract_address: 0x601 portal_contract_address: 0x202020202020202020202020202020202020202 @@ -676,8 +676,8 @@ private_call_stack: [ 0x301 0x302 0x303 0x304 0x305 0x306 0x307 0x308 ] public_call_stack: [ 0x401 0x402 0x403 0x404 0x405 0x406 0x407 0x408 ] -l1_msg_stack: -[ 0x501 0x502 0x503 0x504 ] +new_l2_to_l1_msgs: +[ 0x501 0x502 ] new_contracts: [ contract_address: 0x601 portal_contract_address: 0x202020202020202020202020202020202020202 @@ -839,7 +839,7 @@ current_value: 0x1514 current_value: 0x1515 ] public_call_stack: [ 0x1611 0x1612 0x1613 0x1614 ] -l1_msg_stack: [ 0x1711 0x1712 ] +new_l2_to_l1_msgs: [ 0x1711 0x1712 ] historic_public_data_tree_root: 0x1811 prover_address: 0x1812 @@ -883,7 +883,7 @@ current_value: 0x1814 current_value: 0x1815 ] public_call_stack: [ 0x1911 0x1912 0x1913 0x1914 ] -l1_msg_stack: [ 0x1a11 0x1a12 ] +new_l2_to_l1_msgs: [ 0x1a11 0x1a12 ] historic_public_data_tree_root: 0x1b11 prover_address: 0x1b12 @@ -925,7 +925,7 @@ current_value: 0x1815 current_value: 0x1816 ] public_call_stack: [ 0x1912 0x1913 0x1914 0x1915 ] -l1_msg_stack: [ 0x1a12 0x1a13 ] +new_l2_to_l1_msgs: [ 0x1a12 0x1a13 ] historic_public_data_tree_root: 0x1b12 prover_address: 0x1b13 @@ -967,7 +967,7 @@ current_value: 0x1816 current_value: 0x1817 ] public_call_stack: [ 0x1913 0x1914 0x1915 0x1916 ] -l1_msg_stack: [ 0x1a13 0x1a14 ] +new_l2_to_l1_msgs: [ 0x1a13 0x1a14 ] historic_public_data_tree_root: 0x1b13 prover_address: 0x1b14 @@ -1009,7 +1009,7 @@ current_value: 0x1817 current_value: 0x1818 ] public_call_stack: [ 0x1914 0x1915 0x1916 0x1917 ] -l1_msg_stack: [ 0x1a14 0x1a15 ] +new_l2_to_l1_msgs: [ 0x1a14 0x1a15 ] historic_public_data_tree_root: 0x1b14 prover_address: 0x1b15 @@ -1086,7 +1086,7 @@ current_value: 0x614 current_value: 0x615 ] public_call_stack: [ 0x711 0x712 0x713 0x714 ] -l1_msg_stack: [ 0x811 0x812 ] +new_l2_to_l1_msgs: [ 0x811 0x812 ] historic_public_data_tree_root: 0x911 prover_address: 0x912 @@ -1130,7 +1130,7 @@ current_value: 0x914 current_value: 0x915 ] public_call_stack: [ 0xa11 0xa12 0xa13 0xa14 ] -l1_msg_stack: [ 0xb11 0xb12 ] +new_l2_to_l1_msgs: [ 0xb11 0xb12 ] historic_public_data_tree_root: 0xc11 prover_address: 0xc12 @@ -1172,7 +1172,7 @@ current_value: 0x915 current_value: 0x916 ] public_call_stack: [ 0xa12 0xa13 0xa14 0xa15 ] -l1_msg_stack: [ 0xb12 0xb13 ] +new_l2_to_l1_msgs: [ 0xb12 0xb13 ] historic_public_data_tree_root: 0xc12 prover_address: 0xc13 @@ -1214,7 +1214,7 @@ current_value: 0x916 current_value: 0x917 ] public_call_stack: [ 0xa13 0xa14 0xa15 0xa16 ] -l1_msg_stack: [ 0xb13 0xb14 ] +new_l2_to_l1_msgs: [ 0xb13 0xb14 ] historic_public_data_tree_root: 0xc13 prover_address: 0xc14 @@ -1256,7 +1256,7 @@ current_value: 0x917 current_value: 0x918 ] public_call_stack: [ 0xa14 0xa15 0xa16 0xa17 ] -l1_msg_stack: [ 0xb14 0xb15 ] +new_l2_to_l1_msgs: [ 0xb14 0xb15 ] historic_public_data_tree_root: 0xc14 prover_address: 0xc15 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 index 34df6cb3ea1b..dc71598e333b 100644 --- a/yarn-project/circuits.js/src/structs/kernel/combined_accumulated_data.ts +++ b/yarn-project/circuits.js/src/structs/kernel/combined_accumulated_data.ts @@ -5,7 +5,7 @@ import { serializeToBuffer } from '../../utils/serialize.js'; import { AggregationObject } from '../aggregation_object.js'; import { EMITTED_EVENTS_LENGTH, - KERNEL_L1_MSG_STACK_LENGTH, + KERNEL_NEW_L2_TO_L1_MSGS_LENGTH, KERNEL_NEW_COMMITMENTS_LENGTH, KERNEL_NEW_CONTRACTS_LENGTH, KERNEL_NEW_NULLIFIERS_LENGTH, @@ -167,7 +167,7 @@ export class CombinedAccumulatedData { public privateCallStack: Fr[], public publicCallStack: Fr[], - public l1MsgStack: Fr[], + public newL2ToL1Msgs: Fr[], public newContracts: NewContractData[], @@ -180,7 +180,7 @@ export class CombinedAccumulatedData { 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, 'newL2ToL1Msgs', KERNEL_NEW_L2_TO_L1_MSGS_LENGTH); assertLength(this, 'newContracts', KERNEL_NEW_CONTRACTS_LENGTH); assertLength(this, 'optionallyRevealedData', KERNEL_OPTIONALLY_REVEALED_DATA_LENGTH); assertLength(this, 'stateTransitions', STATE_TRANSITIONS_LENGTH); @@ -196,7 +196,7 @@ export class CombinedAccumulatedData { this.newNullifiers, this.privateCallStack, this.publicCallStack, - this.l1MsgStack, + this.newL2ToL1Msgs, this.newContracts, this.optionallyRevealedData, this.stateTransitions, @@ -218,7 +218,7 @@ export class CombinedAccumulatedData { 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_L2_TO_L1_MSGS_LENGTH, Fr), reader.readArray(KERNEL_NEW_CONTRACTS_LENGTH, NewContractData), reader.readArray(KERNEL_OPTIONALLY_REVEALED_DATA_LENGTH, OptionallyRevealedData), reader.readArray(STATE_TRANSITIONS_LENGTH, PublicDataWrite), @@ -235,7 +235,7 @@ export class CombinedAccumulatedData { 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_L2_TO_L1_MSGS_LENGTH, Fr.zero), times(KERNEL_NEW_CONTRACTS_LENGTH, NewContractData.empty), times(KERNEL_OPTIONALLY_REVEALED_DATA_LENGTH, OptionallyRevealedData.empty), times(STATE_TRANSITIONS_LENGTH, PublicDataWrite.empty), 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 a8acd64909fd..5d296db4419c 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 @@ -5,7 +5,7 @@ import { CallContext } from './call_context.js'; import { ARGS_LENGTH, EMITTED_EVENTS_LENGTH, - L1_MSG_STACK_LENGTH, + NEW_L2_TO_L1_MSGS_LENGTH, NEW_COMMITMENTS_LENGTH, NEW_NULLIFIERS_LENGTH, PRIVATE_CALL_STACK_LENGTH, @@ -29,7 +29,7 @@ export class PrivateCircuitPublicInputs { public newNullifiers: Fr[], public privateCallStack: Fr[], public publicCallStack: Fr[], - public l1MsgStack: Fr[], + public newL2ToL1Msgs: Fr[], public historicPrivateDataTreeRoot: Fr, public historicPrivateNullifierTreeRoot: Fr, public historicContractTreeRoot: Fr, @@ -42,7 +42,7 @@ export class PrivateCircuitPublicInputs { assertLength(this, 'newNullifiers', NEW_NULLIFIERS_LENGTH); assertLength(this, 'privateCallStack', PRIVATE_CALL_STACK_LENGTH); assertLength(this, 'publicCallStack', PUBLIC_CALL_STACK_LENGTH); - assertLength(this, 'l1MsgStack', L1_MSG_STACK_LENGTH); + assertLength(this, 'newL2ToL1Msgs', NEW_L2_TO_L1_MSGS_LENGTH); } /** * Create PrivateCircuitPublicInputs from a fields dictionary. @@ -67,7 +67,7 @@ export class PrivateCircuitPublicInputs { frArray(NEW_NULLIFIERS_LENGTH), frArray(PRIVATE_CALL_STACK_LENGTH), frArray(PUBLIC_CALL_STACK_LENGTH), - frArray(L1_MSG_STACK_LENGTH), + frArray(NEW_L2_TO_L1_MSGS_LENGTH), Fr.ZERO, Fr.ZERO, Fr.ZERO, @@ -90,7 +90,7 @@ export class PrivateCircuitPublicInputs { fields.newNullifiers, fields.privateCallStack, fields.publicCallStack, - fields.l1MsgStack, + fields.newL2ToL1Msgs, fields.historicPrivateDataTreeRoot, fields.historicPrivateNullifierTreeRoot, fields.historicContractTreeRoot, 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 46da4d2bd438..64893ffff197 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 @@ -5,7 +5,7 @@ import { CallContext } from './call_context.js'; import { ARGS_LENGTH, EMITTED_EVENTS_LENGTH, - L1_MSG_STACK_LENGTH, + NEW_L2_TO_L1_MSGS_LENGTH, PUBLIC_CALL_STACK_LENGTH, RETURN_VALUES_LENGTH, STATE_READS_LENGTH, @@ -73,7 +73,7 @@ export class PublicCircuitPublicInputs { public stateTransitions: StateTransition[], public stateReads: StateRead[], public publicCallStack: Fr[], - public l1MsgStack: Fr[], + public newL2ToL1Msgs: Fr[], public historicPublicDataTreeRoot: Fr, public proverAddress: AztecAddress, ) { @@ -81,7 +81,7 @@ export class PublicCircuitPublicInputs { assertLength(this, 'returnValues', RETURN_VALUES_LENGTH); assertLength(this, 'emittedEvents', EMITTED_EVENTS_LENGTH); assertLength(this, 'publicCallStack', PUBLIC_CALL_STACK_LENGTH); - assertLength(this, 'l1MsgStack', L1_MSG_STACK_LENGTH); + assertLength(this, 'newL2ToL1Msgs', NEW_L2_TO_L1_MSGS_LENGTH); assertLength(this, 'stateTransitions', STATE_TRANSITIONS_LENGTH); assertLength(this, 'stateReads', STATE_READS_LENGTH); } @@ -109,7 +109,7 @@ export class PublicCircuitPublicInputs { times(STATE_TRANSITIONS_LENGTH, StateTransition.empty), times(STATE_READS_LENGTH, StateRead.empty), frArray(PUBLIC_CALL_STACK_LENGTH), - frArray(L1_MSG_STACK_LENGTH), + frArray(NEW_L2_TO_L1_MSGS_LENGTH), Fr.ZERO, AztecAddress.ZERO, ); @@ -128,7 +128,7 @@ export class PublicCircuitPublicInputs { fields.stateTransitions, fields.stateReads, fields.publicCallStack, - fields.l1MsgStack, + fields.newL2ToL1Msgs, fields.historicPublicDataTreeRoot, fields.proverAddress, ] as const; diff --git a/yarn-project/circuits.js/src/structs/rollup/__snapshots__/base_rollup.test.ts.snap b/yarn-project/circuits.js/src/structs/rollup/__snapshots__/base_rollup.test.ts.snap index 1e76e911043d..c02edc5e1d13 100644 --- a/yarn-project/circuits.js/src/structs/rollup/__snapshots__/base_rollup.test.ts.snap +++ b/yarn-project/circuits.js/src/structs/rollup/__snapshots__/base_rollup.test.ts.snap @@ -25,8 +25,8 @@ private_call_stack: [ 0x400 0x401 0x402 0x403 0x404 0x405 0x406 0x407 ] public_call_stack: [ 0x500 0x501 0x502 0x503 0x504 0x505 0x506 0x507 ] -l1_msg_stack: -[ 0x600 0x601 0x602 0x603 ] +new_l2_to_l1_msgs: +[ 0x600 0x601 ] new_contracts: [ contract_address: 0x700 portal_contract_address: 0x101010101010101010101010101010101010101 @@ -170,8 +170,8 @@ private_call_stack: [ 0x500 0x501 0x502 0x503 0x504 0x505 0x506 0x507 ] public_call_stack: [ 0x600 0x601 0x602 0x603 0x604 0x605 0x606 0x607 ] -l1_msg_stack: -[ 0x700 0x701 0x702 0x703 ] +new_l2_to_l1_msgs: +[ 0x700 0x701 ] new_contracts: [ contract_address: 0x800 portal_contract_address: 0x101010101010101010101010101010101010101 diff --git a/yarn-project/circuits.js/src/tests/factories.ts b/yarn-project/circuits.js/src/tests/factories.ts index 73231ffbc74f..e496bb428ffd 100644 --- a/yarn-project/circuits.js/src/tests/factories.ts +++ b/yarn-project/circuits.js/src/tests/factories.ts @@ -38,14 +38,14 @@ import { CONTRACT_TREE_ROOTS_TREE_HEIGHT, EMITTED_EVENTS_LENGTH, FUNCTION_TREE_HEIGHT, - KERNEL_L1_MSG_STACK_LENGTH, + KERNEL_NEW_L2_TO_L1_MSGS_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, - L1_MSG_STACK_LENGTH, + NEW_L2_TO_L1_MSGS_LENGTH, NEW_COMMITMENTS_LENGTH, NEW_NULLIFIERS_LENGTH, NULLIFIER_TREE_HEIGHT, @@ -118,7 +118,7 @@ export function makeAccumulatedData(seed = 1): CombinedAccumulatedData { range(KERNEL_NEW_NULLIFIERS_LENGTH, seed + 0x200).map(fr), range(KERNEL_PRIVATE_CALL_STACK_LENGTH, seed + 0x300).map(fr), range(KERNEL_PUBLIC_CALL_STACK_LENGTH, seed + 0x400).map(fr), - range(KERNEL_L1_MSG_STACK_LENGTH, seed + 0x500).map(fr), + range(KERNEL_NEW_L2_TO_L1_MSGS_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(makePublicDataWrite), @@ -174,7 +174,7 @@ export function makePublicCircuitPublicInputs(seed = 0): PublicCircuitPublicInpu range(STATE_TRANSITIONS_LENGTH, seed + 0x400).map(makeStateTransition), range(STATE_READS_LENGTH, seed + 0x500).map(makeStateRead), frArray(PUBLIC_CALL_STACK_LENGTH, seed + 0x600), - frArray(L1_MSG_STACK_LENGTH, seed + 0x700), + frArray(NEW_L2_TO_L1_MSGS_LENGTH, seed + 0x700), fr(seed + 0x800), makeAztecAddress(seed + 0x801), ); @@ -316,7 +316,7 @@ export function makePrivateCircuitPublicInputs(seed = 0): PrivateCircuitPublicIn newNullifiers: range(NEW_NULLIFIERS_LENGTH, seed + 0x500).map(fr), privateCallStack: range(PRIVATE_CALL_STACK_LENGTH, seed + 0x600).map(fr), publicCallStack: range(PUBLIC_CALL_STACK_LENGTH, seed + 0x700).map(fr), - l1MsgStack: range(L1_MSG_STACK_LENGTH, seed + 0x800).map(fr), + newL2ToL1Msgs: range(NEW_L2_TO_L1_MSGS_LENGTH, seed + 0x800).map(fr), historicContractTreeRoot: fr(seed + 0x900), // TODO not in spec historicPrivateDataTreeRoot: fr(seed + 0x1000), historicPrivateNullifierTreeRoot: fr(seed + 0x1100), // TODO not in spec diff --git a/yarn-project/noir-contracts/src/contracts/noir-aztec3/src/abi.nr b/yarn-project/noir-contracts/src/contracts/noir-aztec3/src/abi.nr index 5b5ab2ad7e4f..52ed54067eda 100644 --- a/yarn-project/noir-contracts/src/contracts/noir-aztec3/src/abi.nr +++ b/yarn-project/noir-contracts/src/contracts/noir-aztec3/src/abi.nr @@ -73,7 +73,7 @@ struct PrivateCircuitPublicInputs { new_nullifiers: [Field; crate::abi::MAX_NEW_NULLIFIERS], private_call_stack: [Field; crate::abi::MAX_PRIVATE_CALL_STACK], public_call_stack: [Field; crate::abi::MAX_PUBLIC_CALL_STACK], - l1_msg_stack: [Field; crate::abi::MAX_L1_MSG_STACK], + new_l2_to_l1_msgs: [Field; crate::abi::MAX_L1_MSG_STACK], historic_private_data_tree_root: Field, historic_private_nullifier_tree_root: Field, historic_contract_tree_root: Field, @@ -96,7 +96,7 @@ impl PrivateCircuitPublicInputs { fields = fields.push_array(self.new_nullifiers); fields = fields.push_array(self.private_call_stack); fields = fields.push_array(self.public_call_stack); - fields = fields.push_array(self.l1_msg_stack); + fields = fields.push_array(self.new_l2_to_l1_msgs); fields = fields.push(self.historic_private_data_tree_root); fields = fields.push(self.historic_private_nullifier_tree_root); fields = fields.push(self.historic_contract_tree_root); @@ -172,7 +172,7 @@ impl Outputs { new_nullifiers: self.new_nullifiers.storage, private_call_stack: self.private_call_stack.storage, public_call_stack: self.public_call_stack.storage, - l1_msg_stack: self.l1_message_stack.storage, + new_l2_to_l1_msgs: self.l1_message_stack.storage, historic_private_data_tree_root: inputs.old_private_data_tree_root, historic_private_nullifier_tree_root: inputs.old_nullifier_tree_root, historic_contract_tree_root: inputs.old_contract_tree_root, diff --git a/yarn-project/noir-contracts/src/contracts/noir-aztec3/src/private_call_stack_item.nr b/yarn-project/noir-contracts/src/contracts/noir-aztec3/src/private_call_stack_item.nr index 4df7d3c989e3..162656317d78 100644 --- a/yarn-project/noir-contracts/src/contracts/noir-aztec3/src/private_call_stack_item.nr +++ b/yarn-project/noir-contracts/src/contracts/noir-aztec3/src/private_call_stack_item.nr @@ -108,7 +108,7 @@ impl PrivateCallStackItem { new_nullifiers: arr_copy_slice(fields, [0; crate::abi::MAX_NEW_NULLIFIERS], 30), private_call_stack: arr_copy_slice(fields, [0; crate::abi::MAX_PRIVATE_CALL_STACK], 34), public_call_stack: arr_copy_slice(fields, [0; crate::abi::MAX_PUBLIC_CALL_STACK], 38), - l1_msg_stack:arr_copy_slice(fields, [0; crate::abi::MAX_L1_MSG_STACK], 42), + new_l2_to_l1_msgs:arr_copy_slice(fields, [0; crate::abi::MAX_L1_MSG_STACK], 42), historic_private_data_tree_root: fields[44], historic_private_nullifier_tree_root: fields[45], historic_contract_tree_root: fields[46], 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 f55806304c88..805f28d01fa3 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 @@ -4,6 +4,7 @@ import { BaseRollupInputs, CircuitsWasm, Fr, + NewContractData, PublicDataRead, PublicDataWrite, RootRollupPublicInputs, @@ -18,8 +19,8 @@ import { makeProof, makeRootRollupPublicInputs, } from '@aztec/circuits.js/factories'; -import { toBufferBE } from '@aztec/foundation'; -import { Tx } from '@aztec/types'; +import { AztecAddress, EthAddress, toBufferBE } from '@aztec/foundation'; +import { ContractData, Tx } from '@aztec/types'; import { MerkleTreeId, MerkleTreeOperations, MerkleTrees } from '@aztec/world-state'; import { MockProxy, mock } from 'jest-mock-extended'; import { default as levelup } from 'levelup'; @@ -34,6 +35,7 @@ import { ProcessedTx, makeEmptyProcessedTx, makeProcessedTx } from '../sequencer import { RollupSimulator } from '../simulator/index.js'; import { WasmRollupCircuitSimulator } from '../simulator/rollup.js'; import { CircuitBlockBuilder } from './circuit_block_builder.js'; +import { makePrivateTx } from '../index.js'; export const createMemDown = () => (memdown as any)() as MemDown; @@ -302,6 +304,118 @@ describe('sequencer/circuit_block_builder', () => { const [l2Block] = await builder.buildL2Block(blockNumber, txs); expect(l2Block.number).toEqual(blockNumber); }); + + it('Build blocks on top of blocks l2 block with 4 txs', async () => { + const txs = [...(await Promise.all(times(4, makeEmptyProcessedTx)))]; + const [block1] = await builder.buildL2Block(1, txs); + const [block2] = await builder.buildL2Block(2, txs); + + expect(block1.number).toEqual(1); + expect(block2.number).toEqual(2); + + /*const blocks = [block1, block2]; + for (let i = 0; i < 2; i++) { + const block = blocks[i]; + console.log(block.encode().toString('hex')); + console.log(`call data hash : ${block.getCalldataHash().toString('hex')}`); + console.log(`start state hash: ${block.getStartStateHash().toString('hex')}`); + console.log(`end state hash : ${block.getEndStateHash().toString('hex')}`); + console.log(`public input hash: ${block.getPublicInputsHash().toString()}`); + }*/ + }, 10000); + + it('Build blocks on top of blocks l2 block with 4 txs', async () => { + for (let i = 0; i < 2; i++) { + const tx = await makeProcessedTx( + Tx.createPrivate(makeKernelPublicInputs(1 + i), emptyProof, makeEmptyUnverifiedData()), + ); + /* + const b = Buffer.alloc(20, 0); + b[19] = 2; + console.log(b); + tx.data.end.newContracts[0] = new NewContractData( + new AztecAddress(fr(1).toBuffer()), + new EthAddress(b), + fr(3), + ); + console.log(tx.data.end.newContracts[0]);*/ + + const txsLeft = [tx, await makeEmptyProcessedTx()]; + const txsRight = [await makeEmptyProcessedTx(), await makeEmptyProcessedTx()]; + + // Set tree roots to proper values in the tx + await setTxHistoricTreeRoots(tx); + + // Calculate what would be the tree roots after the txs from the first base rollup land and update mock circuit output + await updateExpectedTreesFromTxs(txsLeft); + baseRollupOutputLeft.endContractTreeSnapshot = await getTreeSnapshot(MerkleTreeId.CONTRACT_TREE); + baseRollupOutputLeft.endNullifierTreeSnapshot = await getTreeSnapshot(MerkleTreeId.NULLIFIER_TREE); + baseRollupOutputLeft.endPrivateDataTreeSnapshot = await getTreeSnapshot(MerkleTreeId.PRIVATE_DATA_TREE); + + // Same for the two txs on the right + await updateExpectedTreesFromTxs(txsRight); + baseRollupOutputRight.endContractTreeSnapshot = await getTreeSnapshot(MerkleTreeId.CONTRACT_TREE); + baseRollupOutputRight.endNullifierTreeSnapshot = await getTreeSnapshot(MerkleTreeId.NULLIFIER_TREE); + baseRollupOutputRight.endPrivateDataTreeSnapshot = await getTreeSnapshot(MerkleTreeId.PRIVATE_DATA_TREE); + + // And update the root trees now to create proper output to the root rollup circuit + await updateRootTrees(); + rootRollupOutput.endContractTreeSnapshot = await getTreeSnapshot(MerkleTreeId.CONTRACT_TREE); + rootRollupOutput.endNullifierTreeSnapshot = await getTreeSnapshot(MerkleTreeId.NULLIFIER_TREE); + rootRollupOutput.endPrivateDataTreeSnapshot = await getTreeSnapshot(MerkleTreeId.PRIVATE_DATA_TREE); + rootRollupOutput.endTreeOfHistoricContractTreeRootsSnapshot = await getTreeSnapshot( + MerkleTreeId.CONTRACT_TREE_ROOTS_TREE, + ); + rootRollupOutput.endTreeOfHistoricPrivateDataTreeRootsSnapshot = await getTreeSnapshot( + MerkleTreeId.PRIVATE_DATA_TREE_ROOTS_TREE, + ); + + // Actually build a block! + const txs = [tx, await makeEmptyProcessedTx(), await makeEmptyProcessedTx(), await makeEmptyProcessedTx()]; + const [block] = await builder.buildL2Block(1 + i, txs); + + console.log(block); + + // These output values are the same as in Decoder.t.sol tests + if (i === 0) { + expect(block.number).toEqual(1); + expect(block.getCalldataHash()).toEqual( + Buffer.from('9f1a00d7220a2b51a9c2591c2f85e089f03d06b01138586ea5e3656435d5e749', 'hex'), + ); + expect(block.getStartStateHash()).toEqual( + Buffer.from('d3f7645c4b49d31bca62aca09aa26740d7e47d264f3021e2de2db40562944745', 'hex'), + ); + expect(block.getEndStateHash()).toEqual( + Buffer.from('e3b20add23469bcbf25157ff75b81665564b089aa95083f8e095a3bb77062831', 'hex'), + ); + expect(block.getPublicInputsHash().toBuffer()).toEqual( + Buffer.from('20638cd5e03d287dbd356af6e16fd852337f535b12d06f7266599c035696098d', 'hex'), + ); + } else { + expect(block.number).toEqual(2); + expect(block.getCalldataHash()).toEqual( + Buffer.from('50f2f2dc986fc4022b8fdde8f2d610c82ee36776b282ca3514c12726dd9081ef', 'hex'), + ); + expect(block.getStartStateHash()).toEqual( + Buffer.from('e3b20add23469bcbf25157ff75b81665564b089aa95083f8e095a3bb77062831', 'hex'), + ); + expect(block.getEndStateHash()).toEqual( + Buffer.from('dc4f85374d479c6388a9bed0ddea9880422b515c88de0a76fd96b5c93c809b21', 'hex'), + ); + expect(block.getPublicInputsHash().toBuffer()).toEqual( + Buffer.from('12e84ea31aa75fab86269181c8c09dbb8486e518e5db9ce4dad204068fc0a925', 'hex'), + ); + } + + // Printer useful for checking that output match contracts. + /*console.log(block); + console.log(block.encode().toString('hex')); + console.log(`call data hash : ${block.getCalldataHash().toString('hex')}`); + console.log(`start state hash: ${block.getStartStateHash().toString('hex')}`); + console.log(`end state hash : ${block.getEndStateHash().toString('hex')}`); + console.log(`public input hash: ${block.getPublicInputsHash().toString()}`);*/ + } + }, 20000); }); }); 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 953bca2abb99..5adc26ce7e34 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 @@ -114,6 +114,7 @@ export class CircuitBlockBuilder implements BlockBuilder { const wasm = await CircuitsWasm.get(); const newNullifiers = flatMap(txs, tx => tx.data.end.newNullifiers); const newCommitments = flatMap(txs, tx => tx.data.end.newCommitments); + const newL2ToL1Msgs = flatMap(txs, tx => tx.data.end.newL2ToL1Msgs); const newContracts = flatMap(txs, tx => tx.data.end.newContracts).map(cd => computeContractLeaf(wasm, cd)); const newContractData = flatMap(txs, tx => tx.data.end.newContracts).map( n => new ContractData(n.contractAddress, n.portalContractAddress), @@ -133,6 +134,7 @@ export class CircuitBlockBuilder implements BlockBuilder { endTreeOfHistoricContractTreeRootsSnapshot, newCommitments, newNullifiers, + newL2ToL1Msgs, newContracts, newContractData, }); diff --git a/yarn-project/sequencer-client/src/block_builder/standalone_block_builder.ts b/yarn-project/sequencer-client/src/block_builder/standalone_block_builder.ts index 39d805a764cb..1771c7852486 100644 --- a/yarn-project/sequencer-client/src/block_builder/standalone_block_builder.ts +++ b/yarn-project/sequencer-client/src/block_builder/standalone_block_builder.ts @@ -42,8 +42,14 @@ export class StandaloneBlockBuilder implements BlockBuilder { MerkleTreeId.CONTRACT_TREE_ROOTS_TREE, ); + // Note: The L2 -> L1 don't have a tree, so we can do it in the same manner there. + const l2ToL1TreeLeaves: Fr[] = []; + for (const tx of txs) { await this.updateTrees(tx); + tx.data.end.newL2ToL1Msgs.forEach(n => { + l2ToL1TreeLeaves.push(n); + }); } await this.updateRootTrees(); @@ -72,6 +78,7 @@ export class StandaloneBlockBuilder implements BlockBuilder { endTreeOfHistoricContractTreeRootsSnapshot, newCommitments: this.dataTreeLeaves.map(b => Fr.fromBuffer(b)), newNullifiers: this.nullifierTreeLeaves.map(b => Fr.fromBuffer(b)), + newL2ToL1Msgs: l2ToL1TreeLeaves, newContracts: this.contractTreeLeaves.map(b => Fr.fromBuffer(b)), newContractData: txs.flatMap(tx => tx.data.end.newContracts.map(mapContractData)), }); diff --git a/yarn-project/sequencer-client/src/simulator/fake_public.ts b/yarn-project/sequencer-client/src/simulator/fake_public.ts index 51b008fe009a..408ce4fa90db 100644 --- a/yarn-project/sequencer-client/src/simulator/fake_public.ts +++ b/yarn-project/sequencer-client/src/simulator/fake_public.ts @@ -25,7 +25,7 @@ export class FakePublicCircuitSimulator implements PublicCircuitSimulator { args: tx.args, callContext: execution.callContext, emittedEvents: [], - l1MsgStack: [], + newL2ToL1Msgs: [], proverAddress: AztecAddress.random(), publicCallStack: [], returnValues: result.returnValues, diff --git a/yarn-project/types/src/contract_data.ts b/yarn-project/types/src/contract_data.ts index d6485b844ff8..b3cf56a24842 100644 --- a/yarn-project/types/src/contract_data.ts +++ b/yarn-project/types/src/contract_data.ts @@ -96,8 +96,7 @@ export class ContractData { public toBuffer(): Buffer { return serializeToBuffer( this.contractAddress, - this.portalContractAddress.toBuffer(), - this.bytecode || Buffer.alloc(4, 0), + this.portalContractAddress.toBuffer() ); } @@ -110,8 +109,7 @@ export class ContractData { const reader = BufferReader.asReader(buffer); const aztecAddr = AztecAddress.fromBuffer(reader); const ethAddr = new EthAddress(reader.readBytes(EthAddress.SIZE_IN_BYTES)); - const publicFns = reader.readVector(EncodedContractFunction); - return new ContractData(aztecAddr, ethAddr, publicFns); + return new ContractData(aztecAddr, ethAddr); } /** diff --git a/yarn-project/types/src/l2_block.ts b/yarn-project/types/src/l2_block.ts index ab8a3f0284f8..193b3377ee85 100644 --- a/yarn-project/types/src/l2_block.ts +++ b/yarn-project/types/src/l2_block.ts @@ -3,10 +3,11 @@ import { KERNEL_NEW_COMMITMENTS_LENGTH, KERNEL_NEW_CONTRACTS_LENGTH, KERNEL_NEW_NULLIFIERS_LENGTH, + KERNEL_NEW_L2_TO_L1_MSGS_LENGTH, } from '@aztec/circuits.js'; import { makeAppendOnlyTreeSnapshot } from '@aztec/circuits.js/factories'; import { BufferReader, serializeToBuffer } from '@aztec/circuits.js/utils'; -import { Fr } from '@aztec/foundation'; +import { Fr, sha256, toBigIntBE, toBufferBE } from '@aztec/foundation'; import { ContractData } from './contract_data.js'; import { L2Tx } from './l2_tx.js'; @@ -48,6 +49,7 @@ export class L2Block { public endTreeOfHistoricContractTreeRootsSnapshot: AppendOnlyTreeSnapshot, public newCommitments: Fr[], public newNullifiers: Fr[], + public newL2ToL1Msgs: Fr[], public newContracts: Fr[], public newContractData: ContractData[], ) {} @@ -59,6 +61,9 @@ export class L2Block { const newCommitments = Array(KERNEL_NEW_COMMITMENTS_LENGTH * txsPerBlock) .fill(0) .map(() => Fr.random()); + const newL2ToL1Msgs = Array(KERNEL_NEW_L2_TO_L1_MSGS_LENGTH * txsPerBlock) + .fill(0) + .map(() => Fr.random()); const newContracts = Array(KERNEL_NEW_CONTRACTS_LENGTH * txsPerBlock) .fill(0) .map(() => Fr.random()); @@ -80,6 +85,7 @@ export class L2Block { makeAppendOnlyTreeSnapshot(1), newCommitments, newNullifiers, + newL2ToL1Msgs, newContracts, newContractsData, ); @@ -104,6 +110,7 @@ export class L2Block { endTreeOfHistoricContractTreeRootsSnapshot: AppendOnlyTreeSnapshot; newCommitments: Fr[]; newNullifiers: Fr[]; + newL2ToL1Msgs: Fr[]; newContracts: Fr[]; newContractData: ContractData[]; }) { @@ -121,6 +128,7 @@ export class L2Block { fields.endTreeOfHistoricContractTreeRootsSnapshot, fields.newCommitments, fields.newNullifiers, + fields.newL2ToL1Msgs, fields.newContracts, fields.newContractData, ); @@ -147,6 +155,8 @@ export class L2Block { this.newCommitments, this.newNullifiers.length, this.newNullifiers, + this.newL2ToL1Msgs.length, + this.newL2ToL1Msgs, this.newContracts.length, this.newContracts, this.newContractData, @@ -181,6 +191,7 @@ export class L2Block { const endTreeOfHistoricContractTreeRootsSnapshot = reader.readObject(AppendOnlyTreeSnapshot); const newCommitments = reader.readVector(Fr); const newNullifiers = reader.readVector(Fr); + const newL2ToL1Msgs = reader.readVector(Fr); const newContracts = reader.readVector(Fr); const newContractData = reader.readArray(newContracts.length, ContractData); @@ -198,11 +209,134 @@ export class L2Block { endTreeOfHistoricContractTreeRootsSnapshot, newCommitments, newNullifiers, + newL2ToL1Msgs, newContracts, newContractData, ); } + /** + * Computes the public inputs hash for the L2 block. + * The same output as the hash of RootRollupPublicInputs + * @return The public input hash for the L2 block as a field element + */ + getPublicInputsHash() { + const buf = serializeToBuffer( + this.startPrivateDataTreeSnapshot, + this.startNullifierTreeSnapshot, + this.startContractTreeSnapshot, + this.startTreeOfHistoricPrivateDataTreeRootsSnapshot, + this.startTreeOfHistoricContractTreeRootsSnapshot, + this.endPrivateDataTreeSnapshot, + this.endNullifierTreeSnapshot, + this.endContractTreeSnapshot, + this.endTreeOfHistoricPrivateDataTreeRootsSnapshot, + this.endTreeOfHistoricContractTreeRootsSnapshot, + this.getCalldataHash(), + ); + const temp = toBigIntBE(sha256(buf)); + const p = BigInt('21888242871839275222246405745257275088548364400416034343698204186575808495617'); + return Fr.fromBuffer(toBufferBE(temp % p, 32)); + } + + /** + * Computes the start state hash (should equal contract data before block) + * @returns The start state hash for the L2 block + */ + getStartStateHash() { + const inputValue = serializeToBuffer( + this.number - 1, + this.startPrivateDataTreeSnapshot, + this.startNullifierTreeSnapshot, + this.startContractTreeSnapshot, + this.startTreeOfHistoricPrivateDataTreeRootsSnapshot, + this.startTreeOfHistoricContractTreeRootsSnapshot, + ); + return sha256(inputValue); + } + + /** + * Computes the end state hash (should equal contract data after block) + * @returns The end state hash for the L2 block + */ + getEndStateHash() { + const inputValue = serializeToBuffer( + this.number, + this.endPrivateDataTreeSnapshot, + this.endNullifierTreeSnapshot, + this.endContractTreeSnapshot, + this.endTreeOfHistoricPrivateDataTreeRootsSnapshot, + this.endTreeOfHistoricContractTreeRootsSnapshot, + ); + return sha256(inputValue); + } + + /** + * Computes the calldata hash for the L2 block + * This calldata hash is also computed by the rollup contract when the block is submitted, + * and inside the circuit, it is part of the public inputs. + * @returns The calldata hash. + */ + getCalldataHash() { + const computeRoot = (leafs: Buffer[]): Buffer => { + const layers: Buffer[][] = [leafs]; + let activeLayer = 0; + + while (layers[activeLayer].length > 1) { + const layer: Buffer[] = []; + const layerLength = layers[activeLayer].length; + + for (let i = 0; i < layerLength; i += 2) { + const left = layers[activeLayer][i]; + const right = layers[activeLayer][i + 1]; + + layer.push(sha256(Buffer.concat([left, right]))); + } + + layers.push(layer); + activeLayer++; + } + + return layers[layers.length - 1][0]; + }; + + const leafCount = this.newCommitments.length / (KERNEL_NEW_COMMITMENTS_LENGTH * 2); + const leafs: Buffer[] = []; + + for (let i = 0; i < leafCount; i++) { + const inputValue = Buffer.concat([ + this.newNullifiers[i * 8].toBuffer(), + this.newNullifiers[i * 8 + 1].toBuffer(), + this.newNullifiers[i * 8 + 2].toBuffer(), + this.newNullifiers[i * 8 + 3].toBuffer(), + this.newNullifiers[i * 8 + 4].toBuffer(), + this.newNullifiers[i * 8 + 5].toBuffer(), + this.newNullifiers[i * 8 + 6].toBuffer(), + this.newNullifiers[i * 8 + 7].toBuffer(), + this.newCommitments[i * 8].toBuffer(), + this.newCommitments[i * 8 + 1].toBuffer(), + this.newCommitments[i * 8 + 2].toBuffer(), + this.newCommitments[i * 8 + 3].toBuffer(), + this.newCommitments[i * 8 + 4].toBuffer(), + this.newCommitments[i * 8 + 5].toBuffer(), + this.newCommitments[i * 8 + 6].toBuffer(), + this.newCommitments[i * 8 + 7].toBuffer(), + this.newL2ToL1Msgs[i * 4].toBuffer(), + this.newL2ToL1Msgs[i * 4 + 1].toBuffer(), + this.newL2ToL1Msgs[i * 4 + 2].toBuffer(), + this.newL2ToL1Msgs[i * 4 + 3].toBuffer(), + this.newContracts[i * 2].toBuffer(), + this.newContracts[i * 2 + 1].toBuffer(), + this.newContractData[i * 2].contractAddress.toBuffer(), + this.newContractData[i * 2].portalContractAddress.toBuffer32(), + this.newContractData[i * 2 + 1].contractAddress.toBuffer(), + this.newContractData[i * 2 + 1].portalContractAddress.toBuffer32(), + ]); + leafs.push(sha256(inputValue)); + } + return computeRoot(leafs); + } + /** * Get the ith transaction in an L2 block. * @param txIndex - The index of the tx in the block. @@ -222,6 +356,10 @@ export class L2Block { KERNEL_NEW_NULLIFIERS_LENGTH * txIndex, KERNEL_NEW_NULLIFIERS_LENGTH * (txIndex + 1), ); + const newL2ToL1Msgs = this.newL2ToL1Msgs.slice( + KERNEL_NEW_L2_TO_L1_MSGS_LENGTH * txIndex, + KERNEL_NEW_L2_TO_L1_MSGS_LENGTH * (txIndex + 1), + ); const newContracts = this.newContracts.slice( KERNEL_NEW_CONTRACTS_LENGTH * txIndex, KERNEL_NEW_CONTRACTS_LENGTH * (txIndex + 1), @@ -230,7 +368,7 @@ export class L2Block { KERNEL_NEW_CONTRACTS_LENGTH * txIndex, KERNEL_NEW_CONTRACTS_LENGTH * (txIndex + 1), ); - return new L2Tx(newCommitments, newNullifiers, newContracts, newContractData); + return new L2Tx(newCommitments, newNullifiers, newL2ToL1Msgs, newContracts, newContractData); } /** @@ -278,6 +416,7 @@ export class L2Block { )}`, `newCommitments: ${inspectFrArray(this.newCommitments)}`, `newNullifiers: ${inspectFrArray(this.newNullifiers)}`, + `newL2ToL1Msgs: ${inspectFrArray(this.newL2ToL1Msgs)}`, `newContracts: ${inspectFrArray(this.newContracts)}`, `newContractData: ${inspectContractDataArray(this.newContractData)}`, ].join('\n'); diff --git a/yarn-project/types/src/l2_tx.ts b/yarn-project/types/src/l2_tx.ts index fed27ef3cdd3..b891ef8f8b72 100644 --- a/yarn-project/types/src/l2_tx.ts +++ b/yarn-project/types/src/l2_tx.ts @@ -7,6 +7,7 @@ export class L2Tx { constructor( public newCommitments: Fr[], public newNullifiers: Fr[], + public newL2ToL1Msgs: Fr[], public newContracts: Fr[], public newContractData: ContractData[], private hash?: TxHash, diff --git a/yarn-project/world-state/src/synchroniser/server_world_state_synchroniser.test.ts b/yarn-project/world-state/src/synchroniser/server_world_state_synchroniser.test.ts index 882e0315add9..26db83dea118 100644 --- a/yarn-project/world-state/src/synchroniser/server_world_state_synchroniser.test.ts +++ b/yarn-project/world-state/src/synchroniser/server_world_state_synchroniser.test.ts @@ -48,6 +48,7 @@ const getMockBlock = (blockNumber: number, newContractsCommitments?: Buffer[]) = getMockTreeSnapshot(), [Fr.random()], [Fr.random()], + [Fr.random()], newContractsCommitments?.map(x => Fr.fromBuffer(x)) ?? [Fr.random()], [getMockContractData()], );