Skip to content

Commit

Permalink
feat(da-clients): add secrets (#2954)
Browse files Browse the repository at this point in the history
## What ❔

Add an opportunity to store the sensitive information of DA clients in
the secrets.

## Why ❔

Some sensitive info is currently stored as plaintext, which is not
secure, we should use secrets for those values

## 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`.

---------

Co-authored-by: Danil <[email protected]>
  • Loading branch information
dimazhornyk and Deniallugo authored Sep 27, 2024
1 parent 7ad0425 commit f4631e4
Show file tree
Hide file tree
Showing 21 changed files with 225 additions and 76 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions core/bin/zksync_server/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use zksync_config::{
},
fri_prover_group::FriProverGroupConfig,
house_keeper::HouseKeeperConfig,
secrets::DataAvailabilitySecrets,
BasicWitnessInputProducerConfig, ContractsConfig, DatabaseSecrets, ExperimentalVmConfig,
ExternalPriceApiClientConfig, FriProofCompressorConfig, FriProverConfig,
FriProverGatewayConfig, FriWitnessGeneratorConfig, FriWitnessVectorGeneratorConfig,
Expand Down Expand Up @@ -116,6 +117,7 @@ fn main() -> anyhow::Result<()> {
consensus: config::read_consensus_secrets().context("read_consensus_secrets()")?,
database: DatabaseSecrets::from_env().ok(),
l1: L1Secrets::from_env().ok(),
data_availability: DataAvailabilitySecrets::from_env().ok(),
},
};

Expand Down
15 changes: 9 additions & 6 deletions core/bin/zksync_server/src/node_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
use anyhow::Context;
use zksync_config::{
configs::{
da_client::DAClient, eth_sender::PubdataSendingMode, wallets::Wallets, GeneralConfig,
Secrets,
da_client::DAClientConfig, eth_sender::PubdataSendingMode,
secrets::DataAvailabilitySecrets, wallets::Wallets, GeneralConfig, Secrets,
},
ContractsConfig, GenesisConfig,
};
Expand Down Expand Up @@ -509,11 +509,14 @@ impl MainNodeBuilder {
return Ok(self);
};

