Skip to content

Commit

Permalink
test: publish_state_diff unit test
Browse files Browse the repository at this point in the history
  • Loading branch information
Tranduy1dol authored and zk-steve committed Aug 6, 2024
1 parent e653bfd commit 3ad20d8
Show file tree
Hide file tree
Showing 6 changed files with 4,268 additions and 86 deletions.
4 changes: 3 additions & 1 deletion crates/da-clients/aptos/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ async-trait = { workspace = true }
c-kzg = { workspace = true }
color-eyre = { workspace = true }
da-client-interface = { workspace = true }
dotenv = { workspace = true }
dotenvy = { workspace = true }
hex = "0.4.3"
serde = { workspace = true }
tokio = "1.38.0"
url = { workspace = true }
utils = { workspace = true }
55 changes: 38 additions & 17 deletions crates/da-clients/aptos/src/config.rs
Original file line number Diff line number Diff line change
@@ -1,32 +1,53 @@
use aptos_sdk::crypto::_once_cell::sync::Lazy;
use crate::AptosDaClient;
use aptos_sdk::crypto::ed25519::Ed25519PrivateKey;
use aptos_sdk::crypto::ValidCryptoMaterialStringExt;
use aptos_sdk::rest_client::Client;
use aptos_sdk::types::chain_id::ChainId;
use aptos_sdk::types::{AccountKey, LocalAccount};
use async_trait::async_trait;
use c_kzg::KzgSettings;
use da_client_interface::DaConfig;
use dotenvy::dotenv;
use std::path::Path;
use std::str::FromStr;
use url::Url;
use utils::env_utils::get_env_var_or_panic;

#[derive(Clone, Debug)]
pub struct AptosDaConfig {
pub node_url: String,
pub private_key: String,
pub account_address: String,
pub module_address: String,
pub chain_id: String,
pub trusted_setup: String,
}

