Skip to content

Commit

Permalink
small changes
Browse files Browse the repository at this point in the history
  • Loading branch information
apoorvsadana committed Aug 18, 2024
1 parent a8f4bb1 commit ca51313
Show file tree
Hide file tree
Showing 4 changed files with 157 additions and 110 deletions.
2 changes: 1 addition & 1 deletion .env.test
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ MONGODB_CONNECTION_STRING="mongodb://localhost:27017"


# Ethereum Settlement
DEFAULT_SETTLEMENT_CLIENT_RPC="http://localhost:3000"
DEFAULT_SETTLEMENT_CLIENT_RPC="http://localhost:8545"
DEFAULT_L1_CORE_CONTRACT_ADDRESS="0xc662c410C0ECf747543f5bA90660f6ABeBD9C8c4"
SHOULD_IMPERSONATE_ACCOUNT="true"
TEST_DUMMY_CONTRACT_ADDRESS="0xE5b6F5e695BA6E4aeD92B68c4CC8Df1160D69A81"
106 changes: 59 additions & 47 deletions crates/settlement-clients/ethereum/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use alloy::{
use alloy::eips::eip2930::AccessList;
use alloy::eips::eip4844::BYTES_PER_BLOB;
use alloy::hex;
use alloy::providers::ext::AnvilApi;
// use alloy::node_bindings::Anvil;
use alloy::rpc::types::TransactionRequest;
use alloy_primitives::Bytes;
Expand All @@ -29,6 +30,7 @@ use mockall::{automock, lazy_static, predicate::*};
use alloy::providers::ProviderBuilder;
use conversion::{get_input_data_for_eip_4844, prepare_sidecar};
use settlement_client_interface::{SettlementClient, SettlementVerificationStatus, SETTLEMENT_SETTINGS_NAME};
use url::Url;
use utils::{env_utils::get_env_var_or_panic, settings::SettingsProvider};

use crate::clients::interfaces::validity_interface::StarknetValidityContractTrait;
Expand All @@ -39,23 +41,12 @@ pub mod clients;
pub mod config;
pub mod conversion;

// IMPORTANT to understand #[cfg(test)], #[cfg(not(test))] and SHOULD_IMPERSONATE_ACCOUNT
// Two tests : `update_state_blob_with_dummy_contract_works` & `update_state_blob_with_impersonation_works` use a env var `SHOULD_IMPERSONATE_ACCOUNT` to inform the function `update_state_with_blobs` about the kind of testing,
// `SHOULD_IMPERSONATE_ACCOUNT` can have any of "0" or "1" value :
// - if "0" then : Testing via default Anvil address.
// - if "1" then : Testing via impersonating `Starknet Operator Address`.
// Note : changing between "0" and "1" is handled automatically by each test function, `no` manual change in `env.test` is needed.

#[cfg(test)]
mod tests;
pub mod types;

#[cfg(test)]
use {alloy::providers::RootProvider, alloy::transports::http::Http, reqwest::Client};

#[cfg(not(test))]
use types::EthHttpProvider;

pub const ENV_PRIVATE_KEY: &str = "ETHEREUM_PRIVATE_KEY";

lazy_static! {
Expand All @@ -66,19 +57,16 @@ lazy_static! {
.expect("Error loading trusted setup file");
}

#[allow(dead_code)]
pub struct EthereumSettlementClient {
core_contract_client: StarknetValidityContractClient,
wallet: EthereumWallet,
wallet_address: Address,
#[cfg(not(test))]
provider: Arc<EthHttpProvider>,
provider: Arc<RootProvider<Http<Client>>>,
#[cfg(test)]
provider: RootProvider<Http<Client>>,
impersonate_account: Option<Address>,
}

impl EthereumSettlementClient {
#[cfg(not(test))]
pub fn with_settings(settings: &impl SettingsProvider) -> Self {
let settlement_cfg: EthereumSettlementConfig = settings.get_settings(SETTLEMENT_SETTINGS_NAME).unwrap();

Expand All @@ -87,46 +75,63 @@ impl EthereumSettlementClient {
let wallet_address = signer.address();
let wallet = EthereumWallet::from(signer);

let provider = Arc::new(
// provider without wallet
let provider = Arc::new(ProviderBuilder::new().on_http(settlement_cfg.rpc_url.clone()));

// provider with wallet
let filler_provider = Arc::new(
ProviderBuilder::new().with_recommended_fillers().wallet(wallet.clone()).on_http(settlement_cfg.rpc_url),
);

let core_contract_client = StarknetValidityContractClient::new(
Address::from_str(&settlement_cfg.core_contract_address)
.expect("Failed to convert the validity contract address.")
.0
.into(),
provider.clone(),
filler_provider,
);

EthereumSettlementClient { provider, core_contract_client, wallet, wallet_address }
EthereumSettlementClient {
provider,
core_contract_client,
wallet,
wallet_address,
#[cfg(test)]
impersonate_account: None,
}
}

#[cfg(test)]
pub fn with_test_settings(settings: &impl SettingsProvider, provider: RootProvider<Http<Client>>) -> Self {
use tests::{SHOULD_IMPERSONATE_ACCOUNT, TEST_DUMMY_CONTRACT_ADDRESS};
let settlement_cfg: EthereumSettlementConfig = settings.get_settings(SETTLEMENT_SETTINGS_NAME).unwrap();

pub fn with_test_settings(
provider: RootProvider<Http<Client>>,
core_contract_address: Option<Address>,
rpc_url: Url,
impersonate_account: Option<Address>,
) -> Self {
let private_key = get_env_var_or_panic(ENV_PRIVATE_KEY);
let signer: PrivateKeySigner = private_key.parse().expect("Failed to parse private key");
let wallet_address = signer.address();
let wallet = EthereumWallet::from(signer);

let fill_provider = Arc::new(
ProviderBuilder::new().with_recommended_fillers().wallet(wallet.clone()).on_http(settlement_cfg.rpc_url),
);
let fill_provider =
Arc::new(ProviderBuilder::new().with_recommended_fillers().wallet(wallet.clone()).on_http(rpc_url));

let core_contract_address = if *SHOULD_IMPERSONATE_ACCOUNT {
&settlement_cfg.core_contract_address
let core_contract_address = if let Some(core_contract_address) = core_contract_address {
core_contract_address.clone()
} else {
&*TEST_DUMMY_CONTRACT_ADDRESS
// dummy address
Address::from_str("0x0").unwrap()
};

let core_contract_client = StarknetValidityContractClient::new(
Address::from_str(core_contract_address).unwrap().0.into(),
fill_provider,
);
let core_contract_client = StarknetValidityContractClient::new(core_contract_address, fill_provider);

EthereumSettlementClient { provider, core_contract_client, wallet, wallet_address }
EthereumSettlementClient {
provider: Arc::new(provider),
core_contract_client,
wallet,
wallet_address,
impersonate_account,
}
}

/// Build kzg proof for the x_0 point evaluation
Expand Down Expand Up @@ -184,12 +189,6 @@ impl SettlementClient for EthereumSettlementClient {
}

/// Should be used to update state on core contract when DA is in blobs/alt DA
async fn update_state_blobs(&self, program_output: Vec<[u8; 32]>, kzg_proof: [u8; 48]) -> Result<String> {
let program_output: Vec<U256> = vec_u8_32_to_vec_u256(&program_output)?;
let tx_receipt = self.core_contract_client.update_state_kzg(program_output, kzg_proof).await?;
Ok(format!("0x{:x}", tx_receipt.transaction_hash))
}

async fn update_state_with_blobs(
&self,
program_output: Vec<[u8; 32]>,
Expand Down Expand Up @@ -246,13 +245,14 @@ impl SettlementClient for EthereumSettlementClient {
let signature = self.wallet.default_signer().sign_transaction(&mut variant).await?;
let tx_signed = variant.into_signed(signature);
let tx_envelope: TxEnvelope = tx_signed.into();
// IMP: this conversion strips signature from the transaction

// IMP: this conversion strips signature from the transaction
#[cfg(not(test))]
let txn_request: TransactionRequest = tx_envelope.into();

#[cfg(test)]
let txn_request = test_config::configure_transaction(tx_envelope);
let txn_request =
test_config::configure_transaction(self.provider.clone(), tx_envelope, self.impersonate_account).await;

let pending_transaction = self.provider.send_transaction(txn_request).await?;
return Ok(pending_transaction.tx_hash().to_string());
Expand Down Expand Up @@ -297,14 +297,26 @@ impl SettlementClient for EthereumSettlementClient {
mod test_config {
use super::*;
use alloy::network::TransactionBuilder;
use tests::{ADDRESS_TO_IMPERSONATE, SHOULD_IMPERSONATE_ACCOUNT, TEST_NONCE};
use tests::STARKNET_OPERATOR_ADDRESS;

pub fn configure_transaction(tx_envelope: TxEnvelope) -> TransactionRequest {
pub async fn configure_transaction(
provider: Arc<RootProvider<Http<Client>>>,
tx_envelope: TxEnvelope,
impersonate_account: Option<Address>,
) -> TransactionRequest {
let mut txn_request: TransactionRequest = tx_envelope.into();

if *SHOULD_IMPERSONATE_ACCOUNT {
txn_request.set_nonce(*TEST_NONCE);
txn_request = txn_request.with_from(*ADDRESS_TO_IMPERSONATE);
// IMPORTANT to understand #[cfg(test)], #[cfg(not(test))] and SHOULD_IMPERSONATE_ACCOUNT
// Two tests : `update_state_blob_with_dummy_contract_works` & `update_state_blob_with_impersonation_works` use a env var `SHOULD_IMPERSONATE_ACCOUNT` to inform the function `update_state_with_blobs` about the kind of testing,
// `SHOULD_IMPERSONATE_ACCOUNT` can have any of "0" or "1" value :
// - if "0" then : Testing via default Anvil address.
// - if "1" then : Testing via impersonating `Starknet Operator Address`.
// Note : changing between "0" and "1" is handled automatically by each test function, `no` manual change in `env.test` is needed.
if let Some(impersonate_account) = impersonate_account {
let nonce =
provider.get_transaction_count(impersonate_account).await.unwrap().to_string().parse::<u64>().unwrap();
txn_request.set_nonce(nonce);
txn_request = txn_request.with_from(impersonate_account);
}

txn_request
Expand Down
Loading

0 comments on commit ca51313

Please sign in to comment.