fn main() {
let n = 10000;
let wasm_binary = fs::read("res/fib.wasm").expect("No wasm");
let prefix = "zkwasm";
let zkwasm_k = 24;
let function_name = "entrypoint";
let output_dir: PathBuf = "zk".into();
let public_inputs: Vec<u64> = vec![n];
let private_inputs: Vec<u64> = vec![];
let proof_path: PathBuf = "zk/zkwasm.0.transcript.data".into();
/////////// setup
let start = std::time::Instant::now();
let circuit = build_circuit_without_witness(&wasm_binary, function_name);
let params = {
let params_path = &output_dir.join(format!("K{}.params", zkwasm_k));
load_or_build_unsafe_params::<Bn256>(zkwasm_k, Some(params_path))
};
{
let vk_path = &output_dir.join(format!("{}.{}.vkey.data", prefix, 0));
load_or_build_vkey::<Bn256, _>(¶ms, &circuit, Some(vk_path))
};
println!("setup time: {:?}", start.elapsed());
/////////// proof
let start = std::time::Instant::now();
let circuit =
build_circuit_with_witness(&wasm_binary, function_name, &public_inputs, &private_inputs).expect("=== Something went wrong");
let mut public_inputs_fri = public_inputs
.iter()
.map(|v| Fr::from(*v))
.collect::<Vec<_>>()
.clone();
let mut instances = vec![];
instances.append(&mut public_inputs_fri);
circuit.tables.write_json(Some(output_dir.clone()));
let vkey = load_vkey::<Bn256, TestCircuit<_>>(
¶ms,
&output_dir.join(format!("{}.{}.vkey.data", prefix, 0)),
);
load_or_create_proof::<Bn256, _>(
¶ms,
vkey,
circuit.clone(),
&[&instances],
Some(&output_dir.join(format!("{}.{}.transcript.data", prefix, 0))),
TranscriptHash::Poseidon,
false,
);
println!("proof time: {:?}", start.elapsed());
/////////// dry run
build_circuit_with_witness(&wasm_binary, function_name, &public_inputs, &private_inputs);
/////////// verify
let start = std::time::Instant::now();
let public_inputs_size = public_inputs.len() + 1;
let mut public_inputs_fri = public_inputs
.iter()
.map(|v| Fr::from(*v))
.collect::<Vec<_>>()
.clone();
let instances = {
let mut instances = vec![];
instances.append(&mut public_inputs_fri);
instances
};
let vkey = load_vkey::<Bn256, TestCircuit<_>>(
¶ms,
&output_dir.join(format!("{}.{}.vkey.data", prefix, 0)),
);
let proof = load_proof(&proof_path);
let params_verifier: ParamsVerifier<Bn256> = params.verifier(public_inputs_size).unwrap();
let strategy = SingleVerifier::new(¶ms_verifier);
verify_proof(
¶ms_verifier,
&vkey,
strategy,
&[&[&instances]],
&mut PoseidonRead::init(&proof[..]),
)
.expect("Something is incorrect noooooooo");
println!("verify time: {:?}", start.elapsed());
}
I'm not able to run pretty simple fibonacci guest function in zkWasm with reasonable performance, meaning I won't be able to run my custom tough app on it.
I've tried to launch that fibonacci program on zkWasm for
n > 10000and it always ends inassertion failed: event_table.0.len() * EVENT_TABLE_ENTRY_ROWS as usize <= self.max_available_rows). I've tried to increasekfrom default18up to24and more, and got the same error. Fork=25setup run for more than 20mins, btw.I understand that wasm is a pretty complex case to zk-verify, but failing calculate fibonacci program means for me no production code could be run on zkWasm. Moreover, other zk-sokutions (such as risk-0) show much better performance. For instance, I'm able to generate proof for
n=150000in 2 mins and verify it for 5ms, compared to my best result with zkWasm withn=1000with proof generation in 1.5 mins and verification in 170ms.The question is - is there any way to run the full setup-proof-verify cycle for such a large
nlike 10000? Is there any parameter other thankwhich I can change?Here is the guest function
log_foreignis just a renamed methodlogadded inregister_log_foreign.I've used methods same as cli uses and my host looks like this
I tried using both
mainand latestv2branches ofzkWasmwith default features. I'm running these benchmarks on my M1 mac btw.