zksync_protobuf_config 0.1.0

Protobuf deserialization for ZKsync configs
Documentation
use std::collections::HashSet;

use anyhow::Context as _;
use zksync_basic_types::basic_fri_types::CircuitIdRoundTuple;
use zksync_config::configs;
use zksync_protobuf::{repr::ProtoRepr, required};

use crate::proto::prover as proto;

impl ProtoRepr for proto::ProofCompressor {
    type Type = configs::FriProofCompressorConfig;
    fn read(&self) -> anyhow::Result<Self::Type> {
        Ok(Self::Type {
            compression_mode: required(&self.compression_mode)
                .and_then(|x| Ok((*x).try_into()?))
                .context("compression_mode")?,
            prometheus_listener_port: required(&self.prometheus_listener_port)
                .and_then(|x| Ok((*x).try_into()?))
                .context("prometheus_listener_port")?,
            prometheus_pushgateway_url: required(&self.prometheus_pushgateway_url)
                .context("prometheus_pushgateway_url")?
                .clone(),
            prometheus_push_interval_ms: self.prometheus_push_interval_ms,
            generation_timeout_in_secs: required(&self.generation_timeout_in_secs)
                .and_then(|x| Ok((*x).try_into()?))
                .context("generation_timeout_in_secs")?,
            max_attempts: *required(&self.max_attempts).context("max_attempts")?,
            universal_setup_path: required(&self.universal_setup_path)
                .context("universal_setup_path")?
                .clone(),
            universal_setup_download_url: required(&self.universal_setup_download_url)
                .context("universal_setup_download_url")?
                .clone(),
            verify_wrapper_proof: *required(&self.verify_wrapper_proof)
                .context("verify_wrapper_proof")?,
        })
    }

    fn build(this: &Self::Type) -> Self {
        Self {
            compression_mode: Some(this.compression_mode.into()),
            prometheus_listener_port: Some(this.prometheus_listener_port.into()),
            prometheus_pushgateway_url: Some(this.prometheus_pushgateway_url.clone()),
            prometheus_push_interval_ms: this.prometheus_push_interval_ms,
            generation_timeout_in_secs: Some(this.generation_timeout_in_secs.into()),
            max_attempts: Some(this.max_attempts),
            universal_setup_path: Some(this.universal_setup_path.clone()),
            universal_setup_download_url: Some(this.universal_setup_download_url.clone()),
            verify_wrapper_proof: Some(this.verify_wrapper_proof),
        }
    }
}

impl ProtoRepr for proto::CircuitIdRoundTuple {
    type Type = CircuitIdRoundTuple;
    fn read(&self) -> anyhow::Result<Self::Type> {
        Ok(Self::Type {
            circuit_id: required(&self.circuit_id)
                .and_then(|x| Ok((*x).try_into()?))
                .context("circuit_id")?,
            aggregation_round: required(&self.aggregation_round)
                .and_then(|x| Ok((*x).try_into()?))
                .context("aggregation_round")?,
        })
    }

    fn build(this: &Self::Type) -> Self {
        Self {
            circuit_id: Some(this.circuit_id.into()),
            aggregation_round: Some(this.aggregation_round.into()),
        }
    }
}

fn read_vec(v: &[proto::CircuitIdRoundTuple]) -> anyhow::Result<HashSet<CircuitIdRoundTuple>> {
    v.iter()
        .enumerate()
        .map(|(i, x)| x.read().context(i))
        .collect()
}

fn build_vec(v: &HashSet<CircuitIdRoundTuple>) -> Vec<proto::CircuitIdRoundTuple> {
    let mut v: Vec<_> = v.iter().cloned().collect();
    v.sort();
    v.iter().map(ProtoRepr::build).collect()
}

