Skip to content

Commit

Permalink
update: build_da_client impl with basic builder
Browse files Browse the repository at this point in the history
  • Loading branch information
heemankv committed Jul 20, 2024
1 parent 7eacba4 commit 21de5fb
Show file tree
Hide file tree
Showing 6 changed files with 86 additions and 55 deletions.
27 changes: 13 additions & 14 deletions crates/da-clients/celestia/src/config.rs
Original file line number Diff line number Diff line change
@@ -1,32 +1,31 @@
use da_client_interface::DaConfig;
use std::fs::File;
use std::path::PathBuf;
use utils::env_utils::get_env_var_or_panic;
use async_trait::async_trait;
use serde::Deserialize;
use dotenv::dotenv;
use celestia_rpc::Client;
use utils::env_utils::{get_env_car_optional_or_panic, get_env_var_or_panic};

#[derive(Clone, PartialEq, Deserialize, Debug)]
pub struct CelestiaDaConfig {
pub http_provider: String,
pub auth_token: Option<String>,
pub nid: String,
}

impl TryFrom<&PathBuf> for CelestiaDaConfig {
type Error = String;

fn try_from(path: &PathBuf) -> Result<Self, Self::Error> {
let file = File::open(path).map_err(|e| format!("error opening da config: {e}"))?;
serde_json::from_reader(file).map_err(|e| format!("error parsing da config: {e}"))
}
}

impl DaConfig for CelestiaDaConfig {
#[async_trait]
impl DaConfig<Client> for CelestiaDaConfig {
// TODO: Possibility to merge these two ?
fn new_from_env() -> Self {
dotenv().ok();
Self {
http_provider: get_env_var_or_panic("CELESTIA_DA_RPC_URL"),
auth_token: Some(get_env_var_or_panic("CELESTIA_DA_AUTH_TOKEN")),
auth_token: get_env_car_optional_or_panic("CELESTIA_DA_AUTH_TOKEN"),
nid: get_env_var_or_panic("CELESTIA_DA_NID"),

}
}
}
async fn build_da_client(&self) -> Client{
Client::new(&self.http_provider, self.auth_token.as_deref()).await.expect("Failed to create Client: ")
}
}
61 changes: 29 additions & 32 deletions crates/da-clients/celestia/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,25 @@ pub mod error;

use async_trait::async_trait;
use color_eyre::Result;
use config::CelestiaDaConfig;
use error::CelestiaDaError;
use jsonrpsee::http_client::{HeaderMap, HeaderValue, HttpClient, HttpClientBuilder};
use reqwest::header;

use celestia_rpc::BlobClient;
use celestia_rpc::{BlobClient, Client};
use celestia_types::blob::GasPrice;
use celestia_types::{nmt::Namespace, Blob};

use da_client_interface::{DaClient, DaVerificationStatus};

#[derive(Clone, Debug)]
pub struct CelestiaDaClient {
celestia_client: HttpClient,
client: Client,
nid: Namespace,
}

pub struct CelestiaDaConfigAndClient {
pub config : CelestiaDaConfig,
pub client : Client
}

