1
0
Fork 0
mirror of synced 2025-09-24 04:40:05 +00:00
This commit is contained in:
schaeff 2022-04-04 15:37:03 +02:00
parent 8d9064797c
commit fc8de3e1f2
25 changed files with 394 additions and 3378 deletions

View file

@ -18,9 +18,6 @@ jobs:
- run:
name: Version information
command: rustc --version; cargo --version; rustup --version
- run:
name: Calculate dependencies
command: cargo generate-lockfile
- restore_cache:
keys:
- cargo-cache-{{ .Environment.CACHE_VERSION }}-{{ arch }}-{{ checksum "Cargo.lock" }}
@ -37,15 +34,12 @@ jobs:
test:
docker:
- image: zokrates/env:latest
resource_class: large
resource_class: xlarge
steps:
- checkout
- run:
name: Version information
command: rustc --version; cargo --version; rustup --version
- run:
name: Calculate dependencies
command: cargo generate-lockfile
- restore_cache:
keys:
- cargo-cache-{{ .Environment.CACHE_VERSION }}-{{ arch }}-{{ checksum "Cargo.lock" }}
@ -58,9 +52,6 @@ jobs:
- run:
name: Run tests
command: WITH_LIBSNARK=1 RUSTFLAGS="-D warnings" ./test.sh
# - run:
# name: Generate code coverage report
# command: ./scripts/cov.sh
cpp_format:
docker:
- image: zokrates/env:latest
@ -77,9 +68,6 @@ jobs:
- run:
name: Version information
command: rustc --version; cargo --version; rustup --version
- run:
name: Calculate dependencies
command: cargo generate-lockfile
- restore_cache:
keys:
- cargo-cache-{{ .Environment.CACHE_VERSION }}-{{ arch }}-{{ checksum "Cargo.lock" }}
@ -98,9 +86,6 @@ jobs:
- run:
name: Version information
command: rustc --version; cargo --version; rustup --version
- run:
name: Calculate dependencies
command: cargo generate-lockfile
- restore_cache:
keys:
- cargo-cache-{{ .Environment.CACHE_VERSION }}-{{ arch }}-{{ checksum "Cargo.lock" }}
@ -160,9 +145,6 @@ jobs:
executor: << parameters.os >>
steps:
- checkout
- run:
name: Calculate dependencies
command: cargo generate-lockfile
- when:
condition: << parameters.add-target >>
steps:

3
Cargo.lock generated
View file

@ -3010,6 +3010,7 @@ dependencies = [
"log",
"primitive-types",
"rand 0.4.6",
"rand 0.8.5",
"regex 0.2.11",
"serde",
"serde_cbor",
@ -3169,7 +3170,7 @@ dependencies = [
"ethabi",
"hex 0.4.3",
"primitive-types",
"rand 0.4.6",
"rand 0.8.5",
"revm",
"serde_json",
"solc",

View file

@ -28,7 +28,8 @@ 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"

View file

@ -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();
}

View file

@ -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");

View file

@ -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

View file

@ -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();

View file

@ -1,15 +1,13 @@
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, Backend, Marlin, Proof, Scheme, SolidityCompatibleField, SolidityCompatibleScheme, G16,
GM17, PGHR13,
Marlin, Proof, SolidityCompatibleField, SolidityCompatibleScheme, G16, GM17, PGHR13,
};
use zokrates_field::{Bls12_381Field, Bn128Field, Field};
use zokrates_field::Bn128Field;
pub fn subcommand() -> App<'static, 'static> {
SubCommand::with_name("print-proof")
@ -32,17 +30,19 @@ 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 to use in the setup. Available options are G16 (default), PGHR13 and GM17")
.help("Proving scheme the proof was created with")
.value_name("FILE")
.takes_value(true)
.required(false)
.default_value(constants::G16)
.possible_values(constants::SCHEMES)
.default_value(constants::G16),
)
.arg(
Arg::with_name("curve")
@ -52,7 +52,7 @@ pub fn subcommand() -> App<'static, 'static> {
.takes_value(true)
.required(false)
.possible_values(constants::CURVES)
.default_value(constants::BN128)
.default_value(constants::BN128),
)
}
@ -63,18 +63,6 @@ pub fn exec(sub_matches: &ArgMatches) -> Result<(), String> {
let parameters: (CurveParameter, SchemeParameter) =
(curve.try_into().unwrap(), scheme.try_into().unwrap());
println!(
"Printing proof at location {:?} using proving scheme {:?} and curve {:?}",
sub_matches
.values_of("proof-path")
.clone()
.unwrap()
.next()
.unwrap(),
parameters.1,
parameters.0
);
match parameters {
(CurveParameter::Bn128, SchemeParameter::PGHR13) => {
cli_print_proof::<Bn128Field, PGHR13>(sub_matches)
@ -110,26 +98,25 @@ fn cli_print_proof<T: SolidityCompatibleField, S: SolidityCompatibleScheme<T>>(
match format {
"json" => {
println!("~~~~~~~~ Copy the output below for valid ABIv2 format ~~~~~~~~");
println!();
print!("{}", inputs);
print!("{}", proof_object);
print!(",");
println!("{}", proof_object);
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.as_object().unwrap().iter() {
print!("{}", value);
print!(",");
}
println!("{}", inputs);
println!();
println!("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
}
_ => unreachable!(),
}

View file

@ -1 +0,0 @@
node_modules

File diff suppressed because it is too large Load diff

View file

@ -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"
}
}

View file

@ -1,164 +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: '20000000'
})
.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)]);
})
.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);
}
}
console.log("PROOF:", proof)
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];
console.log(args);
return contract.methods.verifyTx(...args).send({
from: account,
gas: '20000000'
});
}
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);
}
});
}
})();