impl ProtoRepr for proto::ProverGroup {
    type Type = configs::fri_prover_group::FriProverGroupConfig;
    fn read(&self) -> anyhow::Result<Self::Type> {
        Ok(Self::Type {
            group_0: read_vec(&self.group_0).context("group_0")?,
            group_1: read_vec(&self.group_1).context("group_1")?,
            group_2: read_vec(&self.group_2).context("group_2")?,
            group_3: read_vec(&self.group_3).context("group_3")?,
            group_4: read_vec(&self.group_4).context("group_4")?,
            group_5: read_vec(&self.group_5).context("group_5")?,
            group_6: read_vec(&self.group_6).context("group_6")?,
            group_7: read_vec(&self.group_7).context("group_7")?,
            group_8: read_vec(&self.group_8).context("group_8")?,
            group_9: read_vec(&self.group_9).context("group_9")?,
            group_10: read_vec(&self.group_10).context("group_10")?,
            group_11: read_vec(&self.group_11).context("group_11")?,
            group_12: read_vec(&self.group_12).context("group_12")?,
            group_13: read_vec(&self.group_13).context("group_13")?,
            group_14: read_vec(&self.group_14).context("group_14")?,
        })
    }

    fn build(this: &Self::Type) -> Self {
        Self {
            group_0: build_vec(&this.group_0),
            group_1: build_vec(&this.group_1),
            group_2: build_vec(&this.group_2),
            group_3: build_vec(&this.group_3),
            group_4: build_vec(&this.group_4),
            group_5: build_vec(&this.group_5),
            group_6: build_vec(&this.group_6),
            group_7: build_vec(&this.group_7),
            group_8: build_vec(&this.group_8),
            group_9: build_vec(&this.group_9),
            group_10: build_vec(&this.group_10),
            group_11: build_vec(&this.group_11),
            group_12: build_vec(&this.group_12),
            group_13: build_vec(&this.group_13),
            group_14: build_vec(&this.group_14),
        }
    }
}

impl ProtoRepr for proto::ProverGateway {
    type Type = configs::FriProverGatewayConfig;
    fn read(&self) -> anyhow::Result<Self::Type> {
        Ok(Self::Type {
            api_url: required(&self.api_url).context("api_url")?.clone(),
            api_poll_duration_secs: required(&self.api_poll_duration_secs)
                .and_then(|x| Ok((*x).try_into()?))
                .context("api_poll_duration_secs")?,
            prometheus_listener_port: required(&self.prometheus_listener_port)
                .and_then(|x| Ok((*x).try_into()?))
                .context("prometheus_listener_port")?,
            prometheus_pushgateway_url: required(&self.prometheus_pushgateway_url)
                .context("prometheus_pushgateway_url")?
                .clone(),
            prometheus_push_interval_ms: self.prometheus_push_interval_ms,
        })
    }

    fn build(this: &Self::Type) -> Self {
        Self {
            api_url: Some(this.api_url.clone()),
            api_poll_duration_secs: Some(this.api_poll_duration_secs.into()),
            prometheus_listener_port: Some(this.prometheus_listener_port.into()),
            prometheus_pushgateway_url: Some(this.prometheus_pushgateway_url.clone()),
            prometheus_push_interval_ms: this.prometheus_push_interval_ms,
        }
    }
}

