Skip to content

Commit

Permalink
feat: Adding SLChainID (#2547)
Browse files Browse the repository at this point in the history
## What ❔

Adding settlement layer chain id. Note, that in the future zkSync may
settle onto other instances of Era. This PR does not introduce any
legacy-inducing changes (e.g. amending configs) in case we'll need to
change something.

I also did not rename components / structs that mention "Eth", e.g.
`QueryEthClientLayer`. For now, we can say that everything that says Eth
means "Eth-compatible".

With this PR:
- L1ChainId should not be used only when *exactly* L1 is meant and not
settlement layer.
- SLChainId should be used otherwise.

## Why ❔

<!-- Why are these changes done? What goal do they contribute to? What
are the principles behind them? -->
<!-- Example: PR templates ensure PR reviewers, observers, and future
iterators are in context about the evolution of repos. -->

## 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
StanislavBreadless authored Aug 1, 2024
1 parent 23f9d7a commit 656e830
Show file tree
Hide file tree
Showing 31 changed files with 148 additions and 88 deletions.
14 changes: 11 additions & 3 deletions core/bin/external_node/src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ use zksync_protobuf_config::proto;
use zksync_snapshots_applier::SnapshotsApplierConfig;
use zksync_types::{
api::BridgeAddresses, commitment::L1BatchCommitmentMode, url::SensitiveUrl, Address,
L1BatchNumber, L1ChainId, L2ChainId, ETHEREUM_ADDRESS,
L1BatchNumber, L1ChainId, L2ChainId, SLChainId, ETHEREUM_ADDRESS,
};
use zksync_web3_decl::{
client::{DynClient, L2},
Expand Down Expand Up @@ -908,9 +908,11 @@ impl OptionalENConfig {
/// This part of the external node config is required for its operation.
#[derive(Debug, Deserialize)]
pub(crate) struct RequiredENConfig {
/// L1 chain ID (e.g., 9 for Ethereum mainnet). This ID will be checked against the `eth_client_url` RPC provider on initialization
/// to ensure that there's no mismatch between the expected and actual L1 network.
/// The chain ID of the L1 network (e.g., 1 for Ethereum mainnet). In the future, it may be different from the settlement layer.
pub l1_chain_id: L1ChainId,
/// The chain ID of the settlement layer (e.g., 1 for Ethereum mainnet). This ID will be checked against the `eth_client_url` RPC provider on initialization
/// to ensure that there's no mismatch between the expected and actual settlement layer network.
pub sl_chain_id: Option<SLChainId>,
/// L2 chain ID (e.g., 270 for ZKsync Era mainnet). This ID will be checked against the `main_node_url` RPC provider on initialization
/// to ensure that there's no mismatch between the expected and actual L2 network.
pub l2_chain_id: L2ChainId,
Expand All @@ -932,6 +934,10 @@ pub(crate) struct RequiredENConfig {
}

impl RequiredENConfig {
pub fn settlement_layer_id(&self) -> SLChainId {
self.sl_chain_id.unwrap_or(self.l1_chain_id.into())
}

fn from_env() -> anyhow::Result<Self> {
envy::prefixed("EN_")
.from_env()
Expand All @@ -953,6 +959,7 @@ impl RequiredENConfig {
.context("Database config is required")?;
Ok(RequiredENConfig {
l1_chain_id: en_config.l1_chain_id,
sl_chain_id: None,
l2_chain_id: en_config.l2_chain_id,
http_port: api_config.web3_json_rpc.http_port,
ws_port: api_config.web3_json_rpc.ws_port,
Expand All @@ -973,6 +980,7 @@ impl RequiredENConfig {
fn mock(temp_dir: &tempfile::TempDir) -> Self {
Self {
l1_chain_id: L1ChainId(9),
sl_chain_id: None,
l2_chain_id: L2ChainId::default(),
http_port: 0,
ws_port: 0,
Expand Down
5 changes: 3 additions & 2 deletions core/bin/external_node/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -841,7 +841,7 @@ async fn main() -> anyhow::Result<()> {
let eth_client_url = &config.required.eth_client_url;
let eth_client = Client::http(eth_client_url.clone())
.context("failed creating JSON-RPC client for Ethereum")?
.for_network(config.required.l1_chain_id.into())
.for_network(config.required.settlement_layer_id().into())
.build();
let eth_client = Box::new(eth_client);

Expand Down Expand Up @@ -880,6 +880,7 @@ async fn main() -> anyhow::Result<()> {
RUST_METRICS.initialize();
EN_METRICS.observe_config(
config.required.l1_chain_id,
config.required.settlement_layer_id(),
config.required.l2_chain_id,
config.postgres.max_connections,
);
Expand Down Expand Up @@ -985,7 +986,7 @@ async fn run_node(
});

let validate_chain_ids_task = ValidateChainIdsTask::new(
config.required.l1_chain_id,
config.required.settlement_layer_id(),
config.required.l2_chain_id,
eth_client.clone(),
main_node_client.clone(),
Expand Down
10 changes: 8 additions & 2 deletions core/bin/external_node/src/metrics/framework.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@ use zksync_node_framework::{
FromContext, IntoContext, StopReceiver, Task, TaskId, WiringError, WiringLayer,
};
use zksync_shared_metrics::rustc::RUST_METRICS;
use zksync_types::{L1ChainId, L2ChainId};
use zksync_types::{L1ChainId, L2ChainId, SLChainId};

use super::EN_METRICS;

#[derive(Debug)]
pub struct ExternalNodeMetricsLayer {
pub l1_chain_id: L1ChainId,
pub sl_chain_id: SLChainId,
pub l2_chain_id: L2ChainId,
pub postgres_pool_size: u32,
}
Expand All @@ -39,7 +40,12 @@ impl WiringLayer for ExternalNodeMetricsLayer {

async fn wire(self, input: Self::Input) -> Result<Self::Output, WiringError> {
RUST_METRICS.initialize();
EN_METRICS.observe_config(self.l1_chain_id, self.l2_chain_id, self.postgres_pool_size);
EN_METRICS.observe_config(
self.l1_chain_id,
self.sl_chain_id,
self.l2_chain_id,
self.postgres_pool_size,
);

let pool = input.master_pool.get_singleton().await?;
let task = ProtocolVersionMetricsTask { pool };
Expand Down
5 changes: 4 additions & 1 deletion core/bin/external_node/src/metrics/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::time::Duration;
use tokio::sync::watch;
use vise::{EncodeLabelSet, Gauge, Info, Metrics};
use zksync_dal::{ConnectionPool, Core, CoreDal};
use zksync_types::{L1ChainId, L2ChainId};
use zksync_types::{L1ChainId, L2ChainId, SLChainId};

use crate::metadata::SERVER_VERSION;

Expand All @@ -14,6 +14,7 @@ pub(crate) mod framework;
struct ExternalNodeInfo {
server_version: &'static str,
l1_chain_id: u64,
sl_chain_id: u64,
l2_chain_id: u64,
/// Size of the main Postgres connection pool.
postgres_pool_size: u32,
Expand All @@ -32,12 +33,14 @@ impl ExternalNodeMetrics {
pub(crate) fn observe_config(
&self,
l1_chain_id: L1ChainId,
sl_chain_id: SLChainId,
l2_chain_id: L2ChainId,
postgres_pool_size: u32,
) {
let info = ExternalNodeInfo {
server_version: SERVER_VERSION,
l1_chain_id: l1_chain_id.0,
sl_chain_id: sl_chain_id.0,
l2_chain_id: l2_chain_id.as_u64(),
postgres_pool_size,
};
Expand Down
5 changes: 3 additions & 2 deletions core/bin/external_node/src/node_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ impl ExternalNodeBuilder {
fn add_external_node_metrics_layer(mut self) -> anyhow::Result<Self> {
self.node.add_layer(ExternalNodeMetricsLayer {
l1_chain_id: self.config.required.l1_chain_id,
sl_chain_id: self.config.required.settlement_layer_id(),
l2_chain_id: self.config.required.l2_chain_id,
postgres_pool_size: self.config.postgres.max_connections,
});
Expand Down Expand Up @@ -166,7 +167,7 @@ impl ExternalNodeBuilder {

fn add_query_eth_client_layer(mut self) -> anyhow::Result<Self> {
let query_eth_client_layer = QueryEthClientLayer::new(
self.config.required.l1_chain_id,
self.config.required.settlement_layer_id(),
self.config.required.eth_client_url.clone(),
);
self.node.add_layer(query_eth_client_layer);
Expand Down Expand Up @@ -256,7 +257,7 @@ impl ExternalNodeBuilder {

fn add_validate_chain_ids_layer(mut self) -> anyhow::Result<Self> {
let layer = ValidateChainIdsLayer::new(
self.config.required.l1_chain_id,
self.config.required.settlement_layer_id(),
self.config.required.l2_chain_id,
);
self.node.add_layer(layer);
Expand Down
4 changes: 2 additions & 2 deletions core/bin/external_node/src/tests/framework.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use zksync_node_framework::{
task::TaskKind,
FromContext, IntoContext, StopReceiver, Task, TaskId, WiringError, WiringLayer,
};
use zksync_types::{L1ChainId, L2ChainId};
use zksync_types::{L2ChainId, SLChainId};
use zksync_web3_decl::client::{MockClient, L1, L2};

use super::ExternalNodeBuilder;
Expand Down Expand Up @@ -127,7 +127,7 @@ impl WiringLayer for MockL1ClientLayer {

fn layer_name(&self) -> &'static str {
// We don't care about values, we just want to hijack the layer name.
QueryEthClientLayer::new(L1ChainId(1), "https://example.com".parse().unwrap()).layer_name()
QueryEthClientLayer::new(SLChainId(1), "https://example.com".parse().unwrap()).layer_name()
}

async fn wire(self, _: Self::Input) -> Result<Self::Output, WiringError> {
Expand Down
4 changes: 2 additions & 2 deletions core/bin/zksync_server/src/node_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ impl MainNodeBuilder {
self.node.add_layer(PKSigningEthClientLayer::new(
eth_config,
self.contracts_config.clone(),
self.genesis_config.l1_chain_id,
self.genesis_config.settlement_layer_id(),
wallets,
));
Ok(self)
Expand All @@ -152,7 +152,7 @@ impl MainNodeBuilder {
let genesis = self.genesis_config.clone();
let eth_config = try_load_config!(self.secrets.l1);
let query_eth_client_layer =
QueryEthClientLayer::new(genesis.l1_chain_id, eth_config.l1_rpc_url);
QueryEthClientLayer::new(genesis.settlement_layer_id(), eth_config.l1_rpc_url);
self.node.add_layer(query_eth_client_layer);
Ok(self)
}
Expand Down
16 changes: 16 additions & 0 deletions core/lib/basic_types/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,12 +213,28 @@ basic_type!(
u64
);

basic_type!(
/// ChainId of a settlement layer.
SLChainId,
u64
);

basic_type!(
/// ChainId in the Ethereum network.
/// IMPORTANT: Please, use this method when exactly the L1 chain id is required.
/// Note, that typically this is not the case and the majority of methods need to work
/// with *settlement layer* chain id, which is represented by `SLChainId`.
L1ChainId,
u64
);

// Every L1 can be a settlement layer.
impl From<L1ChainId> for SLChainId {
fn from(value: L1ChainId) -> Self {
SLChainId(value.0)
}
}

#[allow(clippy::derivable_impls)]
impl Default for L2BlockNumber {
fn default() -> Self {
Expand Down
24 changes: 15 additions & 9 deletions core/lib/basic_types/src/network.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use std::{fmt, str::FromStr};
use serde::{Deserialize, Serialize};

// Workspace uses
use crate::L1ChainId;
use crate::SLChainId;

// Local uses

Expand All @@ -28,6 +28,8 @@ pub enum Network {
Sepolia,
/// Self-hosted Ethereum network.
Localhost,
/// Self-hosted L2 network.
LocalhostL2,
/// Unknown network type.
Unknown,
/// Test network for testkit purposes
Expand All @@ -44,6 +46,7 @@ impl FromStr for Network {
"ropsten" => Self::Ropsten,
"goerli" => Self::Goerli,
"localhost" => Self::Localhost,
"localhostL2" => Self::LocalhostL2,
"sepolia" => Self::Sepolia,
"test" => Self::Test,
another => return Err(another.to_owned()),
Expand All @@ -59,6 +62,7 @@ impl fmt::Display for Network {
Self::Ropsten => write!(f, "ropsten"),
Self::Goerli => write!(f, "goerli"),
Self::Localhost => write!(f, "localhost"),
Self::LocalhostL2 => write!(f, "localhostL2"),
Self::Sepolia => write!(f, "sepolia"),
Self::Unknown => write!(f, "unknown"),
Self::Test => write!(f, "test"),
Expand All @@ -68,27 +72,29 @@ impl fmt::Display for Network {

impl Network {
/// Returns the network chain ID on the Ethereum side.
pub fn from_chain_id(chain_id: L1ChainId) -> Self {
pub fn from_chain_id(chain_id: SLChainId) -> Self {
match *chain_id {
1 => Self::Mainnet,
3 => Self::Ropsten,
4 => Self::Rinkeby,
5 => Self::Goerli,
9 => Self::Localhost,
11155111 => Self::Sepolia,
270 => Self::LocalhostL2,
_ => Self::Unknown,
}
}

/// Returns the network chain ID on the Ethereum side.
pub fn chain_id(self) -> L1ChainId {
pub fn chain_id(self) -> SLChainId {
match self {
Self::Mainnet => L1ChainId(1),
Self::Ropsten => L1ChainId(3),
Self::Rinkeby => L1ChainId(4),
Self::Goerli => L1ChainId(5),
Self::Localhost => L1ChainId(9),
Self::Sepolia => L1ChainId(11155111),
Self::Mainnet => SLChainId(1),
Self::Ropsten => SLChainId(3),
Self::Rinkeby => SLChainId(4),
Self::Goerli => SLChainId(5),
Self::Localhost => SLChainId(9),
Self::Sepolia => SLChainId(11155111),
Self::LocalhostL2 => SLChainId(270),
Self::Unknown => panic!("Unknown chain ID"),
Self::Test => panic!("Test chain ID"),
}
Expand Down
3 changes: 2 additions & 1 deletion core/lib/config/src/configs/en_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@ use std::num::NonZeroUsize;

use serde::Deserialize;
use zksync_basic_types::{
commitment::L1BatchCommitmentMode, url::SensitiveUrl, L1ChainId, L2ChainId,
commitment::L1BatchCommitmentMode, url::SensitiveUrl, L1ChainId, L2ChainId, SLChainId,
};

/// Temporary config for initializing external node, will be completely replaced by consensus config later
#[derive(Debug, Clone, PartialEq, Deserialize)]
pub struct ENConfig {
// Genesis
pub l2_chain_id: L2ChainId,
pub sl_chain_id: Option<SLChainId>,
pub l1_chain_id: L1ChainId,
pub l1_batch_commit_data_generator_mode: L1BatchCommitmentMode,

Expand Down
10 changes: 9 additions & 1 deletion core/lib/config/src/configs/genesis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use serde::{Deserialize, Serialize};
use zksync_basic_types::{
commitment::L1BatchCommitmentMode,
protocol_version::{ProtocolSemanticVersion, ProtocolVersionId},
Address, L1ChainId, L2ChainId, H256,
Address, L1ChainId, L2ChainId, SLChainId, H256,
};

/// This config represents the genesis state of the chain.
Expand All @@ -18,13 +18,20 @@ pub struct GenesisConfig {
pub bootloader_hash: Option<H256>,
pub default_aa_hash: Option<H256>,
pub l1_chain_id: L1ChainId,
pub sl_chain_id: Option<SLChainId>,
pub l2_chain_id: L2ChainId,
pub recursion_scheduler_level_vk_hash: H256,
pub fee_account: Address,
pub dummy_verifier: bool,
pub l1_batch_commit_data_generator_mode: L1BatchCommitmentMode,
}

impl GenesisConfig {
pub fn settlement_layer_id(&self) -> SLChainId {
self.sl_chain_id.unwrap_or(self.l1_chain_id.into())
}
}

impl GenesisConfig {
pub fn for_tests() -> Self {
GenesisConfig {
Expand All @@ -36,6 +43,7 @@ impl GenesisConfig {
bootloader_hash: Default::default(),
default_aa_hash: Default::default(),
l1_chain_id: L1ChainId(9),
sl_chain_id: None,
protocol_version: Some(ProtocolSemanticVersion {
minor: ProtocolVersionId::latest(),
patch: 0.into(),
Expand Down
2 changes: 2 additions & 0 deletions core/lib/config/src/testonly.rs
Original file line number Diff line number Diff line change
Expand Up @@ -703,6 +703,7 @@ impl Distribution<configs::GenesisConfig> for EncodeDist {
default_aa_hash: Some(rng.gen()),
fee_account: rng.gen(),
l1_chain_id: L1ChainId(self.sample(rng)),
sl_chain_id: None,
l2_chain_id: L2ChainId::default(),
recursion_scheduler_level_vk_hash: rng.gen(),
dummy_verifier: rng.gen(),
Expand Down Expand Up @@ -875,6 +876,7 @@ impl Distribution<configs::en_config::ENConfig> for EncodeDist {
configs::en_config::ENConfig {
l2_chain_id: L2ChainId::default(),
l1_chain_id: L1ChainId(rng.gen()),
sl_chain_id: None,
main_node_url: format!("localhost:{}", rng.gen::<u16>()).parse().unwrap(),
l1_batch_commit_data_generator_mode: match rng.gen_range(0..2) {
0 => L1BatchCommitmentMode::Rollup,
Expand Down
6 changes: 4 additions & 2 deletions core/lib/env_config/src/genesis.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use anyhow::Context;
use serde::{Deserialize, Serialize};
use zksync_basic_types::{protocol_version::ProtocolSemanticVersion, Address, H256};
use zksync_basic_types::{protocol_version::ProtocolSemanticVersion, Address, L1ChainId, H256};
use zksync_config::{
configs::chain::{NetworkConfig, StateKeeperConfig},
GenesisConfig,
Expand Down Expand Up @@ -68,7 +68,9 @@ impl FromEnv for GenesisConfig {
genesis_commitment: contracts_config.genesis_batch_commitment,
bootloader_hash: state_keeper.bootloader_hash,
default_aa_hash: state_keeper.default_aa_hash,
l1_chain_id: network_config.network.chain_id(),
// TODO(EVM-676): for now, the settlement layer is always the same as the L1 network
l1_chain_id: L1ChainId(network_config.network.chain_id().0),
sl_chain_id: Some(network_config.network.chain_id()),
l2_chain_id: network_config.zksync_network_id,
recursion_scheduler_level_vk_hash: contracts_config.snark_wrapper_vk_hash,
fee_account: state_keeper
Expand Down
Loading

0 comments on commit 656e830

Please sign in to comment.