Skip to content
This repository has been archived by the owner on Aug 2, 2024. It is now read-only.

Commit

Permalink
feat(da): base Ethereum config for DA/settlement tasks (#1452)
Browse files Browse the repository at this point in the history
  • Loading branch information
m-kus authored Feb 28, 2024
1 parent 4ffec37 commit eb40b3d
Show file tree
Hide file tree
Showing 27 changed files with 393 additions and 317 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
- feat: add transparent representation to `Felt252Wrapper`
- feat(rpc/trace_api): add `trace_block_transaction`
- chore(db): changed the way hashes are encoded
- refacto: reusable Eth client config for settlement/DA/other tasks
- ci: add gomu gomu no gatling perfomrance test
- feat(runtime): moved StarkEvents from Substrate events to runtime storage

Expand Down
19 changes: 18 additions & 1 deletion Cargo.lock

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

3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ members = [
"crates/client/storage",
"crates/client/commitment-state-diff",
"crates/client/settlement",
"crates/client/eth-client",
"starknet-rpc-test",
"da-test",
"starknet-e2e-test",
Expand Down Expand Up @@ -60,6 +61,7 @@ default-members = [
"crates/client/storage",
"crates/client/commitment-state-diff",
"crates/client/settlement",
"crates/client/eth-client",
]

[profile.release]
Expand Down Expand Up @@ -248,6 +250,7 @@ mc-data-availability = { path = "crates/client/data-availability" }
mc-commitment-state-diff = { path = "crates/client/commitment-state-diff" }
mc-l1-messages = { path = "crates/client/l1-messages" }
mc-settlement = { path = "crates/client/settlement" }
mc-eth-client = { path = "crates/client/eth-client" }

# Madara runtime
madara-runtime = { path = "crates/runtime" }
Expand Down
4 changes: 4 additions & 0 deletions crates/client/data-availability/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ sp-runtime = { workspace = true, features = ["std"] }
blockifier = { workspace = true, default-features = true }
mc-commitment-state-diff = { workspace = true, default-features = true }
mc-db = { workspace = true, default-features = true }
mc-eth-client = { workspace = true }
pallet-starknet-runtime-api = { workspace = true, features = ["std"] }
starknet-core = { workspace = true, features = ["std"] }
starknet_api = { workspace = true, default-features = true }
Expand All @@ -55,6 +56,9 @@ mp-felt = { workspace = true, default-features = true }
mp-hashers = { workspace = true, default-features = true }
mp-storage = { workspace = true, default-features = true }

# Zaun
starknet-core-contract-client = { workspace = true }

# Prometheus
prometheus-endpoint = { workspace = true }

Expand Down
72 changes: 10 additions & 62 deletions crates/client/data-availability/src/ethereum/config.rs
Original file line number Diff line number Diff line change
@@ -1,68 +1,16 @@
use std::fs::File;
use std::path::PathBuf;

use mc_eth_client::config::{EthereumProviderConfig, EthereumWalletConfig, StarknetContracts};
use serde::{Deserialize, Serialize};

use crate::{DaError, DaMode};

pub const DEFAULT_ETHEREUM_NODE: &str = "127.0.0.1:8545";
// default key derived from starting anvil as follows:
// anvil -b 5 --config-out $BUILD_DIR/anvil.json
// PRE_PRIVATE=$(jq -r '.private_keys[0]' $BUILD_DIR/anvil.json)
pub const DEFAULT_SEQUENCER_KEY: &str = "ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80";
pub const DEFAULT_STARKNET_CORE_CONTRACTS: &str = "0x5FbDB2315678afecb367f032d93F642f64180aa3";
pub const DEFAULT_CHAIN_ID: u64 = 31337;
use crate::DaMode;

#[derive(Clone, PartialEq, Serialize, Deserialize, Debug)]
pub struct EthereumConfig {
#[serde(default = "default_http")]
pub http_provider: String,
#[serde(default = "default_core_contracts")]
pub core_contracts: String,
#[serde(default = "default_sequencer_key")]
pub sequencer_key: String,
#[serde(default = "default_chain_id")]
pub chain_id: u64,
#[derive(Clone, Serialize, Deserialize, Debug)]
pub struct EthereumDaConfig {
#[serde(default)]
pub provider: EthereumProviderConfig,
#[serde(default)]
pub wallet: Option<EthereumWalletConfig>,
#[serde(default)]
pub contracts: StarknetContracts,
#[serde(default)]
pub mode: DaMode,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub poll_interval_ms: Option<u64>,
}

impl TryFrom<&PathBuf> for EthereumConfig {
type Error = DaError;

fn try_from(path: &PathBuf) -> Result<Self, Self::Error> {
let file = File::open(path).map_err(DaError::FailedOpeningConfig)?;
serde_json::from_reader(file).map_err(DaError::FailedParsingConfig)
}
}

fn default_http() -> String {
format!("http://{DEFAULT_ETHEREUM_NODE}")
}

fn default_core_contracts() -> String {
DEFAULT_STARKNET_CORE_CONTRACTS.to_string()
}

fn default_sequencer_key() -> String {
DEFAULT_SEQUENCER_KEY.to_string()
}

fn default_chain_id() -> u64 {
DEFAULT_CHAIN_ID
}

impl Default for EthereumConfig {
fn default() -> Self {
Self {
http_provider: default_http(),
mode: DaMode::default(),
core_contracts: default_core_contracts(),
sequencer_key: default_sequencer_key(),
chain_id: default_chain_id(),
poll_interval_ms: None,
}
}
}
93 changes: 24 additions & 69 deletions crates/client/data-availability/src/ethereum/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,72 +4,32 @@ use std::collections::HashMap;
use std::sync::Arc;

use async_trait::async_trait;
use ethers::prelude::{abigen, SignerMiddleware};
use ethers::providers::{Http, Provider};
use ethers::signers::{LocalWallet, Signer};
use ethers::types::{Address, I256, U256};
use ethers::types::{I256, U256};
use starknet_core_contract_client::interfaces::StarknetSovereignContract;

use crate::utils::is_valid_http_endpoint;
use crate::{DaClient, DaError, DaMode};

#[derive(Clone, Debug)]
pub struct EthereumClient {
http_provider: Provider<Http>,
signer: Arc<SignerMiddleware<Provider<Http>, LocalWallet>>,
cc_address: Address,
pub struct EthereumDaClient {
core_contract: StarknetSovereignContract<Provider<Http>>,
mode: DaMode,
}

#[async_trait]
impl DaClient for EthereumClient {
impl DaClient for EthereumDaClient {
async fn publish_state_diff(&self, state_diff: Vec<U256>) -> Result<(), anyhow::Error> {
log::debug!("State Update: {:?}", state_diff);
let fmt_tx = match self.mode {
DaMode::Sovereign => {
abigen!(
STARKNET,
r#"[
function updateState(uint256[] calldata programOutput) external
]"#,
);

let core_contracts = STARKNET::new(self.cc_address, self.signer.clone());
core_contracts.update_state(state_diff)
}
_ => {
abigen!(
STARKNET,
r#"[
function updateState(uint256[] calldata programOutput, uint256 onchainDataHash, uint256 onchainDataSize) external
]"#,
);

let core_contracts = STARKNET::new(self.cc_address, self.signer.clone());
core_contracts.update_state(state_diff, U256::default(), U256::default())
}
};

let tx = fmt_tx
.send()
.await
.map_err(|e| DaError::FailedDataSubmission(e.into()))?
.await
.map_err(|e| DaError::FailedDataSubmission(e.into()))?;

log::debug!("State Update: {:?}", tx);
log::debug!("State diff: {:?}", state_diff);
Ok(())
}

async fn last_published_state(&self) -> Result<I256, anyhow::Error> {
abigen!(
STARKNET,
r#"[
function stateBlockNumber() external view returns (int256)
]"#,
);

let contract = STARKNET::new(self.cc_address, self.http_provider.clone().into());
Ok(contract.state_block_number().call().await.map_err(|e| DaError::FailedDataSubmission(e.into()))?)
self.core_contract
.state_block_number()
.call()
.await
.map_err(|e| DaError::FailedDataSubmission(e.into()))
.map_err(Into::into)
}

fn get_mode(&self) -> DaMode {
Expand All @@ -81,28 +41,23 @@ impl DaClient for EthereumClient {
}
}

impl TryFrom<config::EthereumConfig> for EthereumClient {
impl TryFrom<config::EthereumDaConfig> for EthereumDaClient {
type Error = DaError;

fn try_from(conf: config::EthereumConfig) -> Result<Self, Self::Error> {
if !is_valid_http_endpoint(&conf.http_provider) {
return Err(DaError::InvalidHttpEndpoint(conf.http_provider));
fn try_from(conf: config::EthereumDaConfig) -> Result<Self, Self::Error> {
// NOTE: only sovereign mode is supported (for now)
// In sovereign mode both proof and state diff are populated on-chain
// without verification. A full Madara node should be able to index
// from scratch using just that info: verify proof -> apply diff
if conf.mode != DaMode::Sovereign {
return Err(DaError::UnsupportedMode(conf.mode));
}

let address = conf.contracts.core_contract().map_err(|e| DaError::FailedConversion(e.into()))?;
let provider =
Provider::<Http>::try_from(conf.http_provider).map_err(|e| DaError::FailedBuildingClient(e.into()))?;

let wallet: LocalWallet = conf
.sequencer_key
.parse::<LocalWallet>()
.map_err(|e| DaError::FailedConversion(e.into()))?
.with_chain_id(conf.chain_id);

let signer = Arc::new(SignerMiddleware::new(provider.clone(), wallet));

let cc_address: Address =
conf.core_contracts.parse::<Address>().map_err(|e| DaError::FailedConversion(e.into()))?;
Provider::<Http>::try_from(conf.provider).map_err(|e| DaError::FailedBuildingClient(e.into()))?;
let core_contract = StarknetSovereignContract::new(address, Arc::new(provider));

Ok(Self { http_provider: provider, signer, cc_address, mode: conf.mode })
Ok(Self { mode: conf.mode, core_contract })
}
}
2 changes: 2 additions & 0 deletions crates/client/data-availability/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ pub enum DaError {
FailedDataValidation(anyhow::Error),
#[error("Invalid http endpoint: {0}")]
InvalidHttpEndpoint(String),
#[error("Unsupported mode: {0}")]
UnsupportedMode(DaMode),
}

impl Display for DaLayer {
Expand Down
20 changes: 20 additions & 0 deletions crates/client/eth-client/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
[package]
name = "mc-eth-client"
version = "0.1.0"
description = "Base Ethereum client configuration and instantiation"
homepage = "https://github.com/keep-starknet-strange/madara"
edition = "2021"
license = "MIT"
publish = false
repository = "https://github.com/keep-starknet-strange/madara"

[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]

[dependencies]
ethers = { workspace = true }
rustc-hex = { workspace = true }
serde = { workspace = true }
serde_json = { workspace = true }
thiserror = { workspace = true }
url = { workspace = true }
Loading

0 comments on commit eb40b3d

Please sign in to comment.