Merge pull request #1103 from nirvantyagi/marlin-solidity-verifier
Marlin solidity verifier
This commit is contained in:
commit
68daa381e8
48 changed files with 3335 additions and 3692 deletions
|
@ -27,7 +27,7 @@ jobs:
|
|||
test:
|
||||
docker:
|
||||
- image: zokrates/env:latest
|
||||
resource_class: large
|
||||
resource_class: xlarge
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
|
@ -40,9 +40,11 @@ jobs:
|
|||
command: cargo fmt --all -- --check
|
||||
- run:
|
||||
name: Run clippy
|
||||
command: cargo clippy -- -D warnings
|
||||
no_output_timeout: 1h
|
||||
command: cargo clippy -j 4 -- -D warnings
|
||||
- run:
|
||||
name: Run tests
|
||||
no_output_timeout: 1h
|
||||
command: WITH_LIBSNARK=1 RUSTFLAGS="-D warnings" ./test.sh
|
||||
- save-sccache-cache
|
||||
cpp_format:
|
||||
|
|
1200
Cargo.lock
generated
1200
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -10,6 +10,7 @@ members = [
|
|||
"zokrates_abi",
|
||||
"zokrates_test",
|
||||
"zokrates_core_test",
|
||||
"zokrates_solidity_test",
|
||||
]
|
||||
|
||||
exclude = ["zokrates_js"]
|
||||
exclude = ["zokrates_js"]
|
1
changelogs/unreleased/1035-schaeff
Normal file
1
changelogs/unreleased/1035-schaeff
Normal file
|
@ -0,0 +1 @@
|
|||
Output structured data for Marlin artifacts
|
1
changelogs/unreleased/1103-nirvantyagi
Normal file
1
changelogs/unreleased/1103-nirvantyagi
Normal file
|
@ -0,0 +1 @@
|
|||
Add support for EVM verification of the Marlin proof system
|
|
@ -1 +1 @@
|
|||
Handle unconstrained variables gracefully
|
||||
Handle unconstrained variables gracefully
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
set -e
|
||||
|
||||
if [ -n "$WITH_LIBSNARK" ]; then
|
||||
cargo test --release --package zokrates_cli --features="libsnark" -- --ignored
|
||||
cargo test -j 4 --release --package zokrates_cli --features="libsnark" -- --ignored
|
||||
else
|
||||
cargo test --release --package zokrates_cli -- --ignored
|
||||
cargo test -j 4 --release --package zokrates_cli -- --ignored
|
||||
fi
|
4
test.sh
4
test.sh
|
@ -5,8 +5,8 @@ set -e
|
|||
|
||||
if [ -n "$WITH_LIBSNARK" ]; then
|
||||
# run specifically the libsnark tests inside zokrates_core
|
||||
cargo test --release --package zokrates_core --features="libsnark" libsnark -- --test-threads=1
|
||||
cargo test -j 4 --release --package zokrates_core --features="libsnark" libsnark -- --test-threads=1
|
||||
fi
|
||||
|
||||
# run all tests without libsnark on
|
||||
cargo test --release
|
||||
cargo test -j 4 --release
|
|
@ -9,4 +9,4 @@ zokrates_field = { version = "0.5", path = "../zokrates_field", default-features
|
|||
zokrates_core = { version = "0.6", path = "../zokrates_core", default-features = false }
|
||||
serde = "1.0"
|
||||
serde_derive = "1.0"
|
||||
serde_json = "1.0"
|
||||
serde_json = { version = "1.0", features = ["preserve_order"] }
|
||||
|
|
|
@ -23,12 +23,13 @@ zokrates_abi = { version = "0.1", path = "../zokrates_abi" }
|
|||
zokrates_core = { version = "0.6", path = "../zokrates_core", default-features = false }
|
||||
typed-arena = "1.4.1"
|
||||
zokrates_fs_resolver = { version = "0.5", path = "../zokrates_fs_resolver"}
|
||||
serde_json = "1.0"
|
||||
serde_json = { version = "1.0", features = ["preserve_order"] }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
dirs = "3.0.1"
|
||||
lazy_static = "1.4.0"
|
||||
byteorder = "1"
|
||||
rand = "0.4"
|
||||
rand_0_4 = { version = "0.4", package = "rand" }
|
||||
rand_0_8 = { version = "0.8", package = "rand" }
|
||||
hex = "0.3.1"
|
||||
blake2 = "0.8.1"
|
||||
sha2 = "0.10.0"
|
||||
|
@ -37,6 +38,9 @@ sha2 = "0.10.0"
|
|||
glob = "0.2.11"
|
||||
assert_cli = "0.5"
|
||||
tempdir = "0.3"
|
||||
zokrates_solidity_test = { version = "0.1", path = "../zokrates_solidity_test", default-features = false }
|
||||
ethabi = "17.0.0"
|
||||
primitive-types = { version = "0.11", features = ["rlp"] }
|
||||
fs_extra = "1.1.0"
|
||||
|
||||
[build-dependencies]
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
use fs_extra::copy_items;
|
||||
use fs_extra::dir::CopyOptions;
|
||||
use std::env;
|
||||
|
||||
fn main() {
|
||||
// export js test folder to OUT_DIR
|
||||
export_stdlib();
|
||||
}
|
||||
|
||||
fn export_stdlib() {
|
||||
let out_dir = env::var("OUT_DIR").unwrap();
|
||||
let mut options = CopyOptions::new();
|
||||
options.overwrite = true;
|
||||
copy_items(&["tests/contract"], out_dir, &options).unwrap();
|
||||
}
|
|
@ -71,6 +71,9 @@ pub fn exec(sub_matches: &ArgMatches) -> Result<(), String> {
|
|||
(CurveParameter::Bn128, SchemeParameter::PGHR13) => {
|
||||
cli_export_verifier::<Bn128Field, PGHR13>(sub_matches)
|
||||
}
|
||||
(CurveParameter::Bn128, SchemeParameter::MARLIN) => {
|
||||
cli_export_verifier::<Bn128Field, Marlin>(sub_matches)
|
||||
}
|
||||
_ => Err(format!("Could not export verifier with given parameters (curve: {}, scheme: {}): not supported", curve, scheme))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -53,9 +53,6 @@ fn cli_inspect<T: Field, I: Iterator<Item = ir::Statement<T>>>(
|
|||
let curve = format!("{:<17} {}", "curve:", T::name());
|
||||
let constraint_count = format!("{:<17} {}", "constraint_count:", ir_prog.constraint_count());
|
||||
|
||||
println!("{}", curve);
|
||||
println!("{}", constraint_count);
|
||||
|
||||
if sub_matches.is_present("ztf") {
|
||||
let output_path =
|
||||
PathBuf::from(sub_matches.value_of("input").unwrap()).with_extension("ztf");
|
||||
|
|
|
@ -87,8 +87,8 @@ fn cli_mpc_beacon<T: Field + BellmanFieldExtensions, S: MpcScheme<T>, B: MpcBack
|
|||
// Create an RNG based on the outcome of the random beacon
|
||||
let mut rng = {
|
||||
use byteorder::{BigEndian, ReadBytesExt};
|
||||
use rand::chacha::ChaChaRng;
|
||||
use rand::SeedableRng;
|
||||
use rand_0_4::chacha::ChaChaRng;
|
||||
use rand_0_4::SeedableRng;
|
||||
use sha2::{Digest, Sha256};
|
||||
|
||||
// The hash used for the beacon
|
||||
|
|
|
@ -76,8 +76,8 @@ pub fn cli_mpc_contribute<
|
|||
let mut rng = {
|
||||
use blake2::{Blake2b, Digest};
|
||||
use byteorder::{BigEndian, ReadBytesExt};
|
||||
use rand::chacha::ChaChaRng;
|
||||
use rand::{OsRng, Rng, SeedableRng};
|
||||
use rand_0_4::chacha::ChaChaRng;
|
||||
use rand_0_4::{OsRng, Rng, SeedableRng};
|
||||
|
||||
let h = {
|
||||
let mut system_rng = OsRng::new().unwrap();
|
||||
|
|
|
@ -1,8 +1,13 @@
|
|||
use crate::constants::JSON_PROOF_PATH;
|
||||
use crate::constants::{self, JSON_PROOF_PATH};
|
||||
use crate::helpers::{CurveParameter, SchemeParameter};
|
||||
use clap::{App, Arg, ArgMatches, SubCommand};
|
||||
use serde_json::Value;
|
||||
use std::convert::TryInto;
|
||||
use std::fs::File;
|
||||
use std::path::Path;
|
||||
use zokrates_core::proof_system::{
|
||||
Marlin, Proof, SolidityCompatibleField, SolidityCompatibleScheme, G16, GM17, PGHR13,
|
||||
};
|
||||
use zokrates_field::Bn128Field;
|
||||
|
||||
pub fn subcommand() -> App<'static, 'static> {
|
||||
SubCommand::with_name("print-proof")
|
||||
|
@ -25,41 +30,93 @@ pub fn subcommand() -> App<'static, 'static> {
|
|||
.help("Format in which the proof should be printed")
|
||||
.takes_value(true)
|
||||
.possible_values(&["remix", "json"])
|
||||
.required(true),
|
||||
.required(true)
|
||||
.default_value("remix"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("proving-scheme")
|
||||
.short("s")
|
||||
.long("proving-scheme")
|
||||
.help("Proving scheme the proof was created with")
|
||||
.value_name("FILE")
|
||||
.takes_value(true)
|
||||
.required(false)
|
||||
.possible_values(constants::SCHEMES)
|
||||
.default_value(constants::G16),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("curve")
|
||||
.short("c")
|
||||
.long("curve")
|
||||
.help("Curve to be used in the verification")
|
||||
.takes_value(true)
|
||||
.required(false)
|
||||
.possible_values(constants::CURVES)
|
||||
.default_value(constants::BN128),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn exec(sub_matches: &ArgMatches) -> Result<(), String> {
|
||||
let curve = sub_matches.value_of("curve").unwrap();
|
||||
let scheme = sub_matches.value_of("proving-scheme").unwrap();
|
||||
|
||||
let parameters: (CurveParameter, SchemeParameter) =
|
||||
(curve.try_into().unwrap(), scheme.try_into().unwrap());
|
||||
|
||||
match parameters {
|
||||
(CurveParameter::Bn128, SchemeParameter::PGHR13) => {
|
||||
cli_print_proof::<Bn128Field, PGHR13>(sub_matches)
|
||||
}
|
||||
(CurveParameter::Bn128, SchemeParameter::G16) => {
|
||||
cli_print_proof::<Bn128Field, G16>(sub_matches)
|
||||
}
|
||||
(CurveParameter::Bn128, SchemeParameter::GM17) => {
|
||||
cli_print_proof::<Bn128Field, GM17>(sub_matches)
|
||||
}
|
||||
(CurveParameter::Bn128, SchemeParameter::MARLIN) => {
|
||||
cli_print_proof::<Bn128Field, Marlin>(sub_matches)
|
||||
}
|
||||
_ => Err(format!("Could not print proof with given parameters (curve: {}, scheme: {}): only bn128 is supported", curve, scheme))
|
||||
}
|
||||
}
|
||||
|
||||
fn cli_print_proof<T: SolidityCompatibleField, S: SolidityCompatibleScheme<T>>(
|
||||
sub_matches: &ArgMatches,
|
||||
) -> Result<(), String> {
|
||||
let format = sub_matches.value_of("format").unwrap();
|
||||
let path = Path::new(sub_matches.value_of("proof-path").unwrap());
|
||||
|
||||
let file =
|
||||
File::open(&path).map_err(|why| format!("Couldn't open {}: {}", path.display(), why))?;
|
||||
|
||||
let proof_object: Value = serde_json::from_reader(file).map_err(|why| format!("{:?}", why))?;
|
||||
let proof: Proof<T, S> = serde_json::from_reader(file).map_err(|why| format!("{:?}", why))?;
|
||||
|
||||
let inputs = serde_json::to_value(&proof.inputs).unwrap();
|
||||
|
||||
let res = S::Proof::from(proof.proof);
|
||||
let proof_object = serde_json::to_value(&res).unwrap();
|
||||
|
||||
match format {
|
||||
"json" => {
|
||||
println!("~~~~~~~~ Copy the output below for valid ABIv2 format ~~~~~~~~");
|
||||
println!();
|
||||
print!("{}", proof_object["proof"]);
|
||||
print!("{}", proof_object);
|
||||
print!(",");
|
||||
println!("{}", proof_object["inputs"]);
|
||||
print!("{}", inputs);
|
||||
println!();
|
||||
println!("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
|
||||
}
|
||||
"remix" => {
|
||||
println!("~~~~~~~~ Copy the output below for valid ABIv1 format ~~~~~~~~");
|
||||
print!(
|
||||
"[{}]",
|
||||
proof_object
|
||||
.as_object()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.map(|(_, value)| value.to_string())
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ")
|
||||
);
|
||||
print!(",");
|
||||
print!("{}", inputs);
|
||||
println!();
|
||||
|
||||
for (_, value) in proof_object["proof"].as_object().unwrap().iter() {
|
||||
print!("{}", value);
|
||||
print!(",");
|
||||
}
|
||||
|
||||
println!("{}", proof_object["inputs"]);
|
||||
println!();
|
||||
println!("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
|
|
1
zokrates_cli/tests/contract/.gitignore
vendored
1
zokrates_cli/tests/contract/.gitignore
vendored
|
@ -1 +0,0 @@
|
|||
node_modules
|
2746
zokrates_cli/tests/contract/package-lock.json
generated
2746
zokrates_cli/tests/contract/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -1,15 +0,0 @@
|
|||
{
|
||||
"name": "zokrates-solidity-tester",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "test.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"author": "Paul Etscheit",
|
||||
"license": "LGPL-3.0-only",
|
||||
"dependencies": {
|
||||
"solc": "0.8.0",
|
||||
"web3": "^1.0.0"
|
||||
}
|
||||
}
|
|
@ -1,160 +0,0 @@
|
|||
var fs = require("fs");
|
||||
let Web3 = require('web3');
|
||||
const solc = require('solc');
|
||||
const contractPath = process.argv[2]
|
||||
const proofPath = process.argv[3]
|
||||
const format = process.argv[4]
|
||||
const web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:8545'));
|
||||
|
||||
const source = fs.readFileSync(contractPath, 'UTF-8');
|
||||
let jsonContractSource = {
|
||||
language: 'Solidity',
|
||||
sources: {
|
||||
[contractPath]: {
|
||||
content: source,
|
||||
},
|
||||
},
|
||||
settings: {
|
||||
optimizer: {
|
||||
enabled: true
|
||||
},
|
||||
outputSelection: {
|
||||
[contractPath]: {
|
||||
"Verifier": ['abi', "evm.bytecode"],
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
(async () => {
|
||||
const accounts = await web3.eth.getAccounts();
|
||||
|
||||
// The BN256G2 library needs to be deployed and linked separately
|
||||
// because it has `public` functions.
|
||||
// This is not needed for the Pairing library because all its functions
|
||||
// are `internal` and therefore are compiled into the contract that uses it.
|
||||
if (format == "gm17") {
|
||||
let library = await deployLibrary();
|
||||
jsonContractSource.settings.libraries = {
|
||||
[contractPath]: {
|
||||
BN256G2: library["_address"]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// -----Compile contract-----
|
||||
let jsonInterface = JSON.parse(solc.compile(JSON.stringify(jsonContractSource)));
|
||||
console.log(jsonInterface);
|
||||
|
||||
let abi = jsonInterface.contracts[contractPath]["Verifier"].abi;
|
||||
let bytecode = jsonInterface.contracts[contractPath]["Verifier"].evm.bytecode;
|
||||
|
||||
let contract = new web3.eth.Contract(abi)
|
||||
.deploy({
|
||||
data: '0x' + bytecode.object
|
||||
})
|
||||
.send({
|
||||
from: accounts[0],
|
||||
gas: '2000000'
|
||||
})
|
||||
.on('receipt', (tx) => {
|
||||
if (tx.status == true) {
|
||||
console.log("Contract Deployed! Gas used: " + tx.gasUsed);
|
||||
}
|
||||
})
|
||||
.then(newContractInstance => {
|
||||
contract = newContractInstance;
|
||||
Promise.all([makeTransaction(accounts[0], true), makeTransaction(accounts[0], false)]);
|
||||
})
|
||||
.catch(err => {
|
||||
console.log(err);
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
function makeTransaction(account, correct) {
|
||||
let proof = getProof(correct);
|
||||
|
||||
function handleReceipt(tx) {
|
||||
if (tx.status == true && !correct) {
|
||||
console.log("Verification has been successful with invalid proof data! THIS IS A BUG");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (tx.status == true) {
|
||||
console.log("Correct proof works! Gas used: " + tx.gasUsed);
|
||||
}
|
||||
}
|
||||
|
||||
function handleError(err, correct) {
|
||||
if (!correct) {
|
||||
console.log("False proof not verified! Success");
|
||||
} else {
|
||||
console.log(err);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
verifyTx(proof, account, correct).on('receipt', handleReceipt)
|
||||
.catch(handleError);
|
||||
}
|
||||
|
||||
function verifyTx(proof, account, correct) {
|
||||
var args = proof[0];
|
||||
args = proof[1].length > 0 ? [args, proof[1]] : [args];
|
||||
|
||||
return contract.methods.verifyTx(...args).send({
|
||||
from: account,
|
||||
gas: 5000000
|
||||
});
|
||||
}
|
||||
|
||||
function getProof(correct) {
|
||||
let json = JSON.parse(fs.readFileSync(proofPath));
|
||||
let inputs = json["inputs"];
|
||||
let proof = json["proof"];
|
||||
//falsifies proof to check if verification fails
|
||||
if (!correct) {
|
||||
proof["a"][0] = "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
|
||||
}
|
||||
return [Object.values(proof), Object.values(inputs)];
|
||||
}
|
||||
|
||||
//function used for deploying BN256G2 Library, used for gm17 only
|
||||
function deployLibrary() {
|
||||
let jsonContractSourceBin = JSON.stringify({
|
||||
language: 'Solidity',
|
||||
sources: {
|
||||
["BN256G2"]: {
|
||||
content: source,
|
||||
},
|
||||
},
|
||||
settings: {
|
||||
optimizer: {
|
||||
enabled: true
|
||||
},
|
||||
outputSelection: {
|
||||
'*': {
|
||||
'*': ['abi', "evm.bytecode"],
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
let jsonInterfaceBin = JSON.parse(solc.compile(jsonContractSourceBin));
|
||||
let abiLib = jsonInterfaceBin.contracts["BN256G2"]["BN256G2"].abi;
|
||||
let bytecodeLib = jsonInterfaceBin.contracts["BN256G2"]['BN256G2'].evm.bytecode;
|
||||
return new web3.eth.Contract(abiLib)
|
||||
.deploy({
|
||||
data: '0x' + bytecodeLib.object
|
||||
})
|
||||
.send({
|
||||
from: accounts[0],
|
||||
gas: '2000000'
|
||||
})
|
||||
.on('receipt', (tx) => {
|
||||
if (tx.status == false) {
|
||||
console.log("Library couldn't be deployed");
|
||||
process.exit(1);
|
||||
}
|
||||
});
|
||||
}
|
||||
})();
|
|
@ -1,11 +1,16 @@
|
|||
extern crate assert_cli;
|
||||
extern crate ethabi;
|
||||
extern crate primitive_types;
|
||||
extern crate rand_0_4;
|
||||
extern crate rand_0_8;
|
||||
extern crate serde_json;
|
||||
extern crate zokrates_solidity_test;
|
||||
|
||||
#[cfg(test)]
|
||||
mod integration {
|
||||
|
||||
use fs_extra::copy_items;
|
||||
use fs_extra::dir::CopyOptions;
|
||||
use primitive_types::U256;
|
||||
use serde_json::from_reader;
|
||||
use std::fs;
|
||||
use std::fs::File;
|
||||
|
@ -14,7 +19,12 @@ mod integration {
|
|||
use std::path::Path;
|
||||
use tempdir::TempDir;
|
||||
use zokrates_abi::{parse_strict, Encode};
|
||||
use zokrates_core::proof_system::{
|
||||
to_token::ToToken, Marlin, Proof, SolidityCompatibleScheme, G16, GM17, PGHR13,
|
||||
SOLIDITY_G2_ADDITION_LIB,
|
||||
};
|
||||
use zokrates_core::typed_absy::abi::Abi;
|
||||
use zokrates_field::Bn128Field;
|
||||
|
||||
macro_rules! map(
|
||||
{
|
||||
|
@ -30,8 +40,23 @@ mod integration {
|
|||
#[test]
|
||||
#[ignore]
|
||||
fn test_compile_and_witness_dir() {
|
||||
// install nodejs dependencies for the verification contract tester
|
||||
install_nodejs_deps();
|
||||
let global_dir = TempDir::new("global").unwrap();
|
||||
let global_base = global_dir.path();
|
||||
let universal_setup_path = global_base.join("universal_setup.dat");
|
||||
|
||||
// GENERATE A UNIVERSAL SETUP
|
||||
assert_cli::Assert::main_binary()
|
||||
.with_args(&[
|
||||
"universal-setup",
|
||||
"--size",
|
||||
"10",
|
||||
"--proving-scheme",
|
||||
"marlin",
|
||||
"--universal-setup-path",
|
||||
universal_setup_path.to_str().unwrap(),
|
||||
])
|
||||
.succeeds()
|
||||
.unwrap();
|
||||
|
||||
let dir = Path::new("./tests/code");
|
||||
assert!(dir.is_dir());
|
||||
|
@ -44,32 +69,26 @@ mod integration {
|
|||
let prog = dir.join(program_name).with_extension("zok");
|
||||
let witness = dir.join(program_name).with_extension("expected.witness");
|
||||
let json_input = dir.join(program_name).with_extension("arguments.json");
|
||||
|
||||
test_compile_and_witness(
|
||||
program_name.to_str().unwrap(),
|
||||
&prog,
|
||||
&json_input,
|
||||
&witness,
|
||||
global_base,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn install_nodejs_deps() {
|
||||
let out_dir = concat!(env!("OUT_DIR"), "/contract");
|
||||
|
||||
assert_cli::Assert::command(&["npm", "install"])
|
||||
.current_dir(out_dir)
|
||||
.succeeds()
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
fn test_compile_and_witness(
|
||||
program_name: &str,
|
||||
program_path: &Path,
|
||||
inputs_path: &Path,
|
||||
expected_witness_path: &Path,
|
||||
global_path: &Path,
|
||||
) {
|
||||
let tmp_dir = TempDir::new(".tmp").unwrap();
|
||||
let tmp_dir = TempDir::new(program_name).unwrap();
|
||||
let tmp_base = tmp_dir.path();
|
||||
let test_case_path = tmp_base.join(program_name);
|
||||
let flattened_path = tmp_base.join(program_name).join("out");
|
||||
|
@ -77,6 +96,7 @@ mod integration {
|
|||
let witness_path = tmp_base.join(program_name).join("witness");
|
||||
let inline_witness_path = tmp_base.join(program_name).join("inline_witness");
|
||||
let proof_path = tmp_base.join(program_name).join("proof.json");
|
||||
let universal_setup_path = global_path.join("universal_setup.dat");
|
||||
let verification_key_path = tmp_base
|
||||
.join(program_name)
|
||||
.join("verification")
|
||||
|
@ -97,7 +117,6 @@ mod integration {
|
|||
|
||||
// prepare compile arguments
|
||||
let compile = vec![
|
||||
"../target/release/zokrates",
|
||||
"compile",
|
||||
"-i",
|
||||
program_path.to_str().unwrap(),
|
||||
|
@ -110,12 +129,13 @@ mod integration {
|
|||
];
|
||||
|
||||
// compile
|
||||
assert_cli::Assert::command(&compile).succeeds().unwrap();
|
||||
assert_cli::Assert::main_binary()
|
||||
.with_args(&compile)
|
||||
.succeeds()
|
||||
.unwrap();
|
||||
|
||||
// COMPUTE_WITNESS
|
||||
|
||||
let compute = vec![
|
||||
"../target/release/zokrates",
|
||||
"compute-witness",
|
||||
"-i",
|
||||
flattened_path.to_str().unwrap(),
|
||||
|
@ -130,7 +150,8 @@ mod integration {
|
|||
// run witness-computation for ABI-encoded inputs through stdin
|
||||
let json_input_str = fs::read_to_string(inputs_path).unwrap();
|
||||
|
||||
assert_cli::Assert::command(&compute)
|
||||
assert_cli::Assert::main_binary()
|
||||
.with_args(&compute)
|
||||
.stdin(&json_input_str)
|
||||
.succeeds()
|
||||
.unwrap();
|
||||
|
@ -162,7 +183,6 @@ mod integration {
|
|||
.collect();
|
||||
|
||||
let mut compute_inline = vec![
|
||||
"../target/release/zokrates",
|
||||
"compute-witness",
|
||||
"-i",
|
||||
flattened_path.to_str().unwrap(),
|
||||
|
@ -178,7 +198,8 @@ mod integration {
|
|||
}
|
||||
}
|
||||
|
||||
assert_cli::Assert::command(&compute_inline)
|
||||
assert_cli::Assert::main_binary()
|
||||
.with_args(&compute_inline)
|
||||
.succeeds()
|
||||
.unwrap();
|
||||
|
||||
|
@ -225,81 +246,71 @@ mod integration {
|
|||
"ark" => vec!["g16", "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 {
|
||||
println!("test with {}, {}", backend, scheme);
|
||||
// SETUP
|
||||
let setup = assert_cli::Assert::command(&[
|
||||
"../target/release/zokrates",
|
||||
"setup",
|
||||
"-i",
|
||||
flattened_path.to_str().unwrap(),
|
||||
"-p",
|
||||
proving_key_path.to_str().unwrap(),
|
||||
"-v",
|
||||
verification_key_path.to_str().unwrap(),
|
||||
"--backend",
|
||||
backend,
|
||||
"--proving-scheme",
|
||||
scheme,
|
||||
])
|
||||
.succeeds()
|
||||
.stdout()
|
||||
.doesnt_contain("This program is too small to generate a setup with Marlin")
|
||||
.execute();
|
||||
let setup = assert_cli::Assert::main_binary()
|
||||
.with_args(&[
|
||||
"setup",
|
||||
"-i",
|
||||
flattened_path.to_str().unwrap(),
|
||||
"-p",
|
||||
proving_key_path.to_str().unwrap(),
|
||||
"-v",
|
||||
verification_key_path.to_str().unwrap(),
|
||||
"--backend",
|
||||
backend,
|
||||
"--proving-scheme",
|
||||
scheme,
|
||||
"--universal-setup-path",
|
||||
universal_setup_path.to_str().unwrap(),
|
||||
])
|
||||
.succeeds()
|
||||
.stdout()
|
||||
.doesnt_contain("This program is too small to generate a setup with Marlin")
|
||||
.execute();
|
||||
|
||||
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();
|
||||
assert_cli::Assert::main_binary()
|
||||
.with_args(&[
|
||||
"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();
|
||||
assert_cli::Assert::main_binary()
|
||||
.with_args(&[
|
||||
"verify",
|
||||
"--backend",
|
||||
backend,
|
||||
"--proving-scheme",
|
||||
scheme,
|
||||
"-j",
|
||||
proof_path.to_str().unwrap(),
|
||||
"-v",
|
||||
verification_key_path.to_str().unwrap(),
|
||||
])
|
||||
.succeeds()
|
||||
.unwrap();
|
||||
|
||||
if scheme != &"marlin" {
|
||||
// EXPORT-VERIFIER
|
||||
assert_cli::Assert::command(&[
|
||||
"../target/release/zokrates",
|
||||
// EXPORT-VERIFIER
|
||||
assert_cli::Assert::main_binary()
|
||||
.with_args(&[
|
||||
"export-verifier",
|
||||
"-i",
|
||||
verification_key_path.to_str().unwrap(),
|
||||
|
@ -311,29 +322,158 @@ mod integration {
|
|||
.succeeds()
|
||||
.unwrap();
|
||||
|
||||
// TEST VERIFIER
|
||||
assert_cli::Assert::command(&[
|
||||
"node",
|
||||
"test.js",
|
||||
verification_contract_path.to_str().unwrap(),
|
||||
proof_path.to_str().unwrap(),
|
||||
scheme,
|
||||
])
|
||||
.current_dir(concat!(env!("OUT_DIR"), "/contract"))
|
||||
.succeeds()
|
||||
.unwrap();
|
||||
// TEST VERIFIER
|
||||
// Get the contract
|
||||
let contract_str =
|
||||
std::fs::read_to_string(verification_contract_path.to_str().unwrap())
|
||||
.unwrap();
|
||||
match *scheme {
|
||||
"marlin" => {
|
||||
// Get the proof
|
||||
let proof: Proof<Bn128Field, Marlin> = serde_json::from_reader(
|
||||
File::open(proof_path.to_str().unwrap()).unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
test_solidity_verifier(contract_str, proof);
|
||||
}
|
||||
"g16" => {
|
||||
// Get the proof
|
||||
let proof: Proof<Bn128Field, G16> = serde_json::from_reader(
|
||||
File::open(proof_path.to_str().unwrap()).unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
test_solidity_verifier(contract_str, proof);
|
||||
}
|
||||
"gm17" => {
|
||||
// Get the proof
|
||||
let proof: Proof<Bn128Field, GM17> = serde_json::from_reader(
|
||||
File::open(proof_path.to_str().unwrap()).unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
test_solidity_verifier(contract_str, proof);
|
||||
}
|
||||
"pghr13" => {
|
||||
// Get the proof
|
||||
let proof: Proof<Bn128Field, PGHR13> = serde_json::from_reader(
|
||||
File::open(proof_path.to_str().unwrap()).unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
test_solidity_verifier(contract_str, proof);
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn test_solidity_verifier<S: SolidityCompatibleScheme<Bn128Field> + ToToken<Bn128Field>>(
|
||||
src: String,
|
||||
proof: Proof<Bn128Field, S>,
|
||||
) {
|
||||
use ethabi::Token;
|
||||
use rand_0_8::{rngs::StdRng, SeedableRng};
|
||||
use zokrates_solidity_test::{address::*, contract::*, evm::*, to_be_bytes};
|
||||
|
||||
// Setup EVM
|
||||
let mut rng = StdRng::from_seed([0; 32]);
|
||||
let mut evm = Evm::default();
|
||||
let deployer = Address::random(&mut rng);
|
||||
evm.create_account(&deployer, 0);
|
||||
|
||||
// Compile lib
|
||||
let g2_lib =
|
||||
Contract::compile_from_src_string(&SOLIDITY_G2_ADDITION_LIB, "BN256G2", true, &[])
|
||||
.unwrap();
|
||||
|
||||
// Deploy lib
|
||||
let create_result = evm
|
||||
.deploy(g2_lib.encode_create_contract_bytes(&[]).unwrap(), &deployer)
|
||||
.unwrap();
|
||||
let lib_addr = create_result.addr.clone();
|
||||
|
||||
// Compile contract
|
||||
let contract = Contract::compile_from_src_string(
|
||||
&src,
|
||||
"Verifier",
|
||||
true,
|
||||
&[("BN256G2", lib_addr.as_token())],
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// Deploy contract
|
||||
let create_result = evm
|
||||
.deploy(
|
||||
contract.encode_create_contract_bytes(&[]).unwrap(),
|
||||
&deployer,
|
||||
)
|
||||
.unwrap();
|
||||
let contract_addr = create_result.addr.clone();
|
||||
|
||||
// convert to the solidity proof format
|
||||
let solidity_proof = S::Proof::from(proof.proof);
|
||||
|
||||
// convert to tokens to build a call
|
||||
let proof_token = S::to_token(solidity_proof.clone());
|
||||
|
||||
let input_token = Token::FixedArray(
|
||||
proof
|
||||
.inputs
|
||||
.iter()
|
||||
.map(|s| {
|
||||
let bytes = hex::decode(s.trim_start_matches("0x")).unwrap();
|
||||
debug_assert_eq!(bytes.len(), 32);
|
||||
Token::Uint(U256::from(&bytes[..]))
|
||||
})
|
||||
.collect::<Vec<_>>(),
|
||||
);
|
||||
|
||||
let inputs = [proof_token, input_token.clone()];
|
||||
|
||||
// Call verify function on contract
|
||||
let result = evm
|
||||
.call(
|
||||
contract
|
||||
.encode_call_contract_bytes("verifyTx", &inputs)
|
||||
.unwrap(),
|
||||
&contract_addr,
|
||||
&deployer,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(&result.out, &to_be_bytes(&U256::from(1)));
|
||||
|
||||
// modify the proof
|
||||
let modified_solidity_proof = S::modify(solidity_proof.clone());
|
||||
|
||||
let modified_proof_token = S::to_token(modified_solidity_proof.clone());
|
||||
|
||||
let inputs = [modified_proof_token, input_token.clone()];
|
||||
|
||||
// Call verify function on contract
|
||||
let result = evm
|
||||
.call(
|
||||
contract
|
||||
.encode_call_contract_bytes("verifyTx", &inputs)
|
||||
.unwrap(),
|
||||
&contract_addr,
|
||||
&deployer,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(result.op_out, Return::InvalidOpcode);
|
||||
}
|
||||
|
||||
fn test_compile_and_smtlib2(
|
||||
program_name: &str,
|
||||
program_path: &Path,
|
||||
expected_smtlib2_path: &Path,
|
||||
) {
|
||||
let tmp_dir = TempDir::new(".tmp").unwrap();
|
||||
let tmp_dir = TempDir::new(program_name).unwrap();
|
||||
let tmp_base = tmp_dir.path();
|
||||
let test_case_path = tmp_base.join(program_name);
|
||||
let flattened_path = tmp_base.join(program_name).join("out");
|
||||
|
@ -346,7 +486,6 @@ mod integration {
|
|||
|
||||
// prepare compile arguments
|
||||
let compile = vec![
|
||||
"../target/release/zokrates",
|
||||
"compile",
|
||||
"-i",
|
||||
program_path.to_str().unwrap(),
|
||||
|
@ -357,11 +496,13 @@ mod integration {
|
|||
];
|
||||
|
||||
// compile
|
||||
assert_cli::Assert::command(&compile).succeeds().unwrap();
|
||||
assert_cli::Assert::main_binary()
|
||||
.with_args(&compile)
|
||||
.succeeds()
|
||||
.unwrap();
|
||||
|
||||
// prepare generate-smtlib2 arguments
|
||||
let gen = vec![
|
||||
"../target/release/zokrates",
|
||||
"generate-smtlib2",
|
||||
"-i",
|
||||
flattened_path.to_str().unwrap(),
|
||||
|
@ -370,7 +511,10 @@ mod integration {
|
|||
];
|
||||
|
||||
// generate-smtlib2
|
||||
assert_cli::Assert::command(&gen).succeeds().unwrap();
|
||||
assert_cli::Assert::main_binary()
|
||||
.with_args(&gen)
|
||||
.succeeds()
|
||||
.unwrap();
|
||||
|
||||
// load the expected smtlib2
|
||||
let mut expected_smtlib2_file = File::open(&expected_smtlib2_path).unwrap();
|
||||
|
|
|
@ -13,7 +13,7 @@ libsnark = ["cc", "cmake"]
|
|||
bellman = ["bellman_ce", "pairing_ce", "ff_ce", "zokrates_field/bellman"]
|
||||
wasm = ["bellman_ce/nolog", "bellman_ce/wasm"]
|
||||
multicore = ["bellman_ce/multicore", "phase2/multicore"]
|
||||
ark = ["ark-ff", "ark-ec", "ark-bn254", "ark-bls12-377", "ark-bw6-761", "ark-gm17", "ark-groth16", "ark-crypto-primitives", "ark-serialize", "ark-relations", "ark-marlin", "ark-poly", "ark-poly-commit", "sha2"]
|
||||
ark = ["ark-ff", "ark-ec", "ark-bn254", "ark-bls12-377", "ark-bw6-761", "ark-gm17", "ark-groth16", "ark-crypto-primitives", "ark-serialize", "ark-relations", "ark-marlin", "ark-poly", "ark-poly-commit", "sha3", "digest" ]
|
||||
|
||||
[dependencies]
|
||||
log = "0.4"
|
||||
|
@ -25,7 +25,7 @@ typed-arena = "1.4.1"
|
|||
reduce = "0.1.1"
|
||||
# serialization and deserialization
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
serde_json = { version = "1.0", features = ["preserve_order"] }
|
||||
serde_cbor = "0.11.2"
|
||||
hex = "0.4.2"
|
||||
regex = "0.2"
|
||||
|
@ -33,9 +33,9 @@ zokrates_field = { version = "0.5.0", path = "../zokrates_field", default-featur
|
|||
zokrates_pest_ast = { version = "0.2.0", path = "../zokrates_pest_ast" }
|
||||
zokrates_common = { path = "../zokrates_common" }
|
||||
zokrates_embed = { version = "0.1.0", path = "../zokrates_embed" }
|
||||
getrandom = { version = "0.2", features = ["js"] }
|
||||
getrandom = { version = "0.2", features = ["js", "wasm-bindgen"] }
|
||||
rand_0_4 = { version = "0.4", package = "rand" }
|
||||
rand_0_7 = { version = "0.7", package = "rand", features = ["wasm-bindgen"] }
|
||||
rand_0_8 = { version = "0.8", package = "rand" }
|
||||
csv = "1"
|
||||
phase2 = { git = "https://github.com/Zokrates/phase2", default-features = false }
|
||||
|
||||
|
@ -45,20 +45,23 @@ pairing_ce = { version = "^0.21", optional = true }
|
|||
ff_ce = { version = "^0.9", optional = true }
|
||||
|
||||
# ark
|
||||
ark-ff = { version = "^0.2.0", default-features = false, optional = true }
|
||||
ark-ec = { version = "^0.2.0", default-features = false, optional = true }
|
||||
ark-bn254 = { version = "^0.2.0", features = ["curve"], default-features = false, optional = true }
|
||||
ark-bls12-377 = { version = "^0.2.0", features = ["curve"], default-features = false, optional = true }
|
||||
ark-bw6-761 = { version = "^0.2.0", default-features = false, optional = true }
|
||||
ark-gm17 = { version = "^0.2.0", default-features = false, optional = true }
|
||||
ark-groth16 = { 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 }
|
||||
ark-crypto-primitives = { version = "^0.2.0", default-features = false, optional = true }
|
||||
sha2 = { version = "0.9.3", optional = true }
|
||||
ark-ff = { version = "^0.3.0", default-features = false, optional = true }
|
||||
ark-ec = { version = "^0.3.0", default-features = false, optional = true }
|
||||
ark-bn254 = { version = "^0.3.0", features = ["curve"], default-features = false, optional = true }
|
||||
ark-bls12-377 = { version = "^0.3.0", features = ["curve"], default-features = false, optional = true }
|
||||
ark-bw6-761 = { version = "^0.3.0", default-features = false, optional = true }
|
||||
ark-gm17 = { version = "^0.3.0", default-features = false, optional = true }
|
||||
ark-groth16 = { version = "^0.3.0", default-features = false, optional = true }
|
||||
ark-serialize = { version = "^0.3.0", default-features = false, optional = true }
|
||||
ark-relations = { version = "^0.3.0", default-features = false, optional = true }
|
||||
ark-marlin = { git = "https://github.com/arkworks-rs/marlin", rev = "63cfd82", default-features = false, optional = true }
|
||||
ark-poly = { version = "^0.3.0", default-features = false, optional = true }
|
||||
ark-poly-commit = { version = "^0.3.0", default-features = false, optional = true }
|
||||
ark-crypto-primitives = { version = "^0.3.0", default-features = false, optional = true }
|
||||
sha3 = { version = "0.9", optional = true }
|
||||
digest = { version = "0.9", optional = true }
|
||||
ethabi = "17.0.0"
|
||||
primitive-types = { version = "0.11", features = ["rlp"] }
|
||||
|
||||
[dev-dependencies]
|
||||
wasm-bindgen-test = "^0.3.0"
|
||||
|
|
|
@ -103,6 +103,10 @@ impl<T, I: IntoIterator<Item = Statement<T>>> ProgIterator<T, I> {
|
|||
pub fn returns(&self) -> Vec<FlatVariable> {
|
||||
(0..self.return_count).map(FlatVariable::public).collect()
|
||||
}
|
||||
|
||||
pub fn public_count(&self) -> usize {
|
||||
self.arguments.iter().filter(|a| !a.private).count() + self.return_count
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Field, I: IntoIterator<Item = Statement<T>>> ProgIterator<T, I> {
|
||||
|
|
|
@ -14,7 +14,7 @@ use crate::proof_system::gm17::{ProofPoints, VerificationKey, GM17};
|
|||
use crate::proof_system::{Backend, NonUniversalBackend, Proof, SetupKeypair};
|
||||
use crate::proof_system::{NotBw6_761Field, Scheme};
|
||||
use ark_bw6_761::BW6_761;
|
||||
use rand_0_7::SeedableRng;
|
||||
use rand_0_8::{rngs::StdRng, SeedableRng};
|
||||
|
||||
impl<T: Field + ArkFieldExtensions + NotBw6_761Field> NonUniversalBackend<T, GM17> for Ark {
|
||||
fn setup<I: IntoIterator<Item = Statement<T>>>(
|
||||
|
@ -22,7 +22,7 @@ impl<T: Field + ArkFieldExtensions + NotBw6_761Field> NonUniversalBackend<T, GM1
|
|||
) -> SetupKeypair<<GM17 as Scheme<T>>::VerificationKey> {
|
||||
let computation = Computation::without_witness(program);
|
||||
|
||||
let rng = &mut rand_0_7::rngs::StdRng::from_entropy();
|
||||
let rng = &mut StdRng::from_entropy();
|
||||
let (pk, vk) = ArkGM17::<T::ArkEngine>::circuit_specific_setup(computation, rng).unwrap();
|
||||
|
||||
let mut pk_vec: Vec<u8> = Vec::new();
|
||||
|
@ -46,7 +46,7 @@ impl<T: Field + ArkFieldExtensions + NotBw6_761Field> Backend<T, GM17> for Ark {
|
|||
program: ProgIterator<T, I>,
|
||||
witness: Witness<T>,
|
||||
proving_key: Vec<u8>,
|
||||
) -> Proof<<GM17 as Scheme<T>>::ProofPoints> {
|
||||
) -> Proof<T, GM17> {
|
||||
let computation = Computation::with_witness(program, witness);
|
||||
|
||||
let inputs = computation
|
||||
|
@ -60,7 +60,7 @@ impl<T: Field + ArkFieldExtensions + NotBw6_761Field> Backend<T, GM17> for Ark {
|
|||
)
|
||||
.unwrap();
|
||||
|
||||
let rng = &mut rand_0_7::rngs::StdRng::from_entropy();
|
||||
let rng = &mut StdRng::from_entropy();
|
||||
let proof = ArkGM17::<T::ArkEngine>::prove(&pk, computation, rng).unwrap();
|
||||
|
||||
let proof_points = ProofPoints {
|
||||
|
@ -72,10 +72,7 @@ impl<T: Field + ArkFieldExtensions + NotBw6_761Field> Backend<T, GM17> for Ark {
|
|||
Proof::new(proof_points, inputs)
|
||||
}
|
||||
|
||||
fn verify(
|
||||
vk: <GM17 as Scheme<T>>::VerificationKey,
|
||||
proof: Proof<<GM17 as Scheme<T>>::ProofPoints>,
|
||||
) -> bool {
|
||||
fn verify(vk: <GM17 as Scheme<T>>::VerificationKey, proof: Proof<T, GM17>) -> bool {
|
||||
let vk = VerifyingKey {
|
||||
h_g2: serialization::to_g2::<T>(vk.h),
|
||||
g_alpha_g1: serialization::to_g1::<T>(vk.g_alpha),
|
||||
|
@ -118,7 +115,7 @@ impl NonUniversalBackend<Bw6_761Field, GM17> for Ark {
|
|||
) -> SetupKeypair<<GM17 as Scheme<Bw6_761Field>>::VerificationKey> {
|
||||
let computation = Computation::without_witness(program);
|
||||
|
||||
let rng = &mut rand_0_7::rngs::StdRng::from_entropy();
|
||||
let rng = &mut StdRng::from_entropy();
|
||||
let (pk, vk) = ArkGM17::<BW6_761>::circuit_specific_setup(computation, rng).unwrap();
|
||||
|
||||
let mut pk_vec: Vec<u8> = Vec::new();
|
||||
|
@ -142,7 +139,7 @@ impl Backend<Bw6_761Field, GM17> for Ark {
|
|||
program: ProgIterator<Bw6_761Field, I>,
|
||||
witness: Witness<Bw6_761Field>,
|
||||
proving_key: Vec<u8>,
|
||||
) -> Proof<<GM17 as Scheme<Bw6_761Field>>::ProofPoints> {
|
||||
) -> Proof<Bw6_761Field, GM17> {
|
||||
let computation = Computation::with_witness(program, witness);
|
||||
|
||||
let inputs = computation
|
||||
|
@ -157,7 +154,7 @@ impl Backend<Bw6_761Field, GM17> for Ark {
|
|||
)
|
||||
.unwrap();
|
||||
|
||||
let rng = &mut rand_0_7::rngs::StdRng::from_entropy();
|
||||
let rng = &mut StdRng::from_entropy();
|
||||
let proof = ArkGM17::<BW6_761>::prove(&pk, computation, rng).unwrap();
|
||||
|
||||
let proof_points = ProofPoints {
|
||||
|
@ -171,7 +168,7 @@ impl Backend<Bw6_761Field, GM17> for Ark {
|
|||
|
||||
fn verify(
|
||||
vk: <GM17 as Scheme<Bw6_761Field>>::VerificationKey,
|
||||
proof: Proof<<GM17 as Scheme<Bw6_761Field>>::ProofPoints>,
|
||||
proof: Proof<Bw6_761Field, GM17>,
|
||||
) -> bool {
|
||||
let vk = VerifyingKey {
|
||||
h_g2: serialization::to_g2_fq::<Bw6_761Field>(vk.h),
|
||||
|
|
|
@ -15,7 +15,7 @@ use crate::proof_system::ark::{parse_g1, parse_g2};
|
|||
use crate::proof_system::groth16::{ProofPoints, VerificationKey, G16};
|
||||
use crate::proof_system::Scheme;
|
||||
use ark_bw6_761::BW6_761;
|
||||
use rand_0_7::SeedableRng;
|
||||
use rand_0_8::{rngs::StdRng, SeedableRng};
|
||||
|
||||
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.";
|
||||
|
||||
|
@ -24,7 +24,7 @@ impl<T: Field + ArkFieldExtensions + NotBw6_761Field> Backend<T, G16> for Ark {
|
|||
program: ProgIterator<T, I>,
|
||||
witness: Witness<T>,
|
||||
proving_key: Vec<u8>,
|
||||
) -> Proof<<G16 as Scheme<T>>::ProofPoints> {
|
||||
) -> Proof<T, G16> {
|
||||
println!("{}", G16_WARNING);
|
||||
|
||||
let computation = Computation::with_witness(program, witness);
|
||||
|
@ -40,7 +40,7 @@ impl<T: Field + ArkFieldExtensions + NotBw6_761Field> Backend<T, G16> for Ark {
|
|||
)
|
||||
.unwrap();
|
||||
|
||||
let rng = &mut rand_0_7::rngs::StdRng::from_entropy();
|
||||
let rng = &mut StdRng::from_entropy();
|
||||
let proof = Groth16::<T::ArkEngine>::prove(&pk, computation, rng).unwrap();
|
||||
|
||||
let proof_points = ProofPoints {
|
||||
|
@ -52,10 +52,7 @@ impl<T: Field + ArkFieldExtensions + NotBw6_761Field> Backend<T, G16> for Ark {
|
|||
Proof::new(proof_points, inputs)
|
||||
}
|
||||
|
||||
fn verify(
|
||||
vk: <G16 as Scheme<T>>::VerificationKey,
|
||||
proof: Proof<<G16 as Scheme<T>>::ProofPoints>,
|
||||
) -> bool {
|
||||
fn verify(vk: <G16 as Scheme<T>>::VerificationKey, proof: Proof<T, G16>) -> bool {
|
||||
let vk = VerifyingKey {
|
||||
alpha_g1: serialization::to_g1::<T>(vk.alpha),
|
||||
beta_g2: serialization::to_g2::<T>(vk.beta),
|
||||
|
@ -97,7 +94,7 @@ impl<T: Field + ArkFieldExtensions + NotBw6_761Field> NonUniversalBackend<T, G16
|
|||
|
||||
let computation = Computation::without_witness(program);
|
||||
|
||||
let rng = &mut rand_0_7::rngs::StdRng::from_entropy();
|
||||
let rng = &mut StdRng::from_entropy();
|
||||
let (pk, vk) = Groth16::<T::ArkEngine>::circuit_specific_setup(computation, rng).unwrap();
|
||||
|
||||
let mut pk_vec: Vec<u8> = Vec::new();
|
||||
|
@ -120,7 +117,7 @@ impl Backend<Bw6_761Field, G16> for Ark {
|
|||
program: ProgIterator<Bw6_761Field, I>,
|
||||
witness: Witness<Bw6_761Field>,
|
||||
proving_key: Vec<u8>,
|
||||
) -> Proof<<G16 as Scheme<Bw6_761Field>>::ProofPoints> {
|
||||
) -> Proof<Bw6_761Field, G16> {
|
||||
println!("{}", G16_WARNING);
|
||||
|
||||
let computation = Computation::with_witness(program, witness);
|
||||
|
@ -134,7 +131,7 @@ impl Backend<Bw6_761Field, G16> for Ark {
|
|||
let pk =
|
||||
ProvingKey::<BW6_761>::deserialize_uncompressed(&mut proving_key.as_slice()).unwrap();
|
||||
|
||||
let rng = &mut rand_0_7::rngs::StdRng::from_entropy();
|
||||
let rng = &mut StdRng::from_entropy();
|
||||
let proof = Groth16::<BW6_761>::prove(&pk, computation, rng).unwrap();
|
||||
|
||||
let proof_points = ProofPoints {
|
||||
|
@ -148,7 +145,7 @@ impl Backend<Bw6_761Field, G16> for Ark {
|
|||
|
||||
fn verify(
|
||||
vk: <G16 as Scheme<Bw6_761Field>>::VerificationKey,
|
||||
proof: Proof<<G16 as Scheme<Bw6_761Field>>::ProofPoints>,
|
||||
proof: Proof<Bw6_761Field, G16>,
|
||||
) -> bool {
|
||||
let vk = VerifyingKey {
|
||||
alpha_g1: serialization::to_g1::<Bw6_761Field>(vk.alpha),
|
||||
|
@ -191,7 +188,7 @@ impl NonUniversalBackend<Bw6_761Field, G16> for Ark {
|
|||
|
||||
let computation = Computation::without_witness(program);
|
||||
|
||||
let rng = &mut rand_0_7::rngs::StdRng::from_entropy();
|
||||
let rng = &mut StdRng::from_entropy();
|
||||
let (pk, vk) = Groth16::<BW6_761>::circuit_specific_setup(computation, rng).unwrap();
|
||||
|
||||
let mut pk_vec: Vec<u8> = Vec::new();
|
||||
|
|
|
@ -1,40 +1,129 @@
|
|||
use ark_marlin::{IndexProverKey, IndexVerifierKey, Proof as ArkProof};
|
||||
use ark_marlin::{
|
||||
ahp::indexer::IndexInfo, ahp::prover::ProverMsg, rng::FiatShamirRng, IndexProverKey,
|
||||
IndexVerifierKey, Proof as ArkProof,
|
||||
};
|
||||
|
||||
use ark_marlin::Marlin as ArkMarlin;
|
||||
|
||||
use ark_ec::PairingEngine;
|
||||
use ark_ff::{to_bytes, FftField, FromBytes, ToBytes};
|
||||
use ark_poly::univariate::DensePolynomial;
|
||||
use ark_poly_commit::marlin_pc::MarlinKZG10;
|
||||
use ark_poly_commit::{
|
||||
data_structures::BatchLCProof,
|
||||
kzg10::Commitment as KZG10Commitment,
|
||||
kzg10::Proof as KZG10Proof,
|
||||
kzg10::VerifierKey as KZG10VerifierKey,
|
||||
marlin_pc::{Commitment, MarlinKZG10, VerifierKey},
|
||||
};
|
||||
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
|
||||
use sha2::Sha256;
|
||||
use digest::Digest;
|
||||
use rand_0_8::{Error, RngCore, SeedableRng};
|
||||
use sha3::Keccak256;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use zokrates_field::{ArkFieldExtensions, Field};
|
||||
|
||||
use crate::ir::{ProgIterator, Statement, 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::ark::{parse_fr, parse_g1, parse_g2, serialization};
|
||||
use crate::proof_system::marlin::{self, KZGVerifierKey, ProofPoints, VerificationKey};
|
||||
use crate::proof_system::Scheme;
|
||||
use crate::proof_system::{Backend, Proof, SetupKeypair, UniversalBackend};
|
||||
|
||||
const MINIMUM_CONSTRAINT_COUNT: usize = 2;
|
||||
|
||||
/// Simple hash-based Fiat-Shamir RNG that allows for efficient solidity verification.
|
||||
pub struct HashFiatShamirRng<D: Digest> {
|
||||
seed: [u8; 32],
|
||||
ctr: u32,
|
||||
digest: PhantomData<D>,
|
||||
}
|
||||
|
||||
impl<D: Digest> RngCore for HashFiatShamirRng<D> {
|
||||
fn next_u32(&mut self) -> u32 {
|
||||
let mut bytes = [0; 4];
|
||||
self.fill_bytes(&mut bytes);
|
||||
u32::from_be_bytes(bytes)
|
||||
}
|
||||
|
||||
fn next_u64(&mut self) -> u64 {
|
||||
let mut bytes = [0; 8];
|
||||
self.fill_bytes(&mut bytes);
|
||||
u64::from_be_bytes(bytes)
|
||||
}
|
||||
|
||||
fn fill_bytes(&mut self, dest: &mut [u8]) {
|
||||
let bytes_per_hash = D::output_size();
|
||||
let n_hashes = (dest.len() - 1) / bytes_per_hash + 1;
|
||||
let mut seed_ctr = self.seed.to_vec();
|
||||
for i in 0..n_hashes {
|
||||
seed_ctr.extend_from_slice(&self.ctr.to_be_bytes());
|
||||
let mut h = D::digest(&seed_ctr).to_vec();
|
||||
h.reverse(); // Switch to big endian representation for solidity translation
|
||||
let len = dest.len();
|
||||
if i * bytes_per_hash + bytes_per_hash >= len {
|
||||
dest[i * bytes_per_hash..]
|
||||
.copy_from_slice(&h.as_slice()[..len - i * bytes_per_hash]);
|
||||
} else {
|
||||
dest[i * bytes_per_hash..i * bytes_per_hash + bytes_per_hash]
|
||||
.copy_from_slice(h.as_slice());
|
||||
}
|
||||
self.ctr += 1;
|
||||
seed_ctr.truncate(seed_ctr.len() - 4);
|
||||
}
|
||||
}
|
||||
|
||||
fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
|
||||
self.fill_bytes(dest);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Digest> FiatShamirRng for HashFiatShamirRng<D> {
|
||||
fn initialize<'a, T: 'a + ToBytes>(initial_input: &'a T) -> Self {
|
||||
let mut bytes = Vec::new();
|
||||
initial_input
|
||||
.write(&mut bytes)
|
||||
.expect("failed to convert to bytes");
|
||||
let seed = FromBytes::read(D::digest(&bytes).as_ref()).expect("failed to get [u8; 32]");
|
||||
Self {
|
||||
seed,
|
||||
ctr: 0,
|
||||
digest: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
fn absorb<'a, T: 'a + ToBytes>(&mut self, new_input: &'a T) {
|
||||
let mut bytes = Vec::new();
|
||||
new_input
|
||||
.write(&mut bytes)
|
||||
.expect("failed to convert to bytes");
|
||||
bytes.extend_from_slice(&self.seed);
|
||||
self.seed = FromBytes::read(D::digest(&bytes).as_ref()).expect("failed to get [u8; 32]");
|
||||
self.ctr = 0;
|
||||
}
|
||||
}
|
||||
|
||||
type PCInst<T> = MarlinKZG10<
|
||||
<T as ArkFieldExtensions>::ArkEngine,
|
||||
DensePolynomial<<<T as ArkFieldExtensions>::ArkEngine as PairingEngine>::Fr>,
|
||||
>;
|
||||
type MarlinInst<T> = ArkMarlin<
|
||||
<<T as ArkFieldExtensions>::ArkEngine as PairingEngine>::Fr,
|
||||
PCInst<T>,
|
||||
HashFiatShamirRng<Keccak256>,
|
||||
>;
|
||||
|
||||
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_8::rngs::StdRng::from_entropy();
|
||||
|
||||
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
|
||||
let srs = MarlinInst::<T>::universal_setup(
|
||||
2usize.pow(size),
|
||||
2usize.pow(size),
|
||||
2usize.pow(size),
|
||||
rng,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
|
@ -55,6 +144,8 @@ impl<T: Field + ArkFieldExtensions> UniversalBackend<T, marlin::Marlin> for Ark
|
|||
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 num_public_inputs = program.public_count();
|
||||
|
||||
let computation = Computation::without_witness(program);
|
||||
|
||||
let srs = ark_marlin::UniversalSRS::<
|
||||
|
@ -66,14 +157,7 @@ impl<T: Field + ArkFieldExtensions> UniversalBackend<T, marlin::Marlin> for Ark
|
|||
>::deserialize(&mut 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)
|
||||
let (pk, vk) = MarlinInst::<T>::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")
|
||||
|
@ -82,11 +166,44 @@ impl<T: Field + ArkFieldExtensions> UniversalBackend<T, marlin::Marlin> for Ark
|
|||
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();
|
||||
// Precompute some useful values for solidity contract
|
||||
let fs_seed = to_bytes![&MarlinInst::<T>::PROTOCOL_NAME, &vk].unwrap();
|
||||
let x_root_of_unity =
|
||||
<<T as ArkFieldExtensions>::ArkEngine as PairingEngine>::Fr::get_root_of_unity(
|
||||
vk.index_info.num_instance_variables,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
Ok(SetupKeypair::new(
|
||||
VerificationKey { raw: serialized_vk },
|
||||
VerificationKey {
|
||||
fs_seed,
|
||||
x_root_of_unity: parse_fr::<T>(&x_root_of_unity),
|
||||
index_comms: vk
|
||||
.index_comms
|
||||
.into_iter()
|
||||
.map(|c| (parse_g1::<T>(&c.comm.0), None))
|
||||
.collect(),
|
||||
num_public_inputs,
|
||||
num_constraints: vk.index_info.num_constraints,
|
||||
num_non_zero: vk.index_info.num_non_zero,
|
||||
num_instance_variables: vk.index_info.num_instance_variables,
|
||||
num_variables: vk.index_info.num_variables,
|
||||
vk: KZGVerifierKey {
|
||||
g: parse_g1::<T>(&vk.verifier_key.vk.g),
|
||||
gamma_g: parse_g1::<T>(&vk.verifier_key.vk.gamma_g),
|
||||
h: parse_g2::<T>(&vk.verifier_key.vk.h),
|
||||
beta_h: parse_g2::<T>(&vk.verifier_key.vk.beta_h),
|
||||
},
|
||||
max_degree: vk.verifier_key.max_degree,
|
||||
supported_degree: vk.verifier_key.supported_degree,
|
||||
degree_bounds_and_shift_powers: vk.verifier_key.degree_bounds_and_shift_powers.map(
|
||||
|vk| {
|
||||
vk.into_iter()
|
||||
.map(|(bound, pow)| (bound, parse_g1::<T>(&pow)))
|
||||
.collect()
|
||||
},
|
||||
),
|
||||
},
|
||||
serialized_pk,
|
||||
))
|
||||
}
|
||||
|
@ -97,12 +214,10 @@ impl<T: Field + ArkFieldExtensions> Backend<T, marlin::Marlin> for Ark {
|
|||
program: ProgIterator<T, I>,
|
||||
witness: Witness<T>,
|
||||
proving_key: Vec<u8>,
|
||||
) -> Proof<<marlin::Marlin as Scheme<T>>::ProofPoints> {
|
||||
) -> Proof<T, marlin::Marlin> {
|
||||
let computation = Computation::with_witness(program, witness);
|
||||
|
||||
use rand_0_7::SeedableRng;
|
||||
|
||||
let rng = &mut rand_0_7::rngs::StdRng::from_entropy();
|
||||
let rng = &mut rand_0_8::rngs::StdRng::from_entropy();
|
||||
|
||||
let pk = IndexProverKey::<
|
||||
<<T as ArkFieldExtensions>::ArkEngine as PairingEngine>::Fr,
|
||||
|
@ -113,28 +228,40 @@ impl<T: Field + ArkFieldExtensions> Backend<T, marlin::Marlin> for Ark {
|
|||
>::deserialize_uncompressed(&mut proving_key.as_slice())
|
||||
.unwrap();
|
||||
|
||||
let inputs = computation
|
||||
.public_inputs_values()
|
||||
.iter()
|
||||
.map(parse_fr::<T>)
|
||||
.collect::<Vec<_>>();
|
||||
let public_inputs = computation.public_inputs_values();
|
||||
|
||||
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 inputs = public_inputs.iter().map(parse_fr::<T>).collect::<Vec<_>>();
|
||||
|
||||
let mut serialized_proof: Vec<u8> = Vec::new();
|
||||
proof.serialize_uncompressed(&mut serialized_proof).unwrap();
|
||||
let proof = MarlinInst::<T>::prove(&pk, computation, rng).unwrap();
|
||||
|
||||
assert!(proof.pc_proof.evals.is_none());
|
||||
|
||||
Proof::new(
|
||||
ProofPoints {
|
||||
raw: serialized_proof,
|
||||
commitments: proof
|
||||
.commitments
|
||||
.into_iter()
|
||||
.map(|r| {
|
||||
r.into_iter()
|
||||
.map(|c| {
|
||||
(
|
||||
parse_g1::<T>(&c.comm.0),
|
||||
c.shifted_comm
|
||||
.map(|shifted_comm| parse_g1::<T>(&shifted_comm.0)),
|
||||
)
|
||||
})
|
||||
.collect()
|
||||
})
|
||||
.collect(),
|
||||
evaluations: proof
|
||||
.evaluations
|
||||
.into_iter()
|
||||
.map(|e| parse_fr::<T>(&e))
|
||||
.collect(),
|
||||
pc_lc_opening_1: parse_g1::<T>(&proof.pc_proof.proof[0].w),
|
||||
pc_lc_opening_1_degree: parse_fr::<T>(&proof.pc_proof.proof[0].random_v.unwrap()),
|
||||
pc_lc_opening_2: parse_g1::<T>(&proof.pc_proof.proof[1].w),
|
||||
prover_messages_count: proof.prover_messages.len(),
|
||||
},
|
||||
inputs,
|
||||
)
|
||||
|
@ -142,7 +269,7 @@ impl<T: Field + ArkFieldExtensions> Backend<T, marlin::Marlin> for Ark {
|
|||
|
||||
fn verify(
|
||||
vk: <marlin::Marlin as Scheme<T>>::VerificationKey,
|
||||
proof: Proof<<marlin::Marlin as Scheme<T>>::ProofPoints>,
|
||||
proof: Proof<T, marlin::Marlin>,
|
||||
) -> bool {
|
||||
let inputs: Vec<_> = proof
|
||||
.inputs
|
||||
|
@ -160,8 +287,54 @@ impl<T: Field + ArkFieldExtensions> Backend<T, marlin::Marlin> for Ark {
|
|||
T::ArkEngine,
|
||||
DensePolynomial<<<T as ArkFieldExtensions>::ArkEngine as PairingEngine>::Fr>,
|
||||
>,
|
||||
>::deserialize_uncompressed(&mut proof.proof.raw.as_slice())
|
||||
.unwrap();
|
||||
> {
|
||||
commitments: proof
|
||||
.proof
|
||||
.commitments
|
||||
.iter()
|
||||
.map(|r| {
|
||||
r.iter()
|
||||
.map(|(c, shifted_comm)| Commitment {
|
||||
comm: KZG10Commitment(serialization::to_g1::<T>(c.clone())),
|
||||
shifted_comm: shifted_comm.clone().map(|shifted_comm| {
|
||||
KZG10Commitment(serialization::to_g1::<T>(shifted_comm))
|
||||
}),
|
||||
})
|
||||
.collect()
|
||||
})
|
||||
.collect(),
|
||||
evaluations: proof
|
||||
.proof
|
||||
.evaluations
|
||||
.into_iter()
|
||||
.map(|v| {
|
||||
T::try_from_str(v.trim_start_matches("0x"), 16)
|
||||
.unwrap()
|
||||
.into_ark()
|
||||
})
|
||||
.collect(),
|
||||
prover_messages: vec![ProverMsg::EmptyMessage; proof.proof.prover_messages_count],
|
||||
pc_proof: BatchLCProof {
|
||||
proof: vec![
|
||||
KZG10Proof {
|
||||
w: serialization::to_g1::<T>(proof.proof.pc_lc_opening_1),
|
||||
random_v: Some(
|
||||
T::try_from_str(
|
||||
proof.proof.pc_lc_opening_1_degree.trim_start_matches("0x"),
|
||||
16,
|
||||
)
|
||||
.unwrap()
|
||||
.into_ark(),
|
||||
),
|
||||
},
|
||||
KZG10Proof {
|
||||
w: serialization::to_g1::<T>(proof.proof.pc_lc_opening_2),
|
||||
random_v: None,
|
||||
},
|
||||
],
|
||||
evals: None,
|
||||
},
|
||||
};
|
||||
|
||||
let vk = IndexVerifierKey::<
|
||||
<<T as ArkFieldExtensions>::ArkEngine as PairingEngine>::Fr,
|
||||
|
@ -169,22 +342,45 @@ impl<T: Field + ArkFieldExtensions> Backend<T, marlin::Marlin> for Ark {
|
|||
T::ArkEngine,
|
||||
DensePolynomial<<<T as ArkFieldExtensions>::ArkEngine as PairingEngine>::Fr>,
|
||||
>,
|
||||
>::deserialize_uncompressed(&mut vk.raw.as_slice())
|
||||
.unwrap();
|
||||
> {
|
||||
index_info: IndexInfo::new(
|
||||
vk.num_variables,
|
||||
vk.num_constraints,
|
||||
vk.num_non_zero,
|
||||
vk.num_instance_variables,
|
||||
),
|
||||
index_comms: vk
|
||||
.index_comms
|
||||
.into_iter()
|
||||
.map(|(c, shifted_comm)| Commitment {
|
||||
comm: KZG10Commitment(serialization::to_g1::<T>(c)),
|
||||
shifted_comm: shifted_comm.map(|shifted_comm| {
|
||||
KZG10Commitment(serialization::to_g1::<T>(shifted_comm))
|
||||
}),
|
||||
})
|
||||
.collect(),
|
||||
verifier_key: VerifierKey {
|
||||
degree_bounds_and_shift_powers: vk.degree_bounds_and_shift_powers.map(|vk| {
|
||||
vk.into_iter()
|
||||
.map(|(bound, pow)| (bound, serialization::to_g1::<T>(pow)))
|
||||
.collect()
|
||||
}),
|
||||
max_degree: vk.max_degree,
|
||||
supported_degree: vk.supported_degree,
|
||||
vk: KZG10VerifierKey {
|
||||
g: serialization::to_g1::<T>(vk.vk.g),
|
||||
gamma_g: serialization::to_g1::<T>(vk.vk.gamma_g),
|
||||
h: serialization::to_g2::<T>(vk.vk.h.clone()),
|
||||
beta_h: serialization::to_g2::<T>(vk.vk.beta_h.clone()),
|
||||
prepared_h: serialization::to_g2::<T>(vk.vk.h).into(),
|
||||
prepared_beta_h: serialization::to_g2::<T>(vk.vk.beta_h).into(),
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
use rand_0_7::SeedableRng;
|
||||
let rng = &mut rand_0_8::rngs::StdRng::from_entropy();
|
||||
|
||||
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()
|
||||
MarlinInst::<T>::verify(&vk, &inputs, &proof, rng).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ impl<T: Field + BellmanFieldExtensions> Backend<T, G16> for Bellman {
|
|||
program: ProgIterator<T, I>,
|
||||
witness: Witness<T>,
|
||||
proving_key: Vec<u8>,
|
||||
) -> Proof<<G16 as Scheme<T>>::ProofPoints> {
|
||||
) -> Proof<T, G16> {
|
||||
println!("{}", G16_WARNING);
|
||||
|
||||
let computation = Computation::with_witness(program, witness);
|
||||
|
@ -47,10 +47,7 @@ impl<T: Field + BellmanFieldExtensions> Backend<T, G16> for Bellman {
|
|||
Proof::new(proof_points, public_inputs)
|
||||
}
|
||||
|
||||
fn verify(
|
||||
vk: <G16 as Scheme<T>>::VerificationKey,
|
||||
proof: Proof<<G16 as Scheme<T>>::ProofPoints>,
|
||||
) -> bool {
|
||||
fn verify(vk: <G16 as Scheme<T>>::VerificationKey, proof: Proof<T, G16>) -> bool {
|
||||
let vk = VerifyingKey {
|
||||
alpha_g1: serialization::to_g1::<T>(vk.alpha),
|
||||
beta_g1: <T::BellmanEngine as Engine>::G1Affine::one(), // not used during verification
|
||||
|
|
|
@ -43,7 +43,7 @@ impl Backend<Bn128Field, GM17> for Libsnark {
|
|||
program: ProgIterator<Bn128Field, I>,
|
||||
witness: Witness<Bn128Field>,
|
||||
proving_key: Vec<u8>,
|
||||
) -> Proof<<GM17 as Scheme<Bn128Field>>::ProofPoints> {
|
||||
) -> Proof<Bn128Field, GM17> {
|
||||
let program = program.collect();
|
||||
|
||||
let (public_inputs_arr, public_inputs_length, private_inputs_arr, private_inputs_length) =
|
||||
|
@ -86,7 +86,7 @@ impl Backend<Bn128Field, GM17> for Libsnark {
|
|||
|
||||
fn verify(
|
||||
vk: <GM17 as Scheme<Bn128Field>>::VerificationKey,
|
||||
proof: Proof<<GM17 as Scheme<Bn128Field>>::ProofPoints>,
|
||||
proof: Proof<Bn128Field, GM17>,
|
||||
) -> bool {
|
||||
let vk_buffer = vec![];
|
||||
let mut vk_writer = BufWriter::new(vk_buffer);
|
||||
|
|
|
@ -46,7 +46,7 @@ impl Backend<Bn128Field, PGHR13> for Libsnark {
|
|||
program: ProgIterator<Bn128Field, I>,
|
||||
witness: Witness<Bn128Field>,
|
||||
proving_key: Vec<u8>,
|
||||
) -> Proof<<PGHR13 as Scheme<Bn128Field>>::ProofPoints> {
|
||||
) -> Proof<Bn128Field, PGHR13> {
|
||||
let program = program.collect();
|
||||
|
||||
let (public_inputs_arr, public_inputs_length, private_inputs_arr, private_inputs_length) =
|
||||
|
@ -104,7 +104,7 @@ impl Backend<Bn128Field, PGHR13> for Libsnark {
|
|||
|
||||
fn verify(
|
||||
vk: <PGHR13 as Scheme<Bn128Field>>::VerificationKey,
|
||||
proof: Proof<<PGHR13 as Scheme<Bn128Field>>::ProofPoints>,
|
||||
proof: Proof<Bn128Field, PGHR13>,
|
||||
) -> bool {
|
||||
let vk_buffer = vec![];
|
||||
let mut vk_writer = BufWriter::new(vk_buffer);
|
||||
|
|
|
@ -5,6 +5,8 @@ pub mod bellman;
|
|||
#[cfg(feature = "libsnark")]
|
||||
pub mod libsnark;
|
||||
|
||||
pub mod to_token;
|
||||
|
||||
mod scheme;
|
||||
mod solidity;
|
||||
|
||||
|
@ -43,14 +45,14 @@ impl<V: Serialize + DeserializeOwned> SetupKeypair<V> {
|
|||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct Proof<T> {
|
||||
pub proof: T,
|
||||
pub inputs: Vec<String>,
|
||||
pub struct Proof<T: Field, S: Scheme<T>> {
|
||||
pub proof: S::ProofPoints,
|
||||
pub inputs: Vec<Fr>,
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
impl<T: Serialize + DeserializeOwned> Proof<T> {
|
||||
fn new(proof: T, inputs: Vec<String>) -> Self {
|
||||
impl<T: Field, S: Scheme<T>> Proof<T, S> {
|
||||
fn new(proof: S::ProofPoints, inputs: Vec<String>) -> Self {
|
||||
Proof { proof, inputs }
|
||||
}
|
||||
}
|
||||
|
@ -59,15 +61,15 @@ pub type Fr = String;
|
|||
pub type Fq = String;
|
||||
pub type Fq2 = (String, String);
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct G1Affine(Fq, Fq);
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
pub struct G1Affine(pub Fq, pub Fq);
|
||||
|
||||
// When G2 is defined on Fq2 field
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Serialize, Deserialize, Clone)]
|
||||
pub struct G2Affine(Fq2, Fq2);
|
||||
|
||||
// When G2 is defined on a Fq field (BW6_761 curve)
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Serialize, Deserialize, Clone)]
|
||||
pub struct G2AffineFq(Fq, Fq);
|
||||
|
||||
impl ToString for G1Affine {
|
||||
|
@ -98,9 +100,9 @@ pub trait Backend<T: Field, S: Scheme<T>> {
|
|||
program: ir::ProgIterator<T, I>,
|
||||
witness: ir::Witness<T>,
|
||||
proving_key: Vec<u8>,
|
||||
) -> Proof<S::ProofPoints>;
|
||||
) -> Proof<T, S>;
|
||||
|
||||
fn verify(vk: S::VerificationKey, proof: Proof<S::ProofPoints>) -> bool;
|
||||
fn verify(vk: S::VerificationKey, proof: Proof<T, S>) -> bool;
|
||||
}
|
||||
pub trait NonUniversalBackend<T: Field, S: NonUniversalScheme<T>>: Backend<T, S> {
|
||||
fn setup<I: IntoIterator<Item = ir::Statement<T>>>(
|
||||
|
|
|
@ -11,7 +11,7 @@ use zokrates_field::{Bw6_761Field, Field};
|
|||
#[allow(clippy::upper_case_acronyms)]
|
||||
pub struct GM17;
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Serialize, Deserialize, Clone)]
|
||||
pub struct ProofPoints<G1, G2> {
|
||||
pub a: G1,
|
||||
pub b: G2,
|
||||
|
@ -43,6 +43,8 @@ impl Scheme<Bw6_761Field> for GM17 {
|
|||
}
|
||||
|
||||
impl<T: SolidityCompatibleField + NotBw6_761Field> SolidityCompatibleScheme<T> for GM17 {
|
||||
type Proof = Self::ProofPoints;
|
||||
|
||||
fn export_solidity_verifier(vk: <GM17 as Scheme<T>>::VerificationKey) -> String {
|
||||
let (mut template_text, solidity_pairing_lib) =
|
||||
(String::from(CONTRACT_TEMPLATE), solidity_pairing_lib(true));
|
||||
|
|
|
@ -9,7 +9,7 @@ use zokrates_field::Field;
|
|||
|
||||
pub struct G16;
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Serialize, Deserialize, Clone)]
|
||||
pub struct ProofPoints<G1, G2> {
|
||||
pub a: G1,
|
||||
pub b: G2,
|
||||
|
@ -34,6 +34,8 @@ impl<T: Field> NonUniversalScheme<T> for G16 {}
|
|||
impl<T: Field> MpcScheme<T> for G16 {}
|
||||
|
||||
impl<T: SolidityCompatibleField> SolidityCompatibleScheme<T> for G16 {
|
||||
type Proof = Self::ProofPoints;
|
||||
|
||||
fn export_solidity_verifier(vk: <G16 as Scheme<T>>::VerificationKey) -> String {
|
||||
let (mut template_text, solidity_pairing_lib_sans_bn256g2) =
|
||||
(String::from(CONTRACT_TEMPLATE), solidity_pairing_lib(false));
|
||||
|
|
|
@ -1,23 +1,682 @@
|
|||
use crate::proof_system::scheme::{Scheme, UniversalScheme};
|
||||
use crate::proof_system::solidity::{
|
||||
solidity_pairing_lib, SolidityCompatibleField, SolidityCompatibleScheme,
|
||||
};
|
||||
use crate::proof_system::{Fr, G1Affine, G2Affine, NotBw6_761Field};
|
||||
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>,
|
||||
pub struct ProofPoints<Fr, G1> {
|
||||
pub commitments: Vec<Vec<(G1, Option<G1>)>>,
|
||||
pub evaluations: Vec<Fr>,
|
||||
pub pc_lc_opening_1: G1,
|
||||
pub pc_lc_opening_1_degree: Fr,
|
||||
pub pc_lc_opening_2: G1,
|
||||
pub prover_messages_count: usize,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone)]
|
||||
pub struct SolidityProof<Fr, G1> {
|
||||
pub comms_1: Vec<G1>,
|
||||
pub comms_2: Vec<G1>,
|
||||
pub degree_bound_comms_2_g1: G1,
|
||||
pub comms_3: Vec<G1>,
|
||||
pub degree_bound_comms_3_g2: G1,
|
||||
pub evals: Vec<Fr>,
|
||||
pub batch_lc_proof_1: G1,
|
||||
pub batch_lc_proof_1_r: Fr,
|
||||
pub batch_lc_proof_2: G1,
|
||||
}
|
||||
|
||||
impl<Fr: Clone, G1: Clone> From<ProofPoints<Fr, G1>> for SolidityProof<Fr, G1> {
|
||||
fn from(p: ProofPoints<Fr, G1>) -> Self {
|
||||
SolidityProof {
|
||||
comms_1: p.commitments[0].clone().into_iter().map(|x| x.0).collect(),
|
||||
comms_2: p.commitments[1].clone().into_iter().map(|x| x.0).collect(),
|
||||
degree_bound_comms_2_g1: p.commitments[1][1].1.clone().unwrap(),
|
||||
comms_3: p.commitments[2].clone().into_iter().map(|x| x.0).collect(),
|
||||
degree_bound_comms_3_g2: p.commitments[2][0].1.clone().unwrap(),
|
||||
evals: p.evaluations,
|
||||
batch_lc_proof_1: p.pc_lc_opening_1,
|
||||
batch_lc_proof_1_r: p.pc_lc_opening_1_degree,
|
||||
batch_lc_proof_2: p.pc_lc_opening_2,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct VerificationKey {
|
||||
pub raw: Vec<u8>,
|
||||
pub struct KZGVerifierKey<G1, G2> {
|
||||
/// The generator of G1.
|
||||
pub g: G1,
|
||||
/// The generator of G1 that is used for making a commitment hiding.
|
||||
pub gamma_g: G1,
|
||||
/// The generator of G2.
|
||||
pub h: G2,
|
||||
/// \beta times the above generator of G2.
|
||||
pub beta_h: G2,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct VerificationKey<Fr, G1, G2> {
|
||||
// Useful values to precompute for solidity contract
|
||||
pub fs_seed: Vec<u8>,
|
||||
pub x_root_of_unity: Fr,
|
||||
pub num_public_inputs: usize,
|
||||
// index_info
|
||||
pub num_variables: usize,
|
||||
pub num_constraints: usize,
|
||||
pub num_non_zero: usize,
|
||||
pub num_instance_variables: usize,
|
||||
// index comms
|
||||
pub index_comms: Vec<(G1, Option<G1>)>,
|
||||
// verifier key
|
||||
pub vk: KZGVerifierKey<G1, G2>,
|
||||
pub max_degree: usize,
|
||||
pub supported_degree: usize,
|
||||
pub degree_bounds_and_shift_powers: Option<Vec<(usize, G1)>>,
|
||||
}
|
||||
|
||||
impl<T: Field> Scheme<T> for Marlin {
|
||||
type VerificationKey = VerificationKey;
|
||||
type ProofPoints = ProofPoints;
|
||||
type VerificationKey = VerificationKey<Fr, G1Affine, G2Affine>;
|
||||
type ProofPoints = ProofPoints<Fr, G1Affine>;
|
||||
}
|
||||
|
||||
impl<T: Field> UniversalScheme<T> for Marlin {}
|
||||
|
||||
impl<T: SolidityCompatibleField + NotBw6_761Field> SolidityCompatibleScheme<T> for Marlin {
|
||||
type Proof = SolidityProof<Fr, G1Affine>;
|
||||
|
||||
fn export_solidity_verifier(vk: <Marlin as Scheme<T>>::VerificationKey) -> String {
|
||||
let (template, solidity_pairing_lib) =
|
||||
(String::from(CONTRACT_TEMPLATE), solidity_pairing_lib(false));
|
||||
|
||||
// Replace public parameters in template
|
||||
let src = template
|
||||
.replace(
|
||||
"<%vk_index_comms_length%>",
|
||||
&vk.index_comms.len().to_string(),
|
||||
)
|
||||
.replace("<%vk_populate_index_comms%>", &{
|
||||
let mut populate_index_comms = String::new();
|
||||
for (i, (g, _)) in vk.index_comms.iter().enumerate() {
|
||||
populate_index_comms.push_str(&format!(
|
||||
"vk.index_comms[{}] = Pairing.G1Point({});",
|
||||
i,
|
||||
&g.to_string()
|
||||
));
|
||||
if i < vk.index_comms.len() - 1 {
|
||||
populate_index_comms.push_str("\n ");
|
||||
}
|
||||
}
|
||||
populate_index_comms
|
||||
})
|
||||
.replace("<%vk_kzg_g%>", &vk.vk.g.to_string())
|
||||
.replace("<%vk_kzg_gamma_g%>", &vk.vk.gamma_g.to_string())
|
||||
.replace("<%vk_kzg_h%>", &vk.vk.h.to_string())
|
||||
.replace("<%vk_kzg_beta_h%>", &vk.vk.beta_h.to_string())
|
||||
.replace(
|
||||
"<%vk_degree_bounds_length%>",
|
||||
&vk.degree_bounds_and_shift_powers
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.len()
|
||||
.to_string(),
|
||||
)
|
||||
.replace("<%vk_g1_shift%>", &{
|
||||
let h_domain_size = if vk.num_constraints.is_power_of_two() {
|
||||
vk.num_constraints
|
||||
} else {
|
||||
vk.num_constraints.next_power_of_two()
|
||||
};
|
||||
vk.degree_bounds_and_shift_powers
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.find(|(b, _)| *b == h_domain_size - 2)
|
||||
.unwrap()
|
||||
.1
|
||||
.to_string()
|
||||
})
|
||||
.replace("<%vk_g2_shift%>", &{
|
||||
let k_domain_size = if vk.num_non_zero.is_power_of_two() {
|
||||
vk.num_non_zero
|
||||
} else {
|
||||
vk.num_non_zero.next_power_of_two()
|
||||
};
|
||||
vk.degree_bounds_and_shift_powers
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.find(|(b, _)| *b == k_domain_size - 2)
|
||||
.unwrap()
|
||||
.1
|
||||
.to_string()
|
||||
})
|
||||
.replace("<%fs_init_seed_len%>", &(vk.fs_seed.len() / 32).to_string())
|
||||
.replace("<%fs_init_seed_overflow_len%>", &{
|
||||
let seed_len_in_32_byte_words = vk.fs_seed.len() / 32;
|
||||
let seed_len_overflow_in_bytes =
|
||||
vk.fs_seed.len() - (seed_len_in_32_byte_words * 32);
|
||||
seed_len_overflow_in_bytes.to_string()
|
||||
})
|
||||
.replace("<%fs_populate_init_seed%>", &{
|
||||
let mut populate_init_seed = String::new();
|
||||
for i in 0..vk.fs_seed.len() / 32 {
|
||||
let word_32_bytes = hex::encode(&vk.fs_seed[i * 32..i * 32 + 32]);
|
||||
populate_init_seed
|
||||
.push_str(&format!("init_seed[{}] = 0x{};", i, &word_32_bytes));
|
||||
if i < vk.fs_seed.len() / 32 - 1 {
|
||||
populate_init_seed.push_str("\n ");
|
||||
}
|
||||
}
|
||||
populate_init_seed
|
||||
})
|
||||
.replace("<%fs_init_seed_overflow%>", &{
|
||||
let seed_len_in_32_byte_words = vk.fs_seed.len() / 32;
|
||||
format!(
|
||||
"0x{}",
|
||||
hex::encode(&vk.fs_seed[seed_len_in_32_byte_words * 32..])
|
||||
)
|
||||
})
|
||||
.replace("<%h_domain_size%>", &{
|
||||
let size = if vk.num_constraints.is_power_of_two() {
|
||||
vk.num_constraints as u64
|
||||
} else {
|
||||
vk.num_constraints.next_power_of_two() as u64
|
||||
};
|
||||
size.to_string()
|
||||
})
|
||||
.replace("<%k_domain_size%>", &{
|
||||
let size = if vk.num_non_zero.is_power_of_two() {
|
||||
vk.num_non_zero as u64
|
||||
} else {
|
||||
vk.num_non_zero.next_power_of_two() as u64
|
||||
};
|
||||
size.to_string()
|
||||
})
|
||||
.replace("<%x_domain_size%>", &{
|
||||
let x = vk.num_instance_variables;
|
||||
let size = if x.is_power_of_two() {
|
||||
x as u64
|
||||
} else {
|
||||
x.next_power_of_two() as u64
|
||||
};
|
||||
size.to_string()
|
||||
})
|
||||
.replace("<%pub_padded_size%>", &{
|
||||
let x = vk.num_instance_variables;
|
||||
let size = if x.is_power_of_two() {
|
||||
x as u64
|
||||
} else {
|
||||
x.next_power_of_two() as u64
|
||||
};
|
||||
(size - 1).to_string()
|
||||
})
|
||||
.replace(
|
||||
"<%num_instance_variables%>",
|
||||
&vk.num_instance_variables.to_string(),
|
||||
)
|
||||
.replace("<%num_public_inputs%>", &vk.num_public_inputs.to_string())
|
||||
.replace("<%x_root%>", &vk.x_root_of_unity.to_string())
|
||||
.replace(
|
||||
"<%f_mod%>",
|
||||
"0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001",
|
||||
)
|
||||
.replace(
|
||||
"<%f_r%>",
|
||||
"0x0e0a77c19a07df2f666ea36f7879462e36fc76959f60cd29ac96341c4ffffffb",
|
||||
)
|
||||
.replace("<%f_inv%>", "0xc2e1f593efffffff");
|
||||
|
||||
format!("{}{}", solidity_pairing_lib, src)
|
||||
}
|
||||
}
|
||||
|
||||
const CONTRACT_TEMPLATE: &str = r#"
|
||||
contract Verifier {
|
||||
using Pairing for *;
|
||||
struct KZGVerifierKey {
|
||||
Pairing.G1Point g;
|
||||
Pairing.G1Point gamma_g;
|
||||
Pairing.G2Point h;
|
||||
Pairing.G2Point beta_h;
|
||||
}
|
||||
struct VerifierKey {
|
||||
// index commitments
|
||||
Pairing.G1Point[] index_comms;
|
||||
// verifier key
|
||||
KZGVerifierKey vk;
|
||||
Pairing.G1Point g1_shift;
|
||||
Pairing.G1Point g2_shift;
|
||||
}
|
||||
struct Proof {
|
||||
Pairing.G1Point[] comms_1;
|
||||
Pairing.G1Point[] comms_2;
|
||||
Pairing.G1Point degree_bound_comms_2_g1;
|
||||
Pairing.G1Point[] comms_3;
|
||||
Pairing.G1Point degree_bound_comms_3_g2;
|
||||
uint256[] evals;
|
||||
Pairing.G1Point batch_lc_proof_1;
|
||||
uint256 batch_lc_proof_1_r;
|
||||
Pairing.G1Point batch_lc_proof_2;
|
||||
}
|
||||
function verifierKey() internal pure returns (VerifierKey memory vk) {
|
||||
vk.index_comms = new Pairing.G1Point[](<%vk_index_comms_length%>);
|
||||
<%vk_populate_index_comms%>
|
||||
vk.vk.g = Pairing.G1Point(<%vk_kzg_g%>);
|
||||
vk.vk.gamma_g = Pairing.G1Point(<%vk_kzg_gamma_g%>);
|
||||
vk.vk.h = Pairing.G2Point(<%vk_kzg_h%>);
|
||||
vk.vk.beta_h = Pairing.G2Point(<%vk_kzg_beta_h%>);
|
||||
vk.g1_shift = Pairing.G1Point(<%vk_g1_shift%>);
|
||||
vk.g2_shift = Pairing.G1Point(<%vk_g2_shift%>);
|
||||
}
|
||||
|
||||
function verifyTx(Proof memory proof, uint256[<%num_public_inputs%>] memory input) public view returns (bool) {
|
||||
|
||||
uint256[<%pub_padded_size%>] memory input_padded;
|
||||
for (uint i = 0; i < input.length; i++) {
|
||||
input_padded[i] = input[i];
|
||||
}
|
||||
|
||||
return verifyTxAux(input_padded, proof);
|
||||
}
|
||||
|
||||
function verifyTxAux(uint256[<%pub_padded_size%>] memory input, Proof memory proof) internal view returns (bool) {
|
||||
VerifierKey memory vk = verifierKey();
|
||||
for (uint i = 0; i < input.length; i++) {
|
||||
require(input[i] < <%f_mod%>);
|
||||
}
|
||||
bytes32 fs_seed;
|
||||
uint32 ctr;
|
||||
{
|
||||
bytes32[<%fs_init_seed_len%>] memory init_seed;
|
||||
<%fs_populate_init_seed%>
|
||||
bytes<%fs_init_seed_overflow_len%> init_seed_overflow = <%fs_init_seed_overflow%>;
|
||||
uint256[<%pub_padded_size%>] memory input_reverse;
|
||||
for (uint i = 0; i < input.length; i++) {
|
||||
input_reverse[i] = be_to_le(input[i]);
|
||||
}
|
||||
fs_seed = keccak256(abi.encodePacked(init_seed, init_seed_overflow, input_reverse));
|
||||
}
|
||||
{
|
||||
ctr = 0;
|
||||
uint8 one = 1;
|
||||
uint8 zero = 0;
|
||||
uint256[2] memory empty = [0, be_to_le(1)];
|
||||
fs_seed = keccak256(abi.encodePacked(
|
||||
abi.encodePacked(
|
||||
be_to_le(proof.comms_1[0].X), be_to_le(proof.comms_1[0].Y), zero,
|
||||
zero,
|
||||
empty, one
|
||||
),
|
||||
abi.encodePacked(
|
||||
be_to_le(proof.comms_1[1].X), be_to_le(proof.comms_1[1].Y), zero,
|
||||
zero,
|
||||
empty, one
|
||||
),
|
||||
abi.encodePacked(
|
||||
be_to_le(proof.comms_1[2].X), be_to_le(proof.comms_1[2].Y), zero,
|
||||
zero,
|
||||
empty, one
|
||||
),
|
||||
abi.encodePacked(
|
||||
be_to_le(proof.comms_1[3].X), be_to_le(proof.comms_1[3].Y), zero,
|
||||
zero,
|
||||
empty, one
|
||||
),
|
||||
fs_seed
|
||||
));
|
||||
}
|
||||
uint256[7] memory challenges;
|
||||
{
|
||||
uint256 f;
|
||||
(f, ctr) = sample_field(fs_seed, ctr);
|
||||
while (eval_vanishing_poly(f, <%h_domain_size%>) == 0) {
|
||||
(f, ctr) = sample_field(fs_seed, ctr);
|
||||
}
|
||||
challenges[0] = montgomery_reduction(f);
|
||||
(f, ctr) = sample_field(fs_seed, ctr);
|
||||
challenges[1] = montgomery_reduction(f);
|
||||
(f, ctr) = sample_field(fs_seed, ctr);
|
||||
challenges[2] = montgomery_reduction(f);
|
||||
(f, ctr) = sample_field(fs_seed, ctr);
|
||||
challenges[3] = montgomery_reduction(f);
|
||||
}
|
||||
{
|
||||
ctr = 0;
|
||||
uint8 one = 1;
|
||||
uint8 zero = 0;
|
||||
uint256[2] memory empty = [0, be_to_le(1)];
|
||||
fs_seed = keccak256(abi.encodePacked(
|
||||
abi.encodePacked(
|
||||
be_to_le(proof.comms_2[0].X), be_to_le(proof.comms_2[0].Y), zero,
|
||||
zero,
|
||||
empty, one
|
||||
),
|
||||
abi.encodePacked(
|
||||
be_to_le(proof.comms_2[1].X), be_to_le(proof.comms_2[1].Y), zero,
|
||||
one,
|
||||
be_to_le(proof.degree_bound_comms_2_g1.X), be_to_le(proof.degree_bound_comms_2_g1.Y), zero
|
||||
),
|
||||
abi.encodePacked(
|
||||
be_to_le(proof.comms_2[2].X), be_to_le(proof.comms_2[2].Y), zero,
|
||||
zero,
|
||||
empty, one
|
||||
),
|
||||
fs_seed
|
||||
));
|
||||
}
|
||||
{
|
||||
uint256 f;
|
||||
(f, ctr) = sample_field(fs_seed, ctr);
|
||||
while (eval_vanishing_poly(f, <%h_domain_size%>) == 0) {
|
||||
(f, ctr) = sample_field(fs_seed, ctr);
|
||||
}
|
||||
challenges[4] = montgomery_reduction(f);
|
||||
}
|
||||
{
|
||||
ctr = 0;
|
||||
uint8 one = 1;
|
||||
uint8 zero = 0;
|
||||
uint256[2] memory empty = [0, be_to_le(1)];
|
||||
fs_seed = keccak256(abi.encodePacked(
|
||||
abi.encodePacked(
|
||||
be_to_le(proof.comms_3[0].X), be_to_le(proof.comms_3[0].Y), zero,
|
||||
one,
|
||||
be_to_le(proof.degree_bound_comms_3_g2.X), be_to_le(proof.degree_bound_comms_3_g2.Y), zero
|
||||
),
|
||||
abi.encodePacked(
|
||||
be_to_le(proof.comms_3[1].X), be_to_le(proof.comms_3[1].Y), zero,
|
||||
zero,
|
||||
empty, one
|
||||
),
|
||||
fs_seed
|
||||
));
|
||||
}
|
||||
{
|
||||
uint256 f;
|
||||
(f, ctr) = sample_field(fs_seed, ctr);
|
||||
challenges[5] = montgomery_reduction(f);
|
||||
}
|
||||
{
|
||||
ctr = 0;
|
||||
uint256[] memory evals_reverse = new uint256[](proof.evals.length);
|
||||
for (uint i = 0; i < proof.evals.length; i++) {
|
||||
evals_reverse[i] = be_to_le(proof.evals[i]);
|
||||
}
|
||||
fs_seed = keccak256(abi.encodePacked(evals_reverse, fs_seed));
|
||||
}
|
||||
{
|
||||
uint256 f;
|
||||
(f, ctr) = sample_field_128(fs_seed, ctr);
|
||||
challenges[6] = f;
|
||||
}
|
||||
Pairing.G1Point[2] memory combined_comm;
|
||||
uint256[2] memory combined_eval;
|
||||
{
|
||||
uint256[6] memory intermediate_evals;
|
||||
|
||||
intermediate_evals[0] = eval_unnormalized_bivariate_lagrange_poly(
|
||||
challenges[0],
|
||||
challenges[4],
|
||||
<%h_domain_size%>
|
||||
);
|
||||
intermediate_evals[1] = eval_vanishing_poly(challenges[0], <%h_domain_size%>);
|
||||
intermediate_evals[2] = eval_vanishing_poly(challenges[4], <%h_domain_size%>);
|
||||
intermediate_evals[3] = eval_vanishing_poly(challenges[4], <%x_domain_size%>);
|
||||
|
||||
{
|
||||
uint256[<%x_domain_size%>] memory lagrange_coeffs = eval_all_lagrange_coeffs_x_domain(challenges[4]);
|
||||
intermediate_evals[4] = lagrange_coeffs[0];
|
||||
for (uint i = 1; i < lagrange_coeffs.length; i++) {
|
||||
intermediate_evals[4] = addmod(intermediate_evals[4], mulmod(lagrange_coeffs[i], input[i-1], <%f_mod%>), <%f_mod%>);
|
||||
}
|
||||
}
|
||||
intermediate_evals[5] = eval_vanishing_poly(challenges[5], <%k_domain_size%>);
|
||||
|
||||
{
|
||||
// beta commitments: g_1, outer_sc, t, z_b
|
||||
uint256[4] memory beta_evals;
|
||||
Pairing.G1Point[4] memory beta_commitments;
|
||||
beta_evals[0] = proof.evals[0];
|
||||
beta_evals[2] = proof.evals[2];
|
||||
beta_evals[3] = proof.evals[3];
|
||||
beta_commitments[0] = proof.comms_2[1];
|
||||
beta_commitments[2] = proof.comms_2[0];
|
||||
beta_commitments[3] = proof.comms_1[2];
|
||||
{
|
||||
// outer sum check: mask_poly, z_a, 1, w, 1, h_1, 1
|
||||
uint256[7] memory outer_sc_coeffs;
|
||||
outer_sc_coeffs[0] = 1;
|
||||
outer_sc_coeffs[1] = mulmod(intermediate_evals[0], addmod(challenges[1], mulmod(challenges[3], proof.evals[3], <%f_mod%>), <%f_mod%>), <%f_mod%>);
|
||||
outer_sc_coeffs[2] = mulmod(intermediate_evals[0], mulmod(challenges[2], proof.evals[3], <%f_mod%>), <%f_mod%>);
|
||||
outer_sc_coeffs[3] = mulmod(intermediate_evals[3], submod(0, proof.evals[2], <%f_mod%>), <%f_mod%>);
|
||||
outer_sc_coeffs[4] = mulmod(intermediate_evals[4], submod(0, proof.evals[2], <%f_mod%>), <%f_mod%>);
|
||||
outer_sc_coeffs[5] = submod(0, intermediate_evals[2], <%f_mod%>);
|
||||
outer_sc_coeffs[6] = mulmod(proof.evals[0], submod(0, challenges[4], <%f_mod%>), <%f_mod%>);
|
||||
|
||||
beta_commitments[1] = proof.comms_1[3];
|
||||
beta_commitments[1] = beta_commitments[1].addition(proof.comms_1[1].scalar_mul(outer_sc_coeffs[1]));
|
||||
beta_commitments[1] = beta_commitments[1].addition(proof.comms_1[0].scalar_mul(outer_sc_coeffs[3]));
|
||||
beta_commitments[1] = beta_commitments[1].addition(proof.comms_2[2].scalar_mul(outer_sc_coeffs[5]));
|
||||
beta_evals[1] = submod(beta_evals[1], outer_sc_coeffs[2], <%f_mod%>);
|
||||
beta_evals[1] = submod(beta_evals[1], outer_sc_coeffs[4], <%f_mod%>);
|
||||
beta_evals[1] = submod(beta_evals[1], outer_sc_coeffs[6], <%f_mod%>);
|
||||
}
|
||||
{
|
||||
combined_comm[0] = beta_commitments[0];
|
||||
combined_eval[0] = beta_evals[0];
|
||||
uint256 beta_opening_challenge = challenges[6];
|
||||
{
|
||||
Pairing.G1Point memory tmp = proof.degree_bound_comms_2_g1.addition(vk.g1_shift.scalar_mul(beta_evals[0]).negate());
|
||||
tmp = tmp.scalar_mul(beta_opening_challenge);
|
||||
combined_comm[0] = combined_comm[0].addition(tmp);
|
||||
}
|
||||
beta_opening_challenge = mulmod(beta_opening_challenge, challenges[6], <%f_mod%>);
|
||||
combined_comm[0] = combined_comm[0].addition(beta_commitments[1].scalar_mul(beta_opening_challenge));
|
||||
combined_eval[0] = addmod(combined_eval[0], mulmod(beta_evals[1], beta_opening_challenge, <%f_mod%>), <%f_mod%>);
|
||||
beta_opening_challenge = mulmod(beta_opening_challenge, challenges[6], <%f_mod%>);
|
||||
combined_comm[0] = combined_comm[0].addition(beta_commitments[2].scalar_mul(beta_opening_challenge));
|
||||
combined_eval[0] = addmod(combined_eval[0], mulmod(beta_evals[2], beta_opening_challenge, <%f_mod%>), <%f_mod%>);
|
||||
beta_opening_challenge = mulmod(beta_opening_challenge, challenges[6], <%f_mod%>);
|
||||
combined_comm[0] = combined_comm[0].addition(beta_commitments[3].scalar_mul(beta_opening_challenge));
|
||||
combined_eval[0] = addmod(combined_eval[0], mulmod(beta_evals[3], beta_opening_challenge, <%f_mod%>), <%f_mod%>);
|
||||
}
|
||||
}
|
||||
{
|
||||
// gamma commitments: g_2, inner_sc
|
||||
uint256[2] memory gamma_evals;
|
||||
Pairing.G1Point[2] memory gamma_commitments;
|
||||
gamma_evals[0] = proof.evals[1];
|
||||
gamma_commitments[0] = proof.comms_3[0];
|
||||
{
|
||||
// inner sum check: a_val, b_val, c_val, 1, row, col, row_col, h_2
|
||||
uint256[8] memory inner_sc_coeffs;
|
||||
{
|
||||
uint256 a_poly_coeff = mulmod(intermediate_evals[1], intermediate_evals[2], <%f_mod%>);
|
||||
inner_sc_coeffs[0] = mulmod(challenges[1], a_poly_coeff, <%f_mod%>);
|
||||
inner_sc_coeffs[1] = mulmod(challenges[2], a_poly_coeff, <%f_mod%>);
|
||||
inner_sc_coeffs[2] = mulmod(challenges[3], a_poly_coeff, <%f_mod%>);
|
||||
}
|
||||
{
|
||||
uint256 b_poly_coeff = mulmod(challenges[5], proof.evals[1], <%f_mod%>);
|
||||
b_poly_coeff = addmod(b_poly_coeff, mulmod(proof.evals[2], inverse(<%k_domain_size%>), <%f_mod%>), <%f_mod%>);
|
||||
inner_sc_coeffs[3] = mulmod(b_poly_coeff, submod(0, mulmod(challenges[4], challenges[0], <%f_mod%>), <%f_mod%>), <%f_mod%>);
|
||||
inner_sc_coeffs[4] = mulmod(b_poly_coeff, challenges[0], <%f_mod%>);
|
||||
inner_sc_coeffs[5] = mulmod(b_poly_coeff, challenges[4], <%f_mod%>);
|
||||
inner_sc_coeffs[6] = submod(0, b_poly_coeff, <%f_mod%>);
|
||||
}
|
||||
inner_sc_coeffs[7] = submod(0, intermediate_evals[5], <%f_mod%>);
|
||||
|
||||
gamma_commitments[1] = vk.index_comms[2].scalar_mul(inner_sc_coeffs[0]);
|
||||
gamma_commitments[1] = gamma_commitments[1].addition(vk.index_comms[3].scalar_mul(inner_sc_coeffs[1]));
|
||||
gamma_commitments[1] = gamma_commitments[1].addition(vk.index_comms[4].scalar_mul(inner_sc_coeffs[2]));
|
||||
gamma_commitments[1] = gamma_commitments[1].addition(vk.index_comms[0].scalar_mul(inner_sc_coeffs[4]));
|
||||
gamma_commitments[1] = gamma_commitments[1].addition(vk.index_comms[1].scalar_mul(inner_sc_coeffs[5]));
|
||||
gamma_commitments[1] = gamma_commitments[1].addition(vk.index_comms[5].scalar_mul(inner_sc_coeffs[6]));
|
||||
gamma_commitments[1] = gamma_commitments[1].addition(proof.comms_3[1].scalar_mul(inner_sc_coeffs[7]));
|
||||
gamma_evals[1] = submod(0, inner_sc_coeffs[3], <%f_mod%>);
|
||||
}
|
||||
{
|
||||
combined_comm[1] = gamma_commitments[0];
|
||||
combined_eval[1] = gamma_evals[0];
|
||||
uint256 gamma_opening_challenge = challenges[6];
|
||||
{
|
||||
Pairing.G1Point memory tmp = proof.degree_bound_comms_3_g2.addition(vk.g2_shift.scalar_mul(gamma_evals[0]).negate());
|
||||
tmp = tmp.scalar_mul(gamma_opening_challenge);
|
||||
combined_comm[1] = combined_comm[1].addition(tmp);
|
||||
}
|
||||
gamma_opening_challenge = mulmod(gamma_opening_challenge, challenges[6], <%f_mod%>);
|
||||
combined_comm[1] = combined_comm[1].addition(gamma_commitments[1].scalar_mul(gamma_opening_challenge));
|
||||
combined_eval[1] = addmod(combined_eval[1], mulmod(gamma_evals[1], gamma_opening_challenge, <%f_mod%>), <%f_mod%>);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Final pairing check
|
||||
uint256 r = uint256(keccak256(abi.encodePacked(combined_comm[0].X, combined_comm[0].Y, combined_comm[1].X, combined_comm[1].Y, fs_seed)));
|
||||
|
||||
Pairing.G1Point memory c_final;
|
||||
{
|
||||
Pairing.G1Point[2] memory c;
|
||||
c[0] = combined_comm[0].addition(proof.batch_lc_proof_1.scalar_mul(challenges[4]));
|
||||
c[1] = combined_comm[1].addition(proof.batch_lc_proof_2.scalar_mul(challenges[5]));
|
||||
c_final = c[0].addition(c[1].scalar_mul(r));
|
||||
}
|
||||
Pairing.G1Point memory w_final = proof.batch_lc_proof_1.addition(proof.batch_lc_proof_2.scalar_mul(r));
|
||||
uint256 g_mul_final = addmod(combined_eval[0], mulmod(combined_eval[1], r, <%f_mod%>), <%f_mod%>);
|
||||
|
||||
c_final = c_final.addition(vk.vk.g.scalar_mul(g_mul_final).negate());
|
||||
c_final = c_final.addition(vk.vk.gamma_g.scalar_mul(proof.batch_lc_proof_1_r).negate());
|
||||
bool valid = Pairing.pairingProd2(w_final.negate(), vk.vk.beta_h, c_final, vk.vk.h);
|
||||
return valid;
|
||||
}
|
||||
function be_to_le(uint256 input) internal pure returns (uint256 v) {
|
||||
v = input;
|
||||
// swap bytes
|
||||
v = ((v & 0xFF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00) >> 8) |
|
||||
((v & 0x00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF) << 8);
|
||||
// swap 2-byte long pairs
|
||||
v = ((v & 0xFFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000) >> 16) |
|
||||
((v & 0x0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF) << 16);
|
||||
// swap 4-byte long pairs
|
||||
v = ((v & 0xFFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000) >> 32) |
|
||||
((v & 0x00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF) << 32);
|
||||
// swap 8-byte long pairs
|
||||
v = ((v & 0xFFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF0000000000000000) >> 64) |
|
||||
((v & 0x0000000000000000FFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF) << 64);
|
||||
// swap 16-byte long pairs
|
||||
v = (v >> 128) | (v << 128);
|
||||
}
|
||||
function sample_field(bytes32 fs_seed, uint32 ctr) internal pure returns (uint256, uint32) {
|
||||
// https://github.com/arkworks-rs/algebra/blob/master/ff/src/fields/models/fp/mod.rs#L561
|
||||
while (true) {
|
||||
uint256 v;
|
||||
for (uint i = 0; i < 4; i++) {
|
||||
v |= (uint256(keccak256(abi.encodePacked(fs_seed, ctr))) & uint256(0xFFFFFFFFFFFFFFFF)) << ((3-i) * 64);
|
||||
ctr += 1;
|
||||
}
|
||||
v = be_to_le(v);
|
||||
v &= (1 << 254) - 1;
|
||||
if (v < <%f_mod%>) {
|
||||
return (v, ctr);
|
||||
}
|
||||
}
|
||||
}
|
||||
function sample_field_128(bytes32 fs_seed, uint32 ctr) internal pure returns (uint256, uint32) {
|
||||
// https://github.com/arkworks-rs/algebra/blob/master/ff/src/fields/models/fp/mod.rs#L561
|
||||
uint256 v;
|
||||
for (uint i = 0; i < 2; i++) {
|
||||
v |= (uint256(keccak256(abi.encodePacked(fs_seed, ctr))) & uint256(0xFFFFFFFFFFFFFFFF)) << ((3-i) * 64);
|
||||
ctr += 1;
|
||||
}
|
||||
v = be_to_le(v);
|
||||
return (v, ctr);
|
||||
}
|
||||
function montgomery_reduction(uint256 r) internal pure returns (uint256 v) {
|
||||
uint256[4] memory limbs;
|
||||
uint256[4] memory mod_limbs;
|
||||
for (uint i = 0; i < 4; i++) {
|
||||
limbs[i] = (r >> (i * 64)) & uint256(0xFFFFFFFFFFFFFFFF);
|
||||
mod_limbs[i] = (<%f_mod%> >> (i * 64)) & uint256(0xFFFFFFFFFFFFFFFF);
|
||||
}
|
||||
// Montgomery Reduction
|
||||
for (uint i = 0; i < 4; i++) {
|
||||
uint256 k = mulmod(limbs[i], <%f_inv%>, 1 << 64);
|
||||
uint256 carry = 0;
|
||||
carry = (limbs[i] + (k * mod_limbs[0]) + carry) >> 64;
|
||||
|
||||
for (uint j = 0; j < 4; j++) {
|
||||
uint256 tmp = limbs[(i + j) % 4] + (k * mod_limbs[j]) + carry;
|
||||
limbs[(i + j) % 4] = tmp & uint256(0xFFFFFFFFFFFFFFFF);
|
||||
carry = tmp >> 64;
|
||||
}
|
||||
limbs[i % 4] = carry;
|
||||
}
|
||||
for (uint i = 0; i < 4; i++) {
|
||||
v |= (limbs[i] & uint256(0xFFFFFFFFFFFFFFFF)) << (i * 64);
|
||||
}
|
||||
}
|
||||
function submod(uint256 a, uint256 b, uint256 n) internal pure returns (uint256) {
|
||||
return addmod(a, n - b, n);
|
||||
}
|
||||
function expmod(uint256 _base, uint256 _exponent, uint256 _modulus) internal view returns (uint256 retval){
|
||||
bool success;
|
||||
uint256[1] memory output;
|
||||
uint[6] memory input;
|
||||
input[0] = 0x20; // baseLen = new(big.Int).SetBytes(getData(input, 0, 32))
|
||||
input[1] = 0x20; // expLen = new(big.Int).SetBytes(getData(input, 32, 32))
|
||||
input[2] = 0x20; // modLen = new(big.Int).SetBytes(getData(input, 64, 32))
|
||||
input[3] = _base;
|
||||
input[4] = _exponent;
|
||||
input[5] = _modulus;
|
||||
assembly {
|
||||
success := staticcall(sub(gas(), 2000), 5, input, 0xc0, output, 0x20)
|
||||
// Use "invalid" to make gas estimation work
|
||||
switch success case 0 { invalid() }
|
||||
}
|
||||
require(success);
|
||||
return output[0];
|
||||
}
|
||||
function inverse(uint256 a) internal view returns (uint256){
|
||||
return expmod(a, <%f_mod%> - 2, <%f_mod%>);
|
||||
}
|
||||
function eval_vanishing_poly(uint256 x, uint256 domain_size) internal view returns (uint256){
|
||||
return submod(expmod(x, domain_size, <%f_mod%>), 1, <%f_mod%>);
|
||||
}
|
||||
function eval_unnormalized_bivariate_lagrange_poly(uint256 x, uint256 y, uint256 domain_size) internal view returns (uint256){
|
||||
require(x != y);
|
||||
uint256 tmp = submod(eval_vanishing_poly(x, domain_size), eval_vanishing_poly(y, domain_size), <%f_mod%>);
|
||||
return mulmod(tmp, inverse(submod(x, y, <%f_mod%>)), <%f_mod%>);
|
||||
}
|
||||
function eval_all_lagrange_coeffs_x_domain(uint256 x) internal view returns (uint256[<%x_domain_size%>] memory){
|
||||
uint256[<%x_domain_size%>] memory coeffs;
|
||||
uint256 domain_size = <%x_domain_size%>;
|
||||
uint256 root = <%x_root%>;
|
||||
uint256 v_at_x = eval_vanishing_poly(x, domain_size);
|
||||
uint256 root_inv = inverse(root);
|
||||
if (v_at_x == 0) {
|
||||
uint256 omega_i = 1;
|
||||
for (uint i = 0; i < domain_size; i++) {
|
||||
if (omega_i == x) {
|
||||
coeffs[i] = 1;
|
||||
return coeffs;
|
||||
}
|
||||
omega_i = mulmod(omega_i, root, <%f_mod%>);
|
||||
}
|
||||
} else {
|
||||
uint256 l_i = mulmod(inverse(v_at_x), domain_size, <%f_mod%>);
|
||||
uint256 neg_elem = 1;
|
||||
for (uint i = 0; i < domain_size; i++) {
|
||||
coeffs[i] = mulmod(submod(x, neg_elem, <%f_mod%>), l_i, <%f_mod%>);
|
||||
coeffs[i] = inverse(coeffs[i]);
|
||||
l_i = mulmod(l_i, root_inv, <%f_mod%>);
|
||||
neg_elem = mulmod(neg_elem, root, <%f_mod%>);
|
||||
}
|
||||
return coeffs;
|
||||
}
|
||||
}
|
||||
}
|
||||
"#;
|
||||
|
|
|
@ -8,7 +8,7 @@ use zokrates_field::Field;
|
|||
#[allow(clippy::upper_case_acronyms)]
|
||||
pub struct PGHR13;
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Serialize, Deserialize, Clone)]
|
||||
pub struct ProofPoints<G1, G2> {
|
||||
pub a: G1,
|
||||
pub a_p: G1,
|
||||
|
@ -40,6 +40,8 @@ impl<T: Field> Scheme<T> for PGHR13 {
|
|||
impl<T: Field> NonUniversalScheme<T> for PGHR13 {}
|
||||
|
||||
impl<T: SolidityCompatibleField> SolidityCompatibleScheme<T> for PGHR13 {
|
||||
type Proof = Self::ProofPoints;
|
||||
|
||||
fn export_solidity_verifier(vk: <PGHR13 as Scheme<T>>::VerificationKey) -> String {
|
||||
let (mut template_text, solidity_pairing_lib) =
|
||||
(String::from(CONTRACT_TEMPLATE), solidity_pairing_lib(false));
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
use crate::proof_system::Scheme;
|
||||
use serde::{de::DeserializeOwned, Serialize};
|
||||
use zokrates_field::{Bn128Field, Field};
|
||||
|
||||
pub trait SolidityCompatibleField: Field {}
|
||||
impl SolidityCompatibleField for Bn128Field {}
|
||||
|
||||
pub trait SolidityCompatibleScheme<T: SolidityCompatibleField>: Scheme<T> {
|
||||
type Proof: From<Self::ProofPoints> + Serialize + DeserializeOwned + Clone;
|
||||
|
||||
fn export_solidity_verifier(vk: Self::VerificationKey) -> String;
|
||||
}
|
||||
|
||||
|
|
239
zokrates_core/src/proof_system/to_token.rs
Normal file
239
zokrates_core/src/proof_system/to_token.rs
Normal file
|
@ -0,0 +1,239 @@
|
|||
use ethabi::Token;
|
||||
use primitive_types::U256;
|
||||
|
||||
use super::{
|
||||
Fr, G1Affine, G2Affine, Marlin, NotBw6_761Field, SolidityCompatibleField,
|
||||
SolidityCompatibleScheme, G16, GM17, PGHR13,
|
||||
};
|
||||
|
||||
/// Helper methods for parsing group structure
|
||||
pub fn encode_g1_element(g: &G1Affine) -> (U256, U256) {
|
||||
(
|
||||
U256::from(&hex::decode(&g.0.trim_start_matches("0x")).unwrap()[..]),
|
||||
U256::from(&hex::decode(&g.1.trim_start_matches("0x")).unwrap()[..]),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn encode_g2_element(g: &G2Affine) -> ((U256, U256), (U256, U256)) {
|
||||
(
|
||||
(
|
||||
U256::from(&hex::decode(&g.0 .0.trim_start_matches("0x")).unwrap()[..]),
|
||||
U256::from(&hex::decode(&g.0 .1.trim_start_matches("0x")).unwrap()[..]),
|
||||
),
|
||||
(
|
||||
U256::from(&hex::decode(&g.1 .0.trim_start_matches("0x")).unwrap()[..]),
|
||||
U256::from(&hex::decode(&g.1 .1.trim_start_matches("0x")).unwrap()[..]),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn encode_fr_element(f: &Fr) -> U256 {
|
||||
U256::from(&hex::decode(&f.trim_start_matches("0x")).unwrap()[..])
|
||||
}
|
||||
|
||||
pub trait ToToken<T: SolidityCompatibleField>: SolidityCompatibleScheme<T> {
|
||||
fn to_token(proof: Self::Proof) -> ethabi::Token;
|
||||
|
||||
fn modify(proof: Self::Proof) -> Self::Proof;
|
||||
}
|
||||
|
||||
impl<T: SolidityCompatibleField> ToToken<T> for PGHR13 {
|
||||
fn to_token(proof: Self::Proof) -> Token {
|
||||
let a = {
|
||||
let (x, y) = encode_g1_element(&proof.a);
|
||||
Token::Tuple(vec![Token::Uint(x), Token::Uint(y)])
|
||||
};
|
||||
|
||||
let a_p = {
|
||||
let (x, y) = encode_g1_element(&proof.a_p);
|
||||
Token::Tuple(vec![Token::Uint(x), Token::Uint(y)])
|
||||
};
|
||||
|
||||
let b = {
|
||||
let ((x0, y0), (x1, y1)) = encode_g2_element(&proof.b);
|
||||
Token::Tuple(vec![
|
||||
Token::FixedArray(vec![Token::Uint(x0), Token::Uint(y0)]),
|
||||
Token::FixedArray(vec![Token::Uint(x1), Token::Uint(y1)]),
|
||||
])
|
||||
};
|
||||
|
||||
let b_p = {
|
||||
let (x, y) = encode_g1_element(&proof.b_p);
|
||||
Token::Tuple(vec![Token::Uint(x), Token::Uint(y)])
|
||||
};
|
||||
|
||||
let c = {
|
||||
let (x, y) = encode_g1_element(&proof.c);
|
||||
Token::Tuple(vec![Token::Uint(x), Token::Uint(y)])
|
||||
};
|
||||
|
||||
let c_p = {
|
||||
let (x, y) = encode_g1_element(&proof.c_p);
|
||||
Token::Tuple(vec![Token::Uint(x), Token::Uint(y)])
|
||||
};
|
||||
|
||||
let h = {
|
||||
let (x, y) = encode_g1_element(&proof.h);
|
||||
Token::Tuple(vec![Token::Uint(x), Token::Uint(y)])
|
||||
};
|
||||
|
||||
let k = {
|
||||
let (x, y) = encode_g1_element(&proof.k);
|
||||
Token::Tuple(vec![Token::Uint(x), Token::Uint(y)])
|
||||
};
|
||||
|
||||
let proof_tokens = vec![a, a_p, b, b_p, c, c_p, h, k];
|
||||
|
||||
Token::Tuple(proof_tokens)
|
||||
}
|
||||
|
||||
fn modify(mut proof: Self::Proof) -> Self::Proof {
|
||||
proof.a.0 = "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa".into();
|
||||
proof
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: SolidityCompatibleField> ToToken<T> for G16 {
|
||||
fn to_token(proof: Self::Proof) -> Token {
|
||||
let a = {
|
||||
let (x, y) = encode_g1_element(&proof.a);
|
||||
Token::Tuple(vec![Token::Uint(x), Token::Uint(y)])
|
||||
};
|
||||
|
||||
let b = {
|
||||
let ((x0, y0), (x1, y1)) = encode_g2_element(&proof.b);
|
||||
Token::Tuple(vec![
|
||||
Token::FixedArray(vec![Token::Uint(x0), Token::Uint(y0)]),
|
||||
Token::FixedArray(vec![Token::Uint(x1), Token::Uint(y1)]),
|
||||
])
|
||||
};
|
||||
|
||||
let c = {
|
||||
let (x, y) = encode_g1_element(&proof.c);
|
||||
Token::Tuple(vec![Token::Uint(x), Token::Uint(y)])
|
||||
};
|
||||
|
||||
let proof_tokens = vec![a, b, c];
|
||||
|
||||
Token::Tuple(proof_tokens)
|
||||
}
|
||||
|
||||
fn modify(mut proof: Self::Proof) -> Self::Proof {
|
||||
proof.a.0 = "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa".into();
|
||||
proof
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: SolidityCompatibleField + NotBw6_761Field> ToToken<T> for GM17 {
|
||||
fn to_token(proof: Self::Proof) -> Token {
|
||||
let a = {
|
||||
let (x, y) = encode_g1_element(&proof.a);
|
||||
Token::Tuple(vec![Token::Uint(x), Token::Uint(y)])
|
||||
};
|
||||
|
||||
let b = {
|
||||
let ((x0, y0), (x1, y1)) = encode_g2_element(&proof.b);
|
||||
Token::Tuple(vec![
|
||||
Token::FixedArray(vec![Token::Uint(x0), Token::Uint(y0)]),
|
||||
Token::FixedArray(vec![Token::Uint(x1), Token::Uint(y1)]),
|
||||
])
|
||||
};
|
||||
|
||||
let c = {
|
||||
let (x, y) = encode_g1_element(&proof.c);
|
||||
Token::Tuple(vec![Token::Uint(x), Token::Uint(y)])
|
||||
};
|
||||
|
||||
let proof_tokens = vec![a, b, c];
|
||||
|
||||
Token::Tuple(proof_tokens)
|
||||
}
|
||||
|
||||
fn modify(mut proof: Self::Proof) -> Self::Proof {
|
||||
proof.a.0 = "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa".into();
|
||||
proof
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: SolidityCompatibleField + NotBw6_761Field> ToToken<T> for Marlin {
|
||||
fn to_token(proof: Self::Proof) -> Token {
|
||||
let comms_1_token = Token::Array(
|
||||
proof
|
||||
.comms_1
|
||||
.iter()
|
||||
.map(encode_g1_element)
|
||||
.map(|(x, y)| Token::Tuple(vec![Token::Uint(x), Token::Uint(y)]))
|
||||
.collect(),
|
||||
);
|
||||
|
||||
let comms_2_token = Token::Array(
|
||||
proof
|
||||
.comms_2
|
||||
.iter()
|
||||
.map(encode_g1_element)
|
||||
.map(|(x, y)| Token::Tuple(vec![Token::Uint(x), Token::Uint(y)]))
|
||||
.collect(),
|
||||
);
|
||||
|
||||
let degree_bound_comms_2_g1_token = {
|
||||
let (x, y) = encode_g1_element(&proof.degree_bound_comms_2_g1);
|
||||
Token::Tuple(vec![Token::Uint(x), Token::Uint(y)])
|
||||
};
|
||||
|
||||
let comms_3_token = Token::Array(
|
||||
proof
|
||||
.comms_3
|
||||
.iter()
|
||||
.map(encode_g1_element)
|
||||
.map(|(x, y)| Token::Tuple(vec![Token::Uint(x), Token::Uint(y)]))
|
||||
.collect(),
|
||||
);
|
||||
|
||||
let degree_bound_comms_3_g2_token = {
|
||||
let (x, y) = encode_g1_element(&proof.degree_bound_comms_3_g2);
|
||||
Token::Tuple(vec![Token::Uint(x), Token::Uint(y)])
|
||||
};
|
||||
|
||||
let evals_token = Token::Array(
|
||||
proof
|
||||
.evals
|
||||
.into_iter()
|
||||
.map(|f| encode_fr_element(&f))
|
||||
.map(Token::Uint)
|
||||
.collect::<Vec<_>>(),
|
||||
);
|
||||
|
||||
let pc_lc_opening_1_token = {
|
||||
let (x, y) = encode_g1_element(&proof.batch_lc_proof_1);
|
||||
Token::Tuple(vec![Token::Uint(x), Token::Uint(y)])
|
||||
};
|
||||
|
||||
let degree_bound_pc_lc_opening_1_token =
|
||||
Token::Uint(encode_fr_element(&proof.batch_lc_proof_1_r));
|
||||
|
||||
let pc_lc_opening_2_token = {
|
||||
let (x, y) = encode_g1_element(&proof.batch_lc_proof_2);
|
||||
Token::Tuple(vec![Token::Uint(x), Token::Uint(y)])
|
||||
};
|
||||
|
||||
let proof_tokens = vec![
|
||||
comms_1_token,
|
||||
comms_2_token,
|
||||
degree_bound_comms_2_g1_token,
|
||||
comms_3_token,
|
||||
degree_bound_comms_3_g2_token,
|
||||
evals_token,
|
||||
pc_lc_opening_1_token,
|
||||
degree_bound_pc_lc_opening_1_token,
|
||||
pc_lc_opening_2_token,
|
||||
];
|
||||
|
||||
Token::Tuple(proof_tokens)
|
||||
}
|
||||
|
||||
fn modify(mut proof: Self::Proof) -> Self::Proof {
|
||||
proof.degree_bound_comms_3_g2.0 =
|
||||
"0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa".into();
|
||||
proof
|
||||
}
|
||||
}
|
|
@ -13,12 +13,12 @@ multicore = ["bellman_ce/multicore", "sapling-crypto_ce/multicore"]
|
|||
zokrates_field = { version = "0.5.0", path = "../zokrates_field", default-features = false }
|
||||
bellman_ce = { version = "^0.3", default-features = false }
|
||||
sapling-crypto_ce = { version = "^0.1", default-features = false }
|
||||
ark-bls12-377 = { version = "^0.2.0", features = ["curve", "r1cs"], default-features = false }
|
||||
ark-bw6-761 = { version = "^0.2.0", default-features = false }
|
||||
ark-gm17 = { version = "^0.2.0", default-features = false, features = ["r1cs"] }
|
||||
ark-relations = { version = "^0.2.0", default-features = false }
|
||||
ark-crypto-primitives = { version = "^0.2.0", default-features = false, features = ["r1cs"] }
|
||||
ark-r1cs-std = { version = "^0.2.0", default-features = false }
|
||||
ark-std = { version = "^0.2.0", default-features = false }
|
||||
ark-ec = { version = "^0.2.0", default-features = false }
|
||||
ark-ff = { version = "^0.2.0", default-features = false}
|
||||
ark-bls12-377 = { version = "^0.3.0", features = ["curve", "r1cs"], default-features = false }
|
||||
ark-bw6-761 = { version = "^0.3.0", default-features = false }
|
||||
ark-gm17 = { version = "^0.3.0", default-features = false, features = ["r1cs"] }
|
||||
ark-relations = { version = "^0.3.0", default-features = false }
|
||||
ark-crypto-primitives = { version = "^0.3.0", default-features = false, features = ["r1cs"] }
|
||||
ark-r1cs-std = { version = "^0.3.0", default-features = false }
|
||||
ark-std = { version = "^0.3.0", default-features = false }
|
||||
ark-ec = { version = "^0.3.0", default-features = false }
|
||||
ark-ff = { version = "^0.3.0", default-features = false}
|
|
@ -13,7 +13,7 @@ serde = "1.0"
|
|||
serde_derive = "1.0"
|
||||
lazy_static = "1.4"
|
||||
bincode = "0.8.0"
|
||||
serde_json = "1.0"
|
||||
serde_json = { version = "1.0", features = ["preserve_order"] }
|
||||
sha2 = "0.8.0"
|
||||
num-traits = { version = "0.2", default-features = false }
|
||||
num-integer = { version = "0.1", default-features = false }
|
||||
|
@ -22,13 +22,13 @@ num-integer = { version = "0.1", default-features = false }
|
|||
bellman_ce = { version = "^0.3", default-features = false, optional = true }
|
||||
|
||||
# ark
|
||||
ark-ec = { version = "^0.2.0", default-features = false }
|
||||
ark-ff = { version = "^0.2.0", default-features = false }
|
||||
ark-bn254 = { version = "^0.2.0", features = ["curve"], default-features = false }
|
||||
ark-bls12-377 = { version = "^0.2.0", features = ["curve"], default-features = false }
|
||||
ark-bls12-381 = { version = "^0.2.0", features = ["curve"], default-features = false }
|
||||
ark-bw6-761 = { version = "^0.2.0", default-features = false }
|
||||
ark-serialize = { version = "^0.2.0", default-features = false }
|
||||
ark-ff = { version = "^0.3.0", default-features = false }
|
||||
ark-ec = { version = "^0.3.0", default-features = false }
|
||||
ark-bn254 = { version = "^0.3.0", features = ["curve"], default-features = false }
|
||||
ark-bls12-377 = { version = "^0.3.0", features = ["curve"], default-features = false }
|
||||
ark-bls12-381 = { version = "^0.3.0", features = ["curve"] }
|
||||
ark-bw6-761 = { version = "^0.3.0", default-features = false }
|
||||
ark-serialize = { version = "^0.3.0", default-features = false }
|
||||
|
||||
[dev-dependencies]
|
||||
rand = "0.4"
|
||||
|
|
531
zokrates_js/Cargo.lock
generated
531
zokrates_js/Cargo.lock
generated
|
@ -23,7 +23,7 @@ version = "0.7.6"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47"
|
||||
dependencies = [
|
||||
"getrandom 0.2.3",
|
||||
"getrandom",
|
||||
"once_cell",
|
||||
"version_check",
|
||||
]
|
||||
|
@ -38,10 +38,19 @@ dependencies = [
|
|||
]
|
||||
|
||||
[[package]]
|
||||
name = "ark-bls12-377"
|
||||
version = "0.2.0"
|
||||
name = "aho-corasick"
|
||||
version = "0.7.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eb89b97424403ec9cc22a1df0db748dd7396c9ba5fb5c71a6f0e10ae1d1a7449"
|
||||
checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ark-bls12-377"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc41c02c0d18a226947ee9ee023b1d957bdb6a68fc22ac296722935a9fef423c"
|
||||
dependencies = [
|
||||
"ark-ec",
|
||||
"ark-ff",
|
||||
|
@ -51,9 +60,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "ark-bls12-381"
|
||||
version = "0.2.0"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "70e1c2ad76c4f725520440b981df3ce2d635f2baa1122750c757c0cf0f3d4b74"
|
||||
checksum = "65be532f9dd1e98ad0150b037276cde464c6f371059e6dd02c0222395761f6aa"
|
||||
dependencies = [
|
||||
"ark-ec",
|
||||
"ark-ff",
|
||||
|
@ -62,9 +71,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "ark-bn254"
|
||||
version = "0.2.0"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3ead066869de5e8cb2938123204d1572f09496b629e146a6f80fa8ec508446ba"
|
||||
checksum = "ea691771ebbb28aea556c044e2e5c5227398d840cee0c34d4d20fa8eb2689e8c"
|
||||
dependencies = [
|
||||
"ark-ec",
|
||||
"ark-ff",
|
||||
|
@ -73,9 +82,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "ark-bw6-761"
|
||||
version = "0.2.0"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "69ad8d74a8e083a59defc4a226a19759691337006d5c9397dbd793af9e406418"
|
||||
checksum = "5abb465edcdee2bec3eff283e43f1c2414d1a4f6eaeb8e3de02aba3695d0520b"
|
||||
dependencies = [
|
||||
"ark-bls12-377",
|
||||
"ark-ec",
|
||||
|
@ -85,15 +94,16 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "ark-crypto-primitives"
|
||||
version = "0.2.0"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "74b83a7e125e5c611e4a997123effb2f02e3fbc66531dd77751d3016ee920741"
|
||||
checksum = "ff773c0ef8c655c98071d3026a63950798a66b2f45baef22d8334c1756f1bd18"
|
||||
dependencies = [
|
||||
"ark-ec",
|
||||
"ark-ff",
|
||||
"ark-nonnative-field",
|
||||
"ark-r1cs-std",
|
||||
"ark-relations",
|
||||
"ark-serialize",
|
||||
"ark-snark",
|
||||
"ark-std",
|
||||
"blake2",
|
||||
|
@ -104,9 +114,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "ark-ec"
|
||||
version = "0.2.0"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c56006994f509d76fbce6f6ffe3108f7191b4f3754ecd00bbae7cac20ec05020"
|
||||
checksum = "dea978406c4b1ca13c2db2373b05cc55429c3575b8b21f1b9ee859aa5b03dd42"
|
||||
dependencies = [
|
||||
"ark-ff",
|
||||
"ark-serialize",
|
||||
|
@ -118,25 +128,27 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "ark-ff"
|
||||
version = "0.2.0"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a4d8802d40fce9212c5c09be08f75c4b3becc0c488e87f60fff787b01250ce33"
|
||||
checksum = "6b3235cc41ee7a12aaaf2c575a2ad7b46713a8a50bda2fc3b003a04845c05dd6"
|
||||
dependencies = [
|
||||
"ark-ff-asm",
|
||||
"ark-ff-macros",
|
||||
"ark-serialize",
|
||||
"ark-std",
|
||||
"derivative",
|
||||
"num-bigint 0.4.2",
|
||||
"num-traits 0.2.14",
|
||||
"paste",
|
||||
"rustc_version",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ark-ff-asm"
|
||||
version = "0.2.0"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3e8cb28c2137af1ef058aa59616db3f7df67dbb70bf2be4ee6920008cc30d98c"
|
||||
checksum = "db02d390bf6643fb404d3d22d31aee1c4bc4459600aef9113833d17e786c6e44"
|
||||
dependencies = [
|
||||
"quote 1.0.10",
|
||||
"syn 1.0.80",
|
||||
|
@ -144,9 +156,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "ark-ff-macros"
|
||||
version = "0.2.0"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b9c256a93a10ed9708c16a517d6dcfaba3d215c0d7fab44d29a9affefb5eeb8"
|
||||
checksum = "db2fd794a08ccb318058009eefdf15bcaaaaf6f8161eb3345f907222bac38b20"
|
||||
dependencies = [
|
||||
"num-bigint 0.4.2",
|
||||
"num-traits 0.2.14",
|
||||
|
@ -156,9 +168,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "ark-gm17"
|
||||
version = "0.2.0"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4c9085a6c89aa65178aa2718b2efb62fd7c4dc23fe25285204e30b56e4cbfcac"
|
||||
checksum = "94713045868e99a606a89825ff5a901667ba707ad1966a32c7f3a4d4dbcc0e9a"
|
||||
dependencies = [
|
||||
"ark-crypto-primitives",
|
||||
"ark-ec",
|
||||
|
@ -174,9 +186,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "ark-nonnative-field"
|
||||
version = "0.2.0"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "17887af156e9911d1dba5b30d49256d508f82f6a4f765a6fad8b5c637b700353"
|
||||
checksum = "440ad4569974910adbeb84422b7e622b79e08d27142afd113785b7fcfb446186"
|
||||
dependencies = [
|
||||
"ark-ec",
|
||||
"ark-ff",
|
||||
|
@ -192,22 +204,22 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "ark-poly"
|
||||
version = "0.2.0"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72d6683d21645a2abb94034f6a14e708405e55d9597687952d54b2269922857a"
|
||||
checksum = "7b0f78f47537c2f15706db7e98fe64cc1711dbf9def81218194e17239e53e5aa"
|
||||
dependencies = [
|
||||
"ark-ff",
|
||||
"ark-serialize",
|
||||
"ark-std",
|
||||
"derivative",
|
||||
"hashbrown",
|
||||
"hashbrown 0.11.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ark-r1cs-std"
|
||||
version = "0.2.0"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a90fea2b84ae4443983d56540360ea004cab952292b7a6535798b6b9dcb7f41"
|
||||
checksum = "22e8fdacb1931f238a0d866ced1e916a49d36de832fd8b83dc916b718ae72893"
|
||||
dependencies = [
|
||||
"ark-ec",
|
||||
"ark-ff",
|
||||
|
@ -221,9 +233,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "ark-relations"
|
||||
version = "0.2.0"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a42f124f8dfff2b0561143c0c7ea48d7f7dc8d2c4c1e87eca14a27430c653c0b"
|
||||
checksum = "4cba4c1c99792a6834bd97f7fd76578ec2cd58d2afc5139a17e1d1bec65b38f6"
|
||||
dependencies = [
|
||||
"ark-ff",
|
||||
"ark-std",
|
||||
|
@ -232,19 +244,20 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "ark-serialize"
|
||||
version = "0.2.0"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c3e9b59329dc9b92086b3dc619f31cef4a0c802f10829b575a3666d48a48387d"
|
||||
checksum = "1d6c2b318ee6e10f8c2853e73a83adc0ccb88995aa978d8a3408d492ab2ee671"
|
||||
dependencies = [
|
||||
"ark-serialize-derive",
|
||||
"ark-std",
|
||||
"digest 0.9.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ark-serialize-derive"
|
||||
version = "0.2.0"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5ac3d78c750b01f5df5b2e76d106ed31487a93b3868f14a7f0eb3a74f45e1d8a"
|
||||
checksum = "8dd4e5f0bf8285d5ed538d27fab7411f3e297908fd93c62195de8bee3f199e82"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.30",
|
||||
"quote 1.0.10",
|
||||
|
@ -253,9 +266,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "ark-snark"
|
||||
version = "0.2.0"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39da26432fe584b0010741299820145ec69180fe9ea18ddf96946932763624a1"
|
||||
checksum = "0dc3dff1a5f67a9c0b34df32b079752d8dd17f1e9d06253da0453db6c1b7cc8a"
|
||||
dependencies = [
|
||||
"ark-ff",
|
||||
"ark-relations",
|
||||
|
@ -264,12 +277,12 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "ark-std"
|
||||
version = "0.2.0"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fb5b856a29bea7b810858116a596beee3d20fc4c5aeb240e8e5a8bca4845a470"
|
||||
checksum = "1df2c09229cbc5a028b1d70e00fdb2acee28b1055dfb5ca73eea49c5a25c4e7c"
|
||||
dependencies = [
|
||||
"rand 0.7.3",
|
||||
"rand_xorshift",
|
||||
"num-traits 0.2.14",
|
||||
"rand 0.8.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -281,6 +294,12 @@ dependencies = [
|
|||
"nodrop",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "arrayvec"
|
||||
version = "0.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6"
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.0.1"
|
||||
|
@ -335,6 +354,18 @@ version = "0.6.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb"
|
||||
|
||||
[[package]]
|
||||
name = "bitvec"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1489fcb93a5bb47da0462ca93ad252ad6af2145cce58d10d46a83931ba9f016b"
|
||||
dependencies = [
|
||||
"funty",
|
||||
"radium",
|
||||
"tap",
|
||||
"wyz",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "blake2"
|
||||
version = "0.9.2"
|
||||
|
@ -352,7 +383,7 @@ version = "0.2.18"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"arrayvec 0.4.12",
|
||||
"constant_time_eq",
|
||||
]
|
||||
|
||||
|
@ -362,7 +393,7 @@ version = "0.0.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fdc60350286c7c3db13b98e91dbe5c8b6830a6821bc20af5b0c310ce94d74915"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"arrayvec 0.4.12",
|
||||
"byteorder",
|
||||
"constant_time_eq",
|
||||
]
|
||||
|
@ -379,6 +410,15 @@ dependencies = [
|
|||
"generic-array 0.12.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "block-buffer"
|
||||
version = "0.10.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0bf7fe51849ea569fd452f37822f606a5cabb684dc918707a0193fd4664ff324"
|
||||
dependencies = [
|
||||
"generic-array 0.14.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "block-padding"
|
||||
version = "0.1.5"
|
||||
|
@ -406,6 +446,12 @@ version = "3.8.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f1e260c3a9040a7c19a12468758f4c16f31a81a1fe087482be9570ec864bb6c"
|
||||
|
||||
[[package]]
|
||||
name = "byte-slice-cast"
|
||||
version = "1.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "87c5fdd0166095e1d463fc6cc01aa8ce547ad77a4e84d42eb6762b084e28067e"
|
||||
|
||||
[[package]]
|
||||
name = "byte-tools"
|
||||
version = "0.3.1"
|
||||
|
@ -418,6 +464,12 @@ version = "1.4.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
|
||||
|
||||
[[package]]
|
||||
name = "bytes"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.71"
|
||||
|
@ -530,6 +582,16 @@ version = "0.2.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
|
||||
|
||||
[[package]]
|
||||
name = "crypto-common"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "57952ca27b5e3606ff4dd79b0020231aaf9d6aa76dc05fd30137538c50bd3ce8"
|
||||
dependencies = [
|
||||
"generic-array 0.14.4",
|
||||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crypto-mac"
|
||||
version = "0.8.0"
|
||||
|
@ -591,12 +653,66 @@ dependencies = [
|
|||
"generic-array 0.14.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "digest"
|
||||
version = "0.10.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506"
|
||||
dependencies = [
|
||||
"block-buffer 0.10.2",
|
||||
"crypto-common",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
|
||||
|
||||
[[package]]
|
||||
name = "ethabi"
|
||||
version = "17.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b69517146dfab88e9238c00c724fd8e277951c3cc6f22b016d72f422a832213e"
|
||||
dependencies = [
|
||||
"ethereum-types",
|
||||
"hex",
|
||||
"once_cell",
|
||||
"regex 1.5.5",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sha3",
|
||||
"thiserror",
|
||||
"uint",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ethbloom"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "11da94e443c60508eb62cf256243a64da87304c2802ac2528847f79d750007ef"
|
||||
dependencies = [
|
||||
"crunchy",
|
||||
"fixed-hash",
|
||||
"impl-rlp",
|
||||
"impl-serde",
|
||||
"tiny-keccak",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ethereum-types"
|
||||
version = "0.13.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b2827b94c556145446fcce834ca86b7abf0c39a805883fe20e72c5bfdb5a0dc6"
|
||||
dependencies = [
|
||||
"ethbloom",
|
||||
"fixed-hash",
|
||||
"impl-rlp",
|
||||
"impl-serde",
|
||||
"primitive-types",
|
||||
"uint",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "failure"
|
||||
version = "0.1.8"
|
||||
|
@ -662,6 +778,18 @@ dependencies = [
|
|||
"syn 1.0.80",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fixed-hash"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cfcf0ed7fe52a17a03854ec54a9f76d6d84508d1c0e66bc1793301c73fc8493c"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"rand 0.8.5",
|
||||
"rustc-hex",
|
||||
"static_assertions",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "from-pest"
|
||||
version = "0.3.1"
|
||||
|
@ -678,6 +806,12 @@ version = "0.1.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
|
||||
|
||||
[[package]]
|
||||
name = "funty"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c"
|
||||
|
||||
[[package]]
|
||||
name = "futures"
|
||||
version = "0.3.17"
|
||||
|
@ -775,17 +909,6 @@ dependencies = [
|
|||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.1.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"libc",
|
||||
"wasi 0.9.0+wasi-snapshot-preview1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.3"
|
||||
|
@ -795,7 +918,7 @@ dependencies = [
|
|||
"cfg-if 1.0.0",
|
||||
"js-sys",
|
||||
"libc",
|
||||
"wasi 0.10.2+wasi-snapshot-preview1",
|
||||
"wasi",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
|
@ -811,6 +934,12 @@ version = "1.8.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7"
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04"
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.11.2"
|
||||
|
@ -835,6 +964,54 @@ version = "0.4.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
|
||||
|
||||
[[package]]
|
||||
name = "impl-codec"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ba6a270039626615617f3f36d15fc827041df3b78c439da2cadfa47455a77f2f"
|
||||
dependencies = [
|
||||
"parity-scale-codec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "impl-rlp"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f28220f89297a075ddc7245cd538076ee98b01f2a9c23a53a4f1105d5a322808"
|
||||
dependencies = [
|
||||
"rlp",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "impl-serde"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4551f042f3438e64dbd6226b20527fc84a6e1fe65688b58746a2f53623f25f5c"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "impl-trait-for-tuples"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.30",
|
||||
"quote 1.0.10",
|
||||
"syn 1.0.80",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "1.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "824845a0bf897a9042383849b02c1bc219c2383772efcd5c6f9766fa4b81aef3"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"hashbrown 0.9.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.7.11"
|
||||
|
@ -859,6 +1036,12 @@ dependencies = [
|
|||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "keccak"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "67c21572b4949434e4fc1e1978b99c5f77064153c59d998bf13ecd96fb5ecba7"
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
|
@ -1017,9 +1200,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.8.0"
|
||||
version = "1.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56"
|
||||
checksum = "87f3e037eac156d1775da914196f0f37741a274155e34a0b7e427c35d2a2ecb9"
|
||||
|
||||
[[package]]
|
||||
name = "opaque-debug"
|
||||
|
@ -1044,6 +1227,38 @@ dependencies = [
|
|||
"rand 0.4.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parity-scale-codec"
|
||||
version = "3.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e8b44461635bbb1a0300f100a841e571e7d919c81c73075ef5d152ffdb521066"
|
||||
dependencies = [
|
||||
"arrayvec 0.7.2",
|
||||
"bitvec",
|
||||
"byte-slice-cast",
|
||||
"impl-trait-for-tuples",
|
||||
"parity-scale-codec-derive",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parity-scale-codec-derive"
|
||||
version = "3.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c45ed1f39709f5a89338fab50e59816b2e8815f5bb58276e7ddf9afd495f73f8"
|
||||
dependencies = [
|
||||
"proc-macro-crate",
|
||||
"proc-macro2 1.0.30",
|
||||
"quote 1.0.10",
|
||||
"syn 1.0.80",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "paste"
|
||||
version = "1.0.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0c520e05135d6e763148b6426a837e239041653ba7becd2e538c076c738025fc"
|
||||
|
||||
[[package]]
|
||||
name = "pest"
|
||||
version = "2.1.3"
|
||||
|
@ -1110,7 +1325,7 @@ dependencies = [
|
|||
"blake2-rfc",
|
||||
"byteorder",
|
||||
"crossbeam",
|
||||
"getrandom 0.2.3",
|
||||
"getrandom",
|
||||
"num_cpus",
|
||||
"pairing_ce",
|
||||
"rand 0.4.6",
|
||||
|
@ -1134,6 +1349,29 @@ version = "0.2.14"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c3ca011bd0129ff4ae15cd04c4eef202cadf6c51c21e47aba319b4e0501db741"
|
||||
|
||||
[[package]]
|
||||
name = "primitive-types"
|
||||
version = "0.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e28720988bff275df1f51b171e1b2a18c30d194c4d2b61defdacecd625a5d94a"
|
||||
dependencies = [
|
||||
"fixed-hash",
|
||||
"impl-codec",
|
||||
"impl-rlp",
|
||||
"impl-serde",
|
||||
"uint",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-crate"
|
||||
version = "1.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e17d47ce914bf4de440332250b0edd23ce48c005f59fab39d3335866b114f11a"
|
||||
dependencies = [
|
||||
"thiserror",
|
||||
"toml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "0.4.30"
|
||||
|
@ -1170,6 +1408,12 @@ dependencies = [
|
|||
"proc-macro2 1.0.30",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "radium"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09"
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.4.6"
|
||||
|
@ -1185,25 +1429,23 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.7.3"
|
||||
version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
|
||||
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
||||
dependencies = [
|
||||
"getrandom 0.1.16",
|
||||
"libc",
|
||||
"rand_chacha",
|
||||
"rand_core 0.5.1",
|
||||
"rand_hc",
|
||||
"rand_core 0.6.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_chacha"
|
||||
version = "0.2.2"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"
|
||||
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
|
||||
dependencies = [
|
||||
"ppv-lite86",
|
||||
"rand_core 0.5.1",
|
||||
"rand_core 0.6.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1223,29 +1465,11 @@ checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
|
|||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.5.1"
|
||||
version = "0.6.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
|
||||
checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7"
|
||||
dependencies = [
|
||||
"getrandom 0.1.16",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_hc"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
|
||||
dependencies = [
|
||||
"rand_core 0.5.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_xorshift"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "77d416b86801d23dde1aa643023b775c3a462efc0ed96443add11546cdf1dca8"
|
||||
dependencies = [
|
||||
"rand_core 0.5.1",
|
||||
"getrandom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1269,13 +1493,24 @@ version = "0.2.11"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9329abc99e39129fcceabd24cf5d85b4671ef7c29c50e972bc5afe32438ec384"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"aho-corasick 0.6.10",
|
||||
"memchr",
|
||||
"regex-syntax",
|
||||
"regex-syntax 0.5.6",
|
||||
"thread_local",
|
||||
"utf8-ranges",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.5.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286"
|
||||
dependencies = [
|
||||
"aho-corasick 0.7.18",
|
||||
"memchr",
|
||||
"regex-syntax 0.6.25",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-automata"
|
||||
version = "0.1.10"
|
||||
|
@ -1291,12 +1526,34 @@ dependencies = [
|
|||
"ucd-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.6.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
|
||||
|
||||
[[package]]
|
||||
name = "rlp"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "999508abb0ae792aabed2460c45b89106d97fe4adac593bdaef433c2605847b5"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"rustc-hex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-demangle"
|
||||
version = "0.1.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342"
|
||||
|
||||
[[package]]
|
||||
name = "rustc-hex"
|
||||
version = "2.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6"
|
||||
|
||||
[[package]]
|
||||
name = "rustc_version"
|
||||
version = "0.3.3"
|
||||
|
@ -1389,6 +1646,7 @@ version = "1.0.68"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0f690853975602e1bfe1ccbf50504d67174e3bcf340f23b5ea9992e0587a52d8"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"itoa",
|
||||
"ryu",
|
||||
"serde",
|
||||
|
@ -1400,7 +1658,7 @@ version = "0.8.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df"
|
||||
dependencies = [
|
||||
"block-buffer",
|
||||
"block-buffer 0.7.3",
|
||||
"digest 0.8.1",
|
||||
"fake-simd",
|
||||
"opaque-debug 0.2.3",
|
||||
|
@ -1412,12 +1670,22 @@ version = "0.8.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a256f46ea78a0c0d9ff00077504903ac881a1dafdc20da66545699e7776b3e69"
|
||||
dependencies = [
|
||||
"block-buffer",
|
||||
"block-buffer 0.7.3",
|
||||
"digest 0.8.1",
|
||||
"fake-simd",
|
||||
"opaque-debug 0.2.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha3"
|
||||
version = "0.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "881bf8156c87b6301fc5ca6b27f11eeb2761224c7081e69b409d5a1951a70c86"
|
||||
dependencies = [
|
||||
"digest 0.10.3",
|
||||
"keccak",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "single"
|
||||
version = "1.0.0"
|
||||
|
@ -1433,6 +1701,12 @@ version = "0.4.5"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5"
|
||||
|
||||
[[package]]
|
||||
name = "static_assertions"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
||||
|
||||
[[package]]
|
||||
name = "subtle"
|
||||
version = "2.4.1"
|
||||
|
@ -1473,6 +1747,32 @@ dependencies = [
|
|||
"unicode-xid 0.2.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tap"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.30",
|
||||
"quote 1.0.10",
|
||||
"syn 1.0.80",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thread_local"
|
||||
version = "0.3.6"
|
||||
|
@ -1491,6 +1791,15 @@ dependencies = [
|
|||
"crunchy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.5.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing"
|
||||
version = "0.1.29"
|
||||
|
@ -1544,6 +1853,18 @@ version = "0.1.8"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c85f514e095d348c279b1e5cd76795082cf15bd59b93207832abe0b1d8fed236"
|
||||
|
||||
[[package]]
|
||||
name = "uint"
|
||||
version = "0.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "12f03af7ccf01dd611cc450a0d10dbc9b745770d096473e2faf0ca6e2d66d1e0"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"crunchy",
|
||||
"hex",
|
||||
"static_assertions",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.1.0"
|
||||
|
@ -1574,12 +1895,6 @@ version = "1.0.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.9.0+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.10.2+wasi-snapshot-preview1"
|
||||
|
@ -1674,6 +1989,15 @@ version = "0.4.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "wyz"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "30b31594f29d27036c383b53b59ed3476874d518f0efb151b27a4c275141390e"
|
||||
dependencies = [
|
||||
"tap",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zeroize"
|
||||
version = "1.4.2"
|
||||
|
@ -1712,13 +2036,14 @@ version = "0.1.0"
|
|||
|
||||
[[package]]
|
||||
name = "zokrates_core"
|
||||
version = "0.6.9"
|
||||
version = "0.6.10"
|
||||
dependencies = [
|
||||
"bellman_ce",
|
||||
"cfg-if 0.1.10",
|
||||
"csv",
|
||||
"ethabi",
|
||||
"ff_ce 0.9.0",
|
||||
"getrandom 0.2.3",
|
||||
"getrandom",
|
||||
"hex",
|
||||
"lazy_static",
|
||||
"log",
|
||||
|
@ -1726,10 +2051,11 @@ dependencies = [
|
|||
"num-bigint 0.2.6",
|
||||
"pairing_ce",
|
||||
"phase2",
|
||||
"primitive-types",
|
||||
"rand 0.4.6",
|
||||
"rand 0.7.3",
|
||||
"rand 0.8.5",
|
||||
"reduce",
|
||||
"regex",
|
||||
"regex 0.2.11",
|
||||
"serde",
|
||||
"serde_cbor",
|
||||
"serde_json",
|
||||
|
@ -1783,9 +2109,10 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "zokrates_js"
|
||||
version = "1.0.38"
|
||||
version = "1.0.39"
|
||||
dependencies = [
|
||||
"console_error_panic_hook",
|
||||
"indexmap",
|
||||
"js-sys",
|
||||
"serde",
|
||||
"serde_json",
|
||||
|
|
|
@ -10,11 +10,13 @@ crate-type = ["cdylib"]
|
|||
[dependencies]
|
||||
js-sys = "0.3.33"
|
||||
serde = { version = "^1.0.59", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
serde_json = { version = "1.0", features = ["preserve_order"] }
|
||||
wasm-bindgen = { version = "0.2.46", features = ["serde-serialize"] }
|
||||
typed-arena = "1.4.1"
|
||||
zokrates_core = { path = "../zokrates_core", features = ["wasm", "bellman"], default-features = false }
|
||||
zokrates_common = { path = "../zokrates_common" }
|
||||
zokrates_field = { path = "../zokrates_field", features = ["bellman"] }
|
||||
zokrates_abi = { path = "../zokrates_abi" }
|
||||
console_error_panic_hook = "0.1.6"
|
||||
console_error_panic_hook = "0.1.6"
|
||||
|
||||
indexmap = "~1.6.2" # see https://github.com/rustwasm/wasm-bindgen/issues/2770#issuecomment-1041102532
|
|
@ -214,7 +214,7 @@ pub fn generate_proof(program: &[u8], witness: JsValue, pk: &[u8]) -> Result<JsV
|
|||
#[wasm_bindgen]
|
||||
pub fn verify(vk: JsValue, proof: JsValue) -> Result<JsValue, JsValue> {
|
||||
let vk: <G16 as Scheme<Bn128Field>>::VerificationKey = vk.into_serde().unwrap();
|
||||
let proof: Proof<<G16 as Scheme<Bn128Field>>::ProofPoints> = proof.into_serde().unwrap();
|
||||
let proof: Proof<Bn128Field, G16> = proof.into_serde().unwrap();
|
||||
|
||||
let ans = <Bellman as Backend<Bn128Field, G16>>::verify(vk, proof);
|
||||
Ok(JsValue::from_serde(&ans).unwrap())
|
||||
|
|
18
zokrates_solidity_test/Cargo.toml
Normal file
18
zokrates_solidity_test/Cargo.toml
Normal file
|
@ -0,0 +1,18 @@
|
|||
[package]
|
||||
name = "zokrates_solidity_test"
|
||||
version = "0.1.0"
|
||||
authors = ["Nirvan Tyagi <nirvan.tyagi@gmail.com>"]
|
||||
edition = "2018"
|
||||
|
||||
# Modeled after the testing pipeline of the Fe project: https://github.com/ethereum/fe/
|
||||
|
||||
[dependencies]
|
||||
ethabi = "17.0.0"
|
||||
primitive-types = { version = "0.11", features = ["rlp"] }
|
||||
hex = { version = "0.4" }
|
||||
bytes = { version = "1.1", default-features = false }
|
||||
serde_json = { version = "1.0" }
|
||||
rand = { version = "0.8" }
|
||||
|
||||
revm = { git = "https://github.com/bluealloy/revm", version = "1.2" }
|
||||
solc = { git = "https://github.com/g-r-a-n-t/solc-rust", rev = "52d4146" }
|
18
zokrates_solidity_test/contracts/simple_storage.sol
Normal file
18
zokrates_solidity_test/contracts/simple_storage.sol
Normal file
|
@ -0,0 +1,18 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8.10;
|
||||
|
||||
contract SimpleStorage {
|
||||
Var myVariable;
|
||||
|
||||
struct Var {
|
||||
uint v;
|
||||
}
|
||||
|
||||
function set(Var memory x) public {
|
||||
myVariable = x;
|
||||
}
|
||||
|
||||
function get() public view returns (uint) {
|
||||
return myVariable.v;
|
||||
}
|
||||
}
|
28
zokrates_solidity_test/src/address.rs
Normal file
28
zokrates_solidity_test/src/address.rs
Normal file
|
@ -0,0 +1,28 @@
|
|||
use ethabi::token::Token;
|
||||
use primitive_types::H160;
|
||||
use rand::Rng;
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||
pub struct Address(pub H160);
|
||||
|
||||
impl Address {
|
||||
pub fn random<R: Rng>(rng: &mut R) -> Self {
|
||||
Self(H160(rng.gen()))
|
||||
}
|
||||
|
||||
pub fn as_token(&self) -> Token {
|
||||
Token::Address(self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<H160> for Address {
|
||||
fn as_ref(&self) -> &H160 {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl From<H160> for Address {
|
||||
fn from(hash: H160) -> Self {
|
||||
Self(hash)
|
||||
}
|
||||
}
|
156
zokrates_solidity_test/src/contract.rs
Normal file
156
zokrates_solidity_test/src/contract.rs
Normal file
|
@ -0,0 +1,156 @@
|
|||
use ethabi::{Contract as ContractAbi, Token};
|
||||
use serde_json::{from_str, json};
|
||||
use solc::compile;
|
||||
|
||||
use std::{fs::File, io::Read, path::Path};
|
||||
|
||||
use crate::{Error, EvmTestError};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Contract {
|
||||
pub binary: Vec<u8>,
|
||||
pub abi: ContractAbi,
|
||||
}
|
||||
|
||||
impl Contract {
|
||||
pub fn new(binary: Vec<u8>, abi: ContractAbi) -> Self {
|
||||
Self { binary, abi }
|
||||
}
|
||||
|
||||
pub fn compile_from_solidity_file<P: AsRef<Path>>(
|
||||
path: P,
|
||||
contract_name: &str,
|
||||
opt: bool,
|
||||
) -> Result<Self, Error> {
|
||||
// Load source file
|
||||
let mut src_file = File::open(path)
|
||||
.map_err(|_| Box::new(EvmTestError("src file open failed".to_string())))?;
|
||||
let mut src = String::new();
|
||||
src_file
|
||||
.read_to_string(&mut src)
|
||||
.map_err(|_| Box::new(EvmTestError("src file read failed".to_string())))?;
|
||||
|
||||
Self::compile_from_src_string(&src, contract_name, opt, &[])
|
||||
}
|
||||
|
||||
pub fn compile_from_src_string(
|
||||
src: &str,
|
||||
contract_name: &str,
|
||||
opt: bool,
|
||||
libraries: &[(&str, Token)],
|
||||
) -> Result<Self, Error> {
|
||||
// Compile source file using solc
|
||||
// Configuration: https://docs.soliditylang.org/en/v0.8.10/using-the-compiler.html
|
||||
// TODO: Change output selection to only compile 'input' file
|
||||
let solc_config = format!(
|
||||
r#"
|
||||
{{
|
||||
"language": "Solidity",
|
||||
"sources": {{ "input.sol": {{ "content": {} }} }},
|
||||
"settings": {{
|
||||
"optimizer": {{ "enabled": {} }},
|
||||
"libraries": {{
|
||||
"input.sol" : {{ {} }}
|
||||
}},
|
||||
"outputSelection": {{
|
||||
"*": {{
|
||||
"*": [
|
||||
"evm.bytecode.object", "abi"
|
||||
],
|
||||
"": [ "*" ] }}
|
||||
}}
|
||||
}}
|
||||
}}"#,
|
||||
json!(src),
|
||||
opt,
|
||||
libraries
|
||||
.iter()
|
||||
.map(|(name, address)| format!("\"{}\": \"0x{}\"", name, address))
|
||||
.collect::<Vec<_>>()
|
||||
.join(",\n")
|
||||
);
|
||||
|
||||
Self::compile_from_config(&solc_config, contract_name)
|
||||
}
|
||||
|
||||
pub fn compile_from_config(config: &str, contract_name: &str) -> Result<Self, Error> {
|
||||
// Compile source file using solc
|
||||
// Configuration: https://docs.soliditylang.org/en/v0.8.10/using-the-compiler.html
|
||||
let out = from_str::<serde_json::Value>(&compile(config))
|
||||
.map_err(|_| Box::new(EvmTestError("solc compile failed".to_string())))?;
|
||||
|
||||
if out["errors"].is_array()
|
||||
&& out["errors"]
|
||||
.as_array()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.any(|e| e["severity"] == "error")
|
||||
{
|
||||
return Err(Box::new(EvmTestError(format!(
|
||||
"solc compiled with errors: {}",
|
||||
out["errors"]
|
||||
))));
|
||||
}
|
||||
|
||||
let binary = {
|
||||
let hex_code = out["contracts"]["input.sol"][contract_name]["evm"]["bytecode"]
|
||||
["object"]
|
||||
.to_string()
|
||||
.replace('\"', "");
|
||||
|
||||
hex::decode(&hex_code)
|
||||
.map_err(|_| Box::new(EvmTestError("decode hex binary failed".to_string())))?
|
||||
};
|
||||
let abi = {
|
||||
if out["contracts"]["input.sol"][contract_name]["abi"] == "null" {
|
||||
return Err(Box::new(EvmTestError(
|
||||
"solc compiled with null abi".to_string(),
|
||||
)));
|
||||
}
|
||||
ContractAbi::load(
|
||||
out["contracts"]["input.sol"][contract_name]["abi"]
|
||||
.to_string()
|
||||
.as_bytes(),
|
||||
)
|
||||
.map_err(|_| Box::new(EvmTestError("ethabi failed loading abi".to_string())))?
|
||||
};
|
||||
|
||||
Ok(Contract { binary, abi })
|
||||
}
|
||||
|
||||
pub fn encode_create_contract_bytes(&self, init: &[Token]) -> Result<Vec<u8>, Error> {
|
||||
match &self.abi.constructor {
|
||||
Some(constructor) => {
|
||||
let binary = constructor
|
||||
.encode_input(self.binary.clone(), init)
|
||||
.map_err(|_| {
|
||||
Box::new(EvmTestError(
|
||||
"abi constructor failed to encode inputs".to_string(),
|
||||
))
|
||||
})?;
|
||||
Ok(binary.to_vec())
|
||||
}
|
||||
None => Ok(self.binary.clone()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn encode_call_contract_bytes(
|
||||
&self,
|
||||
fn_name: &str,
|
||||
input: &[Token],
|
||||
) -> Result<Vec<u8>, Error> {
|
||||
match self.abi.functions.get(fn_name) {
|
||||
Some(f) => {
|
||||
let call_binary = f[0].encode_input(input).map_err(|_| {
|
||||
Box::new(EvmTestError(
|
||||
"abi function failed to encode inputs".to_string(),
|
||||
))
|
||||
})?;
|
||||
Ok(call_binary.to_vec())
|
||||
}
|
||||
None => Err(Box::new(EvmTestError(
|
||||
"abi does not include function".to_string(),
|
||||
))),
|
||||
}
|
||||
}
|
||||
}
|
123
zokrates_solidity_test/src/evm.rs
Normal file
123
zokrates_solidity_test/src/evm.rs
Normal file
|
@ -0,0 +1,123 @@
|
|||
use primitive_types::U256;
|
||||
pub use revm::Return;
|
||||
use revm::{AccountInfo, InMemoryDB, Log, TransactOut, TransactTo, EVM};
|
||||
|
||||
use crate::{address::Address, Error, EvmTestError};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct CallResult {
|
||||
pub op_out: Return,
|
||||
pub out: Vec<u8>,
|
||||
pub gas: u64,
|
||||
pub log_out: Vec<Log>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct CreateContractResult {
|
||||
pub addr: Address,
|
||||
pub gas: u64,
|
||||
}
|
||||
|
||||
pub struct Evm {
|
||||
vm: EVM<InMemoryDB>,
|
||||
}
|
||||
|
||||
impl Default for Evm {
|
||||
fn default() -> Self {
|
||||
let mut vm = revm::new();
|
||||
vm.database(InMemoryDB::default());
|
||||
Self { vm }
|
||||
}
|
||||
}
|
||||
|
||||
impl Evm {
|
||||
pub fn call(
|
||||
&mut self,
|
||||
input: Vec<u8>,
|
||||
addr: &Address,
|
||||
caller: &Address,
|
||||
) -> Result<CallResult, Error> {
|
||||
self.vm.env.tx.caller = *caller.as_ref();
|
||||
self.vm.env.tx.transact_to = TransactTo::Call(*addr.as_ref());
|
||||
self.vm.env.tx.data = input.into();
|
||||
let (op_out, tx_out, gas, log_out) = self.vm.transact_commit();
|
||||
let out = match tx_out {
|
||||
TransactOut::Call(out) => Ok(out.to_vec()),
|
||||
_ => Err(Box::new(EvmTestError(
|
||||
"call contract function failed".to_string(),
|
||||
))),
|
||||
}?;
|
||||
Ok(CallResult {
|
||||
op_out,
|
||||
out,
|
||||
gas,
|
||||
log_out,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn deploy(
|
||||
&mut self,
|
||||
contract: Vec<u8>,
|
||||
deployer: &Address,
|
||||
) -> Result<CreateContractResult, Error> {
|
||||
match self
|
||||
.vm
|
||||
.db()
|
||||
.unwrap()
|
||||
.cache()
|
||||
.get_key_value(deployer.as_ref())
|
||||
{
|
||||
Some(_) => {
|
||||
self.vm.env.tx.caller = *deployer.as_ref();
|
||||
self.vm.env.tx.transact_to = TransactTo::create();
|
||||
self.vm.env.tx.data = contract.into();
|
||||
let (_, tx_out, gas, _) = self.vm.transact_commit();
|
||||
let contract_address = match tx_out {
|
||||
TransactOut::Create(_, Some(addr)) => Ok(Address(addr)),
|
||||
_ => Err(Box::new(EvmTestError("create contract failed".to_string()))),
|
||||
}?;
|
||||
Ok(CreateContractResult {
|
||||
addr: contract_address,
|
||||
gas,
|
||||
})
|
||||
}
|
||||
None => Err(Box::new(EvmTestError(
|
||||
"deployer address not found".to_string(),
|
||||
))),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create_account(&mut self, address: &Address, balance: impl Into<U256>) {
|
||||
let acc = AccountInfo::from_balance(balance.into());
|
||||
self.vm.db().unwrap().insert_cache(*address.as_ref(), acc);
|
||||
}
|
||||
|
||||
pub fn set_account_balance(
|
||||
&mut self,
|
||||
address: &Address,
|
||||
balance: impl Into<U256>,
|
||||
) -> Result<(), Error> {
|
||||
let mut acc = self
|
||||
.vm
|
||||
.db()
|
||||
.unwrap()
|
||||
.cache()
|
||||
.get(address.as_ref())
|
||||
.ok_or_else(|| Box::new(EvmTestError("account address not found".to_string())))?
|
||||
.clone();
|
||||
acc.balance = balance.into();
|
||||
self.vm.db().unwrap().insert_cache(*address.as_ref(), acc);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn balance_of(&mut self, address: &Address) -> U256 {
|
||||
match self.vm.db().unwrap().cache().get(address.as_ref()) {
|
||||
Some(acc) => acc.balance,
|
||||
None => 0.into(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_account(&mut self, address: &Address) -> Option<AccountInfo> {
|
||||
self.vm.db().unwrap().cache().get(address.as_ref()).cloned()
|
||||
}
|
||||
}
|
104
zokrates_solidity_test/src/lib.rs
Normal file
104
zokrates_solidity_test/src/lib.rs
Normal file
|
@ -0,0 +1,104 @@
|
|||
use primitive_types::U256;
|
||||
|
||||
use std::{
|
||||
error::Error as ErrorTrait,
|
||||
fmt::{self, Debug},
|
||||
};
|
||||
|
||||
pub mod address;
|
||||
pub mod contract;
|
||||
pub mod evm;
|
||||
|
||||
pub type Error = Box<dyn ErrorTrait>;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct EvmTestError(String);
|
||||
|
||||
impl ErrorTrait for EvmTestError {
|
||||
fn source(&self) -> Option<&(dyn ErrorTrait + 'static)> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for EvmTestError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{}", self.0)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_be_bytes(n: &U256) -> [u8; 32] {
|
||||
let mut input_bytes: [u8; 32] = [0; 32];
|
||||
n.to_big_endian(&mut input_bytes);
|
||||
input_bytes
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::{address::Address, contract::Contract, evm::Evm};
|
||||
use ethabi::Token;
|
||||
use rand::{rngs::StdRng, SeedableRng};
|
||||
|
||||
#[test]
|
||||
fn simple_storage_contract_test() {
|
||||
let mut rng = StdRng::seed_from_u64(0u64);
|
||||
|
||||
// Compile contract
|
||||
let contract_path = format!(
|
||||
"{}/contracts/simple_storage.sol",
|
||||
env!("CARGO_MANIFEST_DIR")
|
||||
);
|
||||
let contract =
|
||||
Contract::compile_from_solidity_file(contract_path, "SimpleStorage", false).unwrap();
|
||||
|
||||
// Setup EVM
|
||||
let mut evm = Evm::default();
|
||||
let deployer = Address::random(&mut rng);
|
||||
evm.create_account(&deployer, 0);
|
||||
|
||||
// Deploy contract
|
||||
let create_result = evm
|
||||
.deploy(
|
||||
contract.encode_create_contract_bytes(&[]).unwrap(),
|
||||
&deployer,
|
||||
)
|
||||
.unwrap();
|
||||
let contract_addr = create_result.addr.clone();
|
||||
println!("Contract deploy gas cost: {}", create_result.gas);
|
||||
|
||||
// Call get function on contract
|
||||
let get_result = evm
|
||||
.call(
|
||||
contract.encode_call_contract_bytes("get", &[]).unwrap(),
|
||||
&contract_addr,
|
||||
&deployer,
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(&get_result.out, &to_be_bytes(&U256::from(0)));
|
||||
|
||||
// Call set function on contract
|
||||
let _ = evm
|
||||
.call(
|
||||
contract
|
||||
.encode_call_contract_bytes(
|
||||
"set",
|
||||
&[Token::Tuple(vec![Token::Uint(U256::from(40))])],
|
||||
)
|
||||
.unwrap(),
|
||||
&contract_addr,
|
||||
&deployer,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// Call get function on contract
|
||||
let get_result = evm
|
||||
.call(
|
||||
contract.encode_call_contract_bytes("get", &[]).unwrap(),
|
||||
&contract_addr,
|
||||
&deployer,
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(&get_result.out, &to_be_bytes(&U256::from(40)));
|
||||
println!("{:?}", get_result);
|
||||
}
|
||||
}
|
|
@ -11,7 +11,7 @@ zokrates_fs_resolver = { version = "0.5", path = "../zokrates_fs_resolver" }
|
|||
zokrates_abi = { version = "0.1", path = "../zokrates_abi" }
|
||||
serde = "1.0"
|
||||
serde_derive = "1.0"
|
||||
serde_json = "1.0"
|
||||
serde_json = { version = "1.0", features = ["preserve_order"] }
|
||||
typed-arena = "1.4.1"
|
||||
|
||||
[lib]
|
||||
|
|
Loading…
Reference in a new issue