impl ProtoRepr for proto::WitnessGenerator {
    type Type = configs::FriWitnessGeneratorConfig;
    fn read(&self) -> anyhow::Result<Self::Type> {
        Ok(Self::Type {
            generation_timeout_in_secs: required(&self.generation_timeout_in_secs)
                .and_then(|x| Ok((*x).try_into()?))
                .context("generation_timeout_in_secs")?,
            max_attempts: *required(&self.max_attempts).context("max_attempts")?,
            last_l1_batch_to_process: self.last_l1_batch_to_process,
            shall_save_to_public_bucket: *required(&self.shall_save_to_public_bucket)
                .context("shall_save_to_public_bucket")?,
            basic_generation_timeout_in_secs: self
                .basic_generation_timeout_in_secs
                .map(|x| x.try_into())
                .transpose()
                .context("basic_generation_timeout_in_secs")?,
            leaf_generation_timeout_in_secs: self
                .leaf_generation_timeout_in_secs
                .map(|x| x.try_into())
                .transpose()
                .context("leaf_generation_timeout_in_secs")?,
            node_generation_timeout_in_secs: self
                .node_generation_timeout_in_secs
                .map(|x| x.try_into())
                .transpose()
                .context("node_generation_timeout_in_secs")?,
            recursion_tip_generation_timeout_in_secs: self
                .recursion_tip_timeout_in_secs
                .map(|x| x.try_into())
                .transpose()
                .context("recursion_tip_generation_timeout_in_secs")?,
            scheduler_generation_timeout_in_secs: self
                .scheduler_generation_timeout_in_secs
                .map(|x| x.try_into())
                .transpose()
                .context("scheduler_generation_timeout_in_secs")?,
            prometheus_listener_port: self
                .prometheus_listener_port
                .map(|x| x.try_into())
                .transpose()
                .context("prometheus_listener_port")?,
        })
    }

    fn build(this: &Self::Type) -> Self {
        Self {
            generation_timeout_in_secs: Some(this.generation_timeout_in_secs.into()),
            max_attempts: Some(this.max_attempts),
            last_l1_batch_to_process: this.last_l1_batch_to_process,
            shall_save_to_public_bucket: Some(this.shall_save_to_public_bucket),
            basic_generation_timeout_in_secs: this
                .basic_generation_timeout_in_secs
                .map(|x| x.into()),
            leaf_generation_timeout_in_secs: this.leaf_generation_timeout_in_secs.map(|x| x.into()),
            node_generation_timeout_in_secs: this.node_generation_timeout_in_secs.map(|x| x.into()),
            recursion_tip_timeout_in_secs: this
                .recursion_tip_generation_timeout_in_secs
                .map(|x| x.into()),
            scheduler_generation_timeout_in_secs: this
                .scheduler_generation_timeout_in_secs
                .map(|x| x.into()),
            prometheus_listener_port: this.prometheus_listener_port.map(|x| x.into()),
        }
    }
}

impl ProtoRepr for proto::WitnessVectorGenerator {
    type Type = configs::FriWitnessVectorGeneratorConfig;
    fn read(&self) -> anyhow::Result<Self::Type> {
        Ok(Self::Type {
            max_prover_reservation_duration_in_secs: required(
                &self.max_prover_reservation_duration_in_secs,
            )
            .and_then(|x| Ok((*x).try_into()?))
            .context("max_prover_reservation_duration_in_secs")?,
            prover_instance_wait_timeout_in_secs: required(
                &self.prover_instance_wait_timeout_in_secs,
            )
            .and_then(|x| Ok((*x).try_into()?))
            .context("prover_instance_wait_timeout_in_secs")?,
            prover_instance_poll_time_in_milli_secs: required(
                &self.prover_instance_poll_time_in_milli_secs,
            )
            .and_then(|x| Ok((*x).try_into()?))
            .context("prover_instance_poll_time_in_milli_secs")?,
            prometheus_listener_port: required(&self.prometheus_listener_port)
                .and_then(|x| Ok((*x).try_into()?))
                .context("prometheus_listener_port")?,
            prometheus_pushgateway_url: required(&self.prometheus_pushgateway_url)
                .context("prometheus_pushgateway_url")?
                .clone(),
            prometheus_push_interval_ms: self.prometheus_push_interval_ms,
            specialized_group_id: required(&self.specialized_group_id)
                .and_then(|x| Ok((*x).try_into()?))
                .context("specialized_group_id")?,
        })
    }

    fn build(this: &Self::Type) -> Self {
        Self {
            max_prover_reservation_duration_in_secs: Some(
                this.max_prover_reservation_duration_in_secs.into(),
            ),
            prover_instance_wait_timeout_in_secs: Some(
                this.prover_instance_wait_timeout_in_secs.into(),
            ),
            prover_instance_poll_time_in_milli_secs: Some(
                this.prover_instance_poll_time_in_milli_secs.into(),
            ),
            prometheus_listener_port: Some(this.prometheus_listener_port.into()),
            prometheus_pushgateway_url: Some(this.prometheus_pushgateway_url.clone()),
            prometheus_push_interval_ms: this.prometheus_push_interval_ms,
            specialized_group_id: Some(this.specialized_group_id.into()),
        }
    }
}