View file

@ -1,7 +1,8 @@
extern crate assert_cli;
extern crate ethabi;
extern crate primitive_types;
extern crate rand;
extern crate rand_0_4;
extern crate rand_0_8;
extern crate serde_json;
extern crate zokrates_solidity_test;
@ -10,7 +11,7 @@ mod integration {
use glob::glob;
use primitive_types::U256;
use serde_json::{from_reader, json};
use serde_json::from_reader;
use std::fs;
use std::fs::File;
use std::io::{BufReader, Read};
@ -18,10 +19,9 @@ mod integration {
use std::path::Path;
use tempdir::TempDir;
use zokrates_abi::{parse_strict, Encode};
use zokrates_core::proof_system::marlin::SolidityProof;
use zokrates_core::proof_system::{
Fr, G1Affine, Marlin, Proof, Scheme, SolidityCompatibleField, SolidityCompatibleScheme,
ToToken, G16, GM17, PGHR13, SOLIDITY_G2_ADDITION_LIB,
to_token::ToToken, Marlin, Proof, SolidityCompatibleScheme, G16, GM17, PGHR13,
SOLIDITY_G2_ADDITION_LIB,
};
use zokrates_core::typed_absy::abi::Abi;
use zokrates_field::Bn128Field;
@ -38,11 +38,8 @@ mod integration {
);
#[test]
//#[ignore]
#[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");
@ -84,15 +81,6 @@ mod integration {
}
}
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,
@ -388,11 +376,11 @@ mod integration {
proof: Proof<Bn128Field, S>,
) {
use ethabi::Token;
use rand::{SeedableRng, StdRng};
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]);
let mut rng = StdRng::from_seed([0; 32]);
let mut evm = Evm::new();
let deployer = Address::random(&mut rng);
evm.create_account(&deployer, 0);
@ -430,7 +418,7 @@ mod integration {
let solidity_proof = S::Proof::from(proof.proof);
// convert to tokens to build a call
let proof_token = S::to_token(solidity_proof);
let proof_token = S::to_token(solidity_proof.clone());
let input_token = Token::FixedArray(
proof
@ -444,7 +432,7 @@ mod integration {
.collect::<Vec<_>>(),
);
let inputs = [proof_token, input_token];
let inputs = [proof_token, input_token.clone()];
// Call verify function on contract
let result = evm
@ -456,7 +444,28 @@ mod integration {
&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(

View file

@ -7,7 +7,7 @@ use ark_marlin::Marlin as ArkMarlin;
use ark_ec::PairingEngine;
use ark_ff::{to_bytes, FftField, FromBytes, ToBytes};
use ark_poly::{univariate::DensePolynomial, EvaluationDomain, GeneralEvaluationDomain};
use ark_poly::univariate::DensePolynomial;
use ark_poly_commit::{
data_structures::BatchLCProof,
kzg10::Commitment as KZG10Commitment,
@ -17,10 +17,8 @@ use ark_poly_commit::{
};
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
use digest::Digest;
use num::Zero;
use rand_0_8::{Error, RngCore, SeedableRng};
use sha3::Keccak256;
use std::convert::TryInto;
use std::{convert::TryFrom, marker::PhantomData};
use zokrates_field::{ArkFieldExtensions, Field};

View file

@ -5,6 +5,8 @@ pub mod bellman;
#[cfg(feature = "libsnark")]
pub mod libsnark;
pub mod to_token;
mod scheme;
mod solidity;
@ -13,7 +15,6 @@ pub use self::solidity::*;
use crate::ir;
use primitive_types::U256;
use serde::de::DeserializeOwned;
use serde::{Deserialize, Serialize};
use zokrates_field::{Bls12_377Field, Bls12_381Field, Bn128Field, Field};
@ -94,31 +95,6 @@ impl ToString for G2Affine {
}
}
/// 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 Backend<T: Field, S: Scheme<T>> {
fn generate_proof<I: IntoIterator<Item = ir::Statement<T>>>(
program: ir::ProgIterator<T, I>,

View file

@ -1,10 +1,9 @@
use crate::proof_system::scheme::{NonUniversalScheme, Scheme};
use crate::proof_system::solidity::{solidity_pairing_lib, SOLIDITY_G2_ADDITION_LIB};
use crate::proof_system::{
encode_g1_element, encode_g2_element, G1Affine, G2Affine, G2AffineFq, NotBw6_761Field,
SolidityCompatibleField, SolidityCompatibleScheme, ToToken,
G1Affine, G2Affine, G2AffineFq, NotBw6_761Field, SolidityCompatibleField,
SolidityCompatibleScheme,
};
use ethabi::Token;
use regex::Regex;
use serde::{Deserialize, Serialize};
use zokrates_field::{Bw6_761Field, Field};
@ -12,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,32 +42,6 @@ impl Scheme<Bw6_761Field> for GM17 {
type ProofPoints = ProofPoints<G1Affine, G2AffineFq>;
}
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)
}
}
impl<T: SolidityCompatibleField + NotBw6_761Field> SolidityCompatibleScheme<T> for GM17 {
type Proof = Self::ProofPoints;

View file

@ -1,17 +1,15 @@
use crate::proof_system::scheme::{NonUniversalScheme, Scheme};
use crate::proof_system::solidity::solidity_pairing_lib;
use crate::proof_system::{
encode_g1_element, encode_g2_element, G1Affine, G2Affine, MpcScheme, SolidityCompatibleField,
SolidityCompatibleScheme, ToToken,
G1Affine, G2Affine, MpcScheme, SolidityCompatibleField, SolidityCompatibleScheme,
};
use ethabi::Token;
use regex::Regex;
use serde::{Deserialize, Serialize};
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,
@ -35,32 +33,6 @@ impl<T: Field> Scheme<T> for G16 {
impl<T: Field> NonUniversalScheme<T> for G16 {}
impl<T: Field> MpcScheme<T> for G16 {}
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)
}
}
impl<T: SolidityCompatibleField> SolidityCompatibleScheme<T> for G16 {
type Proof = Self::ProofPoints;

View file

@ -1,14 +1,10 @@
use crate::proof_system::ark::parse_fr;
use crate::proof_system::scheme::{Scheme, UniversalScheme};
use crate::proof_system::solidity::{
solidity_pairing_lib, SolidityCompatibleField, SolidityCompatibleScheme,
};
use crate::proof_system::{
encode_fr_element, encode_g1_element, Fr, G1Affine, G2Affine, NotBw6_761Field, ToToken,
};
use ethabi::Token;
use crate::proof_system::{Fr, G1Affine, G2Affine, NotBw6_761Field};
use serde::{Deserialize, Serialize};
use zokrates_field::{ArkFieldExtensions, Field};
use zokrates_field::Field;
pub struct Marlin;
@ -22,7 +18,7 @@ pub struct ProofPoints<Fr, G1> {
pub prover_messages_count: usize,
}
#[derive(Serialize, Deserialize)]
#[derive(Serialize, Deserialize, Clone)]
pub struct SolidityProof<Fr, G1> {
pub comms_1: Vec<G1>,
pub comms_2: Vec<G1>,
@ -90,86 +86,7 @@ impl<T: Field> Scheme<T> for Marlin {
impl<T: Field> UniversalScheme<T> for Marlin {}
impl<T: SolidityCompatibleField + ArkFieldExtensions + 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)
}
}
impl<T: SolidityCompatibleField + NotBw6_761Field + ArkFieldExtensions> SolidityCompatibleScheme<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 {
@ -770,123 +687,95 @@ contract Verifier {
mod tests {
use crate::flat_absy::{FlatParameter, FlatVariable};
use crate::ir::{Interpreter, Prog, QuadComb, Statement};
use crate::proof_system::ark::{parse_fr, Ark};
use crate::proof_system::{Backend, Fr, Proof, UniversalBackend};
use crate::proof_system::ark::Ark;
use crate::proof_system::to_token::ToToken;
use crate::proof_system::{Backend, UniversalBackend};
use super::*;
use ethabi::token::{LenientTokenizer, StrictTokenizer, Tokenizer};
use ethabi::Token;
use primitive_types::{H160, U256};
use rand_0_8::{rngs::StdRng, SeedableRng};
use zokrates_field::Bn128Field;
use zokrates_solidity_test::{address::Address, contract::Contract, evm::Evm, to_be_bytes};
#[test]
fn verify_solidity_bn128() {
// let program: Prog<Bn128Field> = Prog {
// arguments: vec![FlatParameter::private(FlatVariable::new(0))],
// return_count: 1,
// statements: vec![
// Statement::constraint(
// QuadComb::from_linear_combinations(
// FlatVariable::new(0).into(),
// FlatVariable::new(0).into(),
// ),
// FlatVariable::new(1),
// ),
// Statement::constraint(FlatVariable::new(1), FlatVariable::public(0)),
// ],
// };
let program: Prog<Bn128Field> = Prog {
arguments: vec![FlatParameter::private(FlatVariable::new(0))],
return_count: 1,
statements: vec![
Statement::constraint(
QuadComb::from_linear_combinations(
FlatVariable::new(0).into(),
FlatVariable::new(0).into(),
),
FlatVariable::new(1),
),
Statement::constraint(FlatVariable::new(1), FlatVariable::public(0)),
],
};
// let srs = <Ark as UniversalBackend<Bn128Field, Marlin>>::universal_setup(5);
// let keypair =
// <Ark as UniversalBackend<Bn128Field, Marlin>>::setup(srs, program.clone().into())
// .unwrap();
// let interpreter = Interpreter::default();
let srs = <Ark as UniversalBackend<Bn128Field, Marlin>>::universal_setup(5);
let keypair =
<Ark as UniversalBackend<Bn128Field, Marlin>>::setup(srs, program.clone().into())
.unwrap();
let interpreter = Interpreter::default();
// let witness = interpreter
// .execute(program.clone(), &[Bn128Field::from(42u32)])
// .unwrap();
let witness = interpreter
.execute(program.clone(), &[Bn128Field::from(42u32)])
.unwrap();
// let proof = <Ark as Backend<Bn128Field, Marlin>>::generate_proof(
// program.clone(),
// witness,
// keypair.pk,
// );
let proof = <Ark as Backend<Bn128Field, Marlin>>::generate_proof(
program.clone(),
witness,
keypair.pk,
);
// let mut src =
// <Marlin as SolidityCompatibleScheme<Bn128Field>>::export_solidity_verifier(keypair.vk);
// src = src.replace("\"", "\\\"");
let src =
<Marlin as SolidityCompatibleScheme<Bn128Field>>::export_solidity_verifier(keypair.vk);
// let solc_config = r#"
// {
// "language": "Solidity",
// "sources": {
// "input.sol": { "content": "<%src%>" }
// },
// "settings": {
// "optimizer": { "enabled": <%opt%> },
// "outputSelection": {
// "*": {
// "*": [
// "evm.bytecode.object", "abi"
// ],
// "": [ "*" ] } }
// }
// }"#
// .replace("<%opt%>", &true.to_string())
// .replace("<%src%>", &src);
let contract = Contract::compile_from_src_string(&src, "Verifier", true, &[]).unwrap();
// let contract = Contract::compile_from_config(&solc_config, "Verifier").unwrap();
// Setup EVM
let mut evm = Evm::new();
let deployer = Address::from(H160::zero());
evm.create_account(&deployer, 0);
// // Setup EVM
// let mut rng = StdRng::seed_from_u64(0u64);
// let mut evm = Evm::new();
// let deployer = Address::from(H160::zero());
// 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();
// // 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);
let solidity_proof =
<Marlin as SolidityCompatibleScheme<Bn128Field>>::Proof::from(proof.proof);
let proof_token = <Marlin as ToToken<Bn128Field>>::to_token(solidity_proof);
// let solidity_proof =
// <Marlin as SolidityCompatibleScheme<Bn128Field>>::Proof::from(proof.proof);
// let proof_token = <Marlin as ToToken<Bn128Field>>::to_token(solidity_proof);
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];
// println!("{:?}", proof.inputs);
// 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];
// println!("{:?}", inputs);
// // 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)));
// println!("{:?}", result);
// 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)));
}
}

View file

@ -1,10 +1,6 @@
use crate::proof_system::scheme::{NonUniversalScheme, Scheme};
use crate::proof_system::solidity::solidity_pairing_lib;
use crate::proof_system::{
encode_g1_element, encode_g2_element, G1Affine, G2Affine, SolidityCompatibleField,
SolidityCompatibleScheme, ToToken,
};
use ethabi::Token;
use crate::proof_system::{G1Affine, G2Affine, SolidityCompatibleField, SolidityCompatibleScheme};
use regex::Regex;
use serde::{Deserialize, Serialize};
use zokrates_field::Field;
@ -12,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,
@ -43,57 +39,6 @@ impl<T: Field> Scheme<T> for PGHR13 {
impl<T: Field> NonUniversalScheme<T> for PGHR13 {}
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)
}
}
impl<T: SolidityCompatibleField> SolidityCompatibleScheme<T> for PGHR13 {
type Proof = Self::ProofPoints;

View file

@ -4,15 +4,11 @@ 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;
type Proof: From<Self::ProofPoints> + Serialize + DeserializeOwned + Clone;
fn export_solidity_verifier(vk: Self::VerificationKey) -> String;
}
pub trait ToToken<T: SolidityCompatibleField>: SolidityCompatibleScheme<T> {
fn to_token(proof: Self::Proof) -> ethabi::Token;
}
pub const SOLIDITY_G2_ADDITION_LIB: &str = r#"// SPDX-License-Identifier: LGPL-3.0-only
// This file is LGPL3 Licensed

