1
0
Fork 0
mirror of synced 2025-09-24 04:40:05 +00:00

Merge pull request #927 from Zokrates/marlin

Add support for Marlin
This commit is contained in:
Thibaut Schaeffer 2021-07-09 10:37:33 +02:00 committed by GitHub
commit 69b2dd8178
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
29 changed files with 1110 additions and 493 deletions

1
.gitignore vendored
View file

@ -11,6 +11,7 @@ proving.key
verification.key
verifier.sol
proof.json
universal_setup.dat
witness
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries

497
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1 @@
Add support for the Marlin proving scheme

View file

@ -14,6 +14,7 @@ Proving schemes supported by ZoKrates require a pairing-friendly elliptic curve.
Default: `ALT_BN128`
When not using the default, the CLI flag has to be provided for the following commands:
- `universal-setup`
- `compile`
- `export-verifier`
- `verify`
@ -22,15 +23,19 @@ When not using the default, the CLI flag has to be provided for the following co
ZoKrates supports different proving schemes. We identify the schemes by the reference to the paper that introduced them. Currently the options available are:
| Scheme | CLI flag | Curves |
| ---- | -------- | ------ |
| [G16](https://eprint.iacr.org/2016/260) | `--proving-scheme g16` | ALTBN_128, BLS12_381 |
| [GM17](https://eprint.iacr.org/2017/540) | `--proving-scheme gm17` | ALTBN_128, BLS12_377, BW6_761 |
| [PGHR13](https://eprint.iacr.org/2013/279) | `--proving-scheme pghr13` | ALTBN_128 |
| Scheme | CLI flag | Curves | Universal |
| ---- | -------- | ------ | ------------|
| [G16](https://eprint.iacr.org/2016/260) | `--proving-scheme g16` | ALTBN_128, BLS12_381 | No |
| [GM17](https://eprint.iacr.org/2017/540) | `--proving-scheme gm17` | ALTBN_128, BLS12_377, BW6_761 | No |
| [Marlin](https://eprint.iacr.org/2019/1047) | `--proving-scheme marlin` | ALTBN_128, BLS12_377, BW6_761 | Yes |
| [PGHR13](https://eprint.iacr.org/2013/279) | `--proving-scheme pghr13` | ALTBN_128 | No |
Default: `G16`
All schemes have a circuit-specific setup phase called `setup`. Universal schemes also feature a preliminary, circuit-agnostic step called `universal-setup`. The advantage of universal schemes is that only the `universal-setup` step requires trust, so that it can be run a single time and reused trustlessly for many programs.
Default: `G16`, except for `universal-setup` for which the default is `Marlin`
When not using the default, the CLI flag has to be provided for the following commands:
- `universal-setup`
- `setup`
- `export-verifier`
- `generate-proof`
@ -49,6 +54,7 @@ ZoKrates supports multiple backends. The options are the following:
Default: `bellman`
When not using the default, the CLI flag has to be provided for the following commands:
- `universal-setup`
- `setup`
- `generate-proof`
- `verify`

View file

@ -43,6 +43,8 @@ fn cli() -> Result<(), String> {
compile::subcommand(),
check::subcommand(),
compute_witness::subcommand(),
#[cfg(feature = "ark")]
universal_setup::subcommand(),
#[cfg(any(feature = "bellman", feature = "ark", feature = "libsnark"))]
setup::subcommand(),
export_verifier::subcommand(),
@ -58,6 +60,8 @@ fn cli() -> Result<(), String> {
("compile", Some(sub_matches)) => compile::exec(sub_matches),
("check", Some(sub_matches)) => check::exec(sub_matches),
("compute-witness", Some(sub_matches)) => compute_witness::exec(sub_matches),
#[cfg(feature = "ark")]
("universal-setup", Some(sub_matches)) => universal_setup::exec(sub_matches),
#[cfg(any(feature = "bellman", feature = "ark", feature = "libsnark"))]
("setup", Some(sub_matches)) => setup::exec(sub_matches),
("export-verifier", Some(sub_matches)) => export_verifier::exec(sub_matches),

View file

@ -5,6 +5,8 @@ pub const PROVING_KEY_DEFAULT_PATH: &str = "proving.key";
pub const VERIFICATION_CONTRACT_DEFAULT_PATH: &str = "verifier.sol";
pub const WITNESS_DEFAULT_PATH: &str = "witness";
pub const JSON_PROOF_PATH: &str = "proof.json";
pub const UNIVERSAL_SETUP_DEFAULT_PATH: &str = "universal_setup.dat";
pub const UNIVERSAL_SETUP_DEFAULT_SIZE: &str = "10";
pub const SMTLIB2_DEFAULT_PATH: &str = "out.smt2";
pub const BELLMAN: &str = "bellman";
@ -54,5 +56,7 @@ pub const CURVES: &[&str] = &[BN128, BLS12_381, BLS12_377, BW6_761];
pub const G16: &str = "g16";
pub const PGHR13: &str = "pghr13";
pub const GM17: &str = "gm17";
pub const MARLIN: &str = "marlin";
pub const SCHEMES: &[&str] = &[G16, PGHR13, GM17];
pub const SCHEMES: &[&str] = &[G16, PGHR13, GM17, MARLIN];
pub const UNIVERSAL_SCHEMES: &[&str] = &[MARLIN];

View file

@ -9,6 +9,7 @@ pub enum CurveParameter {
Bw6_761,
}
#[derive(Debug)]
pub enum BackendParameter {
#[cfg(feature = "bellman")]
Bellman,
@ -19,10 +20,12 @@ pub enum BackendParameter {
}
#[allow(clippy::upper_case_acronyms)]
#[derive(Debug)]
pub enum SchemeParameter {
G16,
GM17,
PGHR13,
MARLIN,
}
impl TryFrom<&str> for CurveParameter {
@ -63,11 +66,13 @@ impl TryFrom<&str> for SchemeParameter {
G16 => Ok(SchemeParameter::G16),
GM17 => Ok(SchemeParameter::GM17),
PGHR13 => Ok(SchemeParameter::PGHR13),
MARLIN => Ok(SchemeParameter::MARLIN),
_ => Err(format!("Unknown proving scheme {}", s)),
}
}
}
#[derive(Debug)]
pub struct Parameters(
pub BackendParameter,
pub CurveParameter,
@ -93,6 +98,12 @@ impl TryFrom<(&str, &str, &str)> for Parameters {
(BackendParameter::Ark, CurveParameter::Bw6_761, SchemeParameter::GM17) => Ok(()),
#[cfg(feature = "ark")]
(BackendParameter::Ark, CurveParameter::Bn128, SchemeParameter::GM17) => Ok(()),
#[cfg(feature = "ark")]
(BackendParameter::Ark, CurveParameter::Bls12_377, SchemeParameter::MARLIN) => Ok(()),
#[cfg(feature = "ark")]
(BackendParameter::Ark, CurveParameter::Bn128, SchemeParameter::MARLIN) => Ok(()),
#[cfg(feature = "ark")]
(BackendParameter::Ark, CurveParameter::Bw6_761, SchemeParameter::MARLIN) => Ok(()),
#[cfg(feature = "libsnark")]
(BackendParameter::Libsnark, CurveParameter::Bn128, SchemeParameter::GM17) => Ok(()),
#[cfg(feature = "libsnark")]

View file

@ -116,6 +116,13 @@ pub fn exec(sub_matches: &ArgMatches) -> Result<(), String> {
ProgEnum::Bn128Program(p) => cli_generate_proof::<_, GM17, Ark>(p, sub_matches),
_ => unreachable!(),
},
#[cfg(feature = "ark")]
Parameters(BackendParameter::Ark, _, SchemeParameter::MARLIN) => match prog {
ProgEnum::Bls12_377Program(p) => cli_generate_proof::<_, Marlin, Ark>(p, sub_matches),
ProgEnum::Bw6_761Program(p) => cli_generate_proof::<_, Marlin, Ark>(p, sub_matches),
ProgEnum::Bn128Program(p) => cli_generate_proof::<_, Marlin, Ark>(p, sub_matches),
_ => unreachable!(),
},
#[cfg(feature = "libsnark")]
Parameters(BackendParameter::Libsnark, CurveParameter::Bn128, SchemeParameter::GM17) => {
match prog {

View file

@ -8,5 +8,7 @@ pub mod generate_smtlib2;
pub mod print_proof;
#[cfg(any(feature = "bellman", feature = "ark", feature = "libsnark"))]
pub mod setup;
#[cfg(feature = "ark")]
pub mod universal_setup;
#[cfg(any(feature = "bellman", feature = "ark", feature = "libsnark"))]
pub mod verify;

View file

@ -70,6 +70,16 @@ pub fn subcommand() -> App<'static, 'static> {
.possible_values(constants::SCHEMES)
.default_value(constants::G16),
)
.arg(
Arg::with_name("universal-setup-path")
.short("u")
.long("universal-setup-path")
.help("Path of the universal setup file for universal schemes")
.value_name("FILE")
.takes_value(true)
.required(false)
.default_value(constants::UNIVERSAL_SETUP_DEFAULT_PATH),
)
}
pub fn exec(sub_matches: &ArgMatches) -> Result<(), String> {
@ -95,28 +105,64 @@ pub fn exec(sub_matches: &ArgMatches) -> Result<(), String> {
match parameters {
#[cfg(feature = "bellman")]
Parameters(BackendParameter::Bellman, _, SchemeParameter::G16) => match prog {
ProgEnum::Bn128Program(p) => cli_setup::<_, G16, Bellman>(p, sub_matches),
ProgEnum::Bls12_381Program(p) => cli_setup::<_, G16, Bellman>(p, sub_matches),
ProgEnum::Bn128Program(p) => cli_setup_non_universal::<_, G16, Bellman>(p, sub_matches),
ProgEnum::Bls12_381Program(p) => {
cli_setup_non_universal::<_, G16, Bellman>(p, sub_matches)
}
_ => unreachable!(),
},
#[cfg(feature = "ark")]
Parameters(BackendParameter::Ark, _, SchemeParameter::GM17) => match prog {
ProgEnum::Bls12_377Program(p) => cli_setup::<_, GM17, Ark>(p, sub_matches),
ProgEnum::Bw6_761Program(p) => cli_setup::<_, GM17, Ark>(p, sub_matches),
ProgEnum::Bn128Program(p) => cli_setup::<_, GM17, Ark>(p, sub_matches),
ProgEnum::Bls12_377Program(p) => {
cli_setup_non_universal::<_, GM17, Ark>(p, sub_matches)
}
ProgEnum::Bw6_761Program(p) => cli_setup_non_universal::<_, GM17, Ark>(p, sub_matches),
ProgEnum::Bn128Program(p) => cli_setup_non_universal::<_, GM17, Ark>(p, sub_matches),
_ => unreachable!(),
},
#[cfg(feature = "ark")]
Parameters(BackendParameter::Ark, _, SchemeParameter::MARLIN) => {
let setup_path = Path::new(sub_matches.value_of("universal-setup-path").unwrap());
let setup_file = File::open(&setup_path)
.map_err(|why| format!("Couldn't open {}: {}\nExpected an universal setup, make sure `zokrates universal-setup` was run`", setup_path.display(), why))?;
let mut reader = BufReader::new(setup_file);
let mut setup = vec![];
use std::io::Read;
reader
.read_to_end(&mut setup)
.map_err(|_| "Cannot read universal setup".to_string())?;
match prog {
ProgEnum::Bls12_377Program(p) => {
cli_setup_universal::<_, Marlin, Ark>(p, setup, sub_matches)
}
ProgEnum::Bn128Program(p) => {
cli_setup_universal::<_, Marlin, Ark>(p, setup, sub_matches)
}
ProgEnum::Bw6_761Program(p) => {
cli_setup_universal::<_, Marlin, Ark>(p, setup, sub_matches)
}
_ => unreachable!(),
}
}
#[cfg(feature = "libsnark")]
Parameters(BackendParameter::Libsnark, CurveParameter::Bn128, SchemeParameter::GM17) => {
match prog {
ProgEnum::Bn128Program(p) => cli_setup::<_, GM17, Libsnark>(p, sub_matches),
ProgEnum::Bn128Program(p) => {
cli_setup_non_universal::<_, GM17, Libsnark>(p, sub_matches)
}
_ => unreachable!(),
}
}
#[cfg(feature = "libsnark")]
Parameters(BackendParameter::Libsnark, CurveParameter::Bn128, SchemeParameter::PGHR13) => {
match prog {
ProgEnum::Bn128Program(p) => cli_setup::<_, PGHR13, Libsnark>(p, sub_matches),
ProgEnum::Bn128Program(p) => {
cli_setup_non_universal::<_, PGHR13, Libsnark>(p, sub_matches)
}
_ => unreachable!(),
}
}
@ -124,7 +170,7 @@ pub fn exec(sub_matches: &ArgMatches) -> Result<(), String> {
}
}
fn cli_setup<T: Field, S: Scheme<T>, B: Backend<T, S>>(
fn cli_setup_non_universal<T: Field, S: NonUniversalScheme<T>, B: NonUniversalBackend<T, S>>(
program: ir::Prog<T>,
sub_matches: &ArgMatches,
) -> Result<(), String> {
@ -167,3 +213,48 @@ fn cli_setup<T: Field, S: Scheme<T>, B: Backend<T, S>>(
Ok(())
}
fn cli_setup_universal<T: Field, S: UniversalScheme<T>, B: UniversalBackend<T, S>>(
program: ir::Prog<T>,
srs: Vec<u8>,
sub_matches: &ArgMatches,
) -> Result<(), String> {
println!("Performing setup...");
// print deserialized flattened program if in verbose mode
if sub_matches.is_present("verbose") {
println!("{}", program);
}
// get paths for proving and verification keys
let pk_path = Path::new(sub_matches.value_of("proving-key-path").unwrap());
let vk_path = Path::new(sub_matches.value_of("verification-key-path").unwrap());
// run setup phase
let keypair = B::setup(srs, program)?;
// write verification key
let mut vk_file = File::create(vk_path)
.map_err(|why| format!("Could not create {}: {}", vk_path.display(), why))?;
vk_file
.write_all(
serde_json::to_string_pretty(&keypair.vk)
.unwrap()
.as_bytes(),
)
.map_err(|why| format!("Could not write to {}: {}", vk_path.display(), why))?;
println!("Verification key written to '{}'", vk_path.display());
// write proving key
let mut pk_file = File::create(pk_path)
.map_err(|why| format!("Could not create {}: {}", pk_path.display(), why))?;
pk_file
.write_all(keypair.pk.as_ref())
.map_err(|why| format!("Could not write to {}: {}", pk_path.display(), why))?;
println!("Proving key written to '{}'", pk_path.display());
println!("Setup completed");
Ok(())
}

View file

@ -0,0 +1,110 @@
use crate::constants;
use crate::helpers::*;
use clap::{App, Arg, ArgMatches, SubCommand};
use std::convert::TryFrom;
use std::fs::File;
use std::io::Write;
use std::path::Path;
#[cfg(feature = "ark")]
use zokrates_core::proof_system::ark::Ark;
#[cfg(any(feature = "bellman", feature = "ark", feature = "libsnark"))]
use zokrates_core::proof_system::*;
use zokrates_field::{Bls12_377Field, Bn128Field, Bw6_761Field, Field};
pub fn subcommand() -> App<'static, 'static> {
SubCommand::with_name("universal-setup")
.about("Performs the universal phase of a trusted setup")
.arg(
Arg::with_name("curve")
.short("c")
.long("curve")
.help("Curve to be used in the universal setup")
.takes_value(true)
.required(false)
.possible_values(constants::CURVES)
.default_value(constants::BN128),
)
.arg(
Arg::with_name("universal-setup-path")
.short("u")
.long("universal-setup-path")
.help("Path of the generated universal setup file")
.value_name("FILE")
.takes_value(true)
.required(false)
.default_value(constants::UNIVERSAL_SETUP_DEFAULT_PATH),
)
.arg(
Arg::with_name("proving-scheme")
.short("s")
.long("proving-scheme")
.help("Proving scheme to use in the setup")
.takes_value(true)
.required(false)
.possible_values(constants::UNIVERSAL_SCHEMES)
.default_value(constants::MARLIN),
)
.arg(
Arg::with_name("size")
.short("n")
.long("size")
.help("Size of the trusted setup passed as an exponent. For example, 8 for 2**8")
.takes_value(true)
.required(false)
.default_value(constants::UNIVERSAL_SETUP_DEFAULT_SIZE),
)
}
pub fn exec(sub_matches: &ArgMatches) -> Result<(), String> {
let parameters = Parameters::try_from((
constants::ARK,
sub_matches.value_of("curve").unwrap(),
sub_matches.value_of("proving-scheme").unwrap(),
))?;
match parameters {
#[cfg(feature = "ark")]
Parameters(BackendParameter::Ark, CurveParameter::Bls12_377, SchemeParameter::MARLIN) => {
cli_universal_setup::<Bls12_377Field, Marlin, Ark>(sub_matches)
}
#[cfg(feature = "ark")]
Parameters(BackendParameter::Ark, CurveParameter::Bw6_761, SchemeParameter::MARLIN) => {
cli_universal_setup::<Bw6_761Field, Marlin, Ark>(sub_matches)
}
#[cfg(feature = "ark")]
Parameters(BackendParameter::Ark, CurveParameter::Bn128, SchemeParameter::MARLIN) => {
cli_universal_setup::<Bn128Field, Marlin, Ark>(sub_matches)
}
_ => unreachable!(),
}
}
fn cli_universal_setup<T: Field, S: UniversalScheme<T>, B: UniversalBackend<T, S>>(
sub_matches: &ArgMatches,
) -> Result<(), String> {
println!("Performing setup...");
// get paths for the universal setup
let u_path = Path::new(sub_matches.value_of("universal-setup-path").unwrap());
// get the size of the setup
let size = sub_matches.value_of("size").unwrap();
let size = size
.parse::<u32>()
.map_err(|_| format!("Universal setup size {} is invalid", size))?;
// run universal setup phase
let setup = B::universal_setup(size);
// write proving key
let mut u_file = File::create(u_path)
.map_err(|why| format!("Could not create {}: {}", u_path.display(), why))?;
u_file
.write_all(setup.as_ref())
.map_err(|why| format!("Could not write to {}: {}", u_path.display(), why))?;
println!("Universal setup written to '{}'", u_path.display());
println!("Universal setup completed");
Ok(())
}

View file

@ -89,6 +89,18 @@ pub fn exec(sub_matches: &ArgMatches) -> Result<(), String> {
Parameters(BackendParameter::Ark, CurveParameter::Bn128, SchemeParameter::GM17) => {
cli_verify::<Bn128Field, GM17, Ark>(sub_matches)
}
#[cfg(feature = "ark")]
Parameters(BackendParameter::Ark, CurveParameter::Bls12_377, SchemeParameter::MARLIN) => {
cli_verify::<Bls12_377Field, Marlin, Ark>(sub_matches)
}
#[cfg(feature = "ark")]
Parameters(BackendParameter::Ark, CurveParameter::Bw6_761, SchemeParameter::MARLIN) => {
cli_verify::<Bw6_761Field, Marlin, Ark>(sub_matches)
}
#[cfg(feature = "ark")]
Parameters(BackendParameter::Ark, CurveParameter::Bn128, SchemeParameter::MARLIN) => {
cli_verify::<Bn128Field, Marlin, Ark>(sub_matches)
}
#[cfg(feature = "libsnark")]
Parameters(BackendParameter::Libsnark, CurveParameter::Bn128, SchemeParameter::GM17) => {
cli_verify::<Bn128Field, GM17, Libsnark>(sub_matches)

View file

@ -212,21 +212,33 @@ mod integration {
#[cfg(feature = "libsnark")]
let backends = map! {
"bellman" => ["g16"],
"libsnark" => ["pghr13"],
"ark" => ["gm17"]
"bellman" => vec!["g16"],
"libsnark" => vec!["pghr13"],
"ark" => vec!["gm17", "marlin"]
};
#[cfg(not(feature = "libsnark"))]
let backends = map! {
"bellman" => ["g16"],
"ark" => ["gm17"]
"bellman" => vec!["g16"],
"ark" => vec!["gm17", "marlin"]
};
// GENERATE A UNIVERSAL SETUP
assert_cli::Assert::command(&[
"../target/release/zokrates",
"universal-setup",
"--size",
"15",
"--proving-scheme",
"marlin",
])
.succeeds()
.unwrap();
for (backend, schemes) in backends {
for scheme in &schemes {
// SETUP
assert_cli::Assert::command(&[
let setup = assert_cli::Assert::command(&[
"../target/release/zokrates",
"setup",
"-i",
@ -241,74 +253,78 @@ mod integration {
scheme,
])
.succeeds()
.unwrap();
.stdout()
.doesnt_contain("This program is too small to generate a setup with Marlin")
.execute();
// GENERATE-PROOF
assert_cli::Assert::command(&[
"../target/release/zokrates",
"generate-proof",
"-i",
flattened_path.to_str().unwrap(),
"-w",
witness_path.to_str().unwrap(),
"-p",
proving_key_path.to_str().unwrap(),
"--backend",
backend,
"--proving-scheme",
scheme,
"-j",
proof_path.to_str().unwrap(),
])
.succeeds()
.unwrap();
if setup.is_ok() {
// GENERATE-PROOF
assert_cli::Assert::command(&[
"../target/release/zokrates",
"generate-proof",
"-i",
flattened_path.to_str().unwrap(),
"-w",
witness_path.to_str().unwrap(),
"-p",
proving_key_path.to_str().unwrap(),
"--backend",
backend,
"--proving-scheme",
scheme,
"-j",
proof_path.to_str().unwrap(),
])
.succeeds()
.unwrap();
// CLI VERIFICATION
assert_cli::Assert::command(&[
"../target/release/zokrates",
"verify",
"--backend",
backend,
"--proving-scheme",
scheme,
"-j",
proof_path.to_str().unwrap(),
"-v",
verification_key_path.to_str().unwrap(),
])
.succeeds()
.unwrap();
// CLI VERIFICATION
assert_cli::Assert::command(&[
"../target/release/zokrates",
"verify",
"--backend",
backend,
"--proving-scheme",
scheme,
"-j",
proof_path.to_str().unwrap(),
"-v",
verification_key_path.to_str().unwrap(),
])
.succeeds()
.unwrap();
if backend != "ark" {
for abi_version in &["v1", "v2"] {
// EXPORT-VERIFIER
assert_cli::Assert::command(&[
"../target/release/zokrates",
"export-verifier",
"-i",
verification_key_path.to_str().unwrap(),
"-o",
verification_contract_path.to_str().unwrap(),
"--proving-scheme",
scheme,
"-a",
abi_version,
])
.succeeds()
.unwrap();
if scheme != &"marlin" {
for abi_version in &["v1", "v2"] {
// EXPORT-VERIFIER
assert_cli::Assert::command(&[
"../target/release/zokrates",
"export-verifier",
"-i",
verification_key_path.to_str().unwrap(),
"-o",
verification_contract_path.to_str().unwrap(),
"--proving-scheme",
scheme,
"-a",
abi_version,
])
.succeeds()
.unwrap();
// TEST VERIFIER
assert_cli::Assert::command(&[
"node",
"test.js",
verification_contract_path.to_str().unwrap(),
proof_path.to_str().unwrap(),
scheme,
abi_version,
])
.current_dir(concat!(env!("OUT_DIR"), "/contract"))
.succeeds()
.unwrap();
// TEST VERIFIER
assert_cli::Assert::command(&[
"node",
"test.js",
verification_contract_path.to_str().unwrap(),
proof_path.to_str().unwrap(),
scheme,
abi_version,
])
.current_dir(concat!(env!("OUT_DIR"), "/contract"))
.succeeds()
.unwrap();
}
}
}
}

View file

@ -13,7 +13,7 @@ libsnark = ["cc", "cmake", "git2"]
bellman = ["bellman_ce", "pairing_ce", "ff_ce", "zokrates_field/bellman"]
wasm = ["bellman_ce/nolog", "bellman_ce/wasm"]
multicore = ["bellman_ce/multicore"]
ark = ["ark-ff", "ark-ec", "ark-bn254", "ark-bls12-377", "ark-bw6-761", "ark-gm17", "ark-serialize", "ark-relations", "zokrates_field/ark"]
ark = ["ark-ff", "ark-ec", "ark-bn254", "ark-bls12-377", "ark-bw6-761", "ark-gm17", "ark-serialize", "ark-relations", "ark-marlin", "ark-poly", "ark-poly-commit", "zokrates_field/ark", "sha2"]
[dependencies]
cfg-if = "0.1"
@ -51,6 +51,10 @@ ark-bw6-761 = { version = "^0.2.0", default-features = false, optional = true }
ark-gm17 = { version = "^0.2.0", default-features = false, optional = true }
ark-serialize = { version = "^0.2.0", default-features = false, optional = true }
ark-relations = { version = "^0.2.0", default-features = false, optional = true }
ark-marlin = { version = "^0.2.0", default-features = false, optional = true }
ark-poly = { version = "^0.2.0", default-features = false, optional = true }
ark-poly-commit = { version = "^0.2.0", default-features = false, optional = true }
sha2 = { version = "0.9.3", optional = true }
[dev-dependencies]
wasm-bindgen-test = "^0.3.0"

View file

@ -12,9 +12,9 @@ use crate::proof_system::ark::Computation;
use crate::proof_system::ark::{parse_fr, parse_g1, parse_g2, parse_g2_fq};
use crate::proof_system::gm17::{NotBw6_761Field, ProofPoints, VerificationKey, GM17};
use crate::proof_system::Scheme;
use crate::proof_system::{Backend, Proof, SetupKeypair};
use crate::proof_system::{Backend, NonUniversalBackend, Proof, SetupKeypair};
impl<T: Field + ArkFieldExtensions + NotBw6_761Field> Backend<T, GM17> for Ark {
impl<T: Field + ArkFieldExtensions + NotBw6_761Field> NonUniversalBackend<T, GM17> for Ark {
fn setup(program: Prog<T>) -> SetupKeypair<<GM17 as Scheme<T>>::VerificationKey> {
let parameters = Computation::without_witness(program).setup();
@ -37,7 +37,9 @@ impl<T: Field + ArkFieldExtensions + NotBw6_761Field> Backend<T, GM17> for Ark {
SetupKeypair::new(vk, pk)
}
}
impl<T: Field + ArkFieldExtensions + NotBw6_761Field> Backend<T, GM17> for Ark {
fn generate_proof(
program: Prog<T>,
witness: Witness<T>,
@ -105,7 +107,7 @@ impl<T: Field + ArkFieldExtensions + NotBw6_761Field> Backend<T, GM17> for Ark {
}
}
impl Backend<Bw6_761Field, GM17> for Ark {
impl NonUniversalBackend<Bw6_761Field, GM17> for Ark {
fn setup(
program: Prog<Bw6_761Field>,
) -> SetupKeypair<<GM17 as Scheme<Bw6_761Field>>::VerificationKey> {
@ -130,7 +132,9 @@ impl Backend<Bw6_761Field, GM17> for Ark {
SetupKeypair::new(vk, pk)
}
}
impl Backend<Bw6_761Field, GM17> for Ark {
fn generate_proof(
program: Prog<Bw6_761Field>,
witness: Witness<Bw6_761Field>,
@ -267,7 +271,7 @@ mod tests {
private: vec![false],
};
let keypair = <Ark as Backend<Bls12_377Field, GM17>>::setup(program.clone());
let keypair = <Ark as NonUniversalBackend<Bls12_377Field, GM17>>::setup(program.clone());
let interpreter = Interpreter::default();
let witness = interpreter
@ -296,7 +300,7 @@ mod tests {
private: vec![false],
};
let keypair = <Ark as Backend<Bw6_761Field, GM17>>::setup(program.clone());
let keypair = <Ark as NonUniversalBackend<Bw6_761Field, GM17>>::setup(program.clone());
let interpreter = Interpreter::default();
let witness = interpreter

View file

@ -0,0 +1,277 @@
use ark_marlin::{IndexProverKey, IndexVerifierKey, Proof as ArkProof};
use ark_marlin::Marlin as ArkMarlin;
use ark_ec::PairingEngine;
use ark_poly::univariate::DensePolynomial;
use ark_poly_commit::marlin_pc::MarlinKZG10;
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
use sha2::Sha256;
use zokrates_field::{ArkFieldExtensions, Field};
use crate::ir::{Prog, Witness};
use crate::proof_system::ark::parse_fr;
use crate::proof_system::ark::Ark;
use crate::proof_system::ark::Computation;
use crate::proof_system::marlin::{self, ProofPoints, VerificationKey};
use crate::proof_system::Scheme;
use crate::proof_system::{Backend, Proof, SetupKeypair, UniversalBackend};
const MINIMUM_CONSTRAINT_COUNT: usize = 2;
impl<T: Field + ArkFieldExtensions> UniversalBackend<T, marlin::Marlin> for Ark {
fn universal_setup(size: u32) -> Vec<u8> {
use rand_0_7::SeedableRng;
let rng = &mut rand_0_7::rngs::StdRng::from_entropy();
let srs = ArkMarlin::<
<<T as ArkFieldExtensions>::ArkEngine as PairingEngine>::Fr,
MarlinKZG10<
T::ArkEngine,
DensePolynomial<<<T as ArkFieldExtensions>::ArkEngine as PairingEngine>::Fr>,
>,
Sha256,
>::universal_setup(
2usize.pow(size), 2usize.pow(size), 2usize.pow(size), rng
)
.unwrap();
let mut res = vec![];
srs.serialize(&mut res).unwrap();
res
}
fn setup(
universal_srs: Vec<u8>,
program: Prog<T>,
) -> Result<SetupKeypair<<marlin::Marlin as Scheme<T>>::VerificationKey>, String> {
if program.constraint_count() < MINIMUM_CONSTRAINT_COUNT {
return Err(format!("Programs must have a least {} constraints. This program is too small to generate a setup with Marlin, see [this issue](https://github.com/arkworks-rs/marlin/issues/79)", MINIMUM_CONSTRAINT_COUNT));
}
let computation = Computation::without_witness(program);
let srs = ark_marlin::UniversalSRS::<
<<T as ArkFieldExtensions>::ArkEngine as PairingEngine>::Fr,
MarlinKZG10<
T::ArkEngine,
DensePolynomial<<<T as ArkFieldExtensions>::ArkEngine as PairingEngine>::Fr>,
>,
>::deserialize(&mut universal_srs.as_slice())
.unwrap();
let (pk, vk) = ArkMarlin::<
<<T as ArkFieldExtensions>::ArkEngine as PairingEngine>::Fr,
MarlinKZG10<
T::ArkEngine,
DensePolynomial<<<T as ArkFieldExtensions>::ArkEngine as PairingEngine>::Fr>,
>,
Sha256,
>::index(&srs, computation)
.map_err(|e| match e {
ark_marlin::Error::IndexTooLarge => String::from("The universal setup is too small for this program, please provide a larger universal setup"),
_ => String::from("Unknown error specializing the universal setup for this program")
})?;
let mut serialized_pk: Vec<u8> = Vec::new();
pk.serialize_uncompressed(&mut serialized_pk).unwrap();
let mut serialized_vk: Vec<u8> = Vec::new();
vk.serialize_uncompressed(&mut serialized_vk).unwrap();
Ok(SetupKeypair::new(
VerificationKey { raw: serialized_vk },
serialized_pk,
))
}
}
impl<T: Field + ArkFieldExtensions> Backend<T, marlin::Marlin> for Ark {
fn generate_proof(
program: Prog<T>,
witness: Witness<T>,
proving_key: Vec<u8>,
) -> Proof<<marlin::Marlin as Scheme<T>>::ProofPoints> {
let computation = Computation::with_witness(program, witness);
use rand_0_7::SeedableRng;
let rng = &mut rand_0_7::rngs::StdRng::from_entropy();
let pk = IndexProverKey::<
<<T as ArkFieldExtensions>::ArkEngine as PairingEngine>::Fr,
MarlinKZG10<
T::ArkEngine,
DensePolynomial<<<T as ArkFieldExtensions>::ArkEngine as PairingEngine>::Fr>,
>,
>::deserialize_uncompressed(&mut proving_key.as_slice())
.unwrap();
let inputs = computation
.public_inputs_values()
.iter()
.map(parse_fr::<T>)
.collect::<Vec<_>>();
let proof = ArkMarlin::<
<<T as ArkFieldExtensions>::ArkEngine as PairingEngine>::Fr,
MarlinKZG10<
T::ArkEngine,
DensePolynomial<<<T as ArkFieldExtensions>::ArkEngine as PairingEngine>::Fr>,
>,
Sha256,
>::prove(&pk, computation, rng)
.unwrap();
let mut serialized_proof: Vec<u8> = Vec::new();
proof.serialize_uncompressed(&mut serialized_proof).unwrap();
Proof::new(
ProofPoints {
raw: serialized_proof,
},
inputs,
)
}
fn verify(
vk: <marlin::Marlin as Scheme<T>>::VerificationKey,
proof: Proof<<marlin::Marlin as Scheme<T>>::ProofPoints>,
) -> bool {
let inputs: Vec<_> = proof
.inputs
.iter()
.map(|s| {
T::try_from_str(s.trim_start_matches("0x"), 16)
.unwrap()
.into_ark()
})
.collect::<Vec<_>>();
let proof = ArkProof::<
<<T as ArkFieldExtensions>::ArkEngine as PairingEngine>::Fr,
MarlinKZG10<
T::ArkEngine,
DensePolynomial<<<T as ArkFieldExtensions>::ArkEngine as PairingEngine>::Fr>,
>,
>::deserialize_uncompressed(&mut proof.proof.raw.as_slice())
.unwrap();
let vk = IndexVerifierKey::<
<<T as ArkFieldExtensions>::ArkEngine as PairingEngine>::Fr,
MarlinKZG10<
T::ArkEngine,
DensePolynomial<<<T as ArkFieldExtensions>::ArkEngine as PairingEngine>::Fr>,
>,
>::deserialize_uncompressed(&mut vk.raw.as_slice())
.unwrap();
use rand_0_7::SeedableRng;
let rng = &mut rand_0_7::rngs::StdRng::from_entropy();
ArkMarlin::<
<<T as ArkFieldExtensions>::ArkEngine as PairingEngine>::Fr,
MarlinKZG10<
T::ArkEngine,
DensePolynomial<<<T as ArkFieldExtensions>::ArkEngine as PairingEngine>::Fr>,
>,
Sha256,
>::verify(&vk, &inputs, &proof, rng)
.unwrap()
}
}
#[cfg(test)]
mod tests {
use crate::flat_absy::FlatVariable;
use crate::ir::{Function, Interpreter, Prog, QuadComb, Statement};
use super::*;
use crate::proof_system::scheme::Marlin;
use zokrates_field::{Bls12_377Field, Bw6_761Field};
#[test]
fn verify_bls12_377_field() {
let program: Prog<Bls12_377Field> = Prog {
main: Function {
id: String::from("main"),
arguments: vec![FlatVariable::new(0)],
returns: vec![FlatVariable::public(0)],
statements: vec![
Statement::Constraint(
QuadComb::from_linear_combinations(
FlatVariable::new(0).into(),
FlatVariable::new(0).into(),
),
FlatVariable::new(1).into(),
),
Statement::Constraint(
FlatVariable::new(1).into(),
FlatVariable::public(0).into(),
),
],
},
private: vec![true],
};
let srs = <Ark as UniversalBackend<Bls12_377Field, Marlin>>::universal_setup(5);
let keypair =
<Ark as UniversalBackend<Bls12_377Field, Marlin>>::setup(srs, program.clone()).unwrap();
let interpreter = Interpreter::default();
let witness = interpreter
.execute(&program, &[Bls12_377Field::from(42)])
.unwrap();
let proof =
<Ark as Backend<Bls12_377Field, Marlin>>::generate_proof(program, witness, keypair.pk);
let ans = <Ark as Backend<Bls12_377Field, Marlin>>::verify(keypair.vk, proof);
assert!(ans);
}
#[test]
fn verify_bw6_761_field() {
let program: Prog<Bw6_761Field> = Prog {
main: Function {
id: String::from("main"),
arguments: vec![FlatVariable::new(0)],
returns: vec![FlatVariable::public(0)],
statements: vec![
Statement::Constraint(
QuadComb::from_linear_combinations(
FlatVariable::new(0).into(),
FlatVariable::new(0).into(),
),
FlatVariable::new(1).into(),
),
Statement::Constraint(
FlatVariable::new(1).into(),
FlatVariable::public(0).into(),
),
],
},
private: vec![true],
};
let srs = <Ark as UniversalBackend<Bw6_761Field, Marlin>>::universal_setup(5);
let keypair =
<Ark as UniversalBackend<Bw6_761Field, Marlin>>::setup(srs, program.clone()).unwrap();
let interpreter = Interpreter::default();
let witness = interpreter
.execute(&program, &[Bw6_761Field::from(42)])
.unwrap();
let proof =
<Ark as Backend<Bw6_761Field, Marlin>>::generate_proof(program, witness, keypair.pk);
let ans = <Ark as Backend<Bw6_761Field, Marlin>>::verify(keypair.vk, proof);
assert!(ans);
}
}

View file

@ -1,4 +1,5 @@
pub mod gm17;
pub mod marlin;
use crate::ir::{CanonicalLinComb, Prog, Statement, Witness};
use ark_gm17::Proof;

View file

@ -4,7 +4,7 @@ use bellman::groth16::{
};
use pairing::{CurveAffine, Engine};
use crate::proof_system::{Backend, Proof, SetupKeypair};
use crate::proof_system::{Backend, NonUniversalBackend, Proof, SetupKeypair};
use zokrates_field::BellmanFieldExtensions;
use zokrates_field::Field;
@ -18,29 +18,6 @@ use crate::proof_system::Scheme;
const G16_WARNING: &str = "WARNING: You are using the G16 scheme which is subject to malleability. See zokrates.github.io/toolbox/proving_schemes.html#g16-malleability for implications.";
impl<T: Field + BellmanFieldExtensions> Backend<T, G16> for Bellman {
fn setup(program: Prog<T>) -> SetupKeypair<<G16 as Scheme<T>>::VerificationKey> {
println!("{}", G16_WARNING);
let parameters = Computation::without_witness(program).setup();
let mut pk: Vec<u8> = Vec::new();
parameters.write(&mut pk).unwrap();
let vk = VerificationKey {
alpha: parse_g1::<T>(&parameters.vk.alpha_g1),
beta: parse_g2::<T>(&parameters.vk.beta_g2),
gamma: parse_g2::<T>(&parameters.vk.gamma_g2),
delta: parse_g2::<T>(&parameters.vk.delta_g2),
gamma_abc: parameters
.vk
.ic
.iter()
.map(|g1| parse_g1::<T>(g1))
.collect(),
};
SetupKeypair::new(vk, pk)
}
fn generate_proof(
program: Prog<T>,
witness: Witness<T>,
@ -106,6 +83,31 @@ impl<T: Field + BellmanFieldExtensions> Backend<T, G16> for Bellman {
}
}
impl<T: Field + BellmanFieldExtensions> NonUniversalBackend<T, G16> for Bellman {
fn setup(program: Prog<T>) -> SetupKeypair<<G16 as Scheme<T>>::VerificationKey> {
println!("{}", G16_WARNING);
let parameters = Computation::without_witness(program).setup();
let mut pk: Vec<u8> = Vec::new();
parameters.write(&mut pk).unwrap();
let vk = VerificationKey {
alpha: parse_g1::<T>(&parameters.vk.alpha_g1),
beta: parse_g2::<T>(&parameters.vk.beta_g2),
gamma: parse_g2::<T>(&parameters.vk.gamma_g2),
delta: parse_g2::<T>(&parameters.vk.delta_g2),
gamma_abc: parameters
.vk
.ic
.iter()
.map(|g1| parse_g1::<T>(g1))
.collect(),
};
SetupKeypair::new(vk, pk)
}
}
mod serialization {
use pairing::{from_hex, CurveAffine, Engine};
@ -152,7 +154,7 @@ mod tests {
private: vec![false],
};
let keypair = <Bellman as Backend<Bn128Field, G16>>::setup(program.clone());
let keypair = <Bellman as NonUniversalBackend<Bn128Field, G16>>::setup(program.clone());
let interpreter = Interpreter::default();
let witness = interpreter

View file

@ -5,7 +5,7 @@ use crate::proof_system::libsnark::{
prepare_generate_proof, prepare_public_inputs, prepare_setup, serialization::*, Libsnark,
};
use crate::proof_system::Scheme;
use crate::proof_system::{Backend, G1Affine, G2Affine, Proof, SetupKeypair};
use crate::proof_system::{Backend, G1Affine, G2Affine, NonUniversalBackend, Proof, SetupKeypair};
use std::io::{BufReader, BufWriter, Write};
use zokrates_field::{Bn128Field, Field};
@ -39,63 +39,6 @@ extern "C" {
}
impl Backend<Bn128Field, GM17> for Libsnark {
fn setup(
program: Prog<Bn128Field>,
) -> SetupKeypair<<GM17 as Scheme<Bn128Field>>::VerificationKey> {
let (a_arr, b_arr, c_arr, a_vec, b_vec, c_vec, num_constraints, num_variables, num_inputs) =
prepare_setup(program);
let (vk, pk) = unsafe {
let result: SetupResult = gm17_bn128_setup(
a_arr.as_ptr(),
b_arr.as_ptr(),
c_arr.as_ptr(),
a_vec.len() as i32,
b_vec.len() as i32,
c_vec.len() as i32,
num_constraints as i32,
num_variables as i32,
num_inputs as i32,
);
let vk: Vec<u8> =
std::slice::from_raw_parts(result.vk.data, result.vk.length as usize).to_vec();
let pk: Vec<u8> =
std::slice::from_raw_parts(result.pk.data, result.pk.length as usize).to_vec();
// free c allocated buffers
c_free(result.vk.data);
c_free(result.pk.data);
(vk, pk)
};
let vk_slice = vk.as_slice();
let mut reader = BufReader::new(vk_slice);
let h = read_g2(&mut reader).unwrap();
let g_alpha = read_g1(&mut reader).unwrap();
let h_beta = read_g2(&mut reader).unwrap();
let g_gamma = read_g1(&mut reader).unwrap();
let h_gamma = read_g2(&mut reader).unwrap();
let mut query = vec![];
while let Ok(q) = read_g1(&mut reader) {
query.push(q);
}
let vk = VerificationKey::<G1Affine, G2Affine> {
h,
g_alpha,
h_beta,
g_gamma,
h_gamma,
query,
};
SetupKeypair::new(vk, pk)
}
fn generate_proof(
program: Prog<Bn128Field>,
witness: Witness<Bn128Field>,
@ -186,6 +129,65 @@ impl Backend<Bn128Field, GM17> for Libsnark {
}
}
impl NonUniversalBackend<Bn128Field, GM17> for Libsnark {
fn setup(
program: Prog<Bn128Field>,
) -> SetupKeypair<<GM17 as Scheme<Bn128Field>>::VerificationKey> {
let (a_arr, b_arr, c_arr, a_vec, b_vec, c_vec, num_constraints, num_variables, num_inputs) =
prepare_setup(program);
let (vk, pk) = unsafe {
let result: SetupResult = gm17_bn128_setup(
a_arr.as_ptr(),
b_arr.as_ptr(),
c_arr.as_ptr(),
a_vec.len() as i32,
b_vec.len() as i32,
c_vec.len() as i32,
num_constraints as i32,
num_variables as i32,
num_inputs as i32,
);
let vk: Vec<u8> =
std::slice::from_raw_parts(result.vk.data, result.vk.length as usize).to_vec();
let pk: Vec<u8> =
std::slice::from_raw_parts(result.pk.data, result.pk.length as usize).to_vec();
// free c allocated buffers
c_free(result.vk.data);
c_free(result.pk.data);
(vk, pk)
};
let vk_slice = vk.as_slice();
let mut reader = BufReader::new(vk_slice);
let h = read_g2(&mut reader).unwrap();
let g_alpha = read_g1(&mut reader).unwrap();
let h_beta = read_g2(&mut reader).unwrap();
let g_gamma = read_g1(&mut reader).unwrap();
let h_gamma = read_g2(&mut reader).unwrap();
let mut query = vec![];
while let Ok(q) = read_g1(&mut reader) {
query.push(q);
}
let vk = VerificationKey::<G1Affine, G2Affine> {
h,
g_alpha,
h_beta,
g_gamma,
h_gamma,
query,
};
SetupKeypair::new(vk, pk)
}
}
#[cfg(feature = "libsnark")]
#[cfg(test)]
mod tests {
@ -209,7 +211,7 @@ mod tests {
private: vec![true],
};
let keypair = <Libsnark as Backend<Bn128Field, GM17>>::setup(program.clone());
let keypair = <Libsnark as NonUniversalBackend<Bn128Field, GM17>>::setup(program.clone());
let interpreter = Interpreter::default();
let witness = interpreter

View file

@ -2,7 +2,7 @@ use crate::proof_system::libsnark::ffi::{c_free, Buffer, ProofResult, SetupResul
use crate::proof_system::libsnark::{
prepare_generate_proof, prepare_public_inputs, prepare_setup, Libsnark,
};
use crate::proof_system::{Backend, G1Affine, G2Affine, Proof, SetupKeypair};
use crate::proof_system::{Backend, G1Affine, G2Affine, NonUniversalBackend, Proof, SetupKeypair};
use crate::ir::{Prog, Witness};
use crate::proof_system::libsnark::serialization::{read_g1, read_g2, write_g1, write_g2};
@ -42,67 +42,6 @@ extern "C" {
}
impl Backend<Bn128Field, PGHR13> for Libsnark {
fn setup(
program: Prog<Bn128Field>,
) -> SetupKeypair<<PGHR13 as Scheme<Bn128Field>>::VerificationKey> {
let (a_arr, b_arr, c_arr, a_vec, b_vec, c_vec, num_constraints, num_variables, num_inputs) =
prepare_setup(program);
let (vk, pk) = unsafe {
let result: SetupResult = pghr13_bn128_setup(
a_arr.as_ptr(),
b_arr.as_ptr(),
c_arr.as_ptr(),
a_vec.len() as i32,
b_vec.len() as i32,
c_vec.len() as i32,
num_constraints as i32,
num_variables as i32,
num_inputs as i32,
);
let vk: Vec<u8> =
std::slice::from_raw_parts(result.vk.data, result.vk.length as usize).to_vec();
let pk: Vec<u8> =
std::slice::from_raw_parts(result.pk.data, result.pk.length as usize).to_vec();
// free c allocated buffers
c_free(result.vk.data);
c_free(result.pk.data);
(vk, pk)
};
let vk_slice = vk.as_slice();
let mut reader = BufReader::new(vk_slice);
let a = read_g2(&mut reader).unwrap();
let b = read_g1(&mut reader).unwrap();
let c = read_g2(&mut reader).unwrap();
let gamma = read_g2(&mut reader).unwrap();
let gamma_beta_1 = read_g1(&mut reader).unwrap();
let gamma_beta_2 = read_g2(&mut reader).unwrap();
let z = read_g2(&mut reader).unwrap();
let mut ic = vec![];
while let Ok(q) = read_g1(&mut reader) {
ic.push(q);
}
let vk = VerificationKey::<G1Affine, G2Affine> {
a,
b,
c,
gamma,
gamma_beta_1,
gamma_beta_2,
z,
ic,
};
SetupKeypair::new(vk, pk)
}
fn generate_proof(
program: Prog<Bn128Field>,
witness: Witness<Bn128Field>,
@ -216,6 +155,69 @@ impl Backend<Bn128Field, PGHR13> for Libsnark {
}
}
impl NonUniversalBackend<Bn128Field, PGHR13> for Libsnark {
fn setup(
program: Prog<Bn128Field>,
) -> SetupKeypair<<PGHR13 as Scheme<Bn128Field>>::VerificationKey> {
let (a_arr, b_arr, c_arr, a_vec, b_vec, c_vec, num_constraints, num_variables, num_inputs) =
prepare_setup(program);
let (vk, pk) = unsafe {
let result: SetupResult = pghr13_bn128_setup(
a_arr.as_ptr(),
b_arr.as_ptr(),
c_arr.as_ptr(),
a_vec.len() as i32,
b_vec.len() as i32,
c_vec.len() as i32,
num_constraints as i32,
num_variables as i32,
num_inputs as i32,
);
let vk: Vec<u8> =
std::slice::from_raw_parts(result.vk.data, result.vk.length as usize).to_vec();
let pk: Vec<u8> =
std::slice::from_raw_parts(result.pk.data, result.pk.length as usize).to_vec();
// free c allocated buffers
c_free(result.vk.data);
c_free(result.pk.data);
(vk, pk)
};
let vk_slice = vk.as_slice();
let mut reader = BufReader::new(vk_slice);
let a = read_g2(&mut reader).unwrap();
let b = read_g1(&mut reader).unwrap();
let c = read_g2(&mut reader).unwrap();
let gamma = read_g2(&mut reader).unwrap();
let gamma_beta_1 = read_g1(&mut reader).unwrap();
let gamma_beta_2 = read_g2(&mut reader).unwrap();
let z = read_g2(&mut reader).unwrap();
let mut ic = vec![];
while let Ok(q) = read_g1(&mut reader) {
ic.push(q);
}
let vk = VerificationKey::<G1Affine, G2Affine> {
a,
b,
c,
gamma,
gamma_beta_1,
gamma_beta_2,
z,
ic,
};
SetupKeypair::new(vk, pk)
}
}
#[cfg(feature = "libsnark")]
#[cfg(test)]
mod tests {
@ -239,7 +241,7 @@ mod tests {
private: vec![true],
};
let keypair = <Libsnark as Backend<Bn128Field, PGHR13>>::setup(program.clone());
let keypair = <Libsnark as NonUniversalBackend<Bn128Field, PGHR13>>::setup(program.clone());
let interpreter = Interpreter::default();
let witness = interpreter

View file

@ -80,8 +80,6 @@ impl ToString for G2Affine {
}
pub trait Backend<T: Field, S: Scheme<T>> {
fn setup(program: ir::Prog<T>) -> SetupKeypair<S::VerificationKey>;
fn generate_proof(
program: ir::Prog<T>,
witness: ir::Witness<T>,
@ -90,3 +88,15 @@ pub trait Backend<T: Field, S: Scheme<T>> {
fn verify(vk: S::VerificationKey, proof: Proof<S::ProofPoints>) -> bool;
}
pub trait NonUniversalBackend<T: Field, S: NonUniversalScheme<T>>: Backend<T, S> {
fn setup(program: ir::Prog<T>) -> SetupKeypair<S::VerificationKey>;
}
pub trait UniversalBackend<T: Field, S: UniversalScheme<T>>: Backend<T, S> {
fn universal_setup(size: u32) -> Vec<u8>;
fn setup(
srs: Vec<u8>,
program: ir::Prog<T>,
) -> Result<SetupKeypair<S::VerificationKey>, String>;
}

View file

@ -1,4 +1,4 @@
use crate::proof_system::scheme::Scheme;
use crate::proof_system::scheme::{NonUniversalScheme, Scheme};
use crate::proof_system::solidity::{
SolidityAbi, SOLIDITY_G2_ADDITION_LIB, SOLIDITY_PAIRING_LIB, SOLIDITY_PAIRING_LIB_V2,
};
@ -34,6 +34,10 @@ pub struct VerificationKey<G1, G2> {
pub query: Vec<G1>,
}
impl<T: Field + NotBw6_761Field> NonUniversalScheme<T> for GM17 {}
impl NonUniversalScheme<Bw6_761Field> for GM17 {}
impl<T: Field + NotBw6_761Field> Scheme<T> for GM17 {
type VerificationKey = VerificationKey<G1Affine, G2Affine>;
type ProofPoints = ProofPoints<G1Affine, G2Affine>;

View file

@ -1,4 +1,4 @@
use crate::proof_system::scheme::Scheme;
use crate::proof_system::scheme::{NonUniversalScheme, Scheme};
use crate::proof_system::solidity::{
SolidityAbi, SOLIDITY_G2_ADDITION_LIB, SOLIDITY_PAIRING_LIB, SOLIDITY_PAIRING_LIB_V2,
};
@ -30,6 +30,8 @@ impl<T: Field> Scheme<T> for G16 {
type ProofPoints = ProofPoints<G1Affine, G2Affine>;
}
impl<T: Field> NonUniversalScheme<T> for G16 {}
impl<T: SolidityCompatibleField> SolidityCompatibleScheme<T> for G16 {
fn export_solidity_verifier(
vk: <G16 as Scheme<T>>::VerificationKey,

View file

@ -0,0 +1,23 @@
use crate::proof_system::scheme::{Scheme, UniversalScheme};
use serde::{Deserialize, Serialize};
use zokrates_field::Field;
#[allow(clippy::upper_case_acronyms)]
pub struct Marlin;
#[derive(Serialize, Deserialize)]
pub struct ProofPoints {
pub raw: Vec<u8>,
}
#[derive(Serialize, Deserialize)]
pub struct VerificationKey {
pub raw: Vec<u8>,
}
impl<T: Field> Scheme<T> for Marlin {
type VerificationKey = VerificationKey;
type ProofPoints = ProofPoints;
}
impl<T: Field> UniversalScheme<T> for Marlin {}

View file

@ -4,13 +4,19 @@ use zokrates_field::Field;
pub mod gm17;
pub mod groth16;
pub mod marlin;
pub mod pghr13;
pub use self::gm17::GM17;
pub use self::groth16::G16;
pub use self::marlin::Marlin;
pub use self::pghr13::PGHR13;
pub trait Scheme<T: Field> {
type VerificationKey: Serialize + DeserializeOwned;
type ProofPoints: Serialize + DeserializeOwned;
}
pub trait NonUniversalScheme<T: Field>: Scheme<T> {}
pub trait UniversalScheme<T: Field>: Scheme<T> {}

View file

@ -1,4 +1,4 @@
use crate::proof_system::scheme::Scheme;
use crate::proof_system::scheme::{NonUniversalScheme, Scheme};
use crate::proof_system::solidity::{
SolidityAbi, SOLIDITY_G2_ADDITION_LIB, SOLIDITY_PAIRING_LIB, SOLIDITY_PAIRING_LIB_V2,
};
@ -39,6 +39,8 @@ impl<T: Field> Scheme<T> for PGHR13 {
type ProofPoints = ProofPoints<G1Affine, G2Affine>;
}
impl<T: Field> NonUniversalScheme<T> for PGHR13 {}
impl<T: SolidityCompatibleField> SolidityCompatibleScheme<T> for PGHR13 {
fn export_solidity_verifier(
vk: <PGHR13 as Scheme<T>>::VerificationKey,

View file

@ -6,7 +6,7 @@ extern crate zokrates_field;
use wasm_bindgen_test::*;
use zokrates_core::flat_absy::FlatVariable;
use zokrates_core::ir::{Function, Interpreter, Prog, Statement};
use zokrates_core::proof_system::Backend;
use zokrates_core::proof_system::{Backend, NonUniversalBackend};
use zokrates_field::Bn128Field;
use zokrates_core::proof_system::bellman::Bellman;
@ -32,7 +32,7 @@ fn generate_proof() {
.execute(&program, &[Bn128Field::from(42)])
.unwrap();
let keypair = <Bellman as Backend<Bn128Field, G16>>::setup(program.clone());
let keypair = <Bellman as NonUniversalBackend<Bn128Field, G16>>::setup(program.clone());
let _proof =
<Bellman as Backend<Bn128Field, G16>>::generate_proof(program, witness, keypair.pk);
}

View file

@ -1164,7 +1164,7 @@ version = "0.1.0"
[[package]]
name = "zokrates_core"
version = "0.6.3"
version = "0.6.4"
dependencies = [
"bellman_ce",
"bincode",
@ -1192,7 +1192,7 @@ dependencies = [
[[package]]
name = "zokrates_embed"
version = "0.1.2"
version = "0.1.3"
dependencies = [
"bellman_ce",
"sapling-crypto_ce",
@ -1216,7 +1216,7 @@ dependencies = [
[[package]]
name = "zokrates_js"
version = "1.0.32"
version = "1.0.33"
dependencies = [
"console_error_panic_hook",
"js-sys",

View file

@ -12,7 +12,9 @@ use zokrates_core::imports::Error;
use zokrates_core::ir;
use zokrates_core::proof_system::bellman::Bellman;
use zokrates_core::proof_system::groth16::G16;
use zokrates_core::proof_system::{Backend, Proof, Scheme, SolidityAbi, SolidityCompatibleScheme};
use zokrates_core::proof_system::{
Backend, NonUniversalBackend, Proof, Scheme, SolidityAbi, SolidityCompatibleScheme,
};
use zokrates_core::typed_absy::abi::Abi;
use zokrates_core::typed_absy::types::ConcreteSignature as Signature;
use zokrates_field::Bn128Field;
@ -162,7 +164,7 @@ pub fn compute_witness(program: &[u8], abi: JsValue, args: JsValue) -> Result<Js
#[wasm_bindgen]
pub fn setup(program: &[u8]) -> Result<JsValue, JsValue> {
let program_flattened = deserialize_program(program)?;
let keypair = <Bellman as Backend<Bn128Field, G16>>::setup(program_flattened);
let keypair = <Bellman as NonUniversalBackend<Bn128Field, G16>>::setup(program_flattened);
Ok(JsValue::from_serde(&keypair).unwrap())
}