Skip to content

Commit

Permalink
feat(genesis): Validate genesis config against L1 (#2786)
Browse files Browse the repository at this point in the history
## What ❔

Validate protocol version and vk hash from genesis config against L1

## Why ❔

Right now nothing prevents from initializing contracts and node with
different protocol versions or vk hashs, and it already happened 🥲

## Checklist

<!-- Check your PR fulfills the following items. -->
<!-- For draft PRs check the boxes as you complete them. -->

- [ ] PR title corresponds to the body of PR (we generate changelog
entries from PRs).
- [ ] Tests for the changes have been added / updated.
- [ ] Documentation comments have been added / updated.
- [ ] Code has been formatted via `zk fmt` and `zk lint`.
  • Loading branch information
perekopskiy committed Sep 3, 2024
1 parent 19ca512 commit b2dd9a5
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 9 deletions.
61 changes: 52 additions & 9 deletions core/node/genesis/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,12 @@ use std::fmt::Formatter;

use anyhow::Context as _;
use zksync_config::GenesisConfig;
use zksync_contracts::{BaseSystemContracts, BaseSystemContractsHashes, SET_CHAIN_ID_EVENT};
use zksync_contracts::{
hyperchain_contract, verifier_contract, BaseSystemContracts, BaseSystemContractsHashes,
SET_CHAIN_ID_EVENT,
};
use zksync_dal::{Connection, Core, CoreDal, DalError};
use zksync_eth_client::EthInterface;
use zksync_eth_client::{CallFunctionArgs, EthInterface};
use zksync_merkle_tree::{domain::ZkSyncTree, TreeInstruction};
use zksync_multivm::utils::get_max_gas_per_pubdata_byte;
use zksync_system_constants::PRIORITY_EXPIRATION;
Expand All @@ -21,7 +24,7 @@ use zksync_types::{
system_contracts::get_system_smart_contracts,
web3::{BlockNumber, FilterBuilder},
AccountTreeId, Address, Bloom, L1BatchNumber, L1ChainId, L2BlockNumber, L2ChainId,
ProtocolVersion, ProtocolVersionId, StorageKey, H256,
ProtocolVersion, ProtocolVersionId, StorageKey, H256, U256,
};
use zksync_utils::{bytecode::hash_bytecode, u256_to_h256};

Expand Down Expand Up @@ -110,12 +113,9 @@ impl GenesisParams {
},
)));
}
// Try to convert value from config to the real protocol version and return error
// if the version doesn't exist
let _: ProtocolVersionId = config
.protocol_version
.map(|p| p.minor)
.ok_or(GenesisError::MalformedConfig("protocol_version"))?;
if config.protocol_version.is_none() {
return Err(GenesisError::MalformedConfig("protocol_version"));
}
Ok(GenesisParams {
base_system_contracts,
system_contracts,
Expand Down Expand Up @@ -264,6 +264,49 @@ pub async fn is_genesis_needed(storage: &mut Connection<'_, Core>) -> Result<boo
Ok(storage.blocks_dal().is_genesis_needed().await?)
}

pub async fn validate_genesis_params(
genesis_params: &GenesisParams,
query_client: &dyn EthInterface,
diamond_proxy_address: Address,
) -> anyhow::Result<()> {
let hyperchain_abi = hyperchain_contract();
let verifier_abi = verifier_contract();

let packed_protocol_version: U256 = CallFunctionArgs::new("getProtocolVersion", ())
.for_contract(diamond_proxy_address, &hyperchain_abi)
.call(query_client)
.await?;

let protocol_version = ProtocolSemanticVersion::try_from_packed(packed_protocol_version)
.map_err(|err| anyhow::format_err!("Failed to unpack semver: {err}"))?;

if protocol_version != genesis_params.protocol_version() {
return Err(anyhow::anyhow!(
"Protocol version mismatch: {protocol_version} on contract, {} in config",
genesis_params.protocol_version()
));
}

let verifier_address: Address = CallFunctionArgs::new("getVerifier", ())
.for_contract(diamond_proxy_address, &hyperchain_abi)
.call(query_client)
.await?;

let verification_key_hash: H256 = CallFunctionArgs::new("verificationKeyHash", ())
.for_contract(verifier_address, &verifier_abi)
.call(query_client)
.await?;

if verification_key_hash != genesis_params.config().recursion_scheduler_level_vk_hash {
return Err(anyhow::anyhow!(
"Verification key hash mismatch: {verification_key_hash:?} on contract, {:?} in config",
genesis_params.config().recursion_scheduler_level_vk_hash
));
}

Ok(())
}

pub async fn ensure_genesis_state(
storage: &mut Connection<'_, Core>,
genesis_params: &GenesisParams,
Expand Down
6 changes: 6 additions & 0 deletions core/node/node_storage_init/src/main_node/genesis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ impl InitializeStorage for MainNodeGenesis {
}

let params = GenesisParams::load_genesis_params(self.genesis.clone())?;
zksync_node_genesis::validate_genesis_params(
&params,
&self.l1_client,
self.contracts.diamond_proxy_addr,
)
.await?;
zksync_node_genesis::ensure_genesis_state(&mut storage, &params).await?;

if let Some(ecosystem_contracts) = &self.contracts.ecosystem_contracts {
Expand Down

0 comments on commit b2dd9a5

Please sign in to comment.