pod2-blob-example/src/main.rs
src/main.rsRaw
1use alloy::{
2 consensus::{SidecarBuilder, SimpleCoder},
3 eips::eip4844::DATA_GAS_PER_BLOB,
4 network::{TransactionBuilder, TransactionBuilder4844},
5 primitives::Address,
6 providers::{Provider, ProviderBuilder},
7 rpc::types::TransactionRequest,
8 signers::local::PrivateKeySigner,
9};
10use anyhow::Result;
11use std::{
12 fs,
13 fs::File,
14 io::{BufReader, Read, Write},
15 time::Instant,
16};
17
18use pod2::{
19 backends::plonky2::{basetypes::DEFAULT_VD_SET, mainpod::Prover},
20 frontend::{MainPodBuilder, Operation},
21 middleware::{containers::Set, Params},
22};
23
24// ethereum private key to use for the tx
25const PRIV_KEY: &str = "PLACE THE ETHEREUM PRIV KEY HERE";
26// ethereum node rpc url
27const RPC_URL: &str = "PLACE THE RPC URL HERE";
28
29
30// returns a MainPod, example adapted from pod2/examples/main_pod_points.rs
31pub fn compute_pod_proof() -> Result<pod2::frontend::MainPod> {
32 let params = Params {
33 max_input_pods: 0,
34 ..Default::default()
35 };
36
37 let mut builder = MainPodBuilder::new(¶ms, &DEFAULT_VD_SET);
38 let set_entries = [1, 2, 3].into_iter().map(|n| n.into()).collect();
39 let set = Set::new(10, set_entries)?;
40
41 builder.pub_op(Operation::set_contains(set, 1))?;
42
43 let prover = Prover {};
44 let pod = builder.prove(&prover).unwrap();
45 Ok(pod)
46}
47
48#[tokio::main]
49async fn main() -> Result<()> {
50 // PART 1: generate a pod2 proof, and wrap it into one level recursive proof
51 // in order to shrink its size
52
53 // use the compute_pod_proof to obtain an example pod2 proof
54 println!("start to generate a pod2 proof");
55 let start = Instant::now();
56 let pod = compute_pod_proof()?;
57 println!(
58 "[TIME] generate pod & compute pod proof took: {:?}",
59 start.elapsed()
60 );
61 // generate new plonky2 proof from POD's proof. This is 1 extra recursion in
62 // order to shrink the proof size, together with removing extra custom gates
63 let start = Instant::now();
64 let (verifier_data, common_circuit_data, proof_with_pis) = pod2_onchain::prove_pod(pod)?;
65 println!("[TIME] plonky2 (wrapper) proof took: {:?}", start.elapsed());
66
67 // get the compressed proof, which we will send inside a blob
68 let compressed_proof = proof_with_pis.compress(
69 &verifier_data.verifier_only.circuit_digest,
70 &common_circuit_data.common,
71 )?;
72 let compressed_proof_bytes = compressed_proof.to_bytes();
73 // store it in a file just in case we want to check it later
74 let mut file = fs::File::create("proof_with_public_inputs.bin")?;
75 file.write_all(&compressed_proof_bytes)?;
76 dbg!(&compressed_proof_bytes.len());
77
78 // alternatively, instead of generating the pod2 proof, we can load a
79 // previously stored proof with public inputs from the file
80 /*
81 let file = File::open("./proof_with_public_inputs.bin")?;
82 let mut reader = BufReader::new(file);
83 let mut compressed_proof_bytes = Vec::new();
84 reader.read_to_end(&mut compressed_proof_bytes)?;
85 */
86 println!("size of proof_with_pis: {}", compressed_proof_bytes.len());
87
88 // PART 2: send the pod2 proof into a tx blob
89 let signer: PrivateKeySigner = PRIV_KEY.parse()?;
90 let provider = ProviderBuilder::new()
91 .wallet(signer.clone())
92 .connect(RPC_URL)
93 .await?;
94
95 let latest_block = provider.get_block_number().await?;
96 println!("Latest block number: {latest_block}");
97
98 let alice = signer.address();
99 let bob = Address::from([0x42; 20]);
100 dbg!(&alice);
101 dbg!(&bob);
102
103 let sidecar: SidecarBuilder<SimpleCoder> = SidecarBuilder::from_slice(&compressed_proof_bytes);
104 let sidecar = sidecar.build()?;
105
106 let tx = TransactionRequest::default()
107 // 'from' field is filled by signer's first address (Alice in our case)
108 .with_to(bob)
109 .with_blob_sidecar(sidecar);
110
111 let pending_tx = provider.send_transaction(tx).await?;
112
113 println!("Pending transaction... tx hash: {}", pending_tx.tx_hash());
114
115 let receipt = pending_tx.get_receipt().await?;
116
117 println!(
118 "Transaction included in block {}",
119 receipt.block_number.expect("Failed to get block number")
120 );
121
122 assert_eq!(receipt.from, alice);
123 assert_eq!(receipt.to, Some(bob));
124 assert_eq!(
125 receipt
126 .blob_gas_used
127 .expect("Expected to be EIP-4844 transaction"),
128 DATA_GAS_PER_BLOB
129 );
130
131 Ok(())
132}