circom-compat/tests/solidity.rs
tests/solidity.rsRaw
1use ark_circom::{
2 ethereum::{Inputs, Proof, VerifyingKey},
3 CircomBuilder, CircuitConfig,
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 = CircuitConfig::<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!(
74 Groth16Verifier,
75 "./tests/verifier_abi.json"
76);
77
78impl<M: Middleware> Groth16Verifier<M> {
79 async fn check_proof<I: Into<Inputs>, P: Into<Proof>, VK: Into<VerifyingKey>>(
80 &self,
81 proof: P,
82 vk: VK,
83 inputs: I,
84 ) -> Result<bool, ContractError<M>> {
85 // convert into the expected format by the contract
86 let proof = proof.into().as_tuple();
87 let vk = vk.into().as_tuple();
88 let inputs = inputs.into().0;
89
90 // query the contract
91 let res = self.verify(inputs, proof, vk).call().await?;
92
93 Ok(res)
94 }
95}