impl proto::SetupLoadMode {
    fn new(x: &configs::fri_prover::SetupLoadMode) -> Self {
        use configs::fri_prover::SetupLoadMode as From;
        match x {
            From::FromDisk => Self::FromDisk,
            From::FromMemory => Self::FromMemory,
        }
    }

    fn parse(&self) -> configs::fri_prover::SetupLoadMode {
        use configs::fri_prover::SetupLoadMode as To;
        match self {
            Self::FromDisk => To::FromDisk,
            Self::FromMemory => To::FromMemory,
        }
    }
}

impl ProtoRepr for proto::Prover {
    type Type = configs::FriProverConfig;
    fn read(&self) -> anyhow::Result<Self::Type> {
        let public_object_store = if let Some(object_store) = &self.public_object_store {
            Some(object_store.read()?)
        } else {
            None
        };
        let prover_object_store = if let Some(object_store) = &self.prover_object_store {
            Some(object_store.read()?)
        } else {
            None
        };

        Ok(Self::Type {
            setup_data_path: required(&self.setup_data_path)
                .context("setup_data_path")?
                .clone(),
            prometheus_port: required(&self.prometheus_port)
                .and_then(|x| Ok((*x).try_into()?))
                .context("prometheus_port")?,
            max_attempts: *required(&self.max_attempts).context("max_attempts")?,
            generation_timeout_in_secs: required(&self.generation_timeout_in_secs)
                .and_then(|x| Ok((*x).try_into()?))
                .context("generation_timeout_in_secs")?,
            setup_load_mode: required(&self.setup_load_mode)
                .and_then(|x| Ok(proto::SetupLoadMode::try_from(*x)?))
                .context("setup_load_mode")?
                .parse(),
            specialized_group_id: required(&self.specialized_group_id)
                .and_then(|x| Ok((*x).try_into()?))
                .context("specialized_group_id")?,
            queue_capacity: required(&self.queue_capacity)
                .and_then(|x| Ok((*x).try_into()?))
                .context("queue_capacity")?,
            witness_vector_receiver_port: required(&self.witness_vector_receiver_port)
                .and_then(|x| Ok((*x).try_into()?))
                .context("witness_vector_receiver_port")?,
            zone_read_url: required(&self.zone_read_url)
                .context("zone_read_url")?
                .clone(),
            availability_check_interval_in_secs: self.availability_check_interval_in_secs,
            shall_save_to_public_bucket: *required(&self.shall_save_to_public_bucket)
                .context("shall_save_to_public_bucket")?,
            public_object_store,
            prover_object_store,
        })
    }

    fn build(this: &Self::Type) -> Self {
        Self {
            setup_data_path: Some(this.setup_data_path.clone()),
            prometheus_port: Some(this.prometheus_port.into()),
            max_attempts: Some(this.max_attempts),
            generation_timeout_in_secs: Some(this.generation_timeout_in_secs.into()),
            setup_load_mode: Some(proto::SetupLoadMode::new(&this.setup_load_mode).into()),
            specialized_group_id: Some(this.specialized_group_id.into()),
            queue_capacity: Some(this.queue_capacity.try_into().unwrap()),
            witness_vector_receiver_port: Some(this.witness_vector_receiver_port.into()),
            zone_read_url: Some(this.zone_read_url.clone()),
            availability_check_interval_in_secs: this.availability_check_interval_in_secs,
            shall_save_to_public_bucket: Some(this.shall_save_to_public_bucket),
            prover_object_store: this.prover_object_store.as_ref().map(ProtoRepr::build),
            public_object_store: this.public_object_store.as_ref().map(ProtoRepr::build),
        }
    }
}