Skip to content

Commit 635d5c9

Browse files
committed
refactor: config struct, better docs, .env examples
1 parent 735a6e9 commit 635d5c9

10 files changed

Lines changed: 140 additions & 74 deletions

File tree

examples/L2/.env.example

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# .env example for holesky network
2+
NETWORK=holesky
3+
ETH_RPC_URL=https://ethereum-holesky-rpc.publicnode.com
4+
WS_ETH_RPC_URL=wss://ethereum-holesky-rpc.publicnode.com
5+
BEACON_CLIENT_URL=<YOUR_BEACON_CLIENT_URL> # This can't be a public one as we need to retrieve blobs and they don't support that method
6+
PRIVATE_KEY_STORE_PATH=<PATH_TO_STATE_TRANSITION_OWNER_KEYSTORE>
7+
PRIVATE_KEY_STORE_PASSWORD=<STATE_TRANSITION_OWNER_KEYSTORE_PASSWORD>
8+
STATE_TRANSITION_CONTRACT_ADDRESS=<STATE_TRANSITION_CONTRACT_ADDRESS>

examples/L2/Cargo.lock

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

examples/L2/Makefile

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,12 @@
22

33
SHELL := /bin/bash
44

5-
run:
5+
run_l2:
66
@cd crates/l2 && cargo run --release --bin main
77

8-
print_program_id:
8+
generate_program_id:
99
@cd crates/l2 && cargo run --release --bin write_program_id
1010
@cat ./crates/l2/programs_ids.json
1111

12-
1312
deploy_contract_holesky:
1413
@. ./contracts/.env.holesky && . ./contracts/scripts/deploy.sh

examples/L2/contracts/.env.holesky

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
RPC_URL=https://ethereum-holesky-rpc.publicnode.com
2+
# Initial state root of db, see in crates/l2/db.rs
3+
INITIAL_STATE_ROOT=0x454691b501bc38536f4156a5b7d86502c49d13710d5e5b52b22c563fff4afee0
4+
# You can read it from crates/l2/programs_ids.json and generate it via make generate_program_id
5+
PROGRAM_ID=0x5961f68d41b2798f4dab05184d8f9cda39637d28097819906033c2f10b365ab1
6+
# Address of the wallet you want to set as owner
7+
OWNER_ADDRESS=<CONTRACT_OWNER_ADDRESS>
8+
# Private key used to deploy the contract
9+
PRIVATE_KEY=<PRIVATE_KEY_TO_DEPLOY>
10+
# This is the aligned proof aggregator address in holesky see:
11+
# https://docs.alignedlayer.com/guides/7_contract_addresses
12+
ALIGNED_PROOF_AGGREGATOR_ADDRESS=0x7Eace34A8d4C4CacE633946C6F7CF4BeF3F33513
13+
ETHERSCAN_API_KEY=<YOUR_ETHERSCAN_API_KEY>

examples/L2/crates/l2/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ aligned-sdk = { path = "../../../../batcher/aligned-sdk" }
1818
bincode = "1.3.3"
1919
futures-util = "0.3"
2020
tokio = "1.44"
21-
alloy = { version = "0.14", features = ["full", "providers"] }
21+
alloy = { version = "0.14", features = ["full", "signer-keystore", "providers"] }
22+
dotenv = "0.15"
2223

2324
[[bin]]
2425
name = "main"

examples/L2/crates/l2/src/aligned.rs

Lines changed: 34 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,31 @@
11
use aligned_sdk::{
2-
core::types::{AlignedVerificationData, Signer, SigningKey, VerificationData, Wallet},
3-
sdk::estimate_fee,
2+
core::types::{AlignedVerificationData, Signer, VerificationData, Wallet},
3+
sdk::{estimate_fee, get_chain_id},
44
};
55
use alloy::{
66
eips::BlockNumberOrTag,
7-
hex,
87
primitives::Address,
98
providers::{Provider, ProviderBuilder, WsConnect},
109
rpc::types::Filter,
1110
};
1211
use futures_util::StreamExt;
1312
use sp1_sdk::{HashableKey, SP1VerifyingKey};
1413

