Skip to content

Commit

Permalink
refactor(metadata_calculator): Move ObjectStore out from MetadataCalc…
Browse files Browse the repository at this point in the history
…ulatorConfig (matter-labs#816)

## What ❔

title

## Why ❔

- There was some clunky back-and-forth for
`MetadataCalculatorModeConfig` <->`MerkleTreeMode` because of the old
component confuguration.
- ObjectStore may not be available at time when
`MetadataCalculatorModeConfig ` is created (prerequisite for ZK Stack
thing).
- Less code!

## 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`.
- [ ] Spellcheck has been run via `cargo spellcheck
--cfg=./spellcheck/era.cfg --code 1`.
  • Loading branch information
popzxc authored Jan 4, 2024
1 parent 61712a6 commit 5053b0a
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 86 deletions.
13 changes: 6 additions & 7 deletions core/bin/external_node/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use metrics::EN_METRICS;
use prometheus_exporter::PrometheusExporterConfig;
use tokio::{sync::watch, task, time::sleep};
use zksync_basic_types::{Address, L2ChainId};
use zksync_config::configs::database::MerkleTreeMode;
use zksync_core::{
api_server::{
execution_sandbox::VmConcurrencyLimiter,
Expand All @@ -17,9 +18,7 @@ use zksync_core::{
block_reverter::{BlockReverter, BlockReverterFlags, L1ExecutedBatchesRevert},
consistency_checker::ConsistencyChecker,
l1_gas_price::MainNodeGasPriceFetcher,
metadata_calculator::{
MetadataCalculator, MetadataCalculatorConfig, MetadataCalculatorModeConfig,
},
metadata_calculator::{MetadataCalculator, MetadataCalculatorConfig},
reorg_detector::ReorgDetector,
setup_sigint_handler,
state_keeper::{
Expand Down Expand Up @@ -186,17 +185,17 @@ async fn init_tasks(
stop_receiver.clone(),
);

let metadata_calculator = MetadataCalculator::new(MetadataCalculatorConfig {
let metadata_calculator_config = MetadataCalculatorConfig {
db_path: config.required.merkle_tree_path.clone(),
mode: MetadataCalculatorModeConfig::Full { object_store: None },
mode: MerkleTreeMode::Full,
delay_interval: config.optional.metadata_calculator_delay(),
max_l1_batches_per_iter: config.optional.max_l1_batches_per_tree_iter,
multi_get_chunk_size: config.optional.merkle_tree_multi_get_chunk_size,
block_cache_capacity: config.optional.merkle_tree_block_cache_size(),
memtable_capacity: config.optional.merkle_tree_memtable_capacity(),
stalled_writes_timeout: config.optional.merkle_tree_stalled_writes_timeout(),
})
.await;
};
let metadata_calculator = MetadataCalculator::new(metadata_calculator_config, None).await;
healthchecks.push(Box::new(metadata_calculator.tree_health_check()));

let consistency_checker = ConsistencyChecker::new(
Expand Down
29 changes: 12 additions & 17 deletions core/lib/zksync_core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use zksync_config::{
StateKeeperConfig,
},
contracts::ProverAtGenesis,
database::MerkleTreeMode,
database::{MerkleTreeConfig, MerkleTreeMode},
},
ApiConfig, ContractsConfig, DBConfig, ETHSenderConfig, PostgresConfig,
};
Expand Down Expand Up @@ -65,9 +65,7 @@ use crate::{
waiting_to_queued_fri_witness_job_mover::WaitingToQueuedFriWitnessJobMover,
},
l1_gas_price::{GasAdjusterSingleton, L1GasPriceProvider},
metadata_calculator::{
MetadataCalculator, MetadataCalculatorConfig, MetadataCalculatorModeConfig,
},
metadata_calculator::{MetadataCalculator, MetadataCalculatorConfig},
metrics::{InitStage, APP_METRICS},
state_keeper::{
create_state_keeper, MempoolFetcher, MempoolGuard, MiniblockSealer, SequencerSealer,
Expand Down Expand Up @@ -768,21 +766,19 @@ async fn add_trees_to_task_futures(
.contains(&Component::TreeApi)
.then_some(&api_config);

let mode = match db_config.merkle_tree.mode {
MerkleTreeMode::Lightweight => MetadataCalculatorModeConfig::Lightweight,
MerkleTreeMode::Full => MetadataCalculatorModeConfig::Full {
object_store: Some(store_factory.create_store().await),
},
let object_store = match db_config.merkle_tree.mode {
MerkleTreeMode::Lightweight => None,
MerkleTreeMode::Full => Some(store_factory.create_store().await),
};

run_tree(
task_futures,
healthchecks,
&postgres_config,
&db_config,
&db_config.merkle_tree,
api_config,
&operation_config,
mode,
object_store,
stop_receiver,
)
.await
Expand All @@ -794,23 +790,22 @@ async fn run_tree(
task_futures: &mut Vec<JoinHandle<anyhow::Result<()>>>,
healthchecks: &mut Vec<Box<dyn CheckHealth>>,
postgres_config: &PostgresConfig,
db_config: &DBConfig,
merkle_tree_config: &MerkleTreeConfig,
api_config: Option<&MerkleTreeApiConfig>,
operation_manager: &OperationsManagerConfig,
mode: MetadataCalculatorModeConfig,
object_store: Option<Box<dyn ObjectStore>>,
stop_receiver: watch::Receiver<bool>,
) -> anyhow::Result<()> {
let started_at = Instant::now();
let mode_str = if matches!(mode, MetadataCalculatorModeConfig::Full { .. }) {
let mode_str = if matches!(merkle_tree_config.mode, MerkleTreeMode::Full) {
"full"
} else {
"lightweight"
};
tracing::info!("Initializing Merkle tree in {mode_str} mode");

let config =
MetadataCalculatorConfig::for_main_node(&db_config.merkle_tree, operation_manager, mode);
let metadata_calculator = MetadataCalculator::new(config).await;
let config = MetadataCalculatorConfig::for_main_node(merkle_tree_config, operation_manager);
let metadata_calculator = MetadataCalculator::new(config, object_store).await;
if let Some(api_config) = api_config {
let address = (Ipv4Addr::UNSPECIFIED, api_config.port).into();
let tree_reader = metadata_calculator.tree_reader();
Expand Down
41 changes: 7 additions & 34 deletions core/lib/zksync_core/src/metadata_calculator/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,36 +36,13 @@ mod recovery;
pub(crate) mod tests;
mod updater;

/// Part of [`MetadataCalculator`] related to the operation mode of the Merkle tree.
#[derive(Debug)]
pub enum MetadataCalculatorModeConfig {
/// In this mode, `MetadataCalculator` computes Merkle tree root hashes and some auxiliary information
/// for L1 batches, but not witness inputs.
Lightweight,
/// In this mode, `MetadataCalculator` will compute commitments and witness inputs for all storage operations
/// and optionally put witness inputs into the object store (e.g., GCS).
Full {
object_store: Option<Box<dyn ObjectStore>>,
},
}

impl MetadataCalculatorModeConfig {
fn to_mode(&self) -> MerkleTreeMode {
if matches!(self, Self::Full { .. }) {
MerkleTreeMode::Full
} else {
MerkleTreeMode::Lightweight
}
}
}

/// Configuration of [`MetadataCalculator`].
#[derive(Debug)]
pub struct MetadataCalculatorConfig {
/// Filesystem path to the RocksDB instance that stores the tree.
pub db_path: String,
/// Configuration of the Merkle tree mode.
pub mode: MetadataCalculatorModeConfig,
pub mode: MerkleTreeMode,
/// Interval between polling Postgres for updates if no progress was made by the tree.
pub delay_interval: Duration,
/// Maximum number of L1 batches to get from Postgres on a single update iteration.
Expand All @@ -86,11 +63,10 @@ impl MetadataCalculatorConfig {
pub(crate) fn for_main_node(
merkle_tree_config: &MerkleTreeConfig,
operation_config: &OperationsManagerConfig,
mode: MetadataCalculatorModeConfig,
) -> Self {
Self {
db_path: merkle_tree_config.path.clone(),
mode,
mode: merkle_tree_config.mode,
delay_interval: operation_config.delay_interval(),
max_l1_batches_per_iter: merkle_tree_config.max_l1_batches_per_iter,
multi_get_chunk_size: merkle_tree_config.multi_get_chunk_size,
Expand All @@ -113,18 +89,15 @@ pub struct MetadataCalculator {

impl MetadataCalculator {
/// Creates a calculator with the specified `config`.
pub async fn new(config: MetadataCalculatorConfig) -> Self {
pub async fn new(
config: MetadataCalculatorConfig,
object_store: Option<Box<dyn ObjectStore>>,
) -> Self {
assert!(
config.max_l1_batches_per_iter > 0,
"Maximum L1 batches per iteration is misconfigured to be 0; please update it to positive value"
);

let mode = config.mode.to_mode();
let object_store = match config.mode {
MetadataCalculatorModeConfig::Full { object_store } => object_store,
MetadataCalculatorModeConfig::Lightweight => None,
};

let db = create_db(
config.db_path.clone().into(),
config.block_cache_capacity,
Expand All @@ -133,7 +106,7 @@ impl MetadataCalculator {
config.multi_get_chunk_size,
)
.await;
let tree = GenericAsyncTree::new(db, mode).await;
let tree = GenericAsyncTree::new(db, config.mode).await;

let (_, health_updater) = ReactiveHealthCheck::new("tree");
Self {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ use crate::{
extend_db_state, extend_db_state_from_l1_batch, gen_storage_logs, run_calculator,
setup_calculator,
},
MetadataCalculator, MetadataCalculatorConfig, MetadataCalculatorModeConfig,
MetadataCalculator, MetadataCalculatorConfig,
},
};

Expand Down Expand Up @@ -292,9 +292,8 @@ async fn entire_recovery_workflow(case: RecoveryWorkflowCase) {
let calculator_config = MetadataCalculatorConfig::for_main_node(
&merkle_tree_config,
&OperationsManagerConfig { delay_interval: 50 },
MetadataCalculatorModeConfig::Lightweight,
);
let mut calculator = MetadataCalculator::new(calculator_config).await;
let mut calculator = MetadataCalculator::new(calculator_config, None).await;
let (delay_sx, mut delay_rx) = mpsc::unbounded_channel();
calculator.delayer.delay_notifier = delay_sx;

Expand Down
47 changes: 22 additions & 25 deletions core/lib/zksync_core/src/metadata_calculator/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ use assert_matches::assert_matches;
use itertools::Itertools;
use tempfile::TempDir;
use tokio::sync::{mpsc, watch};
use zksync_config::configs::{chain::OperationsManagerConfig, database::MerkleTreeConfig};
use zksync_config::configs::{
chain::OperationsManagerConfig,
database::{MerkleTreeConfig, MerkleTreeMode},
};
use zksync_contracts::BaseSystemContracts;
use zksync_dal::{ConnectionPool, StorageProcessor};
use zksync_health_check::{CheckHealth, HealthStatus};
Expand All @@ -20,10 +23,7 @@ use zksync_types::{
};
use zksync_utils::u32_to_h256;

use super::{
GenericAsyncTree, L1BatchWithLogs, MetadataCalculator, MetadataCalculatorConfig,
MetadataCalculatorModeConfig,
};
use super::{GenericAsyncTree, L1BatchWithLogs, MetadataCalculator, MetadataCalculatorConfig};
use crate::genesis::{ensure_genesis_state, GenesisParams};

const RUN_TIMEOUT: Duration = Duration::from_secs(30);
Expand Down Expand Up @@ -237,16 +237,12 @@ async fn running_metadata_calculator_with_additional_blocks() {
async fn shutting_down_calculator() {
let pool = ConnectionPool::test_pool().await;
let temp_dir = TempDir::new().expect("failed get temporary directory for RocksDB");
let (merkle_tree_config, mut operation_config) = create_config(temp_dir.path());
let (merkle_tree_config, mut operation_config) =
create_config(temp_dir.path(), MerkleTreeMode::Lightweight);
operation_config.delay_interval = 30_000; // ms; chosen to be larger than `RUN_TIMEOUT`

let calculator = setup_calculator_with_options(
&merkle_tree_config,
&operation_config,
&pool,
MetadataCalculatorModeConfig::Lightweight,
)
.await;
let calculator =
setup_calculator_with_options(&merkle_tree_config, &operation_config, &pool, None).await;

reset_db_state(&pool, 5).await;

Expand Down Expand Up @@ -365,24 +361,25 @@ pub(crate) async fn setup_calculator(
) -> (MetadataCalculator, Box<dyn ObjectStore>) {
let store_factory = ObjectStoreFactory::mock();
let store = store_factory.create_store().await;
let (merkle_tree_config, operation_manager) = create_config(db_path);
let mode = MetadataCalculatorModeConfig::Full {
object_store: Some(store),
};
let (merkle_tree_config, operation_manager) = create_config(db_path, MerkleTreeMode::Full);
let calculator =
setup_calculator_with_options(&merkle_tree_config, &operation_manager, pool, mode).await;
setup_calculator_with_options(&merkle_tree_config, &operation_manager, pool, Some(store))
.await;
(calculator, store_factory.create_store().await)
}

async fn setup_lightweight_calculator(db_path: &Path, pool: &ConnectionPool) -> MetadataCalculator {
let mode = MetadataCalculatorModeConfig::Lightweight;
let (db_config, operation_config) = create_config(db_path);
setup_calculator_with_options(&db_config, &operation_config, pool, mode).await
let (db_config, operation_config) = create_config(db_path, MerkleTreeMode::Lightweight);
setup_calculator_with_options(&db_config, &operation_config, pool, None).await
}

fn create_config(db_path: &Path) -> (MerkleTreeConfig, OperationsManagerConfig) {
fn create_config(
db_path: &Path,
mode: MerkleTreeMode,
) -> (MerkleTreeConfig, OperationsManagerConfig) {
let db_config = MerkleTreeConfig {
path: path_to_string(&db_path.join("new")),
mode,
..MerkleTreeConfig::default()
};

Expand All @@ -396,11 +393,11 @@ async fn setup_calculator_with_options(
merkle_tree_config: &MerkleTreeConfig,
operation_config: &OperationsManagerConfig,
pool: &ConnectionPool,
mode: MetadataCalculatorModeConfig,
object_store: Option<Box<dyn ObjectStore>>,
) -> MetadataCalculator {
let calculator_config =
MetadataCalculatorConfig::for_main_node(merkle_tree_config, operation_config, mode);
let metadata_calculator = MetadataCalculator::new(calculator_config).await;
MetadataCalculatorConfig::for_main_node(merkle_tree_config, operation_config);
let metadata_calculator = MetadataCalculator::new(calculator_config, object_store).await;

let mut storage = pool.access_storage().await.unwrap();
if storage.blocks_dal().is_genesis_needed().await.unwrap() {
Expand Down

0 comments on commit 5053b0a

Please sign in to comment.