arnaucube
arnaucube/circom-compatPublic Self-hosted repository
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, &params, &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}