View file

@ -0,0 +1,238 @@
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 = str::replace(&proof.a.0, 'a', "f");
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 = str::replace(&proof.a.0, 'a', "f");
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 = str::replace(&proof.a.0, 'a', "f");
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 = str::replace(&proof.degree_bound_comms_3_g2.0, 'a', "f");
proof
}
}

View file

@ -12,7 +12,7 @@ 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.4" }
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" }

View file

@ -1,4 +1,4 @@
use ethabi::{Address, Contract as ContractAbi, Token};
use ethabi::{Contract as ContractAbi, Token};
use serde_json::{from_str, json};
use solc::compile;
@ -100,10 +100,8 @@ impl Contract {
.to_string()
.replace("\"", "");
let binary = hex::decode(&hex_code).map_err(|e| {
println!("{}", e);
Box::new(EvmTestError("decode hex binary failed".to_string()))
})?;
let binary = hex::decode(&hex_code)
.map_err(|_| Box::new(EvmTestError("decode hex binary failed".to_string())))?;
binary
};
let abi = {
@ -147,7 +145,7 @@ impl Contract {
) -> Result<Vec<u8>, Error> {
match self.abi.functions.get(fn_name) {
Some(f) => {
let call_binary = f[0].encode_input(input).map_err(|e| {
let call_binary = f[0].encode_input(input).map_err(|_| {
Box::new(EvmTestError(
"abi function failed to encode inputs".to_string(),
))

View file

@ -1,5 +1,6 @@
use primitive_types::U256;
use revm::{AccountInfo, InMemoryDB, Log, Return, TransactOut, TransactTo, EVM};
pub use revm::Return;
use revm::{AccountInfo, InMemoryDB, Log, TransactOut, TransactTo, EVM};
use crate::{address::Address, Error, EvmTestError};

View file

@ -77,7 +77,7 @@ mod tests {
assert_eq!(&get_result.out, &to_be_bytes(&U256::from(0)));
// Call set function on contract
let set_result = evm
let _ = evm
.call(
contract
.encode_call_contract_bytes(