14+
use crate::Config;
15+
1516
pub async fn send_proof_to_be_verified_on_aligned(
17+
config: &Config,
1618
proof: &sp1_sdk::SP1ProofWithPublicValues,
1719
vm_program_code: Vec<u8>,
18-
network: aligned_sdk::core::types::Network,
19-
wallet: Wallet<SigningKey>,
2020
) -> AlignedVerificationData {
2121
let proof = bincode::serialize(proof).expect("Serialize sp1 proof to binary");
22+
let chain_id = get_chain_id(&config.eth_rpc_url).await.unwrap();
23+
let wallet = Wallet::decrypt_keystore(
24+
&config.private_key_store_path,
25+
&config.private_key_store_password,
26+
)
27+
.expect("Keystore to be `cast wallet` compliant")
28+
.with_chain_id(chain_id);
2229

2330
let verification_data = VerificationData {
2431
proof_generator_addr: wallet.address(),
@@ -29,38 +36,41 @@ pub async fn send_proof_to_be_verified_on_aligned(
2936
verification_key: None,
3037
};
3138

32-
let nonce = aligned_sdk::sdk::get_nonce_from_batcher(network.clone(), wallet.address())
39+
let nonce = aligned_sdk::sdk::get_nonce_from_batcher(config.network.clone(), wallet.address())
3340
.await
3441
.expect("Retrieve nonce from aligned batcher");
3542

3643
let max_fee = estimate_fee(
37-
"https://ethereum-holesky-rpc.publicnode.com".into(),
44+
&config.eth_rpc_url,
3845
aligned_sdk::core::types::FeeEstimationType::Instant,
3946
)
4047
.await
4148
.expect("Max fee to be retrieved");
4249

43-
let aligned_verification_data =
44-
aligned_sdk::sdk::submit(network, &verification_data, max_fee, wallet, nonce.into())
45-
.await
46-
.expect("Proof to be sent");
50+
let aligned_verification_data = aligned_sdk::sdk::submit(
51+
config.network.clone(),
52+
&verification_data,
53+
max_fee,
54+
wallet,
55+
nonce.into(),
56+
)
57+
.await
58+
.expect("Proof to be sent");
4759

4860
aligned_verification_data
4961
}
5062

5163
pub async fn wait_until_proof_is_aggregated(
52-
network: aligned_sdk::core::types::Network,
53-
eth_rpc_url: String,
54-
beacon_client_url: String,
64+
config: &Config,
5565
proof: &sp1_sdk::SP1ProofWithPublicValues,
5666
vk: &SP1VerifyingKey,
57-
) -> Option<Vec<[u8; 32]>> {
58-
let ws_rpc_url = "wss://ethereum-holesky-rpc.publicnode.com";
67+
) -> Vec<[u8; 32]> {
68+
let ws_rpc_url = &config.ws_eth_rpc_url;
5969
let ws = WsConnect::new(ws_rpc_url);
6070
let provider = ProviderBuilder::new().on_ws(ws).await.unwrap();
6171

6272
let aligned_proof_agg_address =
63-
Address::from(network.get_aligned_proof_agg_service_address().0);
73+
Address::from(config.network.get_aligned_proof_agg_service_address().0);
6474

6575
let filter = Filter::new()
6676
.address(aligned_proof_agg_address)
@@ -75,21 +85,21 @@ pub async fn wait_until_proof_is_aggregated(
7585
vk: vk.hash_bytes(),
7686
public_inputs: proof.public_values.to_vec(),
7787
};
78-
79-
let mut merkle_path = None;
88+
89+
let mut merkle_path = vec![];
8090

8191
while let Some(_) = stream.next().await {
8292
if let Some(merkle_proof) = aligned_sdk::sdk::aggregation::get_merkle_path_for_proof(
83-
network.clone(),
84-
eth_rpc_url.clone(),
85-
beacon_client_url.clone(),
93+
config.network.clone(),
94+
config.eth_rpc_url.clone(),
95+
config.beacon_client_url.clone(),
8696
None,
8797
&verification_data,
8898
)
8999
.await
90-
.unwrap()
100+
.expect("Get merkle path for proof")
91101
{
92-
merkle_path = Some(merkle_proof);
102+
merkle_path = merkle_proof;
93103
break;
94104
};
95105
}

examples/L2/crates/l2/src/eth.rs

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,30 +2,33 @@ use std::str::FromStr;
22

33
use alloy::{
44
network::EthereumWallet, primitives::Address, providers::ProviderBuilder,
5-
rpc::types::TransactionReceipt, signers::local::PrivateKeySigner, sol,
5+
rpc::types::TransactionReceipt, signers::local::LocalSigner, sol,
66
};
77

8+
use crate::Config;
9+
810
sol!(
911
#[sol(rpc)]
1012
StateTransition,
1113
"abi/StateTransition.json"
1214
);
1315

1416
pub async fn send_state_transition_to_chain(
17+
config: &Config,
1518
public_inputs: Vec<u8>,
1619
merkle_proof: Vec<[u8; 32]>,
17-
eth_rpc_url: String,
18-
state_transition_address: String,
19-
private_key: String,
2020
) -> TransactionReceipt {
21-
let rpc_url = eth_rpc_url.parse().expect("RPC URL should be valid");
22-
let signer = PrivateKeySigner::from_str(&private_key)
23-
.expect("Keystore signer should be `cast wallet` compliant");
21+
let rpc_url = config.eth_rpc_url.parse().expect("RPC URL should be valid");
22+
let signer = LocalSigner::decrypt_keystore(
23+
&config.private_key_store_path,
24+
&config.private_key_store_password,
25+
)
26+
.expect("Keystore signer should be `cast wallet` compliant");
2427
let wallet = EthereumWallet::from(signer);
2528

2629
let rpc_provider = ProviderBuilder::new().wallet(wallet).on_http(rpc_url);
2730
let state_transition_contract = StateTransition::new(
28-
Address::from_str(&state_transition_address)
31+
Address::from_str(&config.state_transition_contract_address)
2932
.expect("State transition address should be valid"),
3033
rpc_provider,
3134
);

examples/L2/crates/l2/src/lib.rs

Lines changed: 25 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,45 @@
11
use aligned::{send_proof_to_be_verified_on_aligned, wait_until_proof_is_aggregated};
2-
use alloy::hex::hex;
32
use db::{generate_random_transfers, DB};
43
use eth::send_state_transition_to_chain;
5-
use lambdaworks_crypto::merkle_tree::merkle::MerkleTree;
64
use primitive_types::U256;
75
use sp1_state_transition_program::ProgramOutput;
6+
use tracing::info;
87
use zk::{prove_state_transition, PROGRAM_ELF};
98

109
mod aligned;
1110
mod db;
1211
mod eth;
1312
mod zk;
1413

15-
pub async fn start_l2(
16-
network: aligned_sdk::core::types::Network,
17-
eth_rpc_url: String,
18-
beacon_client_url: String,
19-
wallet: aligned_sdk::core::types::Wallet<aligned_sdk::core::types::SigningKey>,
20-
) {
14+
pub struct Config {
15+
pub network: aligned_sdk::core::types::Network,
16+
pub eth_rpc_url: String,
17+
pub ws_eth_rpc_url: String,
18+
pub beacon_client_url: String,
19+
pub private_key_store_path: String,
20+
pub private_key_store_password: String,
21+
pub state_transition_contract_address: String,
22+
}
23+
24+
pub async fn start_l2(config: Config) {
2125
// 0. Load merkle tree file, if not created, create initial state
2226
let mut db = DB::new("./db".to_string());
2327

2428
// 1. Create random transfers
2529
let transfers = generate_random_transfers(&db, 10);
2630

27-
// 2. Call zkvm and pass (MerkleTree, Updates to perform)
28-
println!("Staring prover");
31+
// 2. Call zkvm and transfer to perform and verify
32+
info!("Staring prover");
2933
let (mut proof, vk) = prove_state_transition(&db, transfers.clone());
3034
let ProgramOutput {
3135
initial_state_merkle_root,
3236
post_state_merkle_root,
3337
} = proof.public_values.read::<ProgramOutput>();
34-
println!("Prover finish");
38+
info!("Prover finish");
3539

3640
// 3. If the proving went alright, update the db and verify that the merkle root matches
3741
assert!(db.commitment() == initial_state_merkle_root);
42+
// Note: we don't have to verify that the user has enough balance, as the prover already validates it
3843
for transfer in transfers {
3944
let mut user_from = db
4045
.user_states
@@ -62,37 +67,20 @@ pub async fn start_l2(
6267
// Once aligned aggregates the proof we will be notified and we'll send the new state commitment on chain
6368

6469
// 4. Send the proof to aligned and wait for verification
65-
println!("Sending proof to aligned batcher");
66-
let _ =
67-
send_proof_to_be_verified_on_aligned(&proof, PROGRAM_ELF.to_vec(), network.clone(), wallet)
68-
.await;
69-
println!("Proof submitted");
70+
info!("Sending proof to aligned batcher");
71+
let _ = send_proof_to_be_verified_on_aligned(&config, &proof, PROGRAM_ELF.to_vec()).await;
72+
info!("Proof submitted");
7073

71-
println!("Waiting until is proof is aggregated");
7274
// 5. Wait until proof is aggregated
73-
let merkle_path = wait_until_proof_is_aggregated(
74-
network.clone(),
75-
eth_rpc_url.clone(),
76-
beacon_client_url,
77-
&proof,
78-
&vk,
79-
)
80-
.await
81-
.expect("To get merkle path in last aggregated proofs");
82-
83-
println!("Proof has been aggregated on aligned, about to send update to chain.");
75+
info!("Waiting until is proof is aggregated");
76+
let merkle_path = wait_until_proof_is_aggregated(&config, &proof, &vk).await;
77+
info!("Proof has been aggregated on aligned, about to send update to chain.");
8478

8579
// 6. Send updateState transaction to Ethereum
86-
let receipt = send_state_transition_to_chain(
87-
proof.public_values.to_vec(),
88-
merkle_path,
89-
eth_rpc_url.clone(),
90-
"0xdC62Bf47Da2a2afD8Eb838C7004337613Af5C3b9".into(),
91-
"".into(),
92-
)
93-
.await;
80+
let receipt =
81+
send_state_transition_to_chain(&config, proof.public_values.to_vec(), merkle_path).await;
9482

95-
println!("State update in contracts tx receipt {:?}", receipt);
83+
info!("State update in contracts tx receipt {:?}", receipt);
9684

9785
// Finally save the db to a file to be retrieved later
9886
db.save().unwrap();

examples/L2/crates/l2/src/main.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
use std::env;
2+
3+
use aligned_sdk::core::types::Network;
4+
use dotenv::dotenv;
5+
use l2_example::{start_l2, Config};
6+
use tracing_subscriber::FmtSubscriber;
7+
8+
#[tokio::main]
9+
async fn main() {
10+
let subscriber = FmtSubscriber::builder().finish();
11+
tracing::subscriber::set_global_default(subscriber).expect("setting default subscriber failed");
12+
13+
dotenv().ok();
14+
15+
let network = match env::var("NETWORK").expect("NETWORK not set").as_str() {
16+
"holesky" => Network::Holesky,
17+
"holesky-stage" => Network::HoleskyStage,
18+
"devnet" => Network::Devnet,
19+
_ => panic!("Invalid network, possible values are: holesky, holesky-stage, devnet"),
20+
};
21+
22+
let config = Config {
23+
network,
24+
eth_rpc_url: env::var("ETH_RPC_URL").expect("ETH_RPC_URL not set"),
25+
ws_eth_rpc_url: env::var("WS_ETH_RPC_URL").expect("WS_ETH_RPC_URL not set"),
26+
beacon_client_url: env::var("BEACON_CLIENT_URL").expect("BEACON_CLIENT_URL not set"),
27+
private_key_store_path: env::var("PRIVATE_KEY_STORE_PATH")
28+
.expect("PRIVATE_KEY_STORE_PATH not set"),
29+
private_key_store_password: env::var("PRIVATE_KEY_STORE_PASSWORD")
30+
.expect("PRIVATE_KEY_STORE_PASSWORD not set"),
31+
state_transition_contract_address: env::var("STATE_TRANSITION_CONTRACT_ADDRESS")
32+
.expect("STATE_TRANSITION_CONTRACT_ADDRESS not set"),
33+
};
34+
35+
start_l2(config).await;
36+
}

examples/L2/crates/l2/src/zk.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ pub fn prove_state_transition(
2222
.prove(&pk, &stdin)
2323
.compressed()
2424
.run()
25-
.expect("Prover to run fine");
25+
.expect("Prover to run well");
2626

2727
(proof, vk)
2828
}

0 commit comments

Comments
 (0)