Skip to content

Commit 54cabea

Browse files
refactor: zkquiz setup and testing locally/devnet (#1153)
Co-authored-by: Urix <[email protected]>
1 parent dca81e0 commit 54cabea

File tree

5 files changed

+85
-50
lines changed

5 files changed

+85
-50
lines changed

batcher/aligned-sdk/src/core/types.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::str::FromStr;
2+
13
use ethers::core::k256::ecdsa::SigningKey;
24
use ethers::signers::Signer;
35
use ethers::signers::Wallet;
@@ -344,6 +346,22 @@ pub enum Network {
344346
HoleskyStage,
345347
}
346348

349+
impl FromStr for Network {
350+
type Err = String;
351+
352+
fn from_str(s: &str) -> Result<Self, Self::Err> {
353+
match s.to_lowercase().as_str() {
354+
"holesky" => Ok(Network::Holesky),
355+
"holesky-stage" => Ok(Network::HoleskyStage),
356+
"devnet" => Ok(Network::Devnet),
357+
_ => Err(
358+
"Invalid network, possible values are: \"holesky\", \"holesky-stage\", \"devnet\""
359+
.to_string(),
360+
),
361+
}
362+
}
363+
}
364+
347365
#[cfg(test)]
348366
mod tests {
349367
use ethers::signers::LocalWallet;

examples/zkquiz/Makefile

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
1+
SHELL := /bin/bash
2+
13
deploy_verifier:
24
@. ./contracts/.env && . ./contracts/deploy.sh
35

6+
deploy_verifier_devnet:
7+
@. ./contracts/.devnet.env && . ./contracts/deploy.sh
8+
49
CONTRACT_ADDRESS=0xA828f1463074d26FB761c662F80194f5dB2d31D0
510
RPC_URL=https://ethereum-holesky-rpc.publicnode.com
611
VERIFICATION_DATA=./aligned_verification_data/0a1fab5df88a71e48633cbdeedc8d1a234b790d15a8a2fd04cd6a03c1e05b5ef_212.json
@@ -10,3 +15,11 @@ answer_quiz:
1015
--keystore-path $(KEYSTORE_PATH) \
1116
--rpc-url $(RPC_URL) \
1217
--verifier-contract-address $(CONTRACT_ADDRESS)
18+
19+
answer_quiz_local:
20+
@cd quiz/script && cargo run -r -- \
21+
--keystore-path ../../../../config-files/devnet/keys/operator-3.ecdsa.key.json \
22+
--rpc-url http://localhost:8545 \
23+
--batcher-url ws://localhost:8080 \
24+
--network devnet \
25+
--verifier-contract-address $(CONTRACT_ADDRESS)

examples/zkquiz/README.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,3 +52,25 @@ This will:
5252
3. Pay & submit proof to aligned for verification
5353
4. Wait for proof to be verified in aligned
5454
5. Claim NFT if proof is verified
55+
56+
## Testing locally
57+
58+
If you want to test the zk quiz on a local network follow these steps:
59+
60+
1. Setup Aligned locally following [this guide](../../docs/3_guides/6_setup_aligned.md)
61+
62+
3. Move into the zkquiz example:
63+
```
64+
cd examples/zkquiz
65+
```
66+
67+
4. Deploy the ZKQuiz verifier contract, and locate the `CONTRACT_ADDRESS` from its output:
68+
```
69+
make deploy_verifier_devnet
70+
```
71+
72+
73+
5. Run the quiz:
74+
```
75+
CONTRACT_ADDRESS=<VERIFIER_CONTRACT_ADDRESS> make answer_quiz_local
76+
```
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
RPC_URL=http://localhost:8545
2+
PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 # a rich anvil account
3+
ALIGNED_SERVICE_MANAGER_ADDRESS=0x1613beB3B2C4f22Ee086B2b38C1476A3cE7f78E8
4+
BATCHER_PAYMENT_SERVICE_ADDRESS=0x7969c5eD335650692Bc04293B07F5BF2e7A673C0

examples/zkquiz/quiz/script/src/main.rs

Lines changed: 28 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
11
#![feature(slice_flatten)]
2-
32
use std::io;
4-
use std::sync::Arc;
53

64
use aligned_sdk::core::types::{
75
AlignedVerificationData, Network, PriceEstimate, ProvingSystemId, VerificationData,
86
};
9-
use aligned_sdk::sdk::{estimate_fee, get_payment_service_address};
7+
use aligned_sdk::sdk::{deposit_to_aligned, estimate_fee};
108
use aligned_sdk::sdk::{get_next_nonce, submit_and_wait_verification};
119
use clap::Parser;
1210
use dialoguer::Confirm;
@@ -18,11 +16,8 @@ use sp1_sdk::{ProverClient, SP1Stdin};
1816

1917
abigen!(VerifierContract, "VerifierContract.json",);
2018

21-
const BATCHER_URL: &str = "wss://batcher.alignedlayer.com";
2219
const ELF: &[u8] = include_bytes!("../../program/elf/riscv32im-succinct-zkvm-elf");
2320

24-
const NETWORK: Network = Network::Holesky;
25-
2621
#[derive(Parser, Debug)]
2722
#[command(version, about, long_about = None)]
2823
struct Args {
@@ -34,6 +29,10 @@ struct Args {
3429
default_value = "https://ethereum-holesky-rpc.publicnode.com"
3530
)]
3631
rpc_url: String,
32+
#[arg(short, long, default_value = "wss://batcher.alignedlayer.com")]
33+
batcher_url: String,
34+
#[arg(short, long, default_value = "holesky")]
35+
network: Network,
3736
#[arg(short, long)]
3837
verifier_contract_address: H160,
3938
}
@@ -48,20 +47,27 @@ async fn main() {
4847
let keystore_password = rpassword::prompt_password("Enter keystore password: ")
4948
.expect("Failed to read keystore password");
5049

51-
let wallet = LocalWallet::decrypt_keystore(args.keystore_path, &keystore_password)
52-
.expect("Failed to decrypt keystore")
53-
.with_chain_id(17000u64);
54-
5550
let provider =
5651
Provider::<Http>::try_from(rpc_url.as_str()).expect("Failed to connect to provider");
5752

58-
let signer = Arc::new(SignerMiddleware::new(provider.clone(), wallet.clone()));
53+
let chain_id = provider
54+
.get_chainid()
55+
.await
56+
.expect("Failed to get chain_id");
57+
58+
let wallet = LocalWallet::decrypt_keystore(args.keystore_path, &keystore_password)
59+
.expect("Failed to decrypt keystore")
60+
.with_chain_id(chain_id.as_u64());
61+
62+
let signer = SignerMiddleware::new(provider.clone(), wallet.clone());
5963

6064
if Confirm::with_theme(&dialoguer::theme::ColorfulTheme::default())
6165
.with_prompt("Do you want to deposit 0.004eth in Aligned ?\nIf you already deposited Ethereum to Aligned before, this is not needed")
6266
.interact()
6367
.expect("Failed to read user input") {
64-
deposit_to_batcher(wallet.address(), signer.clone()).await.expect("Failed to pay for proof submission");
68+
69+
deposit_to_aligned(U256::from(4000000000000000u128), signer.clone(), args.network).await
70+
.expect("Failed to pay for proof submission");
6571
}
6672

6773
// Generate proof.
@@ -114,7 +120,7 @@ async fn main() {
114120
pub_input: None,
115121
};
116122

117-
let max_fee = estimate_fee(&rpc_url, PriceEstimate::Default)
123+
let max_fee = estimate_fee(&rpc_url, PriceEstimate::Instant)
118124
.await
119125
.expect("failed to fetch gas price from the blockchain");
120126

@@ -126,14 +132,16 @@ async fn main() {
126132
.expect("Failed to read user input")
127133
{ return; }
128134

129-
let nonce = get_next_nonce(&rpc_url, wallet.address(), NETWORK)
135+
let nonce = get_next_nonce(&rpc_url, wallet.address(), args.network)
130136
.await
131137
.expect("Failed to get next nonce");
132138

139+
println!("Submitting your proof...");
140+
133141
let aligned_verification_data = submit_and_wait_verification(
134-
BATCHER_URL,
142+
&args.batcher_url,
135143
&rpc_url,
136-
NETWORK,
144+
args.network,
137145
&verification_data,
138146
max_fee,
139147
wallet.clone(),
@@ -143,9 +151,10 @@ async fn main() {
143151
.unwrap();
144152

145153
println!(
146-
"Proof submitted and verified successfully on batch {}, claiming prize...",
154+
"Proof submitted and verified successfully on batch {}",
147155
hex::encode(aligned_verification_data.batch_merkle_root)
148156
);
157+
println!("Claiming NFT prize...");
149158

150159
claim_nft_with_verified_proof(
151160
&aligned_verification_data,
@@ -193,43 +202,12 @@ fn read_answer() -> char {
193202
}
194203
}
195204

196-
async fn deposit_to_batcher(
197-
from: Address,
198-
signer: Arc<SignerMiddleware<Provider<Http>, LocalWallet>>,
199-
) -> anyhow::Result<()> {
200-
let addr = get_payment_service_address(NETWORK);
201-
202-
let tx = TransactionRequest::new()
203-
.from(from)
204-
.to(addr)
205-
.value(4000000000000000u128);
206-
207-
match signer
208-
.send_transaction(tx, None)
209-
.await
210-
.map_err(|e| anyhow::anyhow!("Failed to send tx {}", e))?
211-
.await
212-
.map_err(|e| anyhow::anyhow!("Failed to submit tx {}", e))?
213-
{
214-
Some(receipt) => {
215-
println!(
216-
"Payment sent. Transaction hash: {:x}",
217-
receipt.transaction_hash
218-
);
219-
Ok(())
220-
}
221-
None => {
222-
anyhow::bail!("Payment failed");
223-
}
224-
}
225-
}
226-
227205
async fn claim_nft_with_verified_proof(
228206
aligned_verification_data: &AlignedVerificationData,
229-
signer: Arc<SignerMiddleware<Provider<Http>, LocalWallet>>,
207+
signer: SignerMiddleware<Provider<Http>, LocalWallet>,
230208
verifier_contract_addr: &Address,
231209
) -> anyhow::Result<()> {
232-
let verifier_contract = VerifierContract::new(*verifier_contract_addr, signer);
210+
let verifier_contract = VerifierContract::new(*verifier_contract_addr, signer.into());
233211

234212
let index_in_batch = U256::from(aligned_verification_data.index_in_batch);
235213
let merkle_path = Bytes::from(

0 commit comments

Comments
 (0)