Skip to content

Commit cb5e7f2

Browse files
committed
feat: loop in start_l2, rename zk module, updated initial state and better docs
1 parent 1d6f53d commit cb5e7f2

File tree

6 files changed

+81
-79
lines changed

6 files changed

+81
-79
lines changed

examples/L2/contracts/.env.holesky

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
RPC_URL=https://ethereum-holesky-rpc.publicnode.com
22
# Initial state root of db, see in crates/l2/db.rs
3-
INITIAL_STATE_ROOT=0x454691b501bc38536f4156a5b7d86502c49d13710d5e5b52b22c563fff4afee0
3+
INITIAL_STATE_ROOT=0x3c1d1c01f8e0a4533085bc9d8a3829c5f6872e6d6cf62e04ae71acbc803747ce
44
# You can read it from crates/l2/programs_ids.json and generate it via make generate_program_id
55
PROGRAM_ID=0x5961f68d41b2798f4dab05184d8f9cda39637d28097819906033c2f10b365ab1
66
# Address of the wallet you want to set as owner

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

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ pub async fn send_proof_to_be_verified_on_aligned(
1919
vm_program_code: Vec<u8>,
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();
22+
let chain_id = get_chain_id(&config.eth_rpc_url).await.expect("To query chain id from rpc");
2323
let wallet = Wallet::decrypt_keystore(
2424
&config.private_key_store_path,
2525
&config.private_key_store_password,
@@ -47,17 +47,15 @@ pub async fn send_proof_to_be_verified_on_aligned(
4747
.await
4848
.expect("Max fee to be retrieved");
4949

50-
let aligned_verification_data = aligned_sdk::sdk::submit(
50+
aligned_sdk::sdk::submit(
5151
config.network.clone(),
5252
&verification_data,
5353
max_fee,
5454
wallet,
55-
nonce.into(),
55+
nonce,
5656
)
5757
.await
58-
.expect("Proof to be sent");
59-
60-
aligned_verification_data
58+
.expect("Proof to be sent")
6159
}
6260

6361
pub async fn wait_until_proof_is_aggregated(
@@ -88,7 +86,7 @@ pub async fn wait_until_proof_is_aggregated(
8886

8987
let mut merkle_path = vec![];
9088

91-
while let Some(_) = stream.next().await {
89+
while stream.next().await.is_some() {
9290
if let Some(merkle_proof) = aligned_sdk::sdk::aggregation::get_merkle_path_for_proof(
9391
config.network.clone(),
9492
config.eth_rpc_url.clone(),

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

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use std::{
88
use lambdaworks_crypto::merkle_tree::merkle::MerkleTree;
99
use primitive_types::{H160, U256};
1010
use rand::Rng;
11+
use tracing::warn;
1112
use types::{Transfer, UserState};
1213

1314
pub struct DB {
@@ -17,6 +18,7 @@ pub struct DB {
1718

1819
#[derive(Debug)]
1920
pub enum DBError {
21+
#[allow(dead_code)]
2022
IO(String),
2123
}
2224

@@ -25,7 +27,7 @@ impl DB {
2527
match Self::new_from_file(file_path.clone()) {
2628
Ok(db) => db,
2729
Err(e) => {
28-
println!("Error when loading db from file {:?}, will start a new db with a default initial state", e);
30+
warn!("Error when loading db from file {:?}, will start a new db with a default initial state", e);
2931
// if db does not exists, create one with initial state
3032
let initial_state = Self::initial_state();
3133
let mut user_states: BTreeMap<H160, UserState> = BTreeMap::new();
@@ -71,12 +73,11 @@ impl DB {
7173

7274
pub fn commitment(&self) -> [u8; 32] {
7375
let values: Vec<UserState> = self.user_states.clone().into_values().collect();
74-
let root = MerkleTree::<UserState>::build(&values).unwrap().root;
75-
root
76+
MerkleTree::<UserState>::build(&values).unwrap().root
7677
}
7778

7879
/// Db genesis state used if a file is not provided
79-
/// Its commitment is: 0x454691b501bc38536f4156a5b7d86502c49d13710d5e5b52b22c563fff4afee0
80+
/// Its commitment is: 0x3c1d1c01f8e0a4533085bc9d8a3829c5f6872e6d6cf62e04ae71acbc803747ce
8081
fn initial_state() -> Vec<UserState> {
8182
vec![
8283
UserState {
@@ -87,17 +88,17 @@ impl DB {
8788
UserState {
8889
address: H160::from_str("0x53d284357ec70cE289D6D64134DfAc8E511c8a3D").unwrap(),
8990
balance: U256::from_dec_str("50000000000000000000").unwrap(),
90-
nonce: U256::from(1),
91+
nonce: U256::from(0),
9192
},
9293
UserState {
9394
address: H160::from_str("0xfe9e8709d3215310075d67e3ed32a380ccf451c8").unwrap(),
9495
balance: U256::from_dec_str("250000000000000000000").unwrap(),
95-
nonce: U256::from(2),
96+
nonce: U256::from(0),
9697
},
9798
UserState {
9899
address: H160::from_str("0xab5801a7d398351b8be11c439e05c5b3259aec9b").unwrap(),
99100
balance: U256::from_dec_str("75000000000000000000").unwrap(),
100-
nonce: U256::from(5),
101+
nonce: U256::from(0),
101102
},
102103
]
103104
}

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

Lines changed: 65 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@ use eth::send_state_transition_to_chain;
44
use primitive_types::U256;
55
use sp1_state_transition_program::ProgramOutput;
66
use tracing::info;
7-
use zk::{prove_state_transition, PROGRAM_ELF};
7+
use prover::{prove_state_transition, PROGRAM_ELF};
88

99
mod aligned;
1010
mod db;
1111
mod eth;
12-
mod zk;
12+
mod prover;
1313

1414
pub struct Config {
1515
pub network: aligned_sdk::core::types::Network,
@@ -25,66 +25,69 @@ pub async fn start_l2(config: Config) {
2525
// 0. Load merkle tree file, if not created, create initial state
2626
let mut db = DB::new("./db".to_string());
2727

28-
// 1. Create random transfers
29-
let transfers = generate_random_transfers(&db, 10);
30-
31-
// 2. Call zkvm and transfer to perform and verify
32-
info!("Starting prover");
33-
let (mut proof, vk) = prove_state_transition(&db, transfers.clone());
34-
let ProgramOutput {
35-
initial_state_merkle_root,
36-
post_state_merkle_root,
37-
} = proof.public_values.read::<ProgramOutput>();
38-
info!("Prover finish");
39-
40-
// 3. If the proving went alright, update the db and verify that the merkle root matches
41-
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
43-
for transfer in transfers {
44-
let mut user_from = db
45-
.user_states
46-
.get(&transfer.from)
47-
.expect("User must exist in state")
48-
.clone();
49-
50-
let mut user_to = db
51-
.user_states
52-
.get(&transfer.to)
53-
.expect("User must exist in state")
54-
.clone();
55-
56-
user_from.balance -= transfer.amount;
57-
user_from.nonce += U256::one();
58-
user_to.balance += transfer.amount;
59-
60-
db.user_states.insert(transfer.from, user_from);
61-
db.user_states.insert(transfer.to, user_to);
28+
loop {
29+
// 1. Create random transfers
30+
let transfers = generate_random_transfers(&db, 10);
31+
32+
// 2. Call zkvm and transfer to perform and verify
33+
info!("Starting prover...");
34+
let (mut proof, vk) = prove_state_transition(&db, transfers.clone());
35+
let ProgramOutput {
36+
initial_state_merkle_root,
37+
post_state_merkle_root,
38+
} = proof.public_values.read::<ProgramOutput>();
39+
info!("Prover finish");
40+
41+
// 3. If the proving went alright, update the db and verify that the merkle root matches
42+
assert!(db.commitment() == initial_state_merkle_root);
43+
// Note: we don't have to verify that the user has enough balance, as the prover already validates it
44+
for transfer in transfers {
45+
let mut user_from = db
46+
.user_states
47+
.get(&transfer.from)
48+
.expect("User must exist in state")
49+
.clone();
50+
51+
let mut user_to = db
52+
.user_states
53+
.get(&transfer.to)
54+
.expect("User must exist in state")
55+
.clone();
56+
57+
user_from.balance -= transfer.amount;
58+
user_from.nonce += U256::one();
59+
user_to.balance += transfer.amount;
60+
61+
db.user_states.insert(transfer.from, user_from);
62+
db.user_states.insert(transfer.to, user_to);
63+
}
64+
assert!(db.commitment() == post_state_merkle_root);
65+
66+
// Fow now, in order for a proof to be aggregated, we first need to submit it via the fast mode or verification layer
67+
// Let's suppose that our L2 would run the prover once every 24hs and submit it on aligned
68+
// Once aligned aggregates the proof we will be notified and we'll send the new state commitment on chain
69+
70+
// 4. Send the proof to aligned and wait for verification
71+
info!("Sending proof to aligned batcher...");
72+
let _ = send_proof_to_be_verified_on_aligned(&config, &proof, PROGRAM_ELF.to_vec()).await;
73+
info!("Proof submitted");
74+
75+
// 5. Wait until proof is aggregated
76+
info!("Waiting until is proof is aggregated...");
77+
let merkle_path = wait_until_proof_is_aggregated(&config, &proof, &vk).await;
78+
info!("Proof has been aggregated on aligned, about to send update to chain...");
79+
80+
// 6. Send updateState transaction to Ethereum
81+
let receipt =
82+
send_state_transition_to_chain(&config, proof.public_values.to_vec(), merkle_path).await;
83+
84+
info!(
85+
"State update in contracts tx hash: {:?}",
86+
receipt.transaction_hash
87+
);
88+
89+
// 7. Finally save the db to a file to be retrieved later
90+
db.save().unwrap();
6291
}
63-
assert!(db.commitment() == post_state_merkle_root);
64-
65-
// Fow now, in order for a proof to be aggregated, we first need to submit it via the fast mode or verification layer
66-
// Let's suppose that our L2 would run the prover once every 24hs and submit it on aligned
67-
// Once aligned aggregates the proof we will be notified and we'll send the new state commitment on chain
68-
69-
// 4. Send the proof to aligned and wait for verification
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");
73-
74-
// 5. Wait until proof is aggregated
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.");
78-
79-
// 6. Send updateState transaction to Ethereum
80-
let receipt =
81-
send_state_transition_to_chain(&config, proof.public_values.to_vec(), merkle_path).await;
82-
83-
info!(
84-
"State update in contracts tx hash: {:?}",
85-
receipt.transaction_hash
86-
);
8792

88-
// Finally save the db to a file to be retrieved later
89-
db.save().unwrap();
9093
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ impl IsMerkleTreeBackend for UserState {
2323
leaf.nonce.to_little_endian(&mut nonce_bytes);
2424

2525
hasher.update(leaf.address);
26-
hasher.update(&balance_bytes);
27-
hasher.update(&nonce_bytes);
26+
hasher.update(balance_bytes);
27+
hasher.update(nonce_bytes);
2828
hasher.finalize().into()
2929
}
3030

0 commit comments

Comments
 (0)