#[async_trait]
impl DaClient for CelestiaDaClient {
async fn publish_state_diff(&self, state_diff: Vec<Vec<u8>>, to: &[u8; 32]) -> Result<String> {
Expand All @@ -28,10 +31,11 @@ impl DaClient for CelestiaDaClient {

// Submit the blobs to celestia
let height = self
.celestia_client
.client
.blob_submit(blobs?.as_slice(), GasPrice::default())
.await?;

println!("{}",height);
// // Return back the height of the block that will contain the blob.
Ok(height.to_string())
}
Expand All @@ -58,35 +62,21 @@ impl DaClient for CelestiaDaClient {
}
}

impl TryFrom<config::CelestiaDaConfig> for CelestiaDaClient {
type Error = anyhow::Error;
fn try_from(conf: config::CelestiaDaConfig) -> Result<Self, Self::Error> {
// Borrowed the below code from https://github.com/eigerco/lumina/blob/ccc5b9bfeac632cccd32d35ecb7b7d51d71fbb87/rpc/src/client.rs#L41.
// Directly calling the function wasn't possible as the function is async. Since
// we only need to initiate the http provider and not the ws provider, we don't need async

let mut headers = HeaderMap::new();

// checking if Auth is available
if let Some(auth_token) = conf.auth_token {
let val = HeaderValue::from_str(&format!("Bearer {}", auth_token))?;
headers.insert(header::AUTHORIZATION, val);
}

let http_client = HttpClientBuilder::default()
.set_headers(headers)
.build(conf.http_provider.as_str())
.map_err(|e| CelestiaDaError::Client(format!("could not init http client: {e}")))?;

// Convert the input string to bytes
let bytes = conf.nid.as_bytes();
impl TryFrom<CelestiaDaConfigAndClient> for CelestiaDaClient {
type Error = anyhow::Error;
fn try_from(config_and_client: CelestiaDaConfigAndClient) -> Result<Self, Self::Error> {
let bytes = config_and_client.config.nid.as_bytes();

// Create a new Namespace from these bytes
let nid = Namespace::new_v0(bytes)
.map_err(|e| CelestiaDaError::Generic(format!("could not init namespace: {e}")))
.unwrap();
.map_err(|e| CelestiaDaError::Generic(format!("could not init namespace: {e}")))
.unwrap();

Ok(Self { celestia_client: http_client, nid })
Ok(Self {
client : config_and_client.client,
nid
})
}
}

Expand Down Expand Up @@ -117,10 +107,17 @@ mod tests {
use super::*;

#[tokio::test]
#[ignore = "Can't run without manual intervention, setup celestia-node and fund address."]
// #[ignore = "Can't run without manual intervention, setup celestia-node and fund address."]
async fn test_celestia_publish_state_diff_and_verify_inclusion() {
let config: CelestiaDaConfig = CelestiaDaConfig::new_from_env();
let celestia_da_client = CelestiaDaClient::try_from(config).unwrap();
let client = config.build_da_client().await;

let conf_client = CelestiaDaConfigAndClient{
config,
client
};

let celestia_da_client = CelestiaDaClient::try_from(conf_client).unwrap();

let s = "Hello World!";
let bytes: Vec<u8> = s.bytes().collect();
Expand Down
4 changes: 3 additions & 1 deletion crates/da-clients/da-client-interface/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@ pub trait DaClient: Send + Sync {
}

/// Trait for every new DaConfig to implement
pub trait DaConfig {
#[async_trait]
pub trait DaConfig<T> {
/// Should create a new instance of the DaConfig from the environment variables
fn new_from_env() -> Self;
async fn build_da_client(&self) -> T;
}
7 changes: 6 additions & 1 deletion crates/da-clients/ethereum/src/config.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use da_client_interface::DaConfig;
use utils::env_utils::get_env_var_or_panic;
use async_trait::async_trait;

#[derive(Clone, Debug)]
pub struct EthereumDaConfig {
Expand All @@ -8,12 +9,16 @@ pub struct EthereumDaConfig {
pub private_key: String,
}

impl DaConfig for EthereumDaConfig {
#[async_trait]
impl DaConfig<String> for EthereumDaConfig {
fn new_from_env() -> Self {
Self {
rpc_url: get_env_var_or_panic("ETHEREUM_RPC_URL"),
memory_pages_contract: get_env_var_or_panic("MEMORY_PAGES_CONTRACT_ADDRESS"),
private_key: get_env_var_or_panic("PRIVATE_KEY"),
}
}
async fn build_da_client(&self) -> String{
"Create Ethereum Client here".to_string()
}
}
16 changes: 12 additions & 4 deletions crates/orchestrator/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use dotenvy::dotenv;
use ethereum_da_client::config::EthereumDaConfig;
use ethereum_da_client::EthereumDaClient;
use celestia_da_client::config::CelestiaDaConfig;
use celestia_da_client::CelestiaDaClient;
use celestia_da_client::{CelestiaDaClient, CelestiaDaConfigAndClient};
use ethereum_settlement_client::EthereumSettlementClient;
use prover_client_interface::ProverClient;
use settlement_client_interface::SettlementClient;
Expand Down Expand Up @@ -56,7 +56,7 @@ pub async fn init_config() -> Config {
// init the queue
let queue = Box::new(SqsQueue {});

let da_client = build_da_client();
let da_client = build_da_client().await;

let settings_provider = DefaultSettingsProvider {};
let settlement_client = build_settlement_client(&settings_provider).await;
Expand Down Expand Up @@ -137,15 +137,23 @@ pub async fn config_force_init(config: Config) {
}

/// Builds the DA client based on the environment variable DA_LAYER
fn build_da_client() -> Box<dyn DaClient + Send + Sync> {
async fn build_da_client() -> Box<dyn DaClient + Send + Sync> {
match get_env_var_or_panic("DA_LAYER").as_str() {
"ethereum" => {
let config = EthereumDaConfig::new_from_env();
Box::new(EthereumDaClient::from(config))
}
"celestia" => {
let config: CelestiaDaConfig = CelestiaDaConfig::new_from_env();
Box::new(CelestiaDaClient::try_from(config).unwrap())
let client = config.build_da_client().await;

let conf_client = CelestiaDaConfigAndClient{
config,
client
};

// TODO: might want to move away from unwrap ?
Box::new(CelestiaDaClient::try_from(conf_client).unwrap())
}
_ => panic!("Unsupported DA layer"),
}
Expand Down
26 changes: 23 additions & 3 deletions crates/utils/src/env_utils.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,27 @@
use color_eyre::Result;
use std::env::VarError;


pub fn get_env_var(key: &str) -> Result<String, VarError> {
std::env::var(key)
}

pub fn get_env_var_optional(key: &str) -> Result<Option<String>,VarError> {
match get_env_var(key){
Ok(s) => {
Ok(Some(s))
}
Err(VarError::NotPresent) => {
Ok(None)
}
Err(e) => {
Err(e)
}
}
}

pub fn get_env_car_optional_or_panic(key: &str) -> Option<String> {
get_env_var_optional(key).unwrap_or_else(|e| panic!("Failed to get env var {}: {}", key, e))

pub fn get_env_var(key: &str) -> Result<String> {
std::env::var(key).map_err(|e| e.into())
}

pub fn get_env_var_or_panic(key: &str) -> String {
Expand Down

0 comments on commit 21de5fb

Please sign in to comment.