You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

95 lines
2.7 KiB

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