diff --git a/circuits/cpp/src/aztec3/circuits/abis/global_variables.hpp b/circuits/cpp/src/aztec3/circuits/abis/global_variables.hpp new file mode 100644 index 000000000000..7dab5aa8b973 --- /dev/null +++ b/circuits/cpp/src/aztec3/circuits/abis/global_variables.hpp @@ -0,0 +1,91 @@ +#pragma once +#include "function_data.hpp" +#include "tx_context.hpp" + +#include "aztec3/utils/array.hpp" +#include "aztec3/utils/types/circuit_types.hpp" +#include "aztec3/utils/types/convert.hpp" +#include "aztec3/utils/types/native_types.hpp" + +#include + +namespace aztec3::circuits::abis { + +using aztec3::utils::types::CircuitTypes; +using aztec3::utils::types::NativeTypes; + +template struct GlobalVariables { + using address = typename NCT::address; + using fr = typename NCT::fr; + using boolean = typename NCT::boolean; + + fr chain_id = 0; + fr version = 0; + fr block_number = 0; + fr timestamp = 0; + + boolean operator==(GlobalVariables const& other) const + { + return chain_id == other.chain_id && version == other.version && block_number == other.block_number && + timestamp == other.timestamp; + }; + + template GlobalVariables> to_circuit_type(Composer& composer) const + { + static_assert((std::is_same::value)); + + // Capture the composer: + auto to_ct = [&](auto& e) { return aztec3::utils::types::to_ct(composer, e); }; + auto to_circuit_type = [&](auto& e) { return e.to_circuit_type(composer); }; + + GlobalVariables> globals = { + to_ct(chain_id), + to_ct(version), + to_ct(block_number), + to_ct(timestamp), + }; + + return globals; + }; + + fr hash() const + { + std::vector inputs; + inputs.push_back(chain_id); + inputs.push_back(version); + inputs.push_back(block_number); + inputs.push_back(timestamp); + + return NCT::compress(inputs, GeneratorIndex::GLOBAL_VARIABLES); + } +}; + +template void read(uint8_t const*& it, GlobalVariables& globals) +{ + using serialize::read; + + read(it, globals.chain_id); + read(it, globals.version); + read(it, globals.block_number); + read(it, globals.timestamp); +}; + +template void write(std::vector& buf, GlobalVariables const& globals) +{ + using serialize::write; + + write(buf, globals.chain_id); + write(buf, globals.version); + write(buf, globals.block_number); + write(buf, globals.timestamp); +}; + +template std::ostream& operator<<(std::ostream& os, GlobalVariables const& globals) +{ + return os << "chain_id: " << globals.chain_id << "\n" + << "version: " << globals.version << "\n" + << "block_number: " << globals.block_number << "\n" + << "timestamp: " << globals.timestamp << "\n"; +} + +} // namespace aztec3::circuits::abis \ No newline at end of file diff --git a/circuits/cpp/src/aztec3/circuits/abis/rollup/constant_rollup_data.hpp b/circuits/cpp/src/aztec3/circuits/abis/rollup/constant_rollup_data.hpp index d6e14fb659d3..47819a5b861a 100644 --- a/circuits/cpp/src/aztec3/circuits/abis/rollup/constant_rollup_data.hpp +++ b/circuits/cpp/src/aztec3/circuits/abis/rollup/constant_rollup_data.hpp @@ -1,7 +1,9 @@ #pragma once #include "../append_only_tree_snapshot.hpp" +#include "../global_variables.hpp" +#include "barretenberg/common/serialize.hpp" #include namespace aztec3::circuits::abis { @@ -20,13 +22,16 @@ template struct ConstantRollupData { fr base_rollup_vk_hash = 0; fr merge_rollup_vk_hash = 0; + GlobalVariables global_variables{}; + MSGPACK_FIELDS(start_tree_of_historic_private_data_tree_roots_snapshot, start_tree_of_historic_contract_tree_roots_snapshot, start_tree_of_historic_l1_to_l2_msg_tree_roots_snapshot, private_kernel_vk_tree_root, public_kernel_vk_tree_root, base_rollup_vk_hash, - merge_rollup_vk_hash); + merge_rollup_vk_hash, + global_variables); bool operator==(ConstantRollupData const&) const = default; }; @@ -42,6 +47,7 @@ template void read(uint8_t const*& it, ConstantRollupData& o read(it, obj.public_kernel_vk_tree_root); read(it, obj.base_rollup_vk_hash); read(it, obj.merge_rollup_vk_hash); + read(it, obj.global_variables); }; template void write(std::vector& buf, ConstantRollupData const& obj) @@ -55,6 +61,7 @@ template void write(std::vector& buf, ConstantRollupData write(buf, obj.public_kernel_vk_tree_root); write(buf, obj.base_rollup_vk_hash); write(buf, obj.merge_rollup_vk_hash); + write(buf, obj.global_variables); }; template std::ostream& operator<<(std::ostream& os, ConstantRollupData const& obj) @@ -68,7 +75,8 @@ template std::ostream& operator<<(std::ostream& os, ConstantRollu << "private_kernel_vk_tree_root: " << obj.private_kernel_vk_tree_root << "\n" << "public_kernel_vk_tree_root: " << obj.public_kernel_vk_tree_root << "\n" << "base_rollup_vk_hash: " << obj.base_rollup_vk_hash << "\n" - << "merge_rollup_vk_hash: " << obj.merge_rollup_vk_hash << "\n"; + << "merge_rollup_vk_hash: " << obj.merge_rollup_vk_hash << "\n" + << "global_variables: " << obj.global_variables << "\n"; } } // namespace aztec3::circuits::abis diff --git a/circuits/cpp/src/aztec3/circuits/abis/rollup/root/root_rollup_public_inputs.hpp b/circuits/cpp/src/aztec3/circuits/abis/rollup/root/root_rollup_public_inputs.hpp index b91752857610..e6efa6bc959e 100644 --- a/circuits/cpp/src/aztec3/circuits/abis/rollup/root/root_rollup_public_inputs.hpp +++ b/circuits/cpp/src/aztec3/circuits/abis/rollup/root/root_rollup_public_inputs.hpp @@ -1,6 +1,7 @@ #pragma once #include "aztec3/circuits/abis/append_only_tree_snapshot.hpp" +#include "aztec3/circuits/abis/global_variables.hpp" #include "aztec3/constants.hpp" #include "aztec3/utils/types/circuit_types.hpp" #include "aztec3/utils/types/convert.hpp" @@ -19,6 +20,8 @@ template struct RootRollupPublicInputs { // All below are shared between the base and merge rollups AggregationObject end_aggregation_object; + GlobalVariables globalVariables; + AppendOnlyTreeSnapshot start_private_data_tree_snapshot; AppendOnlyTreeSnapshot end_private_data_tree_snapshot; @@ -52,6 +55,7 @@ template struct RootRollupPublicInputs { { std::vector buf; + write(&buf, globalVariables); write(buf, start_private_data_tree_snapshot); write(buf, start_nullifier_tree_snapshot); write(buf, start_contract_tree_snapshot); @@ -100,6 +104,7 @@ template void read(uint8_t const*& it, RootRollupPublicInputs void write(std::vector& buf, RootRollupPublicIn using serialize::write; write(buf, obj.end_aggregation_object); + write(buf, obj.globalVariables); write(buf, obj.start_private_data_tree_snapshot); write(buf, obj.end_private_data_tree_snapshot); write(buf, obj.start_nullifier_tree_snapshot); @@ -148,6 +154,7 @@ template void write(std::vector& buf, RootRollupPublicIn template std::ostream& operator<<(std::ostream& os, RootRollupPublicInputs const& obj) { return os << "end_aggregation_object: " << obj.end_aggregation_object << "\n" + << "global_variables: " << obj.globalVariables << "\n" << "start_private_data_tree_snapshot: " << obj.start_private_data_tree_snapshot << "\n" << "end_private_data_tree_snapshot: " << obj.end_private_data_tree_snapshot << "\n" << "start_nullifier_tree_snapshot: " << obj.start_nullifier_tree_snapshot << "\n" diff --git a/circuits/cpp/src/aztec3/circuits/abis/tx_context.hpp b/circuits/cpp/src/aztec3/circuits/abis/tx_context.hpp index 329528b1fa4a..16abc72fca7b 100644 --- a/circuits/cpp/src/aztec3/circuits/abis/tx_context.hpp +++ b/circuits/cpp/src/aztec3/circuits/abis/tx_context.hpp @@ -6,6 +6,7 @@ #include "aztec3/utils/types/convert.hpp" #include "aztec3/utils/types/native_types.hpp" +#include "barretenberg/common/serialize.hpp" #include namespace aztec3::circuits::abis { @@ -24,13 +25,22 @@ template struct TxContext { ContractDeploymentData contract_deployment_data{}; + fr chain_id = 0; + fr version = 0; + // for serialization: update up with new fields - MSGPACK_FIELDS(is_fee_payment_tx, is_rebate_payment_tx, is_contract_deployment_tx, contract_deployment_data); + MSGPACK_FIELDS(is_fee_payment_tx, + is_rebate_payment_tx, + is_contract_deployment_tx, + contract_deployment_data, + chain_id, + version); boolean operator==(TxContext const& other) const { return is_fee_payment_tx == other.is_fee_payment_tx && is_rebate_payment_tx == other.is_rebate_payment_tx && is_contract_deployment_tx == other.is_contract_deployment_tx && - contract_deployment_data == other.contract_deployment_data; + contract_deployment_data == other.contract_deployment_data && chain_id == other.chain_id && + version == other.version; }; template TxContext> to_circuit_type(Composer& composer) const @@ -46,6 +56,8 @@ template struct TxContext { to_ct(is_rebate_payment_tx), to_ct(is_contract_deployment_tx), contract_deployment_data.to_circuit_type(composer), + to_ct(chain_id), + to_ct(version), }; return tx_context; @@ -57,12 +69,12 @@ template struct TxContext { auto to_nt = [&](auto& e) { return aztec3::utils::types::to_nt(e); }; auto to_native_type = [](T& e) { return e.template to_native_type(); }; - TxContext tx_context = { - to_nt(is_fee_payment_tx), - to_nt(is_rebate_payment_tx), - to_nt(is_contract_deployment_tx), - to_native_type(contract_deployment_data), - }; + TxContext tx_context = { to_nt(is_fee_payment_tx), + to_nt(is_rebate_payment_tx), + to_nt(is_contract_deployment_tx), + to_native_type(contract_deployment_data), + to_nt(chain_id), + to_nt(version) }; return tx_context; }; @@ -75,6 +87,8 @@ template struct TxContext { fr(is_rebate_payment_tx).set_public(); fr(is_contract_deployment_tx).set_public(); contract_deployment_data.set_public(); + chain_id.set_public(); + version.set_public(); } fr hash() const @@ -84,6 +98,8 @@ template struct TxContext { fr(is_rebate_payment_tx), fr(is_contract_deployment_tx), contract_deployment_data.hash(), + chain_id, + version, }; return NCT::compress(inputs, GeneratorIndex::TX_CONTEXT); @@ -98,6 +114,8 @@ template void read(uint8_t const*& it, TxContext& tx_context read(it, tx_context.is_rebate_payment_tx); read(it, tx_context.is_contract_deployment_tx); read(it, tx_context.contract_deployment_data); + read(it, tx_context.chain_id); + read(it, tx_context.version); }; template void write(std::vector& buf, TxContext const& tx_context) @@ -108,6 +126,8 @@ template void write(std::vector& buf, TxContext con write(buf, tx_context.is_rebate_payment_tx); write(buf, tx_context.is_contract_deployment_tx); write(buf, tx_context.contract_deployment_data); + write(buf, tx_context.chain_id); + write(buf, tx_context.version); }; template std::ostream& operator<<(std::ostream& os, TxContext const& tx_context) @@ -117,7 +137,9 @@ template std::ostream& operator<<(std::ostream& os, TxContext do_private_call_get_kernel_inputs_init( .is_rebate_payment_tx = false, .is_contract_deployment_tx = is_constructor, .contract_deployment_data = contract_deployment_data, + .chain_id = 1, } }; //*************************************************************************** diff --git a/circuits/cpp/src/aztec3/circuits/kernel/public/.test.cpp b/circuits/cpp/src/aztec3/circuits/kernel/public/.test.cpp index f2aeb02869e2..da155ab26467 100644 --- a/circuits/cpp/src/aztec3/circuits/kernel/public/.test.cpp +++ b/circuits/cpp/src/aztec3/circuits/kernel/public/.test.cpp @@ -301,6 +301,7 @@ PublicKernelInputs get_kernel_inputs_with_previous_kernel(NT::boolean privat .is_rebate_payment_tx = false, .is_contract_deployment_tx = false, .contract_deployment_data = {}, + .chain_id = 1, } }; std::array child_call_stacks; diff --git a/circuits/cpp/src/aztec3/circuits/rollup/base/.test.cpp b/circuits/cpp/src/aztec3/circuits/rollup/base/.test.cpp index c65c69f5ba2c..f16467ca0cad 100644 --- a/circuits/cpp/src/aztec3/circuits/rollup/base/.test.cpp +++ b/circuits/cpp/src/aztec3/circuits/rollup/base/.test.cpp @@ -654,6 +654,30 @@ TEST_F(base_rollup_tests, native_constants_dont_change) run_cbind(inputs, outputs); } +TEST_F(base_rollup_tests, native_constants_dont_match_kernels_chain_id) +{ + DummyComposer composer = DummyComposer("base_rollup_tests__native_constants_dont_change"); + BaseRollupInputs inputs = base_rollup_inputs_from_kernels({ get_empty_kernel(), get_empty_kernel() }); + inputs.constants.global_variables.chain_id = 3; + BaseOrMergeRollupPublicInputs const outputs = + aztec3::circuits::rollup::native_base_rollup::base_rollup_circuit(composer, inputs); + ASSERT_EQ(inputs.constants, outputs.constants); + EXPECT_TRUE(composer.failed()); + ASSERT_EQ(composer.get_first_failure().message, "kernel chain_id does not match the rollup chain_id"); +} + +TEST_F(base_rollup_tests, native_constants_dont_match_kernels_version) +{ + DummyComposer composer = DummyComposer("base_rollup_tests__native_constants_dont_change"); + BaseRollupInputs inputs = base_rollup_inputs_from_kernels({ get_empty_kernel(), get_empty_kernel() }); + inputs.constants.global_variables.version = 3; + BaseOrMergeRollupPublicInputs const outputs = + aztec3::circuits::rollup::native_base_rollup::base_rollup_circuit(composer, inputs); + ASSERT_EQ(inputs.constants, outputs.constants); + EXPECT_TRUE(composer.failed()); + ASSERT_EQ(composer.get_first_failure().message, "kernel version does not match the rollup version"); +} + TEST_F(base_rollup_tests, native_aggregate) { // TODO(rahul): Fix this when aggregation works 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 b2e2e87e8a8e..1584e7e77a79 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 @@ -463,6 +463,18 @@ BaseOrMergeRollupPublicInputs base_rollup_circuit(DummyComposer& composer, BaseR CircuitErrorCode::BASE__KERNEL_PROOF_VERIFICATION_FAILED); } + // Verify the kernel chain_id and versions + for (size_t i = 0; i < 2; i++) { + composer.do_assert(baseRollupInputs.kernel_data[i].public_inputs.constants.tx_context.chain_id == + baseRollupInputs.constants.global_variables.chain_id, + "kernel chain_id does not match the rollup chain_id", + CircuitErrorCode::BASE__INVALID_CHAIN_ID); + composer.do_assert(baseRollupInputs.kernel_data[i].public_inputs.constants.tx_context.version == + baseRollupInputs.constants.global_variables.version, + "kernel version does not match the rollup version", + CircuitErrorCode::BASE__INVALID_VERSION); + } + // First we compute the contract tree leaves std::vector const contract_leaves = calculate_contract_leaves(baseRollupInputs); diff --git a/circuits/cpp/src/aztec3/circuits/rollup/merge/.test.cpp b/circuits/cpp/src/aztec3/circuits/rollup/merge/.test.cpp index bd34398996a1..2dd153ae03ff 100644 --- a/circuits/cpp/src/aztec3/circuits/rollup/merge/.test.cpp +++ b/circuits/cpp/src/aztec3/circuits/rollup/merge/.test.cpp @@ -110,6 +110,20 @@ TEST_F(merge_rollup_tests, native_constants_different_failure) ASSERT_EQ(composer.get_first_failure().message, "input proofs have different constants"); } +TEST_F(merge_rollup_tests, native_constants_different_chain_id_failure) +{ + DummyComposer composer = DummyComposer("merge_rollup_tests__native_constants_different_failure"); + std::array const kernels = { + get_empty_kernel(), get_empty_kernel(), get_empty_kernel(), get_empty_kernel() + }; + MergeRollupInputs inputs = get_merge_rollup_inputs(composer, kernels); + inputs.previous_rollup_data[0].base_or_merge_rollup_public_inputs.constants.global_variables.chain_id = fr(1); + inputs.previous_rollup_data[1].base_or_merge_rollup_public_inputs.constants.global_variables.chain_id = fr(0); + merge_rollup_circuit(composer, inputs); + ASSERT_TRUE(composer.failed()); + ASSERT_EQ(composer.get_first_failure().message, "input proofs have different constants"); +} + TEST_F(merge_rollup_tests, native_fail_if_previous_rollups_dont_follow_on) { DummyComposer composerA = DummyComposer("merge_rollup_tests__native_fail_if_previous_rollups_dont_follow_on_A"); diff --git a/circuits/cpp/src/aztec3/circuits/rollup/root/native_root_rollup_circuit.cpp b/circuits/cpp/src/aztec3/circuits/rollup/root/native_root_rollup_circuit.cpp index 3da057791c1c..ac6a67b0fc1a 100644 --- a/circuits/cpp/src/aztec3/circuits/rollup/root/native_root_rollup_circuit.cpp +++ b/circuits/cpp/src/aztec3/circuits/rollup/root/native_root_rollup_circuit.cpp @@ -131,6 +131,7 @@ RootRollupPublicInputs root_rollup_circuit(DummyComposer& composer, RootRollupIn RootRollupPublicInputs public_inputs = { .end_aggregation_object = aggregation_object, + .globalVariables = left.constants.global_variables, .start_private_data_tree_snapshot = left.start_private_data_tree_snapshot, .end_private_data_tree_snapshot = right.end_private_data_tree_snapshot, .start_nullifier_tree_snapshot = left.start_nullifier_tree_snapshot, diff --git a/circuits/cpp/src/aztec3/constants.hpp b/circuits/cpp/src/aztec3/constants.hpp index 79247bcaf055..0ea773fbe69d 100644 --- a/circuits/cpp/src/aztec3/constants.hpp +++ b/circuits/cpp/src/aztec3/constants.hpp @@ -93,6 +93,7 @@ enum GeneratorIndex { SIGNED_TX_REQUEST, L1_TO_L2_MESSAGE_SECRET, FUNCTION_ARGS, + GLOBAL_VARIABLES }; enum StorageSlotGeneratorIndex { diff --git a/circuits/cpp/src/aztec3/utils/circuit_errors.hpp b/circuits/cpp/src/aztec3/utils/circuit_errors.hpp index 9186715c9776..6c7947dc9668 100644 --- a/circuits/cpp/src/aztec3/utils/circuit_errors.hpp +++ b/circuits/cpp/src/aztec3/utils/circuit_errors.hpp @@ -67,6 +67,8 @@ enum CircuitErrorCode : uint16_t { BASE__INVALID_NULLIFIER_RANGE = 4004, BASE__INVALID_PUBLIC_DATA_READS = 4005, BASE__INVALID_PUBLIC_DATA_UPDATE_REQUESTS = 4006, + BASE__INVALID_CHAIN_ID = 4007, + BASE__INVALID_VERSION = 4008, MERGE_CIRCUIT_FAILED = 6000, diff --git a/l1-contracts/src/core/libraries/Decoder.sol b/l1-contracts/src/core/libraries/Decoder.sol index b89355c861ac..99730a8f9669 100644 --- a/l1-contracts/src/core/libraries/Decoder.sol +++ b/l1-contracts/src/core/libraries/Decoder.sol @@ -6,6 +6,8 @@ pragma solidity >=0.8.18; import {Constants} from "@aztec/core/libraries/Constants.sol"; import {Hash} from "@aztec/core/libraries/Hash.sol"; +import {Test} from "forge-std/Test.sol"; + /** * @title Decoder Library * @author Aztec Labs @@ -18,57 +20,60 @@ import {Hash} from "@aztec/core/libraries/Hash.sol"; * L2 Block Data specification * ------------------- * - * | byte start | num bytes | name - * | --- | --- | --- - * | 0x00 | 0x04 | L2 block number - * | 0x04 | 0x20 | startPrivateDataTreeSnapshot.root - * | 0x24 | 0x04 | startPrivateDataTreeSnapshot.nextAvailableLeafIndex - * | 0x28 | 0x20 | startNullifierTreeSnapshot.root - * | 0x48 | 0x04 | startNullifierTreeSnapshot.nextAvailableLeafIndex - * | 0x4c | 0x20 | startContractTreeSnapshot.root - * | 0x6c | 0x04 | startContractTreeSnapshot.nextAvailableLeafIndex - * | 0x70 | 0x20 | startTreeOfHistoricPrivateDataTreeRootsSnapshot.root - * | 0x90 | 0x04 | startTreeOfHistoricPrivateDataTreeRootsSnapshot.nextAvailableLeafIndex - * | 0x94 | 0x20 | startTreeOfHistoricContractTreeRootsSnapshot.root - * | 0xb4 | 0x04 | startTreeOfHistoricContractTreeRootsSnapshot.nextAvailableLeafIndex - * | 0xb8 | 0x20 | startPublicDataTreeRoot - * | 0xd8 | 0x20 | startL1ToL2MessagesTreeSnapshot.root - * | 0xf8 | 0x04 | startL1ToL2MessagesTreeSnapshot.nextAvailableLeafIndex - * | 0xfc | 0x20 | startTreeOfHistoricL1ToL2MessagesTreeRootsSnapshot.root - * | 0x11c | 0x04 | startTreeOfHistoricL1ToL2MessagesTreeRootsSnapshot.nextAvailableLeafIndex - * | 0x120 | 0x20 | endPrivateDataTreeSnapshot.root - * | 0x140 | 0x04 | endPrivateDataTreeSnapshot.nextAvailableLeafIndex - * | 0x144 | 0x20 | endNullifierTreeSnapshot.root - * | 0x164 | 0x04 | endNullifierTreeSnapshot.nextAvailableLeafIndex - * | 0x168 | 0x20 | endContractTreeSnapshot.root - * | 0x188 | 0x04 | endContractTreeSnapshot.nextAvailableLeafIndex - * | 0x18c | 0x20 | endTreeOfHistoricPrivateDataTreeRootsSnapshot.root - * | 0x1ac | 0x04 | endTreeOfHistoricPrivateDataTreeRootsSnapshot.nextAvailableLeafIndex - * | 0x1b0 | 0x20 | endTreeOfHistoricContractTreeRootsSnapshot.root - * | 0x1d0 | 0x04 | endTreeOfHistoricContractTreeRootsSnapshot.nextAvailableLeafIndex - * | 0x1d4 | 0x20 | endPublicDataTreeRoot - * | 0x1f4 | 0x20 | endL1ToL2MessagesTreeSnapshot.root - * | 0x214 | 0x04 | endL1ToL2MessagesTreeSnapshot.nextAvailableLeafIndex - * | 0x218 | 0x20 | endTreeOfHistoricL1ToL2MessagesTreeRootsSnapshot.root - * | 0x238 | 0x04 | endTreeOfHistoricL1ToL2MessagesTreeRootsSnapshot.nextAvailableLeafIndex - * | 0x23c | 0x04 | len(newCommitments) denoted a - * | 0x240 | a * 0x20 | newCommitments (each element 32 bytes) - * | 0x240 + a * 0x20 | 0x04 | len(newNullifiers) denoted b - * | 0x244 + a * 0x20 | b * 0x20 | newNullifiers (each element 32 bytes) - * | 0x244 + (a + b) * 0x20 | 0x04 | len(newPublicDataWrites) denoted c - * | 0x248 + (a + b) * 0x20 | c * 0x40 | newPublicDataWrites (each element 64 bytes) - * | 0x248 + (a + b) * 0x20 + c * 0x40 | 0x04 | len(newL2ToL1msgs) denoted d - * | 0x24c + (a + b) * 0x20 + c * 0x40 | d * 0x20 | newL2ToL1msgs (each element 32 bytes) - * | 0x24c + (a + b + d) * 0x20 + c * 0x40 | 0x04 | len(newContracts) denoted e - * | 0x250 + (a + b + d) * 0x20 + c * 0x40 | e * 0x20 | newContracts (each element 32 bytes) - * | 0x250 + (a + b + d) * 0x20 + c * 0x40 + e * 0x20 | e * 0x34 | newContractData (each element 52 bytes) - * | 0x250 + (a + b + d) * 0x20 + c * 0x40 + e * 0x54 | 0x04 | len(l1ToL2Messages) denoted f - * | K := 0x254 + (a + b + d) * 0x20 + c * 0x40 + e * 0x54| f * 0x20 | l1ToL2Messages (each element 32 bytes) - * | K + f * 0x20 | 0x04 | byteLen(newEncryptedLogs) denoted g - * | K + f * 0x20 + 0x04 | g | newEncryptedLogs - * | K + f * 0x20 + 0x04 + g | 0x04 | byteLen(newUnencryptedLogs) denoted h - * | K + f * 0x20 + 0x04 + g + 0x04 | h | newUnencryptedLogs - * |--- |--- | --- + * | byte start | num bytes | name + * | --- | --- | --- + * | 0x0000 | 0x20 | chain-id + * | 0x0020 | 0x20 | version + * | 0x0040 | 0x20 | L2 block number + * | 0x0060 | 0x20 | L2 timestamp + * | 0x0080 | 0x20 | startPrivateDataTreeSnapshot.root + * | 0x00a0 | 0x04 | startPrivateDataTreeSnapshot.nextAvailableLeafIndex + * | 0x00a4 | 0x20 | startNullifierTreeSnapshot.root + * | 0x00c4 | 0x04 | startNullifierTreeSnapshot.nextAvailableLeafIndex + * | 0x00c8 | 0x20 | startContractTreeSnapshot.root + * | 0x00e8 | 0x04 | startContractTreeSnapshot.nextAvailableLeafIndex + * | 0x00ec | 0x20 | startTreeOfHistoricPrivateDataTreeRootsSnapshot.root + * | 0x010c | 0x04 | startTreeOfHistoricPrivateDataTreeRootsSnapshot.nextAvailableLeafIndex + * | 0x0110 | 0x20 | startTreeOfHistoricContractTreeRootsSnapshot.root + * | 0x0130 | 0x04 | startTreeOfHistoricContractTreeRootsSnapshot.nextAvailableLeafIndex + * | 0x0134 | 0x20 | startPublicDataTreeRoot + * | 0x0154 | 0x20 | startL1ToL2MessagesTreeSnapshot.root + * | 0x0174 | 0x04 | startL1ToL2MessagesTreeSnapshot.nextAvailableLeafIndex + * | 0x0178 | 0x20 | startTreeOfHistoricL1ToL2MessagesTreeRootsSnapshot.root + * | 0x0198 | 0x04 | startTreeOfHistoricL1ToL2MessagesTreeRootsSnapshot.nextAvailableLeafIndex + * | 0x019c | 0x20 | endPrivateDataTreeSnapshot.root + * | 0x01bc | 0x04 | endPrivateDataTreeSnapshot.nextAvailableLeafIndex + * | 0x01c0 | 0x20 | endNullifierTreeSnapshot.root + * | 0x01e0 | 0x04 | endNullifierTreeSnapshot.nextAvailableLeafIndex + * | 0x01e4 | 0x20 | endContractTreeSnapshot.root + * | 0x0204 | 0x04 | endContractTreeSnapshot.nextAvailableLeafIndex + * | 0x0208 | 0x20 | endTreeOfHistoricPrivateDataTreeRootsSnapshot.root + * | 0x0228 | 0x04 | endTreeOfHistoricPrivateDataTreeRootsSnapshot.nextAvailableLeafIndex + * | 0x022c | 0x20 | endTreeOfHistoricContractTreeRootsSnapshot.root + * | 0x024c | 0x04 | endTreeOfHistoricContractTreeRootsSnapshot.nextAvailableLeafIndex + * | 0x0250 | 0x20 | endPublicDataTreeRoot + * | 0x0270 | 0x20 | endL1ToL2MessagesTreeSnapshot.root + * | 0x0290 | 0x04 | endL1ToL2MessagesTreeSnapshot.nextAvailableLeafIndex + * | 0x0294 | 0x20 | endTreeOfHistoricL1ToL2MessagesTreeRootsSnapshot.root + * | 0x02b4 | 0x04 | endTreeOfHistoricL1ToL2MessagesTreeRootsSnapshot.nextAvailableLeafIndex + * | 0x02b8 | 0x04 | len(newCommitments) denoted a + * | 0x02bc | a * 0x20 | newCommitments (each element 32 bytes) + * | 0x02bc + a * 0x20 | 0x04 | len(newNullifiers) denoted b + * | 0x02c0 + a * 0x20 | b * 0x20 | newNullifiers (each element 32 bytes) + * | 0x02c0 + (a + b) * 0x20 | 0x04 | len(newPublicDataWrites) denoted c + * | 0x02c4 + (a + b) * 0x20 | c * 0x40 | newPublicDataWrites (each element 64 bytes) + * | 0x02c4 + (a + b) * 0x20 + c * 0x40 | 0x04 | len(newL2ToL1msgs) denoted d + * | 0x02c8 + (a + b) * 0x20 + c * 0x40 | d * 0x20 | newL2ToL1msgs (each element 32 bytes) + * | 0x02c8 + (a + b + d) * 0x20 + c * 0x40 | 0x04 | len(newContracts) denoted e + * | 0x02cc + (a + b + d) * 0x20 + c * 0x40 | e * 0x20 | newContracts (each element 32 bytes) + * | 0x02cc + (a + b + d) * 0x20 + c * 0x40 + e * 0x20 | e * 0x34 | newContractData (each element 52 bytes) + * | 0x02cc + (a + b + d) * 0x20 + c * 0x40 + e * 0x54 | 0x04 | len(l1ToL2Messages) denoted f + * | K := 0x02cc + (a + b + d) * 0x20 + c * 0x40 + e * 0x54 | f * 0x20 | l1ToL2Messages (each element 32 bytes) + * | K + f * 0x20 | 0x04 | byteLen(newEncryptedLogs) denoted g + * | K + f * 0x20 + 0x04 | g | newEncryptedLogs + * | K + f * 0x20 + 0x04 + g | 0x04 | byteLen(newUnencryptedLogs) denoted h + * | K + f * 0x20 + 0x04 + g + 0x04 | h | newUnencryptedLogs + * |--- |--- | --- */ library Decoder { struct ArrayLengths { @@ -130,8 +135,8 @@ library Decoder { l2BlockNumber = getL2BlockNumber(_l2Block); // Note, for startStateHash to match the storage, the l2 block number must be new - 1. // Only jumping 1 block at a time. - startStateHash = computeStateHash(l2BlockNumber - 1, 0x4, _l2Block); - endStateHash = computeStateHash(l2BlockNumber, 0x120, _l2Block); + startStateHash = computeStateHash(l2BlockNumber - 1, 0x80, _l2Block); + endStateHash = computeStateHash(l2BlockNumber, 0x19c, _l2Block); bytes32 diffRoot; bytes32 l1ToL2MsgsHash; @@ -152,13 +157,11 @@ library Decoder { bytes32 _diffRoot, bytes32 _l1ToL2MsgsHash ) internal pure returns (bytes32) { - uint256 size = 0x23c - 0x04 + 0x20 + 0x20; - bytes memory temp = new bytes(size); + bytes memory temp = new bytes(0x02b8 + 0x20 + 0x20); assembly { - calldatacopy(add(temp, 0x20), add(_l2Block.offset, 0x04), size) - let endOfTreesData := sub(0x23c, 0x04) - mstore(add(temp, add(0x20, endOfTreesData)), _diffRoot) - mstore(add(temp, add(0x40, endOfTreesData)), _l1ToL2MsgsHash) + calldatacopy(add(temp, 0x20), _l2Block.offset, 0x02b8) + mstore(add(temp, add(0x20, 0x02b8)), _diffRoot) + mstore(add(temp, add(0x40, 0x02b8)), _l1ToL2MsgsHash) } return Hash.sha256ToField(temp); } @@ -170,14 +173,14 @@ library Decoder { */ function getL2BlockNumber(bytes calldata _l2Block) internal pure returns (uint256 l2BlockNumber) { assembly { - l2BlockNumber := and(shr(224, calldataload(_l2Block.offset)), 0xffffffff) + l2BlockNumber := calldataload(add(_l2Block.offset, 0x40)) } } /** * @notice Computes a state hash * @param _l2BlockNumber - The L2 block number - * @param _offset - The offset into the data, 0x04 for start, 0xd8 for end + * @param _offset - The offset into the data, 0x80 for start, 0x019c for end * @param _l2Block - The L2 block calldata. * @return The state hash * @dev The state hash is sha256 hash of block's header elements. For each block the header elements are @@ -189,18 +192,14 @@ library Decoder { pure returns (bytes32) { - bytes memory temp = new bytes(0x120); + // 0x20 for the block number + 0x11c for the header elements + bytes memory temp = new bytes(0x20 + 0x11c); assembly { - // Copy the L2 block number byte by byte to memory - mstore8(add(temp, 0x20), shr(24, _l2BlockNumber)) - mstore8(add(temp, 0x21), shr(16, _l2BlockNumber)) - mstore8(add(temp, 0x22), shr(8, _l2BlockNumber)) - mstore8(add(temp, 0x23), _l2BlockNumber) - } - assembly { - // Copy header elements (not including block number) for start or end (size 0xd4) - calldatacopy(add(temp, 0x24), add(_l2Block.offset, _offset), 0x11c) + // Copy block number + mstore(add(temp, 0x20), _l2BlockNumber) + // Copy header elements (not including block number) for start or end + calldatacopy(add(temp, 0x40), add(_l2Block.offset, _offset), 0x11c) } return sha256(temp); @@ -225,7 +224,7 @@ library Decoder { ArrayOffsets memory offsets; { assembly { - let offset := add(_l2Block.offset, 0x23c) + let offset := add(_l2Block.offset, 0x02b8) let commitmentCount := and(shr(224, calldataload(offset)), 0xffffffff) offset := add(add(offset, 0x4), mul(commitmentCount, 0x20)) let nullifierCount := and(shr(224, calldataload(offset)), 0xffffffff) @@ -264,7 +263,7 @@ library Decoder { // Data starts after header. Look at L2 Block Data specification at the top of this file. { - offsets.commitmentOffset = 0x240; + offsets.commitmentOffset = 0x02bc; offsets.nullifierOffset = offsets.commitmentOffset + 0x4 + lengths.commitmentCount * 0x20; offsets.publicDataOffset = offsets.nullifierOffset + 0x4 + lengths.nullifierCount * 0x20; offsets.l2ToL1MsgsOffset = offsets.publicDataOffset + 0x4 + lengths.dataWritesCount * 0x40; diff --git a/l1-contracts/test/Decoder.t.sol b/l1-contracts/test/Decoder.t.sol index 75bb1397bc7f..6c7adeddf0ee 100644 --- a/l1-contracts/test/Decoder.t.sol +++ b/l1-contracts/test/Decoder.t.sol @@ -25,10 +25,10 @@ contract DecoderTest is Test { Rollup internal rollup; bytes internal block_empty_1 = - hex"000000020668938c4a4167faa2b5031e427d74d6e38638d2eef68834b70480c5a93f8e15000000102d39729fd006096882acfbd350c91fd61883578b4fe35b63cdce3c1993a497ea000000180668938c4a4167faa2b5031e427d74d6e38638d2eef68834b70480c5a93f8e1500000004238b20b7bc1d5190f8e928eb2aa2094412588f9cad6c7862f69c09a9b246d6ed00000002238b20b7bc1d5190f8e928eb2aa2094412588f9cad6c7862f69c09a9b246d6ed000000022b72136df9bc7dc9cbfe6b84ec743e8e1d73dd93aecfa79f18afb86be977d3eb0668938c4a4167faa2b5031e427d74d6e38638d2eef68834b70480c5a93f8e1500000010238b20b7bc1d5190f8e928eb2aa2094412588f9cad6c7862f69c09a9b246d6ed000000020668938c4a4167faa2b5031e427d74d6e38638d2eef68834b70480c5a93f8e15000000202d39729fd006096882acfbd350c91fd61883578b4fe35b63cdce3c1993a497ea000000280668938c4a4167faa2b5031e427d74d6e38638d2eef68834b70480c5a93f8e1500000008236394e84a01824e286653b542a923474253251e86c118f02978d5714538236c00000003236394e84a01824e286653b542a923474253251e86c118f02978d5714538236c000000032b72136df9bc7dc9cbfe6b84ec743e8e1d73dd93aecfa79f18afb86be977d3eb0668938c4a4167faa2b5031e427d74d6e38638d2eef68834b70480c5a93f8e1500000020236394e84a01824e286653b542a923474253251e86c118f02978d5714538236c0000000300000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000"; + hex"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000668938c4a4167faa2b5031e427d74d6e38638d2eef68834b70480c5a93f8e15000000002d39729fd006096882acfbd350c91fd61883578b4fe35b63cdce3c1993a497ea000000080668938c4a4167faa2b5031e427d74d6e38638d2eef68834b70480c5a93f8e150000000019c36f7bc2e4116d082865cc0b4ac8e16e9efa00ace9fb2222dd1dfd719cb6710000000119c36f7bc2e4116d082865cc0b4ac8e16e9efa00ace9fb2222dd1dfd719cb671000000012b72136df9bc7dc9cbfe6b84ec743e8e1d73dd93aecfa79f18afb86be977d3eb0668938c4a4167faa2b5031e427d74d6e38638d2eef68834b70480c5a93f8e150000000019c36f7bc2e4116d082865cc0b4ac8e16e9efa00ace9fb2222dd1dfd719cb671000000010668938c4a4167faa2b5031e427d74d6e38638d2eef68834b70480c5a93f8e15000000102d39729fd006096882acfbd350c91fd61883578b4fe35b63cdce3c1993a497ea000000180668938c4a4167faa2b5031e427d74d6e38638d2eef68834b70480c5a93f8e1500000004238b20b7bc1d5190f8e928eb2aa2094412588f9cad6c7862f69c09a9b246d6ed00000002238b20b7bc1d5190f8e928eb2aa2094412588f9cad6c7862f69c09a9b246d6ed000000022b72136df9bc7dc9cbfe6b84ec743e8e1d73dd93aecfa79f18afb86be977d3eb0668938c4a4167faa2b5031e427d74d6e38638d2eef68834b70480c5a93f8e1500000010238b20b7bc1d5190f8e928eb2aa2094412588f9cad6c7862f69c09a9b246d6ed00000002000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000001000000000000000000000000000000000"; bytes internal block_mixed_1 = - hex"000000010668938c4a4167faa2b5031e427d74d6e38638d2eef68834b70480c5a93f8e15000000002d39729fd006096882acfbd350c91fd61883578b4fe35b63cdce3c1993a497ea000000080668938c4a4167faa2b5031e427d74d6e38638d2eef68834b70480c5a93f8e150000000019c36f7bc2e4116d082865cc0b4ac8e16e9efa00ace9fb2222dd1dfd719cb6710000000119c36f7bc2e4116d082865cc0b4ac8e16e9efa00ace9fb2222dd1dfd719cb671000000012b72136df9bc7dc9cbfe6b84ec743e8e1d73dd93aecfa79f18afb86be977d3eb0668938c4a4167faa2b5031e427d74d6e38638d2eef68834b70480c5a93f8e150000000019c36f7bc2e4116d082865cc0b4ac8e16e9efa00ace9fb2222dd1dfd719cb671000000010813349a787d3f13ec3492de8b6a5c06ba871cb7d2533b8859f3c40693384501000000102e18315fa9fc796d3a94dfe61517725dec4e9d0811ce7e8ee3518cdbcf03549d000000181578dee3629aa301b877887a478484ab676934bd9f8228be7c5cdb5873f975580000000412e58befb4676abe3a279ec129e4d48b53eb1b1724a6c01274b39f6122dfc0bf00000002091367641fbcfd08d2b16d6ec75bb365bd807a436fce9163516a1de3532e8de3000000022d9b8d2353587ca56bdf967b4bb8847af3671bd6901e9e28f82c240c6e33129a1b3ab03f9b9fb0f8a31ed10a930e476c7b8bfcc9018d6dfbe20eb15838a701e9000000103036ed03e75f4893197d647af9e8f5dae3659ac9003c6b144dbb86b71820307400000002000000100000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000012100000000000000000000000000000000000000000000000000000000000001220000000000000000000000000000000000000000000000000000000000000123000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000001410000000000000000000000000000000000000000000000000000000000000142000000000000000000000000000000000000000000000000000000000000014300000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000161000000000000000000000000000000000000000000000000000000000000016200000000000000000000000000000000000000000000000000000000000001630000000000000000000000000000000000000000000000000000000000000180000000000000000000000000000000000000000000000000000000000000018100000000000000000000000000000000000000000000000000000000000001820000000000000000000000000000000000000000000000000000000000000183000000100000000000000000000000000000000000000000000000000000000000000220000000000000000000000000000000000000000000000000000000000000022100000000000000000000000000000000000000000000000000000000000002220000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000000000000000000000000000000000002410000000000000000000000000000000000000000000000000000000000000242000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000261000000000000000000000000000000000000000000000000000000000000026200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000028100000000000000000000000000000000000000000000000000000000000002820000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000520000000000000000000000000000000000000000000000000000000000000052a0000000000000000000000000000000000000000000000000000000000000521000000000000000000000000000000000000000000000000000000000000052b0000000000000000000000000000000000000000000000000000000000000522000000000000000000000000000000000000000000000000000000000000052c0000000000000000000000000000000000000000000000000000000000000523000000000000000000000000000000000000000000000000000000000000052d0000000000000000000000000000000000000000000000000000000000000540000000000000000000000000000000000000000000000000000000000000054a0000000000000000000000000000000000000000000000000000000000000541000000000000000000000000000000000000000000000000000000000000054b0000000000000000000000000000000000000000000000000000000000000542000000000000000000000000000000000000000000000000000000000000054c0000000000000000000000000000000000000000000000000000000000000543000000000000000000000000000000000000000000000000000000000000054d0000000000000000000000000000000000000000000000000000000000000560000000000000000000000000000000000000000000000000000000000000056a0000000000000000000000000000000000000000000000000000000000000561000000000000000000000000000000000000000000000000000000000000056b0000000000000000000000000000000000000000000000000000000000000562000000000000000000000000000000000000000000000000000000000000056c0000000000000000000000000000000000000000000000000000000000000563000000000000000000000000000000000000000000000000000000000000056d0000000000000000000000000000000000000000000000000000000000000580000000000000000000000000000000000000000000000000000000000000058a0000000000000000000000000000000000000000000000000000000000000581000000000000000000000000000000000000000000000000000000000000058b0000000000000000000000000000000000000000000000000000000000000582000000000000000000000000000000000000000000000000000000000000058c0000000000000000000000000000000000000000000000000000000000000583000000000000000000000000000000000000000000000000000000000000058d00000008000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000003210000000000000000000000000000000000000000000000000000000000000340000000000000000000000000000000000000000000000000000000000000034100000000000000000000000000000000000000000000000000000000000003600000000000000000000000000000000000000000000000000000000000000361000000000000000000000000000000000000000000000000000000000000038000000000000000000000000000000000000000000000000000000000000003810000000426fcb9639d15aabe6d792e23ab12fb9633046d4be6911a60d64471d7560d3f6809143b7d4943a3485115d37e7596938a16c91b6055f3837640d8c36b8303bb3c06fb5fb553496e5e0b48834087e036acf99d6d935dc2ebf43c82788cb5ed1c6a2f4bd77ac2bb5474d48c2856135d18168cd6f69f77143c60b3cc370319419dac0000000000000000000000000000000000000000000000000000000000001020212121212121212121212121212121212121212100000000000000000000000000000000000000000000000000000000000010404141414141414141414141414141414141414141000000000000000000000000000000000000000000000000000000000000106061616161616161616161616161616161616161610000000000000000000000000000000000000000000000000000000000001080818181818181818181818181818181818181818100000010151de48ca3efbae39f180fe00b8f472ec9f25be10b4f283a87c6d7839353703914c2ea9dedf77698d4afe23bc663263eed0bf9aa3a8b17d9b74812f185610f9e1570cc6641699e3ae87fa258d80a6d853f7b8ccb211dc244d017e2ca6530f8a12806c860af67e9cd50000378411b8c4c4db172ceb2daa862b259b689ccbdc1e005f140c7c95624c8006774279a01ec1ea88617999e4fe6997b6576c4e1c7395a22048b96b586596bd740d0402e15f5577f7ceb5496b65aafc6d89d7c3b34924b0c3f2d50d16279970d682cada30bfa6b29bc0bac0ee2389f6a0444853eccaa932b2a60561da46a58569d71044a84c639e7f88429826e5622581536eb906d9cdd25a2c0a76f7da6924e10751c755227d2535f4ad258b984e78f9f452a853c52300e212d8e2069e4254d81af07744bcbb81121a38f0e2dbed69a523d3fbf85b75c287ca6f33aadbac2e4f058e05924c140d7895a6ed167caf804b710d2ae3ba62b1b51297b3ea37637af6bd56cf33425d95cc5c96e9c2ee3077322fbec86a0c7f32c15d2a888c6cc122e99478c92470a1311635142d82ad7ae67410beeef4ae31f0902ba2fb964922a4610bb18901f7b923885c1d034da5769a48203ae6f0206a92855e2c01ddb3d6553386b5580d681b8230fa4062948668f834f23e0636eaff70aaa64519aafdf4b040bd2f9836e76b9dc13cfec8065dcdf2834d786e06260d100000e1000000380000001bc0000009072e00ac199039c63d022e3654a8261e694431c62056eb7d8e5db4c455ad9c381ec7e8c4804d7be58d2d24f1bb446ef9c097f112f54f1c890b401927d8c14db9ce209f200b3a78e24acf76f1fdfb833bc87d9bcf4f1bf74cdd694fc2ad5e4456a727d4de19f78c5db5ec9b01173a8809029a4d08727f001e71c67bacf5e262d1207f051a101ff1198da289da236cbb5170000009078b47dc02a9536d78b99a91c034cf9c4d24d9ab79ce71275502b98df23f2d048380c007f843b93774f562c63bb021126de1d4ae327889b7d8adca04748176ad7847bcf5780a76cb5ce09a779f1095a4a6e40b7b1da5f40fdd68e37a1f169a0f29a578230f6eab93d809a53d3620bcdcce099b88b6ef025d98f0a1f50cb82e548935486b3fbc16f6941b094e24548265100000090831d0f6df59dc54f6cd81e3522cd77ccb772eabd445767fb56eea880b14de14e4157da9931eecf53a22d22cfd715132ee4ea009ec2a650df1fbb0b08d2174053a449b1e1377f06b1ef506495637ad282b8ca070e354d3aedd1a6010f074707a33a0b5102e82d9d17f9a121004c187dbf560f2f5a8a6575a9cdff997cdd151ba3fd9779aab9d19b7f05a09e5beca9ffa9000001bc000000900b994e74dcd6bcef2b488bdd9d800719283ad9c4fca4cfa58ba24040c772b96069fb4714cf4f8d0f0fc418bf93e9467ca3d3fd39ae69e77d20b50c8c36d367e0feebda5cea829a57a365b6e691e36364fd000c749b1134950e62b2ca3981ef420fe5002977e879dd7cca98e60901eacffdab22e2273958a5e35ef5c23c6003099ba91fbc8cdf1c96702eb4574717b16c0000009081b2241046f3e30b9fc1a707f8dc63e004bd804799cb5570aaee9a97513247d334e4b996126e04cebe47446ed2270802f0e3a700dd357ae9c2ce465e27aa9d94e07e6819f55b0c615e375167de74dc655226a43b1797ab898c04de1e04f6966af6a76b0c610660f55739d9c99b408a1ec54ecaa5035c600021921d19a9aef4502e2695d27eb860da0e507fa7f82d762e00000090f6dc77421d88719308275812cb54030ecafb5424fd0737c535954a03e5351addd5963c5171e4dceeb9938227a71fd69df824526d0756aaae3ba7bb424f445e0baa964ab34b4e273a8f78d8dca828dc4c721521f5fc539059e390f30a3b55f6bef403377188b84e0bd800f8df84b3b7f8eb4e937ca56557dc8b5c7f936486dde2958ccdac3c0df5de851fd250c934a25b00000380000001bc0000009027d8d13f10e00fd185584e3ceeaade6a03d9a6dc92223613f5651c30028148689f417cbd96a6fb36770bdc6996c013558c785f488d9529637d932bda4b28b880a720de1e5fe5fa1ce9c252c2851ad030b76c2f197d30691c8b9c0347303a5cef92261cb96cfaa46d2dd39b3ce154e94b33e387ca638848e99e4c16134942578d43fa72644e7044a16cbd665524d22108000000907a04ee24b2e3b843c1bcc1d964654a0da341cdbfd401411939438642d12ae3b05ff0666bcecd7eda6c4d188572d0846803ca89bdebd82a2f726595cefd9eb6a13e1693352187f7e108a5604b83e1f5ec7ca9046ef2d48ef7700d86b39bdde52b56609160083ef2849566f8211e9db927619117e8c2b08e9b60537be748ea77e9b53831e38c6c235069a853c05b00b0770000009011b60f750164609f0ab2b106e37fade240f36b547e7db8a7ba20db4fc3f959da895d9d9d06ed20fb437ba325d7c459d9c4746fdd65437d2464408b2cebe8db2a764e9f194e2eec6523e70b1891029d92766deb46773e32d3261889614e9c7af67ecd5c5b042dba8d7378b49fec5e2fec36695cf853413f484b494b22053ee3d8a7e20744f19a83e14b2f4463f7db6bda000001bc000000905390e4c97bd17e71e27cff1bf67bb3232e8720dc91a4366c7c6bbefb41eb580b68c8f0279b746f7bd015795bbdb9e5685e67c272069d7ab4ce4fc6bf7367be9a04f4b287a1a4548a4337975778118ca938b411f2b40245e0ad6d097c3c4a817be98325ee908b48f285b6db00663eeee61b257da68c621a2d35d9430fc088fb8048380547981fc91e2a57e526d81019f0000000905993df0a1980841840280ffe2dcff5e4dbf4df72cbac26ea97c21dca0456aa60c905ea9062435f02cca30732dfee413da62aef24ae8eca05b3ef75bb75a1e21fc5cf0d8d1d64f1f98416f67d8d2762410f2bfc8ccf1edf19e94455057732a0e7893d78be21a8326ecbd3f1df416a5c69aa60e759480f4a685c92cd3bc9ca19ba1490340b6ff46a102c4b2f8f312a08b10000009089a029c6028e9579963949a993a0e2da8f115c0bba1922528d6d5afa837190fb2e02cc4bac271afe475366da2e1204bf67a2ed47a57e6bfc3bad28d20bab5f0c19f9312092d5a0e113cb2fb9a758709d2f199cec0d859d017260914d5a352974a15c5ad622127c37f1a68f88199096a2c3b486912ce2ded1a471ae24a4d63dce6b556716e9626379ebd4edc1969a0b9c00000380000001bc000000901a911eee13e7d12fd506f8c8e4a5241879d3bf829531fc2a99edd8e37801f275f532b2853dfb6466d7d905c98669d79af37451d82f023353d3d14805e43bb02ef1cba77620fa74f6e6d4d889d1c810d9b7b4975ca19cb5b555c241cbcfbf581d43d5a81c08c085d2721bf8a6a055cce5effbf826499e247716d81a424027556fcbadf7610ab612283e57a79da9921644000000901149db151803e90a66214707edbda6813f7d53b43844b0843ba5089553a74a33bf41b2ebec09a86572ce4f465af03d2204d824e3a5bcc0f110270c15379e24034c736ee4bd57f1aead4c59efee6ba375c7f3ffb70eb99cc2becdccc9333039ccf0c43df80e5357e47d75064dea4d535e3f6bc55e38102596aa45e12c2390a116bafd402d35f69d2ff35b9d30fcbb79060000009046686bc5cf84791ab8cba777d156fb0a1523403cb547d9ed138f48d7da1bdf4d422a198f2642361b6f8522cda884ff98c653c41da4b1c30126f648ea177248a48110a89eba5a68a2d22634580aa07166113de68ffe40b04211957a61509021cccd8ecc70a7b173ffc8bdeecc3bd91144bb08879bb6b41e6a55336b01ba056860bf4aead4c29cfeb356c12700fe9dc44f000001bc0000009069450cbad55cba7699cf4169bd0d84b4084a490e226629335f6d1a5f7ba3918ebfc603291075420e97aa39b94505cd954af8ce87011a69416b0583196347aa25232ffe73d53393a2987d21b8995602257f547df7d78ef625d1255770fdb21160206ad268e66d1b29d5dd3c3443491baee6969a2759dc57bee02c445ec32c70b8ee17dcbfcbcb07675bffbe7506be970d00000090c0946fab83288189d8941b3bfe689c9066937ae7cf7acf8f06f17e91059a3d3c3ab461e0aa7694d01f79d279b385388fe74487b7cd5806aa40183f0410f832a25738e69972e655d27fefc5da57916df34427dd95ba12107b9f672a7db287ec7fa062152f07f1f2bd3450ed8b1382397d3d07e1a71c8af3402083fe2e0661142a68f73d01eb03d8713705cc559f0802e60000009009e1e00587869c6bb6a6da4b5175a4c01ef134e10ffbea2764dddb4e4cbcae14c206badb7f06623291598b2a2f707b0a65d5960bb1e0c667516866353456a55042ca83279a83c9c4e2aae0f398265aed53321926c7b29e1b8ced9cf8ac4f982b7b5bc17c445e9a34aad8942d0f93570675cd44e5baa061701d3714e41ea4321b1d15c3a508215c2626b8be11787a6dc200000380000001bc0000009060bd3da3c0c9a3ea6f9bd2b80f358e5b5f947213aec718de6e34eff9b759040ea853c67a0ece253b7bb5210d3e884f0f4e52e40d516eedfd2177501453d9e919b57f11d121215deaf1a0c3e85769d0f33ff9446ab0e4a0628958c7c5710b63f0b043099a4fd015a5f69b8cbeb759a617cbbbe82009eb814da07ba8070827fecc387ceef1f01be49f0d997424885dc0b000000090db27b13aac0c4b52ed49a9f3a6fa68cea54347612fa9c1c3d1db61563457074a2e81b5bd59626efc214d658cc105f740e98a67ed738b8120a57b7b95f560575f553c6614484acde24b3f67e5373a3ec659d0de5bc0a2efa13a5ca1a25d4774f17c837c0d7018268cffeb2b130b69bfe7d0e43f2fe57926a8011bdfd09e03b0f27975ab9b97371c9ca3f13ba34eed08dd00000090da585e2184452f14ff88c4bc004a0026f664509509b720ea44b2df59c52e4d1935e36ae76525e962df10c3097f8f6577fab02b2739268312daf5d79c756109485b19aca1184a5a28c416f2756761f583e03b2ad49b3e8dc099da73248e44d04bee66605f3f4320a02db76a55883bfb29790365ea9991a29cd4a6c3bd09fc70b401943f5e512f8bb878d5b0432e686da3000001bc00000090f70e5e3f1d8c6ff6fe772c7777adf7dbfa1803127ecb65279731580f4c149c8b8dc555fbfa4fd8f431adc0af42308e173cae4ee7cdc795e2ed5005146cbc3f5b61ab96a69626a48ab9b450d59b3a3aa6065afc0b290d87884bc3c3acf5ceb1b3e70ba16a68c605d865efb0a1f555cccb0f8fbcf788313baf6e218becec5803ca418f0d725c8d23e93828ef7fd9fafd3000000090aa3ad55008944c461b15642fccca9590ea5b9bbbdb07673a3e4195e4b0a04d944ea5e724a82888ab7cd89e1949eb28d9a054f9567744e70575335eccd2900eeb72ca336ef8323a8439aec04ffb7ff55ace60edd883e934dbf38db9c25bd5c2fe781643a07d4c9136eb8420f9a1a1d2f90182531b912923db5c101303397a425e0f2773a38b989b89a76e90b922eb0a3100000090ab36f55c1a63a848706755f6d6e768fc68e3f785d50b4970820725fcdfbabe4cbe88ae5ea20ae1705ed0f562a53f4f92c85d013854045551b0a44081a810d8db3d056e0bac6fd7e5ff0f23b1db068bb58190a8bede5295e617e50561d9982645792d23eb33d7ef6ae9c7a9ee51f7d806a0f17775452f05ddda359bbb8915917c36511b4bf1c6cc0a37cf330b5228cc58"; + hex"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000668938c4a4167faa2b5031e427d74d6e38638d2eef68834b70480c5a93f8e15000000002d39729fd006096882acfbd350c91fd61883578b4fe35b63cdce3c1993a497ea000000080668938c4a4167faa2b5031e427d74d6e38638d2eef68834b70480c5a93f8e150000000019c36f7bc2e4116d082865cc0b4ac8e16e9efa00ace9fb2222dd1dfd719cb6710000000119c36f7bc2e4116d082865cc0b4ac8e16e9efa00ace9fb2222dd1dfd719cb671000000012b72136df9bc7dc9cbfe6b84ec743e8e1d73dd93aecfa79f18afb86be977d3eb0668938c4a4167faa2b5031e427d74d6e38638d2eef68834b70480c5a93f8e150000000019c36f7bc2e4116d082865cc0b4ac8e16e9efa00ace9fb2222dd1dfd719cb671000000010813349a787d3f13ec3492de8b6a5c06ba871cb7d2533b8859f3c40693384501000000102e18315fa9fc796d3a94dfe61517725dec4e9d0811ce7e8ee3518cdbcf03549d000000181578dee3629aa301b877887a478484ab676934bd9f8228be7c5cdb5873f975580000000412e58befb4676abe3a279ec129e4d48b53eb1b1724a6c01274b39f6122dfc0bf00000002091367641fbcfd08d2b16d6ec75bb365bd807a436fce9163516a1de3532e8de3000000022d9b8d2353587ca56bdf967b4bb8847af3671bd6901e9e28f82c240c6e33129a1b3ab03f9b9fb0f8a31ed10a930e476c7b8bfcc9018d6dfbe20eb15838a701e9000000103036ed03e75f4893197d647af9e8f5dae3659ac9003c6b144dbb86b71820307400000002000000100000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000012100000000000000000000000000000000000000000000000000000000000001220000000000000000000000000000000000000000000000000000000000000123000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000001410000000000000000000000000000000000000000000000000000000000000142000000000000000000000000000000000000000000000000000000000000014300000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000161000000000000000000000000000000000000000000000000000000000000016200000000000000000000000000000000000000000000000000000000000001630000000000000000000000000000000000000000000000000000000000000180000000000000000000000000000000000000000000000000000000000000018100000000000000000000000000000000000000000000000000000000000001820000000000000000000000000000000000000000000000000000000000000183000000100000000000000000000000000000000000000000000000000000000000000220000000000000000000000000000000000000000000000000000000000000022100000000000000000000000000000000000000000000000000000000000002220000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000000000000000000000000000000000002410000000000000000000000000000000000000000000000000000000000000242000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000261000000000000000000000000000000000000000000000000000000000000026200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000028100000000000000000000000000000000000000000000000000000000000002820000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000520000000000000000000000000000000000000000000000000000000000000052a0000000000000000000000000000000000000000000000000000000000000521000000000000000000000000000000000000000000000000000000000000052b0000000000000000000000000000000000000000000000000000000000000522000000000000000000000000000000000000000000000000000000000000052c0000000000000000000000000000000000000000000000000000000000000523000000000000000000000000000000000000000000000000000000000000052d0000000000000000000000000000000000000000000000000000000000000540000000000000000000000000000000000000000000000000000000000000054a0000000000000000000000000000000000000000000000000000000000000541000000000000000000000000000000000000000000000000000000000000054b0000000000000000000000000000000000000000000000000000000000000542000000000000000000000000000000000000000000000000000000000000054c0000000000000000000000000000000000000000000000000000000000000543000000000000000000000000000000000000000000000000000000000000054d0000000000000000000000000000000000000000000000000000000000000560000000000000000000000000000000000000000000000000000000000000056a0000000000000000000000000000000000000000000000000000000000000561000000000000000000000000000000000000000000000000000000000000056b0000000000000000000000000000000000000000000000000000000000000562000000000000000000000000000000000000000000000000000000000000056c0000000000000000000000000000000000000000000000000000000000000563000000000000000000000000000000000000000000000000000000000000056d0000000000000000000000000000000000000000000000000000000000000580000000000000000000000000000000000000000000000000000000000000058a0000000000000000000000000000000000000000000000000000000000000581000000000000000000000000000000000000000000000000000000000000058b0000000000000000000000000000000000000000000000000000000000000582000000000000000000000000000000000000000000000000000000000000058c0000000000000000000000000000000000000000000000000000000000000583000000000000000000000000000000000000000000000000000000000000058d00000008000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000003210000000000000000000000000000000000000000000000000000000000000340000000000000000000000000000000000000000000000000000000000000034100000000000000000000000000000000000000000000000000000000000003600000000000000000000000000000000000000000000000000000000000000361000000000000000000000000000000000000000000000000000000000000038000000000000000000000000000000000000000000000000000000000000003810000000426fcb9639d15aabe6d792e23ab12fb9633046d4be6911a60d64471d7560d3f6809143b7d4943a3485115d37e7596938a16c91b6055f3837640d8c36b8303bb3c06fb5fb553496e5e0b48834087e036acf99d6d935dc2ebf43c82788cb5ed1c6a2f4bd77ac2bb5474d48c2856135d18168cd6f69f77143c60b3cc370319419dac0000000000000000000000000000000000000000000000000000000000001020212121212121212121212121212121212121212100000000000000000000000000000000000000000000000000000000000010404141414141414141414141414141414141414141000000000000000000000000000000000000000000000000000000000000106061616161616161616161616161616161616161610000000000000000000000000000000000000000000000000000000000001080818181818181818181818181818181818181818100000010151de48ca3efbae39f180fe00b8f472ec9f25be10b4f283a87c6d7839353703914c2ea9dedf77698d4afe23bc663263eed0bf9aa3a8b17d9b74812f185610f9e1570cc6641699e3ae87fa258d80a6d853f7b8ccb211dc244d017e2ca6530f8a12806c860af67e9cd50000378411b8c4c4db172ceb2daa862b259b689ccbdc1e005f140c7c95624c8006774279a01ec1ea88617999e4fe6997b6576c4e1c7395a22048b96b586596bd740d0402e15f5577f7ceb5496b65aafc6d89d7c3b34924b0c3f2d50d16279970d682cada30bfa6b29bc0bac0ee2389f6a0444853eccaa932b2a60561da46a58569d71044a84c639e7f88429826e5622581536eb906d9cdd25a2c0a76f7da6924e10751c755227d2535f4ad258b984e78f9f452a853c52300e212d8e2069e4254d81af07744bcbb81121a38f0e2dbed69a523d3fbf85b75c287ca6f33aadbac2e4f058e05924c140d7895a6ed167caf804b710d2ae3ba62b1b51297b3ea37637af6bd56cf33425d95cc5c96e9c2ee3077322fbec86a0c7f32c15d2a888c6cc122e99478c92470a1311635142d82ad7ae67410beeef4ae31f0902ba2fb964922a4610bb18901f7b923885c1d034da5769a48203ae6f0206a92855e2c01ddb3d6553386b5580d681b8230fa4062948668f834f23e0636eaff70aaa64519aafdf4b040bd2f9836e76b9dc13cfec8065dcdf2834d786e06260d100000e1000000380000001bc0000009049198cdd9e2b2aaa4b40bb48de9e900100459b8659c39fb2b69ca1b75607c2333266788a6a92cfadf73ccef88040ecce3fbb31cfa10fa8feffb6dea15c901cc7832f1d0e53e6c5dc680fae811f03755b641417005447d54134d23625948d4f43fb25541e19d42392d7b577e845160e3f2605ea15a18dd1c0403681df495516ab1bd601423477afa47570988ca05e08ed000000903a37b8a4dc05bda1f7c935b81d028f93a79a7fb0703134a2354e174450f9e57a7ff52f670ae4968c873ad44fbed4d291574b3f343a3ef904c3120abce8c3c9aefcefca93ef2bc9eb424feecb40ce89bdb65bed46b8cc208ad1401208272f8b01f287a8d4c4c87d6958db1c00c26f0325e420c3da04039b4737b0af7a5d1c7f52f191b8c47a285d7d568a537dd747b4230000009032861c0de7932ef850d6eda9ab658a1e57dccb15ac5010d465d983dc778a2b29a7a7ee5e517fdd13329b228b6ac2fb17176d079860c9bad05484a3e4063c132ca5b869d48fd7671f4719ba7c50612c7acecc19e0ba568d201e9dda0eb4de91e8a67f6228f254a107dce24efd89ddcd4475ffc9a58cf5ca267d0dc4d0b94f7020afdec717e6937c9e38df527b4e8c5b14000001bc00000090ca31a21b6322cc6911a9cbb946144a7cdddd28ff3407cc826238bf0ffd3f6d8641c1ecf1d8588f0543d5a5dc39013f4832c3ebe9b1e7ab5e4444c8fae56252a8eb9534075301f5c531c0108160d4a11400e75a844cefa8e480cbaf9693e9e57b985940a0d8dbe087defa1984ca8dec6ce350112e592e41e67faee10df9e3758de3c7142fee6161221d27d9d6c5228d0900000090ca81fbcfe99fa433ff011fda6694357bc168e7e64b5bb3a68fcea7055c0c4d35d334c52bdf09dbedfbcb31084dbae9576585a576ace71b17c0cc86b3a94098d50c9e447ba369134141a797d0937974c381252d6c1a23c87cb71d5ba6faec10ef74b030339b0268446212cc2a4b58fddd9333b9a2bb8079c4df5f5de900e5aea728ae0a214a6f7717f2c452bb96cd412d0000009021e89ddef89b241820d2c0863504d416401a6a74c10e4cb1480afe66b3d534d2cf2eed800d18ff06b476ec83b8528839ab8e732216ca1e946368b22532316f98d1bbee0774158d544668108cccdd377c49128f3fcddb6b874efcf669238b2de09194324a098694d8058ead609d211d45311108c45de0a4c0b2011457e739e34ab9f293d40ae9b996a06eff3884edfbfa00000380000001bc00000090ce1c32a7c779a395335903464ba12a01c5cdc9aacc763f1b8841268653b2acaa1d83edbb78236fe2e5d415416e7c50bdefc2b8225fbe724dddeb555471bc4acc4518637ad4dfe797640d61613c4c8168442e6dd8b5255dfb0089c8e1bb3d226feda8768f8b71531ec8be6f799460a0b26ee315b6fb0cff269a12442f738c2592dc70462f3990e749257a3807c8ee349600000090dcffc2907a1e323ae6b6713c8a35b42ec86cbda1468fe7e537da5a87e0c62263e15ad46b28ec46919b964c4187caf2b2592ff34a37891e7fe26de5f1d5daf526282f2d461511dc06dacb26332913efbe5ce7c4175e011c2e1b9c9d5a584601a6cdbb484cacad66e6849dab3b9fd3e10c9ab2a3dcb2fd0fccc951ad41bc4ab129554e5cf32b5eac9ed2d024108f39825600000090a8ff3962b831dccf1a4264e56bb1b4e35c12bdca9d5e9c06106ad221cbc4dfc7af43f397c0117ef91950728fe57a6568778dbe5cd690cb180c4bc3c384519332fee0dfed3464dd555dba7852fb8493ed933618f5ce070c1d462ae58c67043ccdbc7e0c2d2025f78e4ad2050c30bec8ab83276e0a3ac3a1eddc00351c947a436a2d8b979ed8127f00071767387096fdfc000001bc000000909c571096bd209e7ed7838c5c930207859fca91da9e137d3e5f26226b331d14716c7fb19e22946b2beb5e35b8b0c4f9876393d00c765ac055f2d99e5dbaa06e8c3dfac92c7a2c545a9d4e4ed78a4745332b1b77e746621d3883894623a02d035c4446f33500d2d9429c6ae8ab61dd3e128f2266fa67d1faebe7b7e32e02d42c0a39c4156a54c253b78630bb13223f51de000000909d6518bdd4c289b4c3f87551887b39d3379723e225fd9baa03e03b64a626e7d055ba899464f09e26f85e97ff7fe419ee1a413784f1605bf40405cc99764b48eb22bbd2e3ba33b9829eb2903f50a9f466533a3cb4bf7d53eb41d0d8902d116d9939eefe247a179b9d05c92cbf01747564c9d90acd642a782f9844bbc61b28475afd18ca48a7b041364b7f2b9c5aaf64ac000000906d0521a245489bd7b26eab1519cfe2b6789190d6f8e2938630897318afd7393567a189aafd4e7667d59aa423546d8f528e49bcff00b6105d7092a1d7ea591b9635d82b56a8daaeb01484a7f553930417a480082e528bd01b5fb08061dd27f4f4db2d73a88aaef442c124c0fa11a0b907523ea8fdb7ff917584260b352b05525b4aa00df16d40a93bd99db2e97bb7850400000380000001bc00000090386a791bd579f1cfb4a5bdb7c85ca6540bc83b94cb8f7d19aadb98697298830e82d81c5ee309a2a19816636670115d3f302c77a529779aedb1ff838c3b56246620a54162dcc823ff714ec8216f006ada6db20d5cad0b9601d05b2d74a74226e7d2632f0e1b8cce84fbcf273bd326a39a17377fb2f6e4774d6c1bb9bf644d11327f06f7e5acec9d66b878f4ef844662ae00000090921c5863c83cd4940de4ea7b83a80fcaa66e4c400394a09beaef88dbe4c44c40c99f19fa58f49d651e62a5cf04f8777fe488fe4ab4fd5e23a441efadb70ca6c6eed5590162c23e7660f4b84a11bdd785237b6aa3192f8022595f99de713ae9de5f7714a003a905a62022e0938fd379af1af63460720e47c1d867da99d2545f3d51302c4c7b6c2222c2244f1cc10ffb4f000000903d16d6928d6f16699eeb3afb1377d7dfc6407dc758a527f889a24b7ae0783ff4cc381f7f5598ae6eda9994f6632acc019d5a7b098f54079154af8be4681fa485b0ccedcaede624ed72776bf3b80fa0e9291195f563356f1f657c3ab8696441782ca97ffbcb6ebdfe2dd7630e4c1c317442d4576a972a783ec11f5e907d907b83b3949becc48b4c7ab79ba6451bedb2ae000001bc00000090e5512182d01a07b7a70b429bb15ccdd4e22a6517fac7cec8c688aa3e7017fdaa99f0697bb6dfa5baceb29457a64780f24e8d6191dc56479886fe401b25e4d540c83992da55812b78100bca18514d2882a4368ab6250f9ca2d999ade3372383a1e31b3b3f84f6f351c07ab1b1deb48022725af1288c55696ee044dfd404a0a3ad9db91b751abe109286d723441e6effdc000000903dda660da06a637a08fda73cb4011105f6b61c14ad140da6dd2b9452a15a699dabb187f0632ef3978df2eef9781c81e7f24cada850937a814638e8cc1aa9dc8aa23b6bc3ba65649fae24cc44e39e07a5c9004b80c9889fc48dcfbcd435b36ba7678bfc03d32a2d7ea06be6de0c2ab1ede5aee02350d1ff77bfaf634c4b19418e599537883577f96cbaf5543c9f10bc3200000090d297f0feaa39b99c1d2c3986ce8a7242164bc1d815790ab71298badce47193b2ff24ae8d504a47f223e196b24f588181ce25ab5b3ae0a0f58b197519b9646a6a7c6cc630883f3b8cd2076804e6cd720e3e66813ea2a124731ab7e908d6767d55ba79e5d732e49548bc506ec1bb501ffb84a94a15e22cb50111975cf4cba4dfe7a963e1f3c1a0a87507740bc6b2b07a7700000380000001bc000000902cd8de638a8178331826f9a1ca3e4b1c8a5245c35fab369471ecf5cc426de9d2ccde5dcac3c4ce41da20db8801dfdab90307929c35c62e6b3002cb765c1d04e0f25a4ad5abcd959091b85d66c63386e09153dfc03f98dd3442ab3e3b3bbc97ab48359e6b77aaab184e0b23f568c9ca9f9d9831e6424e8427c90bb44652f9243595f935446946d35356f1c73afa1e43ad0000009077a48cdea0c3aca8905b2b08b769dcc004ad8328b84c61cc8833dc2f8bb002b1c5703306bfe165de079107fa1f3e0d369ee7fec01790f80cb9bb9117a084661ce9b9b09c1d4e48819fe86bc673fe0d11f93c1c2ad761c5625604fb2cf6553c0870a3e1461214a78e6adb48ce9c4f976e8108ba18da85764a832b9395750b1486fe4faf6c55f05f2af0b9ad20e1a27c8e00000090c28f713b496ea26597e86a45196e7edee47334eb8284c1d282d9e4d69039b55dbb937933ab0a0c294641e8ce0376cb4bc61c329bab5894a907992e10dca59883af0962d8b911860c98ecc04dddde93c0de92558035702bd25c1680d66afcba6b3db754bc8d34bdffe2f076e89c49316c15ad021a66f0079c07cabc34874fdabd54558a0396a1786697c147a3be728cbd000001bc000000901d68b202159c60e130775a423e727a1b08d92a3ef4a9691b590aea010cefd28f23ab0f5bd855f15dbe6e62285513312c534e5088cbdb361c474824c9c43de5c9edb170e04b482ab52c42d3208f478c7ea2ff4ab459cead4be5cd011ea630eacf56301f5d1fb07cc3d25dd75b247c0fe77fdabae42e1b02fc74077d9bf254d038c01426108498a94db80dd0d4115db3e600000090da5d582dde28f46f43d426ff2e2e55f3bb89afeb433c29e57f19a6c6129c7d65f3c51248453ddb7ebc2b0178377962e9db5c953b1bfdb0a3cd69dd62c941afd02e4548fcd2a84eb01b692fa4da2ce9594e89540b8181bbb9409ff51e7149240144d0867f897fda8b3cc16963fdfa284a21aef26c17e98e847ce07ce15765e28fc6bfaacbd1b476d7f094d834c91cdaeb0000009032b0a6b63df31050e92beba29af28af1817b924ee6e4cc8496e21672e5db58bb9464c7dadd17bf29d608d28ce2e64c34b37136f2fac361501327ab089dd3fc14ad17c93475f204974bac606be0794f3d7b40601a3fed5c01b4664369758dec00a8ca54b5a0d3f6b68892d5dfe933866bdfd8f0280128c5f8b32d0e73cd1a5e56b78a16e229c34b676a9a61c2b71692e9000000400000000c0000000000000000000000000000000c0000000000000000000000000000000c0000000000000000000000000000000c000000000000000000000000"; function setUp() public virtual { helper = new DecoderHelper(); @@ -65,20 +65,20 @@ contract DecoderTest is Test { bytes32[] memory l1ToL2Msgs ) = helper.decode(block_empty_1); - assertEq(l2BlockNumber, 2, "Invalid block number"); + assertEq(l2BlockNumber, 1, "Invalid block number"); assertEq( startStateHash, - 0xca91a84435129ce01602cf819855fd9ce00b768279e4a5133d2515592e2b061b, + 0x3f44449b8c2d3d36f6fe121c5d8d6961cd038fd4135fdf1ced70df6eb5f6ac26, "Invalid start state hash" ); assertEq( endStateHash, - 0x1d8d13ed1e858769c8632feb2eed029fc8616c491494c6f7452360718c1a9426, + 0x4cd75162770eef80e2137e76268a02694251dab36637ff0932a29e81c9dd8c44, "Invalid end state hash" ); assertEq( publicInputsHash, - 0x2baf2ca94d1af42ed94911b73fdadfaf02270c1c00f14313f30fabbf67a7c2e4, + 0x2e071946370d8d6608a36dcd1a48270e94c53516098f58801c7bf7f26cd056b1, "Invalid public input hash" ); @@ -91,43 +91,42 @@ contract DecoderTest is Test { } function testMixBlock() public virtual { + ( + uint256 l2BlockNumber, + bytes32 startStateHash, + bytes32 endStateHash, + bytes32 publicInputsHash, + bytes32[] memory l2ToL1Msgs, + bytes32[] memory l1ToL2Msgs + ) = helper.decode(block_mixed_1); + (bytes32 diffRoot, bytes32 l1ToL2MessagesHash) = helper.computeDiffRootAndMessagesHash(block_mixed_1); + + assertEq(l2BlockNumber, 1, "Invalid block number"); assertEq( diffRoot, - 0x705f9c21bf4a9e898ddf1a175ce98ba796eb9008e6464d3e6dac6015550e099c, + 0x0fc0c81caa8c36e0e4b8490bb73e46a449296c3528dc9e750cb8d4053c5d5408, "Invalid diff root/calldata hash" ); - assertEq( l1ToL2MessagesHash, 0xb213c9c543fce2a66720d26a913fe0d018f72a47ccfe698baafcf4cced343cfd, "Invalid messages hash" ); - - ( - uint256 l2BlockNumber, - bytes32 startStateHash, - bytes32 endStateHash, - bytes32 publicInputsHash, - bytes32[] memory l2ToL1Msgs, - bytes32[] memory l1ToL2Msgs - ) = helper.decode(block_mixed_1); - - assertEq(l2BlockNumber, 1, "Invalid block number"); assertEq( startStateHash, - 0x5b2a06b296be0ef96e45df6e8f927bfc1ca9a5061a5a173f6aa5084421cee34e, + 0x3f44449b8c2d3d36f6fe121c5d8d6961cd038fd4135fdf1ced70df6eb5f6ac26, "Invalid start state hash" ); assertEq( endStateHash, - 0x839ccff0773e7ba72cdb5f98b961cca40fcc39889d207e641a79e2ab9128862a, + 0x1e54f0c574c9a0f80c56323046cd03448e26adf70184d04d44b58659e2828e56, "Invalid end state hash" ); assertEq( publicInputsHash, - 0x1d7b0de8788ec94e9dcbd296322d91caf7f59f9dc549fe152cc02e9289f7f104, + 0x0102bb4aa10e107eea02518d7d37b20e27fabc8f692ffd8f532e37a142947b6b, "Invalid public input hash" ); diff --git a/yarn-project/acir-simulator/src/client/private_execution.test.ts b/yarn-project/acir-simulator/src/client/private_execution.test.ts index 3d6a1742b19d..a64059396438 100644 --- a/yarn-project/acir-simulator/src/client/private_execution.test.ts +++ b/yarn-project/acir-simulator/src/client/private_execution.test.ts @@ -49,7 +49,7 @@ describe('Private Execution test suite', () => { const historicRoots = PrivateHistoricTreeRoots.empty(); const contractDeploymentData = ContractDeploymentData.empty(); - const txContext = new TxContext(false, false, false, contractDeploymentData); + const txContext = new TxContext(false, false, false, contractDeploymentData, Fr.ZERO, Fr.ZERO); const buildTxExecutionRequest = (args: { abi: FunctionAbi; diff --git a/yarn-project/aztec-rpc/src/aztec_rpc_server/aztec_rpc_server.ts b/yarn-project/aztec-rpc/src/aztec_rpc_server/aztec_rpc_server.ts index 788fe4ddb1f3..af2715bd94d0 100644 --- a/yarn-project/aztec-rpc/src/aztec_rpc_server/aztec_rpc_server.ts +++ b/yarn-project/aztec-rpc/src/aztec_rpc_server/aztec_rpc_server.ts @@ -213,7 +213,7 @@ export class AztecRPCServer implements AztecRPCClient { contractAddressSalt, portalContract, ); - const txContext = new TxContext(false, false, true, contractDeploymentData); + const txContext = new TxContext(false, false, true, contractDeploymentData, Fr.ZERO, Fr.ZERO); const contract = contractTree.contract; await this.db.addContract(contract); diff --git a/yarn-project/circuits.js/src/abis/__snapshots__/abis.test.ts.snap b/yarn-project/circuits.js/src/abis/__snapshots__/abis.test.ts.snap index 18be073c8785..19f629caf5ff 100644 --- a/yarn-project/circuits.js/src/abis/__snapshots__/abis.test.ts.snap +++ b/yarn-project/circuits.js/src/abis/__snapshots__/abis.test.ts.snap @@ -115,38 +115,38 @@ Object { exports[`abis wasm bindings hashes a tx request 1`] = ` { "data": [ - 42, - 86, - 151, + 15, + 163, + 36, + 163, + 221, 246, - 17, - 44, - 179, - 110, - 184, - 105, - 19, - 161, - 232, - 195, - 239, - 149, - 18, - 9, - 10, - 158, - 148, - 155, - 69, - 129, - 103, + 197, + 8, + 204, + 213, + 128, + 203, + 35, + 216, + 154, + 194, + 176, + 48, + 29, + 205, + 219, + 167, + 225, + 30, + 138, + 89, 235, - 37, + 60, 174, - 251, - 33, - 102, - 62, + 63, + 167, + 223, ], "type": "Buffer", } diff --git a/yarn-project/circuits.js/src/cbind/circuits.gen.ts b/yarn-project/circuits.js/src/cbind/circuits.gen.ts index 04141331c407..27157f778036 100644 --- a/yarn-project/circuits.js/src/cbind/circuits.gen.ts +++ b/yarn-project/circuits.js/src/cbind/circuits.gen.ts @@ -635,6 +635,8 @@ interface MsgpackTxContext { is_rebate_payment_tx: boolean; is_contract_deployment_tx: boolean; contract_deployment_data: MsgpackContractDeploymentData; + chain_id: Buffer; + version: Buffer; } export function toTxContext(o: MsgpackTxContext): TxContext { @@ -650,11 +652,19 @@ export function toTxContext(o: MsgpackTxContext): TxContext { if (o.contract_deployment_data === undefined) { throw new Error('Expected contract_deployment_data in TxContext deserialization'); } + if (o.chain_id === undefined) { + throw new Error('Expected chain_id in TxContext deserialization'); + } + if (o.version === undefined) { + throw new Error('Expected version in TxContext deserialization'); + } return new TxContext( o.is_fee_payment_tx, o.is_rebate_payment_tx, o.is_contract_deployment_tx, toContractDeploymentData(o.contract_deployment_data), + Fr.fromBuffer(o.chain_id), + Fr.fromBuffer(o.version), ); } @@ -671,11 +681,19 @@ export function fromTxContext(o: TxContext): MsgpackTxContext { if (o.contractDeploymentData === undefined) { throw new Error('Expected contractDeploymentData in TxContext serialization'); } + if (o.chainId === undefined) { + throw new Error('Expected chainId in TxContext serialization'); + } + if (o.version === undefined) { + throw new Error('Expected version in TxContext serialization'); + } return { is_fee_payment_tx: o.isFeePaymentTx, is_rebate_payment_tx: o.isRebatePaymentTx, is_contract_deployment_tx: o.isContractDeploymentTx, contract_deployment_data: fromContractDeploymentData(o.contractDeploymentData), + chain_id: o.chainId.toBuffer(), + version: o.version.toBuffer(), }; } diff --git a/yarn-project/circuits.js/src/structs/__snapshots__/tx_context.test.ts.snap b/yarn-project/circuits.js/src/structs/__snapshots__/tx_context.test.ts.snap index e67afaf161a4..3e79a9138e21 100644 --- a/yarn-project/circuits.js/src/structs/__snapshots__/tx_context.test.ts.snap +++ b/yarn-project/circuits.js/src/structs/__snapshots__/tx_context.test.ts.snap @@ -10,5 +10,8 @@ constructor_vk_hash: 0x2 function_tree_root: 0x3 contract_address_salt: 0x4 portal_contract_address: 0x505050505050505050505050505050505050505 + +chain_id: 0x0 +version: 0x0 " `; diff --git a/yarn-project/circuits.js/src/structs/global_variables.ts b/yarn-project/circuits.js/src/structs/global_variables.ts new file mode 100644 index 000000000000..346960773685 --- /dev/null +++ b/yarn-project/circuits.js/src/structs/global_variables.ts @@ -0,0 +1,45 @@ +import { Fr } from '@aztec/foundation/fields'; +import { BufferReader } from '@aztec/foundation/serialize'; +import { FieldsOf } from '../index.js'; +import { serializeToBuffer } from '../utils/index.js'; + +/** + * Global variables of the L2 block. + */ +export class GlobalVariables { + constructor( + /** + * ChainId for the L2 block. + */ + public chainId: Fr, + /** + * version for the L2 block. + */ + public version: Fr, + /** + * Block number of the L2 block. + */ + public blockNumber: Fr, + /** + * Timestamp of the L2 block. + */ + public timestamp: Fr, + ) {} + + static from(fields: FieldsOf): GlobalVariables { + return new GlobalVariables(...GlobalVariables.getFields(fields)); + } + + static fromBuffer(buffer: Buffer | BufferReader): GlobalVariables { + const reader = BufferReader.asReader(buffer); + return new GlobalVariables(reader.readFr(), reader.readFr(), reader.readFr(), reader.readFr()); + } + + static getFields(fields: FieldsOf) { + return [fields.chainId, fields.version, fields.blockNumber, fields.timestamp] as const; + } + + toBuffer() { + return serializeToBuffer(...GlobalVariables.getFields(this)); + } +} diff --git a/yarn-project/circuits.js/src/structs/index.ts b/yarn-project/circuits.js/src/structs/index.ts index 35cef54530af..fff908413cf3 100644 --- a/yarn-project/circuits.js/src/structs/index.ts +++ b/yarn-project/circuits.js/src/structs/index.ts @@ -1,3 +1,4 @@ +export * from './global_variables.js'; export * from './rollup/base_rollup.js'; export * from './rollup/merge_rollup.js'; export * from './rollup/root_rollup.js'; 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 c17109b918ae..7d7eacb71f42 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 @@ -245,6 +245,9 @@ function_tree_root: 0x107 contract_address_salt: 0x108 portal_contract_address: 0x909090909090909090909090909090909090909 +chain_id: 0x0 +version: 0x0 + is_private: 1 @@ -282,6 +285,9 @@ function_tree_root: 0x403 contract_address_salt: 0x404 portal_contract_address: 0x505050505050505050505050505050505050505 +chain_id: 0x0 +version: 0x0 + private_call: call_stack_item: @@ -635,6 +641,9 @@ function_tree_root: 0x107 contract_address_salt: 0x108 portal_contract_address: 0x909090909090909090909090909090909090909 +chain_id: 0x0 +version: 0x0 + is_private: 1 @@ -1003,6 +1012,9 @@ function_tree_root: 0x107 contract_address_salt: 0x108 portal_contract_address: 0x909090909090909090909090909090909090909 +chain_id: 0x0 +version: 0x0 + is_private: 1 " @@ -1139,6 +1151,9 @@ function_tree_root: 0x107 contract_address_salt: 0x108 portal_contract_address: 0x909090909090909090909090909090909090909 +chain_id: 0x0 +version: 0x0 + is_private: 1 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 221dae3dcd0c..4f20da63b525 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 @@ -131,6 +131,9 @@ function_tree_root: 0x206 contract_address_salt: 0x207 portal_contract_address: 0x808080808080808080808080808080808080808 +chain_id: 0x0 +version: 0x0 + is_private: 1 @@ -276,6 +279,9 @@ function_tree_root: 0x306 contract_address_salt: 0x307 portal_contract_address: 0x808080808080808080808080808080808080808 +chain_id: 0x0 +version: 0x0 + is_private: 1 @@ -396,6 +402,11 @@ private_kernel_vk_tree_root: 0x401 public_kernel_vk_tree_root: 0x402 base_rollup_vk_hash: 0x403 merge_rollup_vk_hash: 0x404 +global_variables: chain_id: 0x405 +version: 0x406 +block_number: 0x407 +timestamp: 0x408 + " `; @@ -434,6 +445,11 @@ private_kernel_vk_tree_root: 0x501 public_kernel_vk_tree_root: 0x502 base_rollup_vk_hash: 0x503 merge_rollup_vk_hash: 0x504 +global_variables: chain_id: 0x505 +version: 0x506 +block_number: 0x507 +timestamp: 0x508 + start_private_data_tree_snapshot: root: 0x300 diff --git a/yarn-project/circuits.js/src/structs/rollup/__snapshots__/root_rollup.test.ts.snap b/yarn-project/circuits.js/src/structs/rollup/__snapshots__/root_rollup.test.ts.snap index 5eeab7ec5d22..3cfde88e2980 100644 --- a/yarn-project/circuits.js/src/structs/rollup/__snapshots__/root_rollup.test.ts.snap +++ b/yarn-project/circuits.js/src/structs/rollup/__snapshots__/root_rollup.test.ts.snap @@ -34,6 +34,11 @@ private_kernel_vk_tree_root: 0x501 public_kernel_vk_tree_root: 0x502 base_rollup_vk_hash: 0x503 merge_rollup_vk_hash: 0x504 +global_variables: chain_id: 0x505 +version: 0x506 +block_number: 0x507 +timestamp: 0x508 + start_private_data_tree_snapshot: root: 0x300 @@ -112,6 +117,11 @@ private_kernel_vk_tree_root: 0x1501 public_kernel_vk_tree_root: 0x1502 base_rollup_vk_hash: 0x1503 merge_rollup_vk_hash: 0x1504 +global_variables: chain_id: 0x1505 +version: 0x1506 +block_number: 0x1507 +timestamp: 0x1508 + start_private_data_tree_snapshot: root: 0x1300 @@ -184,50 +194,55 @@ public_inputs: [ proof_witness_indices: [ 6 7 8 9 10 11 ] has_data: 0 -start_private_data_tree_snapshot: root: 0x100 -next_available_leaf_index: 256 +global_variables: chain_id: 0x100 +version: 0x101 +block_number: 0x102 +timestamp: 0x103 -end_private_data_tree_snapshot: root: 0x200 +start_private_data_tree_snapshot: root: 0x200 next_available_leaf_index: 512 -start_nullifier_tree_snapshot: root: 0x300 +end_private_data_tree_snapshot: root: 0x300 next_available_leaf_index: 768 -end_nullifier_tree_snapshot: root: 0x400 +start_nullifier_tree_snapshot: root: 0x400 next_available_leaf_index: 1024 -start_contract_tree_snapshot: root: 0x500 +end_nullifier_tree_snapshot: root: 0x500 next_available_leaf_index: 1280 -end_contract_tree_snapshot: root: 0x600 +start_contract_tree_snapshot: root: 0x600 next_available_leaf_index: 1536 -start_public_data_tree_root: 0x700 -end_public_data_tree_root: 0x800 -start_tree_of_historic_private_data_tree_roots_snapshot: root: 0x900 -next_available_leaf_index: 2304 +end_contract_tree_snapshot: root: 0x700 +next_available_leaf_index: 1792 -end_tree_of_historic_private_data_tree_roots_snapshot: root: 0xa00 +start_public_data_tree_root: 0x800 +end_public_data_tree_root: 0x900 +start_tree_of_historic_private_data_tree_roots_snapshot: root: 0xa00 next_available_leaf_index: 2560 -start_tree_of_historic_contract_tree_roots_snapshot: root: 0xb00 +end_tree_of_historic_private_data_tree_roots_snapshot: root: 0xb00 next_available_leaf_index: 2816 -end_tree_of_historic_contract_tree_roots_snapshot: root: 0xc00 +start_tree_of_historic_contract_tree_roots_snapshot: root: 0xc00 next_available_leaf_index: 3072 -start_l1_to_l2_messages_tree_snapshot: root: 0xd00 +end_tree_of_historic_contract_tree_roots_snapshot: root: 0xd00 next_available_leaf_index: 3328 -end_l1_tol2_messages_tree_snapshot: root: 0xe00 +start_l1_to_l2_messages_tree_snapshot: root: 0xe00 next_available_leaf_index: 3584 -start_tree_of_historic_l1_to_l2_messages_tree_roots_snapshot: root: 0xf00 +end_l1_tol2_messages_tree_snapshot: root: 0xf00 next_available_leaf_index: 3840 -end_tree_of_historic_l1_tol2_messages_tree_roots_snapshot: root: 0x1000 +start_tree_of_historic_l1_to_l2_messages_tree_roots_snapshot: root: 0x1000 next_available_leaf_index: 4096 +end_tree_of_historic_l1_tol2_messages_tree_roots_snapshot: root: 0x1100 +next_available_leaf_index: 4352 + calldata_hash: [ 0x1 0x2 ] l1_to_l2_messages_hash: [ 0x3 0x4 ] " diff --git a/yarn-project/circuits.js/src/structs/rollup/base_rollup.ts b/yarn-project/circuits.js/src/structs/rollup/base_rollup.ts index c6229857bdb2..35e64d4f01f0 100644 --- a/yarn-project/circuits.js/src/structs/rollup/base_rollup.ts +++ b/yarn-project/circuits.js/src/structs/rollup/base_rollup.ts @@ -20,6 +20,7 @@ import { PreviousKernelData } from '../kernel/previous_kernel_data.js'; import { MembershipWitness } from '../membership_witness.js'; import { UInt32 } from '../shared.js'; import { AppendOnlyTreeSnapshot } from './append_only_tree_snapshot.js'; +import { GlobalVariables } from '../global_variables.js'; /** * Class containing the data of a preimage of a single leaf in the nullifier tree. @@ -84,6 +85,10 @@ export class ConstantBaseRollupData { * Hash of the merge rollup circuit verification key. */ public mergeRollupVkHash: Fr, + /** + * Global variables for the block + */ + public globalVariables: GlobalVariables, ) {} static from(fields: FieldsOf): ConstantBaseRollupData { @@ -100,6 +105,7 @@ export class ConstantBaseRollupData { reader.readFr(), reader.readFr(), reader.readFr(), + reader.readObject(GlobalVariables), ); } @@ -112,6 +118,7 @@ export class ConstantBaseRollupData { fields.publicKernelVkTreeRoot, fields.baseRollupVkHash, fields.mergeRollupVkHash, + fields.globalVariables, ] as const; } diff --git a/yarn-project/circuits.js/src/structs/rollup/root_rollup.ts b/yarn-project/circuits.js/src/structs/rollup/root_rollup.ts index cf70aec2ec83..afd8a55da21f 100644 --- a/yarn-project/circuits.js/src/structs/rollup/root_rollup.ts +++ b/yarn-project/circuits.js/src/structs/rollup/root_rollup.ts @@ -12,6 +12,7 @@ import { PreviousRollupData } from './previous_rollup_data.js'; import { AggregationObject } from '../aggregation_object.js'; import { Fr } from '@aztec/foundation/fields'; import { BufferReader } from '@aztec/foundation/serialize'; +import { GlobalVariables } from '../global_variables.js'; /** * Represents inputs of the root rollup circuit. @@ -94,6 +95,10 @@ export class RootRollupPublicInputs { */ public endAggregationObject: AggregationObject, + /** + * Global variables of the L2 block. + */ + public globalVariables: GlobalVariables, // constants: ConstantRollupData // TODO maybe don't include this /** @@ -182,6 +187,7 @@ export class RootRollupPublicInputs { static getFields(fields: FieldsOf) { return [ fields.endAggregationObject, + fields.globalVariables, fields.startPrivateDataTreeSnapshot, fields.endPrivateDataTreeSnapshot, fields.startNullifierTreeSnapshot, @@ -237,6 +243,7 @@ export class RootRollupPublicInputs { const reader = BufferReader.asReader(buffer); return new RootRollupPublicInputs( reader.readObject(AggregationObject), + reader.readObject(GlobalVariables), reader.readObject(AppendOnlyTreeSnapshot), reader.readObject(AppendOnlyTreeSnapshot), reader.readObject(AppendOnlyTreeSnapshot), diff --git a/yarn-project/circuits.js/src/structs/tx_context.ts b/yarn-project/circuits.js/src/structs/tx_context.ts index 64abd44687e7..1b325bf406f1 100644 --- a/yarn-project/circuits.js/src/structs/tx_context.ts +++ b/yarn-project/circuits.js/src/structs/tx_context.ts @@ -97,6 +97,14 @@ export class TxContext { * Contract deployment data. */ public contractDeploymentData: ContractDeploymentData, + /** + * Chain ID of the transaction. Here for replay protection. + */ + public chainId: Fr, + /** + * Version of the transaction. Here for replay protection. + */ + public version: Fr, ) {} /** @@ -109,6 +117,8 @@ export class TxContext { this.isRebatePaymentTx, this.isContractDeploymentTx, this.contractDeploymentData, + this.chainId, + this.version, ); } @@ -124,10 +134,12 @@ export class TxContext { reader.readBoolean(), reader.readBoolean(), reader.readObject(ContractDeploymentData), + reader.readFr(), + reader.readFr(), ); } static empty() { - return new TxContext(false, false, false, ContractDeploymentData.empty()); + return new TxContext(false, false, false, ContractDeploymentData.empty(), Fr.ZERO, Fr.ZERO); } } diff --git a/yarn-project/circuits.js/src/tests/factories.ts b/yarn-project/circuits.js/src/tests/factories.ts index 95d37d04fe61..8ad94e43924e 100644 --- a/yarn-project/circuits.js/src/tests/factories.ts +++ b/yarn-project/circuits.js/src/tests/factories.ts @@ -86,6 +86,7 @@ import { makeTuple, range, } from '../index.js'; +import { GlobalVariables } from '../structs/global_variables.js'; /** * Creates an arbitrary tx context with the given seed. @@ -93,7 +94,9 @@ import { * @returns A tx context. */ export function makeTxContext(seed: number): TxContext { - return new TxContext(false, false, true, makeContractDeploymentData(seed)); + // @todo @LHerskind should probably take value for chainId as it will be verified later. + // @todo @LHerskind should probably take value for version as it will be verified later. + return new TxContext(false, false, true, makeContractDeploymentData(seed), Fr.ZERO, Fr.ZERO); } /** @@ -638,12 +641,30 @@ export function makeContractDeploymentData(seed = 1) { ); } +/** + * Makes global variables. + * @param seed - The seed to use for generating the global variables. + * @param blockNumber - The block number to use for generating the global variables. + * If blockNumber is undefined, it will be set to seed + 2. + * @returns Global variables. + */ +export function makeGlobalVariables(seed = 1, blockNumber: number | undefined = undefined): GlobalVariables { + if (blockNumber !== undefined) { + return new GlobalVariables(fr(seed), fr(seed + 1), fr(blockNumber), fr(seed + 3)); + } + return new GlobalVariables(fr(seed), fr(seed + 1), fr(seed + 2), fr(seed + 3)); +} + /** * Makes constant base rollup data. * @param seed - The seed to use for generating the constant base rollup data. + * @param blockNumber - The block number to use for generating the global variables. * @returns A constant base rollup data. */ -export function makeConstantBaseRollupData(seed = 1): ConstantBaseRollupData { +export function makeConstantBaseRollupData( + seed = 1, + blockNumber: number | undefined = undefined, +): ConstantBaseRollupData { return ConstantBaseRollupData.from({ startTreeOfHistoricPrivateDataTreeRootsSnapshot: makeAppendOnlyTreeSnapshot(seed), startTreeOfHistoricContractTreeRootsSnapshot: makeAppendOnlyTreeSnapshot(seed + 0x100), @@ -652,6 +673,7 @@ export function makeConstantBaseRollupData(seed = 1): ConstantBaseRollupData { publicKernelVkTreeRoot: fr(seed + 0x302), baseRollupVkHash: fr(seed + 0x303), mergeRollupVkHash: fr(seed + 0x304), + globalVariables: makeGlobalVariables(seed + 0x305, blockNumber), }); } @@ -704,14 +726,18 @@ export function makeEcdsaSignature(seed = 1): EcdsaSignature { /** * Makes arbitrary base or merge rollup circuit public inputs. * @param seed - The seed to use for generating the base rollup circuit public inputs. + * @param blockNumber - The block number to use for generating the base rollup circuit public inputs. * @returns A base or merge rollup circuit public inputs. */ -export function makeBaseOrMergeRollupPublicInputs(seed = 0): BaseOrMergeRollupPublicInputs { +export function makeBaseOrMergeRollupPublicInputs( + seed = 0, + blockNumber: number | undefined = undefined, +): BaseOrMergeRollupPublicInputs { return new BaseOrMergeRollupPublicInputs( RollupTypes.Base, new Fr(0n), makeAggregationObject(seed + 0x100), - makeConstantBaseRollupData(seed + 0x200), + makeConstantBaseRollupData(seed + 0x200, blockNumber), makeAppendOnlyTreeSnapshot(seed + 0x300), makeAppendOnlyTreeSnapshot(seed + 0x400), makeAppendOnlyTreeSnapshot(seed + 0x500), @@ -727,11 +753,12 @@ export function makeBaseOrMergeRollupPublicInputs(seed = 0): BaseOrMergeRollupPu /** * Makes arbitrary previous rollup data. * @param seed - The seed to use for generating the previous rollup data. + * @param blockNumber - The block number to use for generating the previous rollup data. * @returns A previous rollup data. */ -export function makePreviousRollupData(seed = 0): PreviousRollupData { +export function makePreviousRollupData(seed = 0, blockNumber: number | undefined = undefined): PreviousRollupData { return new PreviousRollupData( - makeBaseOrMergeRollupPublicInputs(seed), + makeBaseOrMergeRollupPublicInputs(seed, blockNumber), makeDynamicSizeBuffer(16, seed + 0x50), makeVerificationKey(), seed + 0x110, @@ -742,11 +769,12 @@ export function makePreviousRollupData(seed = 0): PreviousRollupData { /** * Makes root rollup inputs. * @param seed - The seed to use for generating the root rollup inputs. + * @param blockNumber - The block number to use for generating the root rollup inputs. * @returns A root rollup inputs. */ -export function makeRootRollupInputs(seed = 0): RootRollupInputs { +export function makeRootRollupInputs(seed = 0, blockNumber: number | undefined = undefined): RootRollupInputs { return new RootRollupInputs( - [makePreviousRollupData(seed), makePreviousRollupData(seed + 0x1000)], + [makePreviousRollupData(seed, blockNumber), makePreviousRollupData(seed + 0x1000, blockNumber)], makeTuple(PRIVATE_DATA_TREE_ROOTS_TREE_HEIGHT, fr, 0x2000), makeTuple(CONTRACT_TREE_ROOTS_TREE_HEIGHT, fr, 0x2100), makeTuple(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, fr, 0x2100), @@ -760,11 +788,17 @@ export function makeRootRollupInputs(seed = 0): RootRollupInputs { /** * Makes root rollup public inputs. * @param seed - The seed to use for generating the root rollup public inputs. + * @param blockNumber - The block number to use for generating the root rollup public inputs. + * if blockNumber is undefined, it will be set to seed + 2. * @returns A root rollup public inputs. */ -export function makeRootRollupPublicInputs(seed = 0): RootRollupPublicInputs { +export function makeRootRollupPublicInputs( + seed = 0, + blockNumber: number | undefined = undefined, +): RootRollupPublicInputs { return RootRollupPublicInputs.from({ endAggregationObject: makeAggregationObject(seed), + globalVariables: makeGlobalVariables((seed += 0x100), blockNumber), startPrivateDataTreeSnapshot: makeAppendOnlyTreeSnapshot((seed += 0x100)), endPrivateDataTreeSnapshot: makeAppendOnlyTreeSnapshot((seed += 0x100)), startNullifierTreeSnapshot: makeAppendOnlyTreeSnapshot((seed += 0x100)), diff --git a/yarn-project/end-to-end/src/integration_l1_publisher.test.ts b/yarn-project/end-to-end/src/integration_l1_publisher.test.ts index fbbf67eacffa..7fd2292fc65a 100644 --- a/yarn-project/end-to-end/src/integration_l1_publisher.test.ts +++ b/yarn-project/end-to-end/src/integration_l1_publisher.test.ts @@ -280,7 +280,7 @@ describe('L1Publisher integration', () => { console.log(`l1 to l2 message hash: 0x${block.getL1ToL2MessagesHash().toString('hex')}`); console.log(`start state hash: 0x${block.getStartStateHash().toString('hex')}`); console.log(`end state hash: 0x${block.getEndStateHash().toString('hex')}`); - console.log(`public data hash: 0x${block.getPublicInputsHash().toBuffer().toString('hex')}`);*/ + console.log(`public inputs hash: 0x${block.getPublicInputsHash().toBuffer().toString('hex')}`);*/ await publisher.processL2Block(block); diff --git a/yarn-project/sequencer-client/src/block_builder/solo_block_builder.test.ts b/yarn-project/sequencer-client/src/block_builder/solo_block_builder.test.ts index ca823f0dd233..7b82cdfc685a 100644 --- a/yarn-project/sequencer-client/src/block_builder/solo_block_builder.test.ts +++ b/yarn-project/sequencer-client/src/block_builder/solo_block_builder.test.ts @@ -200,6 +200,7 @@ describe('sequencer/solo_block_builder', () => { const l2Block = L2Block.fromFields({ number: blockNumber, + globalVariables: rootRollupOutput.globalVariables, startPrivateDataTreeSnapshot: rootRollupOutput.startPrivateDataTreeSnapshot, endPrivateDataTreeSnapshot: rootRollupOutput.endPrivateDataTreeSnapshot, startNullifierTreeSnapshot: rootRollupOutput.startNullifierTreeSnapshot, diff --git a/yarn-project/sequencer-client/src/block_builder/solo_block_builder.ts b/yarn-project/sequencer-client/src/block_builder/solo_block_builder.ts index ee107d83b930..3d3fd878b2cc 100644 --- a/yarn-project/sequencer-client/src/block_builder/solo_block_builder.ts +++ b/yarn-project/sequencer-client/src/block_builder/solo_block_builder.ts @@ -5,6 +5,7 @@ import { CONTRACT_TREE_ROOTS_TREE_HEIGHT, CircuitsWasm, ConstantBaseRollupData, + GlobalVariables, L1_TO_L2_MESSAGES_ROOTS_TREE_HEIGHT, L1_TO_L2_MESSAGES_SUBTREE_HEIGHT, MembershipWitness, @@ -59,26 +60,35 @@ const DELETE_FR = new Fr(0n); * using the base, merge, and root rollup circuits. */ export class SoloBlockBuilder implements BlockBuilder { + private globalVariables: GlobalVariables; + constructor( protected db: MerkleTreeOperations, protected vks: VerificationKeys, protected simulator: RollupSimulator, protected prover: RollupProver, protected debug = createDebugLogger('aztec:sequencer'), - ) {} + protected chainId: Fr = Fr.ZERO, + protected version: Fr = Fr.ZERO, + ) { + this.globalVariables = new GlobalVariables(chainId, version, Fr.ZERO, Fr.ZERO); + } /** * Builds an L2 block with the given number containing the given txs, updating state trees. * @param blockNumber - Number of the block to create. * @param txs - Processed transactions to include in the block. * @param newL1ToL2Messages - L1 to L2 messages to be part of the block. + * @param timestamp - Timestamp of the block. * @returns The new L2 block and a correctness proof as returned by the root rollup circuit. */ public async buildL2Block( blockNumber: number, txs: ProcessedTx[], newL1ToL2Messages: Fr[], + timestamp = 0, ): Promise<[L2Block, Proof]> { + this.globalVariables = new GlobalVariables(this.chainId, this.version, new Fr(blockNumber), new Fr(timestamp)); const [ startPrivateDataTreeSnapshot, startNullifierTreeSnapshot, @@ -145,6 +155,7 @@ export class SoloBlockBuilder implements BlockBuilder { const l2Block = L2Block.fromFields({ number: blockNumber, + globalVariables: this.globalVariables, startPrivateDataTreeSnapshot, endPrivateDataTreeSnapshot, startNullifierTreeSnapshot, @@ -527,6 +538,7 @@ export class SoloBlockBuilder implements BlockBuilder { startTreeOfHistoricL1ToL2MsgTreeRootsSnapshot: await this.getTreeSnapshot( MerkleTreeId.L1_TO_L2_MESSAGES_ROOTS_TREE, ), + globalVariables: this.globalVariables, }); } diff --git a/yarn-project/types/src/l2_block.ts b/yarn-project/types/src/l2_block.ts index 96afe81f61f5..856ca363b831 100644 --- a/yarn-project/types/src/l2_block.ts +++ b/yarn-project/types/src/l2_block.ts @@ -6,8 +6,9 @@ import { KERNEL_PUBLIC_DATA_UPDATE_REQUESTS_LENGTH, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, KERNEL_NEW_L2_TO_L1_MSGS_LENGTH, + GlobalVariables, } from '@aztec/circuits.js'; -import { makeAppendOnlyTreeSnapshot } from '@aztec/circuits.js/factories'; +import { makeAppendOnlyTreeSnapshot, makeGlobalVariables } from '@aztec/circuits.js/factories'; import { BufferReader, serializeToBuffer } from '@aztec/circuits.js/utils'; import { Fr } from '@aztec/foundation/fields'; import times from 'lodash.times'; @@ -46,6 +47,10 @@ export class L2Block { * The number of the L2 block. */ public number: number, + /** + * The global variables for the L2 block. + */ + public globalVariables: GlobalVariables, /** * The tree snapshot of the private data tree at the start of the rollup. */ @@ -183,6 +188,7 @@ export class L2Block { return L2Block.fromFields({ number: l2BlockNum, + globalVariables: makeGlobalVariables(0, l2BlockNum), startPrivateDataTreeSnapshot: makeAppendOnlyTreeSnapshot(0), startNullifierTreeSnapshot: makeAppendOnlyTreeSnapshot(0), startContractTreeSnapshot: makeAppendOnlyTreeSnapshot(0), @@ -221,6 +227,10 @@ export class L2Block { * The number of the L2 block. */ number: number; + /** + * The global variables of the L2 block. + */ + globalVariables: GlobalVariables; /** * The tree snapshot of the private data tree at the start of the rollup. */ @@ -324,6 +334,7 @@ export class L2Block { }) { return new this( fields.number, + fields.globalVariables, fields.startPrivateDataTreeSnapshot, fields.startNullifierTreeSnapshot, fields.startContractTreeSnapshot, @@ -361,7 +372,7 @@ export class L2Block { throw new Error('newEncryptedLogs and newUnencryptedLogs must be defined when encoding L2BlockData'); } return serializeToBuffer( - this.number, + this.globalVariables, this.startPrivateDataTreeSnapshot, this.startNullifierTreeSnapshot, this.startContractTreeSnapshot, @@ -411,7 +422,8 @@ export class L2Block { */ static decode(encoded: Buffer | BufferReader) { const reader = BufferReader.asReader(encoded); - const number = reader.readNumber(); + const globalVariables = reader.readObject(GlobalVariables); + const number = Number(globalVariables.blockNumber.value); const startPrivateDataTreeSnapshot = reader.readObject(AppendOnlyTreeSnapshot); const startNullifierTreeSnapshot = reader.readObject(AppendOnlyTreeSnapshot); const startContractTreeSnapshot = reader.readObject(AppendOnlyTreeSnapshot); @@ -441,6 +453,7 @@ export class L2Block { return L2Block.fromFields({ number, + globalVariables, startPrivateDataTreeSnapshot, startNullifierTreeSnapshot, startContractTreeSnapshot, @@ -498,6 +511,7 @@ export class L2Block { */ getPublicInputsHash(): Fr { const buf = serializeToBuffer( + this.globalVariables, this.startPrivateDataTreeSnapshot, this.startNullifierTreeSnapshot, this.startContractTreeSnapshot, @@ -527,7 +541,7 @@ export class L2Block { */ getStartStateHash() { const inputValue = serializeToBuffer( - this.number - 1, + new Fr(this.number - 1), this.startPrivateDataTreeSnapshot, this.startNullifierTreeSnapshot, this.startContractTreeSnapshot, @@ -537,6 +551,7 @@ export class L2Block { this.startL1ToL2MessageTreeSnapshot, this.startTreeOfHistoricL1ToL2MessageTreeRootsSnapshot, ); + return sha256(inputValue); } @@ -546,7 +561,7 @@ export class L2Block { */ getEndStateHash() { const inputValue = serializeToBuffer( - this.number, + this.globalVariables.blockNumber, this.endPrivateDataTreeSnapshot, this.endNullifierTreeSnapshot, this.endContractTreeSnapshot, @@ -664,7 +679,7 @@ export class L2Block { getTx(txIndex: number) { const numTxs = Math.floor(this.newCommitments.length / KERNEL_NEW_COMMITMENTS_LENGTH); if (txIndex >= numTxs) { - throw new Error(`Failed to get tx ${txIndex}. Block ${this.number} only has ${numTxs} txs.`); + throw new Error(`Failed to get tx ${txIndex}. Block ${this.globalVariables.blockNumber} only has ${numTxs} txs.`); } const newCommitments = this.newCommitments.slice( @@ -711,6 +726,9 @@ export class L2Block { const inspectTreeSnapshot = (s: AppendOnlyTreeSnapshot): string => `(${s.nextAvailableLeafIndex}, ${inspectHex(s.root)})`; + const inspectGlobalVariables = (gv: GlobalVariables): string => { + return `(${gv.chainId}, ${gv.version}, ${gv.blockNumber}, ${gv.timestamp}))`; + }; const inspectFrArray = (arr: Fr[]): string => inspectArray(arr, inspectHex); const inspectContractDataArray = (arr: ContractData[]): string => inspectArray(arr, cd => `(${inspectHex(cd.contractAddress)}, ${inspectHex(cd.portalContractAddress)})`); @@ -720,6 +738,7 @@ export class L2Block { return [ `L2Block`, `number: ${this.number}`, + `globalVariables: ${inspectGlobalVariables(this.globalVariables)}`, `startPrivateDataTreeSnapshot: ${inspectTreeSnapshot(this.startPrivateDataTreeSnapshot)}`, `startNullifierTreeSnapshot: ${inspectTreeSnapshot(this.startNullifierTreeSnapshot)}`, `startContractTreeSnapshot: ${inspectTreeSnapshot(this.startContractTreeSnapshot)}`, 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 af7ae5a36c54..d46730c85bcb 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 @@ -1,4 +1,9 @@ -import { AppendOnlyTreeSnapshot, CircuitsWasm, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP } from '@aztec/circuits.js'; +import { + AppendOnlyTreeSnapshot, + CircuitsWasm, + GlobalVariables, + NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, +} from '@aztec/circuits.js'; import { INITIAL_LEAF, Pedersen, SiblingPath } from '@aztec/merkle-tree'; import { ContractData, L2Block, L2BlockL2Logs, L2BlockSource, MerkleTreeId, PublicDataWrite } from '@aztec/types'; import { jest } from '@jest/globals'; @@ -33,6 +38,15 @@ const getMockContractData = () => { return ContractData.random(); }; +const getMockGlobalVariables = () => { + return GlobalVariables.from({ + chainId: Fr.random(), + version: Fr.random(), + blockNumber: Fr.random(), + timestamp: Fr.random(), + }); +}; + const getMockL1ToL2MessagesData = () => { return new Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).map(() => Fr.random()); }; @@ -41,6 +55,7 @@ const getMockBlock = (blockNumber: number, newContractsCommitments?: Buffer[]) = const newEncryptedLogs = L2BlockL2Logs.random(1, 2, 3); const block = L2Block.fromFields({ number: blockNumber, + globalVariables: getMockGlobalVariables(), startPrivateDataTreeSnapshot: getMockTreeSnapshot(), startNullifierTreeSnapshot: getMockTreeSnapshot(), startContractTreeSnapshot: getMockTreeSnapshot(),