Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat : kzg proof calculation during state update & state update transaction #34

Merged
merged 22 commits into from
Jul 22, 2024
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ alloy = { version = "0.1.2", features = ["full"] }
axum = { version = "0.7.4" }
axum-macros = "0.4.1"
color-eyre = "0.6.2"
c-kzg = "1.0.0"
dotenvy = "0.15.7"
futures = "0.3.30"
mongodb = { version = "2.8.1" }
Expand Down
121 changes: 33 additions & 88 deletions crates/da-clients/ethereum/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,27 +1,16 @@
#![allow(missing_docs)]
#![allow(clippy::missing_docs_in_private_items)]
use std::env;
use std::path::Path;
use std::str::FromStr;

use alloy::consensus::{
BlobTransactionSidecar, SignableTransaction, TxEip4844, TxEip4844Variant, TxEip4844WithSidecar, TxEnvelope,
};
use alloy::eips::eip2718::Encodable2718;
use alloy::eips::eip2930::AccessList;
use alloy::eips::eip4844::BYTES_PER_BLOB;
use alloy::network::{Ethereum, TxSigner};
use alloy::primitives::{bytes, Address, FixedBytes, TxHash, U256, U64};
use alloy::network::Ethereum;
use alloy::primitives::{TxHash, U64};
use alloy::providers::{Provider, ProviderBuilder, RootProvider};
use alloy::rpc::client::RpcClient;
use alloy::signers::wallet::LocalWallet;
use alloy::transports::http::Http;
use async_trait::async_trait;
use c_kzg::{Blob, KzgCommitment, KzgProof, KzgSettings};
use color_eyre::Result;
use config::EthereumDaConfig;
use da_client_interface::{DaClient, DaVerificationStatus};
use dotenv::dotenv;
use mockall::automock;
use mockall::predicate::*;
use reqwest::Client;
Expand All @@ -30,57 +19,13 @@ pub mod config;
pub struct EthereumDaClient {
#[allow(dead_code)]
provider: RootProvider<Ethereum, Http<Client>>,
wallet: LocalWallet,
trusted_setup: KzgSettings,
}

