Skip to content

Commit 591cd86

Browse files
authored
feat: da_dispatcher refactoring (#3409)
## What ❔ - Don't assume NoDA Validium by default, make the config required even for no DA, that helps avoid misconfiguration issues - Separate threads in da_dispatcer for `dispatch` and `poll_for_inclusion` - Change the default amount of rows that are fetched for dispatching ## Why ❔ To make configuration more resilient and main logic more efficient. ## 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 `zkstack dev fmt` and `zkstack dev lint`.
1 parent 1000f61 commit 591cd86

File tree

12 files changed

+132
-47
lines changed

12 files changed

+132
-47
lines changed

core/bin/zksync_server/src/node_builder.rs

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -121,21 +121,21 @@ impl MainNodeBuilder {
121121
self.node.runtime_handle()
122122
}
123123

124-
pub fn get_pubdata_type(&self) -> PubdataType {
124+
pub fn get_pubdata_type(&self) -> anyhow::Result<PubdataType> {
125125
if self.genesis_config.l1_batch_commit_data_generator_mode == L1BatchCommitmentMode::Rollup
126126
{
127-
return PubdataType::Rollup;
127+
return Ok(PubdataType::Rollup);
128128
}
129129

130-
let Some(da_client_config) = self.configs.da_client_config.clone() else {
131-
return PubdataType::NoDA;
132-
};
133-
134-
match da_client_config {
135-
DAClientConfig::Avail(_) => PubdataType::Avail,
136-
DAClientConfig::Celestia(_) => PubdataType::Celestia,
137-
DAClientConfig::Eigen(_) => PubdataType::Eigen,
138-
DAClientConfig::ObjectStore(_) => PubdataType::ObjectStore,
130+
match self.configs.da_client_config.clone() {
131+
None => Err(anyhow::anyhow!("No config for DA client")),
132+
Some(da_client_config) => Ok(match da_client_config {
133+
DAClientConfig::Avail(_) => PubdataType::Avail,
134+
DAClientConfig::Celestia(_) => PubdataType::Celestia,
135+
DAClientConfig::Eigen(_) => PubdataType::Eigen,
136+
DAClientConfig::ObjectStore(_) => PubdataType::ObjectStore,
137+
DAClientConfig::NoDA => PubdataType::NoDA,
138+
}),
139139
}
140140
}
141141

@@ -273,7 +273,7 @@ impl MainNodeBuilder {
273273
try_load_config!(self.configs.mempool_config),
274274
try_load_config!(wallets.state_keeper),
275275
self.contracts_config.l2_da_validator_addr,
276-
self.get_pubdata_type(),
276+
self.get_pubdata_type()?,
277277
);
278278
let db_config = try_load_config!(self.configs.db_config);
279279
let experimental_vm_config = self
@@ -551,11 +551,22 @@ impl MainNodeBuilder {
551551
}
552552

553553
fn add_da_client_layer(mut self) -> anyhow::Result<Self> {
554+
let eth_sender_config = try_load_config!(self.configs.eth);
555+
if let Some(sender_config) = eth_sender_config.sender {
556+
if sender_config.pubdata_sending_mode != PubdataSendingMode::Custom {
557+
tracing::warn!("DA dispatcher is enabled, but the pubdata sending mode is not `Custom`. DA client will not be started.");
558+
return Ok(self);
559+
}
560+
}
561+
554562
let Some(da_client_config) = self.configs.da_client_config.clone() else {
555-
tracing::warn!("No config for DA client, using the NoDA client");
563+
bail!("No config for DA client");
564+
};
565+
566+
if let DAClientConfig::NoDA = da_client_config {
556567
self.node.add_layer(NoDAClientWiringLayer);
557568
return Ok(self);
558-
};
569+
}
559570

560571
let secrets = try_load_config!(self.secrets.data_availability);
561572
match (da_client_config, secrets) {

core/lib/config/src/configs/da_client/avail.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ use zksync_basic_types::secrets::{APIKey, SeedPhrase};
44
pub const AVAIL_GAS_RELAY_CLIENT_NAME: &str = "GasRelay";
55
pub const AVAIL_FULL_CLIENT_NAME: &str = "FullClient";
66

7+
pub const IN_BLOCK_FINALITY_STATE: &str = "inBlock";
8+
pub const FINALIZED_FINALITY_STATE: &str = "finalized";
9+
710
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
811
#[serde(tag = "avail_client")]
912
pub enum AvailClientConfig {
@@ -23,6 +26,7 @@ pub struct AvailConfig {
2326
pub struct AvailDefaultConfig {
2427
pub api_node_url: String,
2528
pub app_id: u32,
29+
pub finality_state: Option<String>,
2630
}
2731

2832
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
@@ -36,3 +40,20 @@ pub struct AvailSecrets {
3640
pub seed_phrase: Option<SeedPhrase>,
3741
pub gas_relay_api_key: Option<APIKey>,
3842
}
43+
44+
impl AvailDefaultConfig {
45+
pub fn finality_state(&self) -> anyhow::Result<String> {
46+
match self.finality_state.clone() {
47+
Some(finality_state) => match finality_state.as_str() {
48+
IN_BLOCK_FINALITY_STATE | FINALIZED_FINALITY_STATE => Ok(finality_state),
49+
_ => Err(anyhow::anyhow!(
50+
"Invalid finality state: {}. Supported values are: {}, {}",
51+
finality_state,
52+
IN_BLOCK_FINALITY_STATE,
53+
FINALIZED_FINALITY_STATE
54+
)),
55+
},
56+
None => Ok(IN_BLOCK_FINALITY_STATE.to_string()),
57+
}
58+
}
59+
}

core/lib/config/src/configs/da_client/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,15 @@ pub const AVAIL_CLIENT_CONFIG_NAME: &str = "Avail";
88
pub const CELESTIA_CLIENT_CONFIG_NAME: &str = "Celestia";
99
pub const EIGEN_CLIENT_CONFIG_NAME: &str = "Eigen";
1010
pub const OBJECT_STORE_CLIENT_CONFIG_NAME: &str = "ObjectStore";
11+
pub const NO_DA_CLIENT_CONFIG_NAME: &str = "NoDA";
1112

1213
#[derive(Debug, Clone, PartialEq)]
1314
pub enum DAClientConfig {
1415
Avail(AvailConfig),
1516
Celestia(CelestiaConfig),
1617
Eigen(EigenConfig),
1718
ObjectStore(ObjectStoreConfig),
19+
NoDA,
1820
}
1921

2022
impl From<AvailConfig> for DAClientConfig {

core/lib/config/src/configs/da_dispatcher.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,14 @@ use std::time::Duration;
22

33
use serde::Deserialize;
44

5+
/// The default interval between the `da_dispatcher's` iterations.
56
pub const DEFAULT_POLLING_INTERVAL_MS: u32 = 5000;
6-
pub const DEFAULT_MAX_ROWS_TO_DISPATCH: u32 = 100;
7+
/// The maximum number of rows to fetch from the database in a single query. The value has to be
8+
/// not too high to avoid the dispatcher iteration taking too much time.
9+
pub const DEFAULT_MAX_ROWS_TO_DISPATCH: u32 = 3;
10+
/// The maximum number of retries for the dispatch of a blob.
711
pub const DEFAULT_MAX_RETRIES: u16 = 5;
12+
/// Use dummy value as inclusion proof instead of getting it from the client.
813
pub const DEFAULT_USE_DUMMY_INCLUSION_DATA: bool = false;
914

1015
#[derive(Debug, Clone, PartialEq, Deserialize)]

core/lib/config/src/testonly.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -959,6 +959,7 @@ impl Distribution<configs::da_client::DAClientConfig> for EncodeDist {
959959
config: AvailClientConfig::FullClient(AvailDefaultConfig {
960960
api_node_url: self.sample(rng),
961961
app_id: self.sample(rng),
962+
finality_state: None,
962963
}),
963964
})
964965
}

core/lib/env_config/src/da_client.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ mod tests {
146146
config: AvailClientConfig::FullClient(AvailDefaultConfig {
147147
api_node_url: api_node_url.to_string(),
148148
app_id,
149+
finality_state: None,
149150
}),
150151
})
151152
}

core/lib/protobuf_config/src/da_client.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use zksync_config::configs::{
55
avail::{AvailClientConfig, AvailConfig, AvailDefaultConfig, AvailGasRelayConfig},
66
celestia::CelestiaConfig,
77
eigen::EigenConfig,
8-
DAClientConfig::{Avail, Celestia, Eigen, ObjectStore},
8+
DAClientConfig::{Avail, Celestia, Eigen, NoDA, ObjectStore},
99
},
1010
};
1111
use zksync_protobuf::{required, ProtoRepr};
@@ -16,8 +16,7 @@ impl ProtoRepr for proto::DataAvailabilityClient {
1616
type Type = configs::DAClientConfig;
1717

1818
fn read(&self) -> anyhow::Result<Self::Type> {
19-
let config = required(&self.config).context("config")?;
20-
19+
let config = required(&self.config).context("da_client config")?;
2120
let client = match config {
2221
proto::data_availability_client::Config::Avail(conf) => Avail(AvailConfig {
2322
bridge_api_url: required(&conf.bridge_api_url)
@@ -31,6 +30,7 @@ impl ProtoRepr for proto::DataAvailabilityClient {
3130
.context("api_node_url")?
3231
.clone(),
3332
app_id: *required(&full_client_conf.app_id).context("app_id")?,
33+
finality_state: full_client_conf.finality_state.clone(),
3434
})
3535
}
3636
Some(proto::avail_config::Config::GasRelay(gas_relay_conf)) => {
@@ -62,6 +62,7 @@ impl ProtoRepr for proto::DataAvailabilityClient {
6262
proto::data_availability_client::Config::ObjectStore(conf) => {
6363
ObjectStore(object_store_proto::ObjectStore::read(conf)?)
6464
}
65+
proto::data_availability_client::Config::NoDa(_) => NoDA,
6566
};
6667

6768
Ok(client)
@@ -77,6 +78,7 @@ impl ProtoRepr for proto::DataAvailabilityClient {
7778
proto::avail_config::Config::FullClient(proto::AvailClientConfig {
7879
api_node_url: Some(conf.api_node_url.clone()),
7980
app_id: Some(conf.app_id),
81+
finality_state: conf.finality_state.clone(),
8082
}),
8183
),
8284
AvailClientConfig::GasRelay(conf) => Some(
@@ -102,6 +104,7 @@ impl ProtoRepr for proto::DataAvailabilityClient {
102104
ObjectStore(config) => proto::data_availability_client::Config::ObjectStore(
103105
object_store_proto::ObjectStore::build(config),
104106
),
107+
NoDA => proto::data_availability_client::Config::NoDa(proto::NoDaConfig {}),
105108
};
106109

107110
Self {

core/lib/protobuf_config/src/proto/config/da_client.proto

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ message AvailConfig {
2222
message AvailClientConfig {
2323
optional string api_node_url = 1;
2424
optional uint32 app_id = 2;
25+
optional string finality_state = 3;
2526
}
2627

2728
message AvailGasRelayConfig {
@@ -41,12 +42,15 @@ message EigenConfig {
4142
optional uint64 inclusion_polling_interval_ms = 2;
4243
}
4344

45+
message NoDAConfig {}
46+
4447
message DataAvailabilityClient {
4548
// oneof in protobuf allows for None
4649
oneof config {
4750
AvailConfig avail = 1;
4851
object_store.ObjectStore object_store = 2;
4952
CelestiaConfig celestia = 3;
5053
EigenConfig eigen = 4;
54+
NoDAConfig no_da = 5;
5155
}
5256
}

core/node/da_clients/src/avail/client.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,8 +121,12 @@ impl AvailClient {
121121
.seed_phrase
122122
.ok_or_else(|| anyhow::anyhow!("Seed phrase is missing"))?;
123123
// these unwraps are safe because we validate in protobuf config
124-
let sdk_client =
125-
RawAvailClient::new(conf.app_id, seed_phrase.0.expose_secret()).await?;
124+
let sdk_client = RawAvailClient::new(
125+
conf.app_id,
126+
seed_phrase.0.expose_secret(),
127+
conf.finality_state()?,
128+
)
129+
.await?;
126130

127131
Ok(Self {
128132
config,

core/node/da_clients/src/avail/sdk.rs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ const PROTOCOL_VERSION: u8 = 4;
2727
pub(crate) struct RawAvailClient {
2828
app_id: u32,
2929
keypair: Keypair,
30+
finality_state: String,
3031
}
3132

3233
/// Utility type needed for encoding the call data
@@ -44,11 +45,19 @@ struct BoundedVec<_0>(pub Vec<_0>);
4445
impl RawAvailClient {
4546
pub(crate) const MAX_BLOB_SIZE: usize = 512 * 1024; // 512kb
4647

47-
pub(crate) async fn new(app_id: u32, seed: &str) -> anyhow::Result<Self> {
48+
pub(crate) async fn new(
49+
app_id: u32,
50+
seed: &str,
51+
finality_state: String,
52+
) -> anyhow::Result<Self> {
4853
let mnemonic = Mnemonic::parse(seed)?;
4954
let keypair = Keypair::from_phrase(&mnemonic, None)?;
5055

51-
Ok(Self { app_id, keypair })
56+
Ok(Self {
57+
app_id,
58+
keypair,
59+
finality_state,
60+
})
5261
}
5362

5463
/// Returns a hex-encoded extrinsic
@@ -291,7 +300,7 @@ impl RawAvailClient {
291300
let status = sub.next().await.transpose()?;
292301

293302
if status.is_some() && status.as_ref().unwrap().is_object() {
294-
if let Some(block_hash) = status.unwrap().get("finalized") {
303+
if let Some(block_hash) = status.unwrap().get(self.finality_state.as_str()) {
295304
break block_hash
296305
.as_str()
297306
.ok_or_else(|| anyhow::anyhow!("Invalid block hash"))?

0 commit comments

Comments
 (0)