diff --git a/core/node/genesis/src/lib.rs b/core/node/genesis/src/lib.rs index 1f30d314bb06..08b4f02d8590 100644 --- a/core/node/genesis/src/lib.rs +++ b/core/node/genesis/src/lib.rs @@ -8,7 +8,7 @@ use anyhow::Context as _; use zksync_config::GenesisConfig; use zksync_contracts::{ hyperchain_contract, verifier_contract, BaseSystemContracts, BaseSystemContractsHashes, - SET_CHAIN_ID_EVENT, + SystemContractCode, SET_CHAIN_ID_EVENT, }; use zksync_dal::{Connection, Core, CoreDal, DalError}; use zksync_eth_client::{CallFunctionArgs, EthInterface}; @@ -29,7 +29,7 @@ use zksync_types::{ use zksync_utils::{bytecode::hash_bytecode, u256_to_h256}; use crate::utils::{ - add_eth_token, get_deduped_log_queries, get_storage_logs, + add_eth_token, calculate_root_hash_and_commitment, get_deduped_log_queries, get_storage_logs, insert_base_system_contracts_to_factory_deps, insert_system_contracts, save_genesis_l1_batch_metadata, }; @@ -42,14 +42,16 @@ mod utils; pub struct BaseContractsHashError { from_config: BaseSystemContractsHashes, calculated: BaseSystemContractsHashes, + new_root_hash: H256, + new_commitment_hash: H256, } impl std::fmt::Display for BaseContractsHashError { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { write!( f, - "From Config {:?}, Calculated : {:?}", - &self.from_config, &self.calculated + "From Config {:#?}, Calculated : {:#?}, New root hash: {:#?}, New commitment hash: {:#?}", + &self.from_config, &self.calculated, &self.new_root_hash, &self.new_commitment_hash ) } } @@ -105,17 +107,28 @@ impl GenesisParams { .default_aa_hash .ok_or(GenesisError::MalformedConfig("default_aa_hash"))?, }; + if base_system_contracts_hashes != base_system_contracts.hashes() { + let new_genesis_params = GenesisParams { + base_system_contracts: base_system_contracts.clone(), + system_contracts, + config, + }; + let (new_root_hash, new_commitment, _) = + calculate_root_hash_and_commitment(&new_genesis_params); return Err(GenesisError::BaseSystemContractsHashes(Box::new( BaseContractsHashError { from_config: base_system_contracts_hashes, calculated: base_system_contracts.hashes(), + new_root_hash, + new_commitment_hash: new_commitment.hash().commitment, }, ))); } if config.protocol_version.is_none() { return Err(GenesisError::MalformedConfig("protocol_version")); } + Ok(GenesisParams { base_system_contracts, system_contracts, diff --git a/core/node/genesis/src/utils.rs b/core/node/genesis/src/utils.rs index a6c9513dbde8..75d3a83ddc1b 100644 --- a/core/node/genesis/src/utils.rs +++ b/core/node/genesis/src/utils.rs @@ -3,6 +3,7 @@ use std::collections::HashMap; use itertools::Itertools; use zksync_contracts::BaseSystemContracts; use zksync_dal::{Connection, Core, CoreDal}; +use zksync_merkle_tree::{domain::ZkSyncTree, TreeInstruction}; use zksync_multivm::{ circuit_sequencer_api_latest::sort_storage_access::sort_storage_access_queries, zk_evm_latest::aux_structures::{LogQuery as MultiVmLogQuery, Timestamp as MultiVMTimestamp}, @@ -10,7 +11,7 @@ use zksync_multivm::{ use zksync_system_constants::{DEFAULT_ERA_CHAIN_ID, ETHEREUM_ADDRESS}; use zksync_types::{ block::{DeployedContract, L1BatchTreeData}, - commitment::L1BatchCommitment, + commitment::{CommitmentInput, L1BatchCommitment}, get_code_key, get_known_code_key, get_system_context_init_logs, tokens::{TokenInfo, TokenMetadata}, zk_evm_types::{LogQuery, Timestamp}, @@ -18,7 +19,7 @@ use zksync_types::{ }; use zksync_utils::{be_words_to_bytes, bytecode::hash_bytecode, h256_to_u256, u256_to_h256}; -use crate::GenesisError; +use crate::{GenesisError, GenesisParams}; pub(super) async fn add_eth_token(transaction: &mut Connection<'_, Core>) -> anyhow::Result<()> { assert!(transaction.in_transaction()); // sanity check @@ -216,3 +217,38 @@ pub(super) async fn insert_system_contracts( transaction.commit().await?; Ok(()) } + +pub(super) fn calculate_root_hash_and_commitment( + new_genesis_params: &GenesisParams, +) -> (H256, L1BatchCommitment, u64) { + let deduped_log_queries = + get_deduped_log_queries(&get_storage_logs(new_genesis_params.system_contracts())); + let (deduplicated_writes, _): (Vec<_>, Vec<_>) = deduped_log_queries + .into_iter() + .partition(|log_query| log_query.rw_flag); + + let storage_logs: Vec = deduplicated_writes + .iter() + .enumerate() + .map(|(index, log)| { + TreeInstruction::write( + StorageKey::new(AccountTreeId::new(log.address), u256_to_h256(log.key)) + .hashed_key_u256(), + (index + 1) as u64, + u256_to_h256(log.written_value), + ) + }) + .collect(); + + let metadata = ZkSyncTree::process_genesis_batch(&storage_logs); + let genesis_root_hash = metadata.root_hash; + let rollup_last_leaf_index = metadata.leaf_count + 1; + let commitment_input = CommitmentInput::for_genesis_batch( + genesis_root_hash, + rollup_last_leaf_index, + new_genesis_params.base_system_contracts().hashes(), + new_genesis_params.minor_protocol_version(), + ); + let block_commitment = L1BatchCommitment::new(commitment_input); + (genesis_root_hash, block_commitment, rollup_last_leaf_index) +}