Skip to content

Commit 0575785

Browse files
feat(eigen-cllient-extra-features): Address more comments (#386)
* use `H160` for `DEFAULT_EIGENDA_SVC_MANAGER_ADDRESS` * `parse` instead of `from_str` * replace val with shif operation * replace `.map_err` with `.context` * remove needless parentheses * use `div_ceil` * remove needles `Clone` derives * remove redundant `to_vec()` * use `anyhow::bail!` * remove needless `Option` and obscuring `anyhow::Result` * move verifier test to separate file * replace u64 constant with Duration * use `ethabi::encode()` * refactor `decode_bytes` * wrap `G1Affine` inside of `Box` / fix clippy * use `SensitiveUrl` for `eigenda_eth_rpc` * refactor `save_point` fn * remove retriable error wrapping * replace `PKSigningClient` for simpler L1 Client * remove chain id from `EigenConfig` * use temp dir for kzg points * refactor `VerifierClient` trait * remove `VerifierConfig` * fix eigen config not initializing correctly * fix/refactor mock tests * remove unwraps * address comments/suggestions * improve Error handling * create temp file inside closure * Remove unnecessary clone * address comments * address comments * change `path()` fn to return `&std::path::Path` * replace `Path(String)` for `Path(PathBuf)` --------- Co-authored-by: Gianbelinche <39842759+gianbelinche@users.noreply.github.com>
1 parent 9e1ebfa commit 0575785

File tree

14 files changed

+1532
-1454
lines changed

14 files changed

+1532
-1454
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

core/bin/zksync_server/src/node_builder.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -550,7 +550,7 @@ impl MainNodeBuilder {
550550

551551
(DAClientConfig::Eigen(mut config), DataAvailabilitySecrets::Eigen(secret)) => {
552552
if config.eigenda_eth_rpc.is_none() {
553-
config.eigenda_eth_rpc = Some(l1_secrets.l1_rpc_url.expose_str().to_string());
553+
config.eigenda_eth_rpc = Some(l1_secrets.l1_rpc_url);
554554
}
555555
self.node.add_layer(EigenWiringLayer::new(config, secret));
556556
}

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

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
use std::str::FromStr;
22

33
use serde::Deserialize;
4-
use zksync_basic_types::{secrets::PrivateKey, Address, H160};
4+
use zksync_basic_types::{secrets::PrivateKey, url::SensitiveUrl, Address, H160};
55

66
/// Default address of the EigenDA service manager contract deployed on Holesky.
7-
const DEFAULT_EIGENDA_SVC_MANAGER_ADDRESS: &str = "0xD4A7E1Bd8015057293f0D0A557088c286942e84b";
7+
const DEFAULT_EIGENDA_SVC_MANAGER_ADDRESS: H160 = H160([
8+
0xd4, 0xa7, 0xe1, 0xbd, 0x80, 0x15, 0x05, 0x72, 0x93, 0xf0, 0xd0, 0xa5, 0x57, 0x08, 0x8c, 0x28,
9+
0x69, 0x42, 0xe8, 0x4b,
10+
]);
811

912
/// Configuration for the EigenDA remote disperser client.
1013
#[derive(Clone, Debug, PartialEq, Deserialize)]
@@ -15,33 +18,33 @@ pub struct EigenConfig {
1518
/// a value less or equal to 0 means that the disperser will not wait for finalization
1619
pub settlement_layer_confirmation_depth: u32,
1720
/// URL of the Ethereum RPC server
18-
pub eigenda_eth_rpc: Option<String>,
21+
pub eigenda_eth_rpc: Option<SensitiveUrl>,
1922
/// Address of the service manager contract
2023
pub eigenda_svc_manager_address: Address,
2124
/// Wait for the blob to be finalized before returning the response
2225
pub wait_for_finalization: bool,
2326
/// Authenticated dispersal
2427
pub authenticated: bool,
28+
/// Optional path to downloaded points directory
29+
pub points_dir: Option<String>,
2530
/// Url to the file containing the G1 point used for KZG
2631
pub g1_url: String,
2732
/// Url to the file containing the G2 point used for KZG
2833
pub g2_url: String,
29-
/// Chain ID of the Ethereum network
30-
pub chain_id: u64,
3134
}
3235

3336
impl Default for EigenConfig {
3437
fn default() -> Self {
3538
Self {
3639
disperser_rpc: "https://disperser-holesky.eigenda.xyz:443".to_string(),
3740
settlement_layer_confirmation_depth: 0,
38-
eigenda_eth_rpc: Some("https://ethereum-holesky-rpc.publicnode.com".to_string()),
39-
eigenda_svc_manager_address: H160::from_str(DEFAULT_EIGENDA_SVC_MANAGER_ADDRESS).unwrap_or_default(),
41+
eigenda_eth_rpc: Some(SensitiveUrl::from_str("https://ethereum-holesky-rpc.publicnode.com").unwrap()), // Safe to unwrap, never fails
42+
eigenda_svc_manager_address: DEFAULT_EIGENDA_SVC_MANAGER_ADDRESS,
4043
wait_for_finalization: false,
4144
authenticated: false,
45+
points_dir: None,
4246
g1_url: "https://github.com/Layr-Labs/eigenda-proxy/raw/2fd70b99ef5bf137d7bbca3461cf9e1f2c899451/resources/g1.point".to_string(),
4347
g2_url: "https://github.com/Layr-Labs/eigenda-proxy/raw/2fd70b99ef5bf137d7bbca3461cf9e1f2c899451/resources/g2.point.powerOf2".to_string(),
44-
chain_id: 19000,
4548
}
4649
}
4750
}

core/lib/env_config/src/da_client.rs

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ impl FromEnv for DataAvailabilitySecrets {
9292
mod tests {
9393
use std::str::FromStr;
9494

95-
use zksync_basic_types::H160;
95+
use zksync_basic_types::url::SensitiveUrl;
9696
use zksync_config::{
9797
configs::{
9898
da_client::{
@@ -257,9 +257,9 @@ mod tests {
257257
DA_EIGENDA_SVC_MANAGER_ADDRESS="0x0000000000000000000000000000000000000123"
258258
DA_WAIT_FOR_FINALIZATION=true
259259
DA_AUTHENTICATED=false
260+
DA_POINTS_DIR="resources/"
260261
DA_G1_URL="resources1"
261262
DA_G2_URL="resources2"
262-
DA_CHAIN_ID=1
263263
"#;
264264
lock.set_env(config);
265265

@@ -269,16 +269,15 @@ mod tests {
269269
DAClientConfig::Eigen(EigenConfig {
270270
disperser_rpc: "http://localhost:8080".to_string(),
271271
settlement_layer_confirmation_depth: 0,
272-
eigenda_eth_rpc: Some("http://localhost:8545".to_string()),
273-
eigenda_svc_manager_address: H160::from_str(
274-
"0x0000000000000000000000000000000000000123"
275-
)
276-
.unwrap(),
272+
eigenda_eth_rpc: Some(SensitiveUrl::from_str("http://localhost:8545").unwrap()),
273+
eigenda_svc_manager_address: "0x0000000000000000000000000000000000000123"
274+
.parse()
275+
.unwrap(),
277276
wait_for_finalization: true,
278277
authenticated: false,
278+
points_dir: Some("resources/".to_string()),
279279
g1_url: "resources1".to_string(),
280280
g2_url: "resources2".to_string(),
281-
chain_id: 1
282281
})
283282
);
284283
}

core/lib/protobuf_config/src/da_client.rs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::str::FromStr;
2+
13
use anyhow::Context;
24
use zksync_config::configs::{
35
self,
@@ -9,6 +11,7 @@ use zksync_config::configs::{
911
},
1012
};
1113
use zksync_protobuf::{required, ProtoRepr};
14+
use zksync_types::url::SensitiveUrl;
1215

1316
use crate::{
1417
parse_h160,
@@ -66,16 +69,18 @@ impl ProtoRepr for proto::DataAvailabilityClient {
6669
&conf.settlement_layer_confirmation_depth,
6770
)
6871
.context("settlement_layer_confirmation_depth")?,
69-
eigenda_eth_rpc: required(&conf.eigenda_eth_rpc).ok().cloned(),
72+
eigenda_eth_rpc: Some(SensitiveUrl::from_str(
73+
required(&conf.eigenda_eth_rpc).context("eigenda_eth_rpc")?,
74+
)?),
7075
eigenda_svc_manager_address: required(&conf.eigenda_svc_manager_address)
7176
.and_then(|x| parse_h160(x))
7277
.context("eigenda_svc_manager_address")?,
7378
wait_for_finalization: *required(&conf.wait_for_finalization)
7479
.context("wait_for_finalization")?,
7580
authenticated: *required(&conf.authenticated).context("authenticated")?,
81+
points_dir: conf.points_dir.clone(),
7682
g1_url: required(&conf.g1_url).context("g1_url")?.clone(),
7783
g2_url: required(&conf.g2_url).context("g2_url")?.clone(),
78-
chain_id: *required(&conf.chain_id).context("chain_id")?,
7984
}),
8085
proto::data_availability_client::Config::ObjectStore(conf) => {
8186
ObjectStore(object_store_proto::ObjectStore::read(conf)?)
@@ -118,7 +123,10 @@ impl ProtoRepr for proto::DataAvailabilityClient {
118123
settlement_layer_confirmation_depth: Some(
119124
config.settlement_layer_confirmation_depth,
120125
),
121-
eigenda_eth_rpc: config.eigenda_eth_rpc.clone(),
126+
eigenda_eth_rpc: config
127+
.eigenda_eth_rpc
128+
.as_ref()
129+
.map(|a| a.expose_str().to_string()),
122130
eigenda_svc_manager_address: Some(format!(
123131
"{:?}",
124132
config.eigenda_svc_manager_address
@@ -127,7 +135,7 @@ impl ProtoRepr for proto::DataAvailabilityClient {
127135
authenticated: Some(config.authenticated),
128136
g1_url: Some(config.g1_url.clone()),
129137
g2_url: Some(config.g2_url.clone()),
130-
chain_id: Some(config.chain_id),
138+
points_dir: config.points_dir.as_ref().map(|a| a.to_string()),
131139
}),
132140
ObjectStore(config) => proto::data_availability_client::Config::ObjectStore(
133141
object_store_proto::ObjectStore::build(config),

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ message EigenConfig {
4545
optional bool authenticated = 8;
4646
optional string g1_url = 9;
4747
optional string g2_url = 10;
48-
optional uint64 chain_id = 11;
48+
optional string points_dir = 11;
4949
reserved 1,2;
5050
reserved "rpc_node_url","inclusion_polling_interval_ms";
5151
}

core/node/da_clients/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ zksync_web3_decl.workspace = true
6666
zksync_eth_client.workspace = true
6767
url.workspace = true
6868
thiserror.workspace = true
69+
tempfile.workspace = true
6970

7071
[dev-dependencies]
7172
serial_test.workspace = true

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

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -90,19 +90,13 @@ mod tests {
9090
use backon::{ConstantBuilder, Retryable};
9191
use serial_test::file_serial;
9292
use zksync_config::{configs::da_client::eigen::EigenSecrets, EigenConfig};
93-
use zksync_da_client::{
94-
types::{DAError, DispatchResponse},
95-
DataAvailabilityClient,
96-
};
93+
use zksync_da_client::{types::DispatchResponse, DataAvailabilityClient};
9794
use zksync_types::secrets::PrivateKey;
9895

9996
use crate::eigen::{blob_info::BlobInfo, EigenClient, GetBlobData};
10097

10198
impl EigenClient {
102-
async fn get_blob_data(
103-
&self,
104-
blob_id: BlobInfo,
105-
) -> anyhow::Result<Option<Vec<u8>>, DAError> {
99+
async fn get_blob_data(&self, blob_id: BlobInfo) -> anyhow::Result<Vec<u8>> {
106100
self.client.get_blob_data(blob_id).await
107101
}
108102

@@ -111,8 +105,8 @@ mod tests {
111105
}
112106
}
113107

114-
const STATUS_QUERY_TIMEOUT: u64 = 1800000; // 30 minutes
115-
const STATUS_QUERY_INTERVAL: u64 = 5; // 5 ms
108+
const STATUS_QUERY_INTERVAL: Duration = Duration::from_millis(5);
109+
const MAX_RETRY_ATTEMPTS: usize = 1800000; // With this value we retry for a duration of 30 minutes
116110

117111
async fn get_blob_info(
118112
client: &EigenClient,
@@ -127,8 +121,8 @@ mod tests {
127121
})
128122
.retry(
129123
&ConstantBuilder::default()
130-
.with_delay(Duration::from_millis(STATUS_QUERY_INTERVAL))
131-
.with_max_times((STATUS_QUERY_TIMEOUT / STATUS_QUERY_INTERVAL) as usize),
124+
.with_delay(STATUS_QUERY_INTERVAL)
125+
.with_max_times(MAX_RETRY_ATTEMPTS),
132126
)
133127
.when(|e| e.to_string().contains("Blob not found"))
134128
.await?;
@@ -177,7 +171,7 @@ mod tests {
177171
.data;
178172
assert_eq!(expected_inclusion_data, actual_inclusion_data);
179173
let retrieved_data = client.get_blob_data(blob_info).await.unwrap();
180-
assert_eq!(retrieved_data.unwrap(), data);
174+
assert_eq!(retrieved_data, data);
181175
}
182176

183177
#[ignore = "depends on external RPC"]
@@ -205,7 +199,7 @@ mod tests {
205199
.data;
206200
assert_eq!(expected_inclusion_data, actual_inclusion_data);
207201
let retrieved_data = client.get_blob_data(blob_info).await.unwrap();
208-
assert_eq!(retrieved_data.unwrap(), data);
202+
assert_eq!(retrieved_data, data);
209203
}
210204

211205
#[ignore = "depends on external RPC"]
@@ -235,7 +229,7 @@ mod tests {
235229
.data;
236230
assert_eq!(expected_inclusion_data, actual_inclusion_data);
237231
let retrieved_data = client.get_blob_data(blob_info).await.unwrap();
238-
assert_eq!(retrieved_data.unwrap(), data);
232+
assert_eq!(retrieved_data, data);
239233
}
240234

241235
#[ignore = "depends on external RPC"]
@@ -263,7 +257,7 @@ mod tests {
263257
.data;
264258
assert_eq!(expected_inclusion_data, actual_inclusion_data);
265259
let retrieved_data = client.get_blob_data(blob_info).await.unwrap();
266-
assert_eq!(retrieved_data.unwrap(), data);
260+
assert_eq!(retrieved_data, data);
267261
}
268262

269263
#[ignore = "depends on external RPC"]
@@ -292,6 +286,6 @@ mod tests {
292286
.data;
293287
assert_eq!(expected_inclusion_data, actual_inclusion_data);
294288
let retrieved_data = client.get_blob_data(blob_info).await.unwrap();
295-
assert_eq!(retrieved_data.unwrap(), data);
289+
assert_eq!(retrieved_data, data);
296290
}
297291
}
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
use ark_bn254::G1Affine;
2+
use tonic::{transport::Error as TonicError, Status};
3+
use zksync_eth_client::EnrichedClientError;
4+
5+
use super::blob_info::BlobQuorumParam;
6+
7+
/// Errors returned by this crate
8+
#[derive(Debug, thiserror::Error)]
9+
pub enum EigenClientError {
10+
#[error(transparent)]
11+
EthClient(#[from] EthClientError),
12+
#[error(transparent)]
13+
Verification(#[from] VerificationError),
14+
#[error(transparent)]
15+
Communication(#[from] CommunicationError),
16+
#[error(transparent)]
17+
BlobStatus(#[from] BlobStatusError),
18+
#[error(transparent)]
19+
Conversion(#[from] ConversionError),
20+
#[error(transparent)]
21+
Config(#[from] ConfigError),
22+
}
23+
24+
#[derive(Debug, thiserror::Error)]
25+
pub enum ConfigError {
26+
#[error(transparent)]
27+
Secp(#[from] secp256k1::Error),
28+
#[error(transparent)]
29+
Tonic(#[from] TonicError),
30+
}
31+
32+
#[derive(Debug, thiserror::Error)]
33+
pub enum CommunicationError {
34+
#[error(transparent)]
35+
Secp(#[from] secp256k1::Error),
36+
#[error(transparent)]
37+
Hex(#[from] hex::FromHexError),
38+
#[error(transparent)]
39+
GetBlobData(#[from] Box<dyn std::error::Error + Send + Sync>),
40+
}
41+
42+
#[derive(Debug, thiserror::Error)]
43+
pub enum BlobStatusError {
44+
#[error(transparent)]
45+
Prost(#[from] prost::DecodeError),
46+
#[error(transparent)]
47+
Status(#[from] Status),
48+
}
49+
50+
/// Errors specific to conversion
51+
#[derive(Debug, thiserror::Error)]
52+
pub enum ConversionError {}
53+
54+
/// Errors for the EthClient
55+
#[derive(Debug, thiserror::Error)]
56+
pub enum EthClientError {
57+
#[error(transparent)]
58+
HTTPClient(#[from] reqwest::Error),
59+
#[error(transparent)]
60+
SerdeJSON(#[from] serde_json::Error),
61+
#[error("RPC: {0}")]
62+
Rpc(String),
63+
}
64+
65+
#[derive(Debug, thiserror::Error)]
66+
pub enum KzgError {
67+
#[error("Kzg setup error: {0}")]
68+
Setup(String),
69+
#[error(transparent)]
70+
Internal(#[from] rust_kzg_bn254::errors::KzgError),
71+
}
72+
73+
#[derive(Debug, thiserror::Error)]
74+
pub enum ServiceManagerError {
75+
#[error(transparent)]
76+
EnrichedClient(#[from] EnrichedClientError),
77+
#[error("Decoding error: {0}")]
78+
Decoding(String),
79+
}
80+
81+
/// Errors for the Verifier
82+
#[derive(Debug, thiserror::Error)]
83+
pub enum VerificationError {
84+
#[error(transparent)]
85+
ServiceManager(#[from] ServiceManagerError),
86+
#[error(transparent)]
87+
Kzg(#[from] KzgError),
88+
#[error("Wrong proof")]
89+
WrongProof,
90+
#[error("Different commitments: expected {expected:?}, got {actual:?}")]
91+
DifferentCommitments {
92+
expected: Box<G1Affine>,
93+
actual: Box<G1Affine>,
94+
},
95+
#[error("Different roots: expected {expected:?}, got {actual:?}")]
96+
DifferentRoots { expected: String, actual: String },
97+
#[error("Empty hashes")]
98+
EmptyHash,
99+
#[error("Different hashes: expected {expected:?}, got {actual:?}")]
100+
DifferentHashes { expected: String, actual: String },
101+
#[error("Wrong quorum params: {blob_quorum_params:?}")]
102+
WrongQuorumParams { blob_quorum_params: BlobQuorumParam },
103+
#[error("Quorum not confirmed")]
104+
QuorumNotConfirmed,
105+
#[error("Commitment not on curve: {0}")]
106+
CommitmentNotOnCurve(G1Affine),
107+
#[error("Commitment not on correct subgroup: {0}")]
108+
CommitmentNotOnCorrectSubgroup(G1Affine),
109+
#[error("Point download error: {0}")]
110+
PointDownloadError(String),
111+
}

core/node/da_clients/src/eigen/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
mod blob_info;
22
mod client;
3+
mod errors;
34
mod sdk;
45
mod verifier;
56

0 commit comments

Comments
 (0)