async fn ensure_no_l1_batch_divergence(
        &mut self,
        pool: &ConnectionPool<Core>,
    ) -> anyhow::Result<()> {
        let Some(last_tree_l1_batch) = self.next_l1_batch_number().await?.checked_sub(1) else {
            // No L1 batches in the tree means no divergence.
            return Ok(());
        };
        let last_tree_l1_batch = L1BatchNumber(last_tree_l1_batch);

        let mut storage = pool.connection_tagged("metadata_calculator").await?;
        if self
            .l1_batch_matches(&mut storage, last_tree_l1_batch)
            .await?
        {
            tracing::debug!(
                "Last l1 batch in tree #{last_tree_l1_batch} has same data in tree and Postgres"
            );
            return Ok(());
        }

        tracing::debug!("Last l1 batch in tree #{last_tree_l1_batch} has diverging data in tree and Postgres; searching for the last common L1 batch");
        let min_tree_l1_batch = self
            .min_l1_batch_number()
            .await?
            .context("tree shouldn't be empty at this point")?;
        anyhow::ensure!(
            min_tree_l1_batch <= last_tree_l1_batch,
            "potential Merkle tree corruption: minimum L1 batch number ({min_tree_l1_batch}) exceeds the last L1 batch ({last_tree_l1_batch})"
        );

        anyhow::ensure!(
            self.l1_batch_matches(&mut storage, min_tree_l1_batch).await?,
            "diverging min L1 batch in the tree #{min_tree_l1_batch}; the tree cannot recover from this"
        );

        let mut left = min_tree_l1_batch.0;
        let mut right = last_tree_l1_batch.0;
        while left + 1 < right {
            let middle = (left + right) / 2;
            let batch_matches = self
                .l1_batch_matches(&mut storage, L1BatchNumber(middle))
                .await?;
            if batch_matches {
                left = middle;
            } else {
                right = middle;
            }
        }
        let last_common_l1_batch_number = L1BatchNumber(left);
        tracing::info!("Found last common L1 batch between tree and Postgres: #{last_common_l1_batch_number}; will revert tree to it");

        self.roll_back_logs(last_common_l1_batch_number).await?;
        self.save().await?;
        Ok(())
    }
Invariant: the tree is not ahead of Postgres.
core/node/zk_os_tree_manager/src/updater.rs