Skip to content

Commit b2dd9a5

Browse files
authored
feat(genesis): Validate genesis config against L1 (matter-labs#2786)
## 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`.
1 parent 19ca512 commit b2dd9a5

File tree

2 files changed

+58
-9
lines changed

2 files changed

+58
-9
lines changed

core/node/genesis/src/lib.rs

Lines changed: 52 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,12 @@ use std::fmt::Formatter;
66

77
use anyhow::Context as _;
88
use zksync_config::GenesisConfig;
9-
use zksync_contracts::{BaseSystemContracts, BaseSystemContractsHashes, SET_CHAIN_ID_EVENT};
9+
use zksync_contracts::{
10+
hyperchain_contract, verifier_contract, BaseSystemContracts, BaseSystemContractsHashes,
11+
SET_CHAIN_ID_EVENT,
12+
};
1013
use zksync_dal::{Connection, Core, CoreDal, DalError};
11-
use zksync_eth_client::EthInterface;
14+
use zksync_eth_client::{CallFunctionArgs, EthInterface};
1215
use zksync_merkle_tree::{domain::ZkSyncTree, TreeInstruction};
1316
use zksync_multivm::utils::get_max_gas_per_pubdata_byte;
1417
use zksync_system_constants::PRIORITY_EXPIRATION;
@@ -21,7 +24,7 @@ use zksync_types::{
2124
system_contracts::get_system_smart_contracts,
2225
web3::{BlockNumber, FilterBuilder},
2326
AccountTreeId, Address, Bloom, L1BatchNumber, L1ChainId, L2BlockNumber, L2ChainId,
24-
ProtocolVersion, ProtocolVersionId, StorageKey, H256,
27+
ProtocolVersion, ProtocolVersionId, StorageKey, H256, U256,
2528
};
2629
use zksync_utils::{bytecode::hash_bytecode, u256_to_h256};
2730

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

267+
pub async fn validate_genesis_params(
268+
genesis_params: &GenesisParams,
269+
query_client: &dyn EthInterface,
270+
diamond_proxy_address: Address,
271+
) -> anyhow::Result<()> {
272+
let hyperchain_abi = hyperchain_contract();
273+
let verifier_abi = verifier_contract();
274+
275+
let packed_protocol_version: U256 = CallFunctionArgs::new("getProtocolVersion", ())
276+
.for_contract(diamond_proxy_address, &hyperchain_abi)
277+
.call(query_client)
278+
.await?;
279+
280+
let protocol_version = ProtocolSemanticVersion::try_from_packed(packed_protocol_version)
281+
.map_err(|err| anyhow::format_err!("Failed to unpack semver: {err}"))?;
282+
283+
if protocol_version != genesis_params.protocol_version() {
284+
return Err(anyhow::anyhow!(
285+
"Protocol version mismatch: {protocol_version} on contract, {} in config",
286+
genesis_params.protocol_version()
287+
));
288+
}
289+
290+
let verifier_address: Address = CallFunctionArgs::new("getVerifier", ())
291+
.for_contract(diamond_proxy_address, &hyperchain_abi)
292+
.call(query_client)
293+
.await?;
294+
295+
let verification_key_hash: H256 = CallFunctionArgs::new("verificationKeyHash", ())
296+
.for_contract(verifier_address, &verifier_abi)
297+
.call(query_client)
298+
.await?;
299+
300+
if verification_key_hash != genesis_params.config().recursion_scheduler_level_vk_hash {
301+
return Err(anyhow::anyhow!(
302+
"Verification key hash mismatch: {verification_key_hash:?} on contract, {:?} in config",
303+
genesis_params.config().recursion_scheduler_level_vk_hash
304+
));
305+
}
306+
307+
Ok(())
308+
}
309+
267310
pub async fn ensure_genesis_state(
268311
storage: &mut Connection<'_, Core>,
269312
genesis_params: &GenesisParams,

core/node/node_storage_init/src/main_node/genesis.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,12 @@ impl InitializeStorage for MainNodeGenesis {
3030
}
3131

3232
let params = GenesisParams::load_genesis_params(self.genesis.clone())?;
33+
zksync_node_genesis::validate_genesis_params(
34+
&params,
35+
&self.l1_client,
36+
self.contracts.diamond_proxy_addr,
37+
)
38+
.await?;
3339
zksync_node_genesis::ensure_genesis_state(&mut storage, &params).await?;
3440

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

0 commit comments

Comments
 (0)