circom-compat/tests/solidity.rs
tests/solidity.rsRaw
1use ark_circom::{
2 ethereum::{Inputs, Proof, VerifyingKey},
3 CircomBuilder, CircomConfig,
4};
5use ark_std::rand::thread_rng;
6use color_eyre::Result;
7
8use ark_bn254::Bn254;
9use ark_groth16::{create_random_proof as prove, generate_random_parameters};
10
11use ethers::{
12 contract::{abigen, ContractError, ContractFactory},
13 providers::{Http, Middleware, Provider},
14 utils::{compile_and_launch_ganache, Ganache, Solc},
15};
16
17use std::{convert::TryFrom, sync::Arc};
18
19#[tokio::test]
20async fn solidity_verifier() -> Result<()> {
21 let cfg = CircomConfig::<Bn254>::new(
22 "./test-vectors/mycircuit.wasm",
23 "./test-vectors/mycircuit.r1cs",
24 )?;
25 let mut builder = CircomBuilder::new(cfg);
26 builder.push_input("a", 3);
27 builder.push_input("b", 11);
28
29 // create an empty instance for setting it up
30 let circom = builder.setup();
31
32 let mut rng = thread_rng();
33 let params = generate_random_parameters::<Bn254, _, _>(circom, &mut rng)?;
34
35 let circom = builder.build()?;
36 let inputs = circom.get_public_inputs().unwrap();
37
38 let proof = prove(circom, ¶ms, &mut rng)?;
39
40 // launch the network & compile the verifier
41 let (compiled, ganache) =
42 compile_and_launch_ganache(Solc::new("./tests/verifier.sol"), Ganache::new()).await?;
43 let acc = ganache.addresses()[0];
44 let provider = Provider::<Http>::try_from(ganache.endpoint())?;
45 let provider = provider.with_sender(acc);
46 let provider = Arc::new(provider);
47
48 // deploy the verifier
49 let contract = {
50 let contract = compiled
51 .get("TestVerifier")
52 .expect("could not find contract");
53
54 let factory = ContractFactory::new(
55 contract.abi.clone(),
56 contract.bytecode.clone(),
57 provider.clone(),
58 );
59 let contract = factory.deploy(())?.send().await?;
60 let addr = contract.address();
61 Groth16Verifier::new(addr, provider)
62 };
63
64 // check the proof
65 let verified = contract
66 .check_proof(proof, params.vk, inputs.as_slice())
67 .await?;
68 assert!(verified);
69
70 Ok(())
71}
72
73abigen!(Groth16Verifier, "./tests/verifier_abi.json");
74
75impl<M: Middleware> Groth16Verifier<M> {
76 async fn check_proof<I: Into<Inputs>, P: Into<Proof>, VK: Into<VerifyingKey>>(
77 &self,
78 proof: P,
79 vk: VK,
80 inputs: I,
81 ) -> Result<bool, ContractError<M>> {
82 // convert into the expected format by the contract
83 let proof = proof.into().as_tuple();
84 let vk = vk.into().as_tuple();
85 let inputs = inputs.into().0;
86
87 // query the contract
88 let res = self.verify(inputs, proof, vk).call().await?;
89
90 Ok(res)
91 }
92}