#[automock]
#[async_trait]
impl DaClient for EthereumDaClient {
async fn publish_state_diff(&self, state_diff: Vec<Vec<u8>>, to: &[u8; 32]) -> Result<String> {
dotenv().ok();
let provider = &self.provider;
let trusted_setup = &self.trusted_setup;
let wallet = &self.wallet;
let addr = wallet.address();

let (sidecar_blobs, sidecar_commitments, sidecar_proofs) = prepare_sidecar(&state_diff, trusted_setup).await?;
let sidecar = BlobTransactionSidecar::new(sidecar_blobs, sidecar_commitments, sidecar_proofs);

let eip1559_est = provider.estimate_eip1559_fees(None).await?;
let chain_id: u64 = provider.get_chain_id().await?.to_string().parse()?;

let max_fee_per_blob_gas: u128 = provider.get_blob_base_fee().await?.to_string().parse()?;
let max_priority_fee_per_gas: u128 = provider.get_max_priority_fee_per_gas().await?.to_string().parse()?;

let nonce = provider.get_transaction_count(addr, None).await?.to_string().parse()?;
let to = FixedBytes(*to);

let tx = TxEip4844 {
chain_id,
nonce,
gas_limit: 30_000_000,
max_fee_per_gas: eip1559_est.max_fee_per_gas.to_string().parse()?,
max_priority_fee_per_gas,
to: Address::from_word(to),
value: U256::from(0),
access_list: AccessList(vec![]),
blob_versioned_hashes: sidecar.versioned_hashes().collect(),
max_fee_per_blob_gas,
input: bytes!(),
};
let tx_sidecar = TxEip4844WithSidecar { tx: tx.clone(), sidecar: sidecar.clone() };
let mut variant = TxEip4844Variant::from(tx_sidecar);

// Sign and submit
let signature = wallet.sign_transaction(&mut variant).await?;
let tx_signed = variant.into_signed(signature);
let tx_envelope: TxEnvelope = tx_signed.into();
let encoded = tx_envelope.encoded_2718();

let pending_tx = provider.send_raw_transaction(&encoded).await?;

Ok(pending_tx.tx_hash().to_string())
async fn publish_state_diff(&self, _state_diff: Vec<Vec<u8>>, _to: &[u8; 32]) -> Result<String> {
Ok("NA".to_string())
apoorvsadana marked this conversation as resolved.
Show resolved Hide resolved
}

async fn verify_inclusion(&self, external_id: &str) -> Result<DaVerificationStatus> {
apoorvsadana marked this conversation as resolved.
Show resolved Hide resolved
Expand Down Expand Up @@ -114,45 +59,45 @@ impl From<EthereumDaConfig> for EthereumDaClient {
let client =
RpcClient::new_http(Url::from_str(config.rpc_url.as_str()).expect("Failed to parse ETHEREUM_RPC_URL"));
let provider = ProviderBuilder::<_, Ethereum>::new().on_client(client);
let wallet: LocalWallet = env::var("PK").expect("PK must be set").parse().expect("issue while parsing");
// let wallet: LocalWallet = config.private_key.as_str().parse();
let trusted_setup = KzgSettings::load_trusted_setup_file(Path::new("./trusted_setup.txt"))
.expect("issue while loading the trusted setup");
EthereumDaClient { provider, wallet, trusted_setup }
EthereumDaClient { provider }
}
}

async fn prepare_sidecar(
state_diff: &[Vec<u8>],
trusted_setup: &KzgSettings,
) -> Result<(Vec<FixedBytes<131072>>, Vec<FixedBytes<48>>, Vec<FixedBytes<48>>)> {
let mut sidecar_blobs = vec![];
let mut sidecar_commitments = vec![];
let mut sidecar_proofs = vec![];
#[cfg(test)]
mod tests {
use alloy::eips::eip4844::BYTES_PER_BLOB;
use alloy::primitives::FixedBytes;
use c_kzg::{Blob, KzgCommitment, KzgProof, KzgSettings};
use std::fs::File;
use std::io::{self, BufRead};
use std::path::Path;

for blob_data in state_diff {
let mut fixed_size_blob: [u8; BYTES_PER_BLOB] = [0; BYTES_PER_BLOB];
fixed_size_blob.copy_from_slice(blob_data.as_slice());
use super::*;

let blob = Blob::new(fixed_size_blob);
async fn prepare_sidecar(
state_diff: &[Vec<u8>],
trusted_setup: &KzgSettings,
) -> Result<(Vec<FixedBytes<131072>>, Vec<FixedBytes<48>>, Vec<FixedBytes<48>>)> {
let mut sidecar_blobs = vec![];
let mut sidecar_commitments = vec![];
let mut sidecar_proofs = vec![];

let commitment = KzgCommitment::blob_to_kzg_commitment(&blob, trusted_setup)?;
let proof = KzgProof::compute_blob_kzg_proof(&blob, &commitment.to_bytes(), trusted_setup)?;
for blob_data in state_diff {
let mut fixed_size_blob: [u8; BYTES_PER_BLOB] = [0; BYTES_PER_BLOB];
fixed_size_blob.copy_from_slice(blob_data.as_slice());

sidecar_blobs.push(FixedBytes::new(fixed_size_blob));
sidecar_commitments.push(FixedBytes::new(commitment.to_bytes().into_inner()));
sidecar_proofs.push(FixedBytes::new(proof.to_bytes().into_inner()));
}
let blob = Blob::new(fixed_size_blob);

Ok((sidecar_blobs, sidecar_commitments, sidecar_proofs))
}
let commitment = KzgCommitment::blob_to_kzg_commitment(&blob, trusted_setup)?;
let proof = KzgProof::compute_blob_kzg_proof(&blob, &commitment.to_bytes(), trusted_setup)?;

#[cfg(test)]
mod tests {
use std::fs::File;
use std::io::{self, BufRead};
sidecar_blobs.push(FixedBytes::new(fixed_size_blob));
sidecar_commitments.push(FixedBytes::new(commitment.to_bytes().into_inner()));
sidecar_proofs.push(FixedBytes::new(proof.to_bytes().into_inner()));
}

use super::*;
Ok((sidecar_blobs, sidecar_commitments, sidecar_proofs))
}

#[tokio::test]
async fn test_kzg() {
Expand Down
3 changes: 3 additions & 0 deletions crates/orchestrator/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ name = "orchestrator"
path = "src/main.rs"

[dependencies]
alloy = { workspace = true }
arc-swap = { workspace = true }
async-std = "1.12.0"
async-trait = { workspace = true }
Expand All @@ -20,6 +21,7 @@ aws-sdk-s3 = { version = "1.38.0", features = ["behavior-version-latest"] }
axum = { workspace = true, features = ["macros"] }
axum-macros = { workspace = true }
bytes = "1.6.0"
c-kzg = { workspace = true }
cairo-vm = { workspace = true }
color-eyre = { workspace = true }
da-client-interface = { workspace = true }
Expand All @@ -39,6 +41,7 @@ num-bigint = { workspace = true }
num-traits = { workspace = true }
omniqueue = { workspace = true, optional = true }
prover-client-interface = { workspace = true }
rstest = { workspace = true }
serde = { workspace = true }
serde_json = { workspace = true }
settlement-client-interface = { workspace = true }
Expand Down
25 changes: 23 additions & 2 deletions crates/orchestrator/src/config.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
use std::sync::Arc;

use crate::data_storage::aws_s3::config::AWSS3Config;
use crate::data_storage::aws_s3::AWSS3;
use crate::data_storage::{DataStorage, DataStorageConfig};
use arc_swap::{ArcSwap, Guard};
use da_client_interface::{DaClient, DaConfig};
use dotenvy::dotenv;
Expand Down Expand Up @@ -36,7 +39,10 @@ pub struct Config {
settlement_client: Box<dyn SettlementClient>,
/// The database client
database: Box<dyn Database>,
/// Queue client
queue: Box<dyn QueueProvider>,
/// Storage client
storage: Box<dyn DataStorage>,
}

/// Initializes the app config
Expand All @@ -60,7 +66,9 @@ pub async fn init_config() -> Config {
let settlement_client = build_settlement_client(&settings_provider).await;
let prover_client = build_prover_service(&settings_provider);

Config::new(Arc::new(provider), da_client, prover_client, settlement_client, database, queue)
let storage_client = build_storage_client().await;

Config::new(Arc::new(provider), da_client, prover_client, settlement_client, database, queue, storage_client)
}

impl Config {
Expand All @@ -72,8 +80,9 @@ impl Config {
settlement_client: Box<dyn SettlementClient>,
database: Box<dyn Database>,
queue: Box<dyn QueueProvider>,
storage: Box<dyn DataStorage>,
) -> Self {
Self { starknet_client, da_client, prover_client, settlement_client, database, queue }
Self { starknet_client, da_client, prover_client, settlement_client, database, queue, storage }
}

/// Returns the starknet client
Expand Down Expand Up @@ -105,6 +114,11 @@ impl Config {
pub fn queue(&self) -> &dyn QueueProvider {
self.queue.as_ref()
}

/// Returns the storage provider
pub fn storage(&self) -> &dyn DataStorage {
self.storage.as_ref()
}
}

/// The app config. It can be accessed from anywhere inside the service.
Expand Down Expand Up @@ -161,3 +175,10 @@ async fn build_settlement_client(settings_provider: &impl SettingsProvider) -> B
_ => panic!("Unsupported Settlement layer"),
}
}

async fn build_storage_client() -> Box<dyn DataStorage + Send + Sync> {
match get_env_var_or_panic("DATA_STORAGE").as_str() {
"s3" => Box::new(AWSS3::new(AWSS3Config::new_from_env()).await),
_ => panic!("Unsupported Storage Client"),
}
}
5 changes: 3 additions & 2 deletions crates/orchestrator/src/data_storage/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
mod aws_s3;
mod types;
pub mod aws_s3;
pub mod types;

use async_trait::async_trait;
use aws_sdk_s3::primitives::ByteStream;
Expand All @@ -14,6 +14,7 @@ use mockall::automock;
/// ----<block_number>
/// ----<snos_output.json>
/// ----<kzg.txt>
/// ----<blob_data.txt>
#[automock]
#[async_trait]
pub trait DataStorage: Send + Sync {
Expand Down
Loading
Loading