match da_client_config.client {
DAClient::Avail(config) => {
self.node.add_layer(AvailWiringLayer::new(config));
let secrets = try_load_config!(self.secrets.data_availability);

match (da_client_config, secrets) {
(DAClientConfig::Avail(config), DataAvailabilitySecrets::Avail(secret)) => {
self.node.add_layer(AvailWiringLayer::new(config, secret));
}
DAClient::ObjectStore(config) => {

(DAClientConfig::ObjectStore(config), _) => {
self.node
.add_layer(ObjectStorageClientWiringLayer::new(config));
}
Expand Down
1 change: 1 addition & 0 deletions core/lib/basic_types/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ num_enum.workspace = true
anyhow.workspace = true
url = { workspace = true, features = ["serde"] }
serde_with.workspace = true
secrecy.workspace = true

[dev-dependencies]
bincode.workspace = true
1 change: 1 addition & 0 deletions core/lib/basic_types/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ pub mod commitment;
pub mod network;
pub mod protocol_version;
pub mod prover_dal;
pub mod seed_phrase;
pub mod settlement;
pub mod tee_types;
pub mod url;
Expand Down
20 changes: 20 additions & 0 deletions core/lib/basic_types/src/seed_phrase.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
use std::str::FromStr;

use secrecy::{ExposeSecret, Secret};

#[derive(Debug, Clone)]
pub struct SeedPhrase(pub Secret<String>);

impl PartialEq for SeedPhrase {
fn eq(&self, other: &Self) -> bool {
self.0.expose_secret().eq(other.0.expose_secret())
}
}

impl FromStr for SeedPhrase {
type Err = anyhow::Error;

fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(SeedPhrase(s.parse()?))
}
}
7 changes: 6 additions & 1 deletion core/lib/config/src/configs/da_client/avail.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
use serde::Deserialize;
use zksync_basic_types::seed_phrase::SeedPhrase;

#[derive(Clone, Debug, PartialEq, Deserialize)]
pub struct AvailConfig {
pub api_node_url: String,
pub bridge_api_url: String,
pub seed: String,
pub app_id: u32,
pub timeout: usize,
pub max_retries: usize,
}

#[derive(Clone, Debug, PartialEq)]
pub struct AvailSecrets {
pub seed_phrase: Option<SeedPhrase>,
}
10 changes: 1 addition & 9 deletions core/lib/config/src/configs/da_client/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
use serde::Deserialize;

use crate::{AvailConfig, ObjectStoreConfig};

pub mod avail;
Expand All @@ -8,13 +6,7 @@ pub const AVAIL_CLIENT_CONFIG_NAME: &str = "Avail";
pub const OBJECT_STORE_CLIENT_CONFIG_NAME: &str = "ObjectStore";

#[derive(Debug, Clone, PartialEq)]
pub struct DAClientConfig {
pub client: DAClient,
}

#[derive(Debug, Clone, PartialEq, Deserialize)]
#[serde(tag = "client")]
pub enum DAClient {
pub enum DAClientConfig {
Avail(AvailConfig),
ObjectStore(ObjectStoreConfig),
}
8 changes: 7 additions & 1 deletion core/lib/config/src/configs/secrets.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use anyhow::Context;
use zksync_basic_types::url::SensitiveUrl;

use crate::configs::consensus::ConsensusSecrets;
use crate::configs::{consensus::ConsensusSecrets, da_client::avail::AvailSecrets};

#[derive(Debug, Clone, PartialEq)]
pub struct DatabaseSecrets {
Expand All @@ -15,11 +15,17 @@ pub struct L1Secrets {
pub l1_rpc_url: SensitiveUrl,
}

#[derive(Debug, Clone, PartialEq)]
pub enum DataAvailabilitySecrets {
Avail(AvailSecrets),
}

#[derive(Debug, Clone, PartialEq)]
pub struct Secrets {
pub consensus: Option<ConsensusSecrets>,
pub database: Option<DatabaseSecrets>,
pub l1: Option<L1Secrets>,
pub data_availability: Option<DataAvailabilitySecrets>,
}

impl DatabaseSecrets {
Expand Down
30 changes: 19 additions & 11 deletions core/lib/config/src/testonly.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
use std::num::NonZeroUsize;

use rand::{distributions::Distribution, Rng};
use secrecy::Secret;
use zksync_basic_types::{
basic_fri_types::CircuitIdRoundTuple,
commitment::L1BatchCommitmentMode,
network::Network,
protocol_version::{ProtocolSemanticVersion, ProtocolVersionId, VersionPatch},
seed_phrase::SeedPhrase,
vm::FastVmMode,
L1BatchNumber, L1ChainId, L2ChainId,
};
Expand All @@ -14,7 +16,7 @@ use zksync_crypto_primitives::K256PrivateKey;

use crate::{
configs::{
self, da_client::DAClient::Avail, eth_sender::PubdataSendingMode,
self, da_client::DAClientConfig::Avail, eth_sender::PubdataSendingMode,
external_price_api_client::ForcedPriceClientConfig,
},
AvailConfig,
Expand Down Expand Up @@ -863,6 +865,7 @@ impl Distribution<configs::secrets::Secrets> for EncodeDist {
consensus: self.sample_opt(|| self.sample(rng)),
database: self.sample_opt(|| self.sample(rng)),
l1: self.sample_opt(|| self.sample(rng)),
data_availability: self.sample_opt(|| self.sample(rng)),
}
}
}
Expand Down Expand Up @@ -934,16 +937,21 @@ impl Distribution<configs::en_config::ENConfig> for EncodeDist {

impl Distribution<configs::da_client::DAClientConfig> for EncodeDist {
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> configs::da_client::DAClientConfig {
configs::da_client::DAClientConfig {
client: Avail(AvailConfig {
api_node_url: self.sample(rng),
bridge_api_url: self.sample(rng),
seed: self.sample(rng),
app_id: self.sample(rng),
timeout: self.sample(rng),
max_retries: self.sample(rng),
}),
}
Avail(AvailConfig {
api_node_url: self.sample(rng),
bridge_api_url: self.sample(rng),
app_id: self.sample(rng),
timeout: self.sample(rng),
max_retries: self.sample(rng),
})
}
}

impl Distribution<configs::secrets::DataAvailabilitySecrets> for EncodeDist {
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> configs::secrets::DataAvailabilitySecrets {
configs::secrets::DataAvailabilitySecrets::Avail(configs::da_client::avail::AvailSecrets {
seed_phrase: Some(SeedPhrase(Secret::new(self.sample(rng)))),
})
}
}

Expand Down
98 changes: 68 additions & 30 deletions core/lib/env_config/src/da_client.rs
Original file line number Diff line number Diff line change
@@ -1,32 +1,56 @@
use zksync_config::configs::da_client::{
DAClient, DAClientConfig, AVAIL_CLIENT_CONFIG_NAME, OBJECT_STORE_CLIENT_CONFIG_NAME,
use std::env;

use zksync_config::configs::{
da_client::{
avail::AvailSecrets, DAClientConfig, AVAIL_CLIENT_CONFIG_NAME,
OBJECT_STORE_CLIENT_CONFIG_NAME,
},
secrets::DataAvailabilitySecrets,
};

use crate::{envy_load, FromEnv};

impl FromEnv for DAClientConfig {
fn from_env() -> anyhow::Result<Self> {
let client_tag = std::env::var("DA_CLIENT")?;
let client = match client_tag.as_str() {
AVAIL_CLIENT_CONFIG_NAME => DAClient::Avail(envy_load("da_avail_config", "DA_")?),
let config = match client_tag.as_str() {
AVAIL_CLIENT_CONFIG_NAME => Self::Avail(envy_load("da_avail_config", "DA_")?),
OBJECT_STORE_CLIENT_CONFIG_NAME => {
DAClient::ObjectStore(envy_load("da_object_store", "DA_")?)
Self::ObjectStore(envy_load("da_object_store", "DA_")?)
}
_ => anyhow::bail!("Unknown DA client name: {}", client_tag),
};

Ok(config)
}
}

impl FromEnv for DataAvailabilitySecrets {
fn from_env() -> anyhow::Result<Self> {
let client_tag = std::env::var("DA_CLIENT")?;
let secrets = match client_tag.as_str() {
AVAIL_CLIENT_CONFIG_NAME => {
let seed_phrase = env::var("DA_SECRETS_SEED_PHRASE")
.ok()
.map(|s| s.parse())
.transpose()?;
Self::Avail(AvailSecrets { seed_phrase })
}
_ => anyhow::bail!("Unknown DA client name: {}", client_tag),
};

Ok(Self { client })
Ok(secrets)
}
}

#[cfg(test)]
mod tests {
use zksync_config::{
configs::{
da_client::{DAClient, DAClient::ObjectStore},
da_client::{DAClientConfig, DAClientConfig::ObjectStore},
object_store::ObjectStoreMode::GCS,
},
AvailConfig, DAClientConfig, ObjectStoreConfig,
AvailConfig, ObjectStoreConfig,
};

use super::*;
Expand All @@ -35,15 +59,13 @@ mod tests {
static MUTEX: EnvMutex = EnvMutex::new();

fn expected_object_store_da_client_config(url: String, max_retries: u16) -> DAClientConfig {
DAClientConfig {
client: ObjectStore(ObjectStoreConfig {
mode: GCS {
bucket_base_url: url,
},
max_retries,
local_mirror_path: None,
}),
}
ObjectStore(ObjectStoreConfig {
mode: GCS {
bucket_base_url: url,
},
max_retries,
local_mirror_path: None,
})
}

#[test]
Expand All @@ -67,21 +89,17 @@ mod tests {
fn expected_avail_da_layer_config(
api_node_url: &str,
bridge_api_url: &str,
seed: &str,
app_id: u32,
timeout: usize,
max_retries: usize,
) -> DAClientConfig {
DAClientConfig {
client: DAClient::Avail(AvailConfig {
api_node_url: api_node_url.to_string(),
bridge_api_url: bridge_api_url.to_string(),
seed: seed.to_string(),
app_id,
timeout,
max_retries,
}),
}
DAClientConfig::Avail(AvailConfig {
api_node_url: api_node_url.to_string(),
bridge_api_url: bridge_api_url.to_string(),
app_id,
timeout,
max_retries,
})
}

#[test]
Expand All @@ -91,7 +109,6 @@ mod tests {
DA_CLIENT="Avail"
DA_API_NODE_URL="localhost:12345"
DA_BRIDGE_API_URL="localhost:54321"
DA_SEED="bottom drive obey lake curtain smoke basket hold race lonely fit walk"
DA_APP_ID="1"
DA_TIMEOUT="2"
DA_MAX_RETRIES="3"
Expand All @@ -105,11 +122,32 @@ mod tests {
expected_avail_da_layer_config(
"localhost:12345",
"localhost:54321",
"bottom drive obey lake curtain smoke basket hold race lonely fit walk",
"1".parse::<u32>().unwrap(),
"2".parse::<usize>().unwrap(),
"3".parse::<usize>().unwrap(),
)
);
}

#[test]
fn from_env_avail_secrets() {
let mut lock = MUTEX.lock();
let config = r#"
DA_CLIENT="Avail"
DA_SECRETS_SEED_PHRASE="bottom drive obey lake curtain smoke basket hold race lonely fit walk"
"#;

lock.set_env(config);

let actual = match DataAvailabilitySecrets::from_env().unwrap() {
DataAvailabilitySecrets::Avail(avail) => avail.seed_phrase,
};

assert_eq!(
actual.unwrap(),
"bottom drive obey lake curtain smoke basket hold race lonely fit walk"
.parse()
.unwrap()
);
}
}
Loading

0 comments on commit f4631e4

Please sign in to comment.