impl DaConfig for AptosDaConfig {
#[async_trait]
impl DaConfig<AptosDaClient> for AptosDaConfig {
fn new_from_env() -> Self {
static NODE_URL: Lazy<Url> = Lazy::new(|| {
Url::from_str(
std::env::var("APTOS_NODE_URL")
.as_ref()
.map(|s| s.as_str())
.unwrap_or("https://fullnode.devnet.aptoslabs.com"),
)
.unwrap()
});
dotenv().expect("Failed to load .env file");
let node_url = get_env_var_or_panic("APTOS_NODE_URL");
let private_key = get_env_var_or_panic("APTOS_PRIVATE_KEY");
let account_address = get_env_var_or_panic("APTOS_ACCOUNT_ADDRESS");
let module_address = get_env_var_or_panic("APTOS_MODULE_ADDRESS");
let chain_id = get_env_var_or_panic("CHAIN_ID");
let trusted_setup = get_env_var_or_panic("TRUSTED_SETUP");

Self {
node_url: NODE_URL.to_string(),
private_key: get_env_var_or_panic("PRIVATE_KEY"),
account_address: get_env_var_or_panic("ADDRESS"),
}
Self { chain_id, node_url, private_key, account_address, module_address, trusted_setup }
}

async fn build_client(&self) -> AptosDaClient {
let client = Client::new(self.node_url.parse().unwrap());
let private_key =
Ed25519PrivateKey::from_encoded_string(&self.private_key).expect("Failed to parse private key");
let account_key = AccountKey::from(private_key);
let account_address = self.account_address.parse().expect("Invalid account address");
let account = LocalAccount::new(account_address, account_key, 0);
let module_address = self.module_address.parse().expect("Invalid module address");
let chain_id = ChainId::from_str(&self.chain_id).expect("Invalid chain id");
let trusted_setup = KzgSettings::load_trusted_setup_file(Path::new(&self.trusted_setup))
.expect("Failed to load trusted setup");

AptosDaClient { client, account, module_address, chain_id, trusted_setup }
}
}
11 changes: 0 additions & 11 deletions crates/da-clients/aptos/src/conversion.rs

This file was deleted.

120 changes: 63 additions & 57 deletions crates/da-clients/aptos/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,84 +1,83 @@
#![allow(missing_docs)]
#![allow(clippy::missing_docs_in_private_items)]

use crate::config::AptosDaConfig;
use crate::conversion::{vec_fixed_bytes_131072_to_hex_string, vec_fixed_bytes_48_to_hex_string};
use std::str::FromStr;
use std::time::{SystemTime, UNIX_EPOCH};

use alloy::primitives::FixedBytes;
use aptos_sdk::crypto::ed25519::Ed25519PrivateKey;
use aptos_sdk::crypto::HashValue;
use aptos_sdk::move_types::account_address::AccountAddress;
use aptos_sdk::move_types::identifier::Identifier;
use aptos_sdk::move_types::language_storage::ModuleId;
use aptos_sdk::move_types::u256;
use aptos_sdk::move_types::value::{serialize_values, MoveValue};
use aptos_sdk::rest_client::Client;
use aptos_sdk::transaction_builder::TransactionBuilder;
use aptos_sdk::types::chain_id::ChainId;
use aptos_sdk::types::transaction::{EntryFunction, SignedTransaction, TransactionPayload};
use aptos_sdk::types::{AccountKey, LocalAccount};
use aptos_sdk::types::transaction::{EntryFunction, TransactionPayload};
use aptos_sdk::types::LocalAccount;
use async_trait::async_trait;
use c_kzg::{Blob, KzgCommitment, KzgProof, KzgSettings, BYTES_PER_BLOB};

use da_client_interface::{DaClient, DaVerificationStatus};
use dotenv::dotenv;
use std::path::Path;
use std::str::FromStr;
use std::time::{SystemTime, UNIX_EPOCH};

pub mod config;
pub mod conversion;

pub struct AptosDaClient {
#[allow(dead_code)]
client: Client,
account: LocalAccount,
trusted_setup: KzgSettings,
pub client: Client,
pub account: LocalAccount,
pub module_address: AccountAddress,
pub chain_id: ChainId,
pub trusted_setup: KzgSettings,
}

const STARKNET_VALIDITY: &str = "starknet_validity";
const BLOB_SUBMISSION: &str = "blob_submission";

#[async_trait]
impl DaClient for AptosDaClient {
async fn publish_state_diff(&self, state_diff: Vec<Vec<u8>>, _to: &[u8; 32]) -> color_eyre::Result<String> {
dotenv().ok();
let client = &self.client;
let account = &self.account;

let (blobs, commitments, proofs) = prepare_blob(&state_diff, &self.trusted_setup).await?;

let sequence_number =
self.client.get_account(self.account.address()).await.unwrap().into_inner().sequence_number;
self.account.set_sequence_number(sequence_number);
let sequencer_number = self.account.increment_sequence_number();

let payload = TransactionPayload::EntryFunction(EntryFunction::new(
ModuleId::new(account.address(), Identifier::new("starknet").unwrap()),
Identifier::new("update_state").unwrap(),
ModuleId::new(self.account.address(), Identifier::new(STARKNET_VALIDITY).unwrap()),
Identifier::new(BLOB_SUBMISSION).unwrap(),
vec![],
serialize_values(
vec![&MoveValue::Vector(vec![
MoveValue::U256(
u256::U256::from_str(vec_fixed_bytes_131072_to_hex_string(&blobs).as_str()).unwrap(),
),
MoveValue::U256(
u256::U256::from_str(vec_fixed_bytes_48_to_hex_string(&commitments).as_str()).unwrap(),
),
MoveValue::U256(u256::U256::from_str(vec_fixed_bytes_48_to_hex_string(&proofs).as_str()).unwrap()),
])]
.into_iter(),
),
serialize_values(vec![
&MoveValue::vector_u8(blobs[0].last_chunk::<32>().unwrap().to_vec()),
&MoveValue::vector_u8(commitments[0].last_chunk::<32>().unwrap().to_vec()),
&MoveValue::vector_u8(proofs[0].last_chunk::<32>().unwrap().to_vec()),
]),
));

// Build transaction.
let txn = TransactionBuilder::new(
payload,
SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs(),
ChainId::test(),
SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs() + 60,
self.chain_id,
)
.sender(account.address())
.sequence_number(1)
.max_gas_amount(10000000)
.gas_unit_price(1)
.sender(self.account.address())
.sequence_number(sequencer_number)
.max_gas_amount(10000)
.gas_unit_price(100)
.build();

// Sign transaction.
let signed_txn: SignedTransaction = account.sign_transaction(txn);
let signed_txn = self.account.sign_transaction(txn);

// Submit transaction.
client.submit(&signed_txn).await?;

Ok(signed_txn.committed_hash().to_string())
let tx = self
.client
.submit_and_wait(&signed_txn)
.await
.expect("Failed to submit update state transaction")
.into_inner();

Ok(tx.transaction_info().unwrap().hash.to_string())
}

async fn verify_inclusion(&self, external_id: &str) -> color_eyre::Result<DaVerificationStatus> {
Expand All @@ -89,7 +88,7 @@ impl DaClient for AptosDaClient {
true => Ok(DaVerificationStatus::Verified),
false => match response.is_pending() {
true => Ok(DaVerificationStatus::Pending),
false => Ok(DaVerificationStatus::Rejected),
false => Ok(DaVerificationStatus::Rejected("Failed".parse()?)),
},
}
}
Expand All @@ -105,19 +104,6 @@ impl DaClient for AptosDaClient {
}
}

impl From<AptosDaConfig> for AptosDaClient {
fn from(config: AptosDaConfig) -> Self {
let client = Client::new(config.node_url.parse().unwrap());
let private_key = Ed25519PrivateKey::try_from(config.private_key.as_bytes());
let account_key = AccountKey::from_private_key(private_key.unwrap());
let account_address = config.account_address.parse().expect("Issue while loading account address");
let account = LocalAccount::new(account_address, account_key, 0);
let trusted_setup = KzgSettings::load_trusted_setup_file(Path::new("./trusted_setup.txt"))
.expect("Issue while loading the trusted setup");
AptosDaClient { client, account, trusted_setup }
}
}

async fn prepare_blob(
state_diff: &[Vec<u8>],
trusted_setup: &KzgSettings,
Expand All @@ -142,3 +128,23 @@ async fn prepare_blob(

Ok((sidecar_blobs, sidecar_commitments, sidecar_proofs))
}

#[cfg(test)]
mod test {
use super::*;
use crate::config::AptosDaConfig;
use aptos_sdk::move_types::u256;
use da_client_interface::DaConfig;

#[tokio::test]
async fn test_submit_blob() {
let da_config = AptosDaConfig::new_from_env();
let da_client = AptosDaConfig::build_client(&da_config).await;

let data = vec![hex::decode(include_str!("../test_utils/hex_block_630872.txt")).unwrap()];
da_client
.publish_state_diff(data, &u256::U256::from(0u128).to_le_bytes())
.await
.expect("Failed to submit blob!");
}
}
1 change: 1 addition & 0 deletions crates/da-clients/aptos/test_utils/hex_block_630872.txt

Large diffs are not rendered by default.

Loading

0 comments on commit 3ad20d8

Please sign in to comment.