mirror of
https://github.com/zkonduit/ezkl.git
synced 2026-01-08 22:08:07 -05:00
2728 lines
106 KiB
Rust
2728 lines
106 KiB
Rust
#[cfg(all(feature = "ezkl", not(target_arch = "wasm32")))]
|
|
#[cfg(test)]
|
|
mod native_tests {
|
|
|
|
// use ezkl::circuit::table::RESERVED_BLINDING_ROWS_PAD;
|
|
use ezkl::Commitments;
|
|
use ezkl::graph::input::{FileSource, FileSourceInner, GraphData};
|
|
use ezkl::graph::{DataSource, GraphSettings, GraphWitness};
|
|
use ezkl::pfsys::Snark;
|
|
use halo2_proofs::poly::kzg::commitment::KZGCommitmentScheme;
|
|
use halo2curves::bn256::Bn256;
|
|
use lazy_static::lazy_static;
|
|
use rand::Rng;
|
|
use std::env::var;
|
|
use std::io::{Read, Write};
|
|
use std::path::PathBuf;
|
|
use std::process::{Child, Command};
|
|
use std::sync::Once;
|
|
static COMPILE: Once = Once::new();
|
|
#[allow(dead_code)]
|
|
static COMPILE_WASM: Once = Once::new();
|
|
static ENV_SETUP: Once = Once::new();
|
|
|
|
const TEST_BINARY: &str = "test-runs/ezkl";
|
|
|
|
//Sure to run this once
|
|
#[derive(Debug)]
|
|
#[allow(dead_code)]
|
|
enum Hardfork {
|
|
London,
|
|
ArrowGlacier,
|
|
GrayGlacier,
|
|
Paris,
|
|
Shanghai,
|
|
Latest,
|
|
}
|
|
lazy_static! {
|
|
static ref CARGO_TARGET_DIR: String =
|
|
var("CARGO_TARGET_DIR").unwrap_or_else(|_| "./target".to_string());
|
|
static ref ANVIL_URL: String = "http://localhost:3030".to_string();
|
|
static ref LIMITLESS_ANVIL_URL: String = "http://localhost:8545".to_string();
|
|
static ref ANVIL_DEFAULT_PRIVATE_KEY: String =
|
|
"ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80".to_string();
|
|
}
|
|
|
|
fn start_anvil(limitless: bool, hardfork: Hardfork) -> Child {
|
|
let mut args = vec!["-p"];
|
|
if limitless {
|
|
args.push("8545");
|
|
args.push("--code-size-limit=41943040");
|
|
args.push("--disable-block-gas-limit");
|
|
} else {
|
|
args.push("3030");
|
|
}
|
|
match hardfork {
|
|
Hardfork::Paris => args.push("--hardfork=paris"),
|
|
Hardfork::London => args.push("--hardfork=london"),
|
|
Hardfork::Latest => {}
|
|
Hardfork::Shanghai => args.push("--hardfork=shanghai"),
|
|
Hardfork::ArrowGlacier => args.push("--hardfork=arrowGlacier"),
|
|
Hardfork::GrayGlacier => args.push("--hardfork=grayGlacier"),
|
|
}
|
|
let child = Command::new("anvil")
|
|
.args(args)
|
|
.spawn()
|
|
.expect("failed to start anvil process");
|
|
std::thread::sleep(std::time::Duration::from_secs(3));
|
|
child
|
|
}
|
|
|
|
fn init_binary() {
|
|
COMPILE.call_once(|| {
|
|
println!("using cargo target dir: {}", *CARGO_TARGET_DIR);
|
|
build_ezkl();
|
|
});
|
|
}
|
|
|
|
#[allow(dead_code)]
|
|
fn init_wasm() {
|
|
COMPILE_WASM.call_once(|| {
|
|
build_wasm_ezkl();
|
|
});
|
|
}
|
|
|
|
fn setup_py_env() {
|
|
ENV_SETUP.call_once(|| {
|
|
// supposes that you have a virtualenv called .env and have run the following
|
|
// equivalent of python -m venv .env
|
|
// source .env/bin/activate
|
|
// pip install -r requirements.txt
|
|
// maturin develop --release --features python-bindings
|
|
|
|
// now install torch, pandas, numpy, seaborn, jupyter
|
|
let status = Command::new("pip")
|
|
.args(["install", "numpy", "onnxruntime", "onnx"])
|
|
.stdout(std::process::Stdio::null())
|
|
.status()
|
|
.expect("failed to execute process");
|
|
|
|
assert!(status.success());
|
|
});
|
|
}
|
|
|
|
fn download_srs(logrows: u32, commitment: Commitments) {
|
|
// if does not exist, download it
|
|
let status = Command::new(format!("{}/{}", *CARGO_TARGET_DIR, TEST_BINARY))
|
|
.args([
|
|
"get-srs",
|
|
"--logrows",
|
|
&format!("{}", logrows),
|
|
"--commitment",
|
|
&commitment.to_string(),
|
|
])
|
|
.status()
|
|
.expect("failed to execute process");
|
|
assert!(status.success());
|
|
}
|
|
|
|
fn init_params(settings_path: std::path::PathBuf) {
|
|
println!("using settings path: {}", settings_path.to_str().unwrap());
|
|
// read in settings json
|
|
let settings =
|
|
std::fs::read_to_string(settings_path).expect("failed to read settings file");
|
|
// read in to GraphSettings object
|
|
let settings: GraphSettings = serde_json::from_str(&settings).unwrap();
|
|
let logrows = settings.run_args.logrows;
|
|
|
|
download_srs(logrows, settings.run_args.commitment.into());
|
|
}
|
|
|
|
fn mv_test_(test_dir: &str, test: &str) {
|
|
let path: std::path::PathBuf = format!("{}/{}", test_dir, test).into();
|
|
if !path.exists() {
|
|
let status = Command::new("cp")
|
|
.args([
|
|
"-R",
|
|
&format!("./examples/onnx/{}", test),
|
|
&format!("{}/{}", test_dir, test),
|
|
])
|
|
.status()
|
|
.expect("failed to execute process");
|
|
assert!(status.success());
|
|
}
|
|
}
|
|
|
|
fn mk_data_batches_(test_dir: &str, test: &str, output_dir: &str, num_batches: usize) {
|
|
let path: std::path::PathBuf = format!("{}/{}", test_dir, test).into();
|
|
if !path.exists() {
|
|
panic!("test_dir does not exist")
|
|
} else {
|
|
// copy the directory
|
|
let status = Command::new("cp")
|
|
.args([
|
|
"-R",
|
|
&format!("{}/{}", test_dir, test),
|
|
&format!("{}/{}", test_dir, output_dir),
|
|
])
|
|
.status()
|
|
.expect("failed to execute process");
|
|
|
|
assert!(status.success());
|
|
|
|
let data = GraphData::from_path(format!("{}/{}/input.json", test_dir, test).into())
|
|
.expect("failed to load input data");
|
|
|
|
let input_data = match data.input_data {
|
|
DataSource::File(data) => data,
|
|
_ => panic!("Only File data sources support batching"),
|
|
};
|
|
|
|
let duplicated_input_data: FileSource = input_data
|
|
.iter()
|
|
.map(|data| (0..num_batches).flat_map(|_| data.clone()).collect())
|
|
.collect();
|
|
|
|
let duplicated_data = GraphData::new(DataSource::File(duplicated_input_data));
|
|
|
|
let res =
|
|
duplicated_data.save(format!("{}/{}/input.json", test_dir, output_dir).into());
|
|
|
|
assert!(res.is_ok());
|
|
}
|
|
}
|
|
|
|
const PF_FAILURE: &str = "examples/test_failure_proof.json";
|
|
|
|
const PF_FAILURE_AGGR: &str = "examples/test_failure_aggr_proof.json";
|
|
|
|
const LARGE_TESTS: [&str; 8] = [
|
|
"self_attention",
|
|
"nanoGPT",
|
|
"multihead_attention",
|
|
"mobilenet",
|
|
"mnist_gan",
|
|
"smallworm",
|
|
"fr_age",
|
|
"1d_conv",
|
|
];
|
|
|
|
const ACCURACY_CAL_TESTS: [&str; 6] = [
|
|
"accuracy",
|
|
"1l_mlp",
|
|
"4l_relu_conv_fc",
|
|
"1l_elu",
|
|
"1l_prelu",
|
|
"1l_tiny_div",
|
|
];
|
|
|
|
const TESTS: [&str; 99] = [
|
|
"1l_mlp", //0
|
|
"1l_slice", //1
|
|
"1l_concat", //2
|
|
"1l_flatten", //3
|
|
// "1l_average",
|
|
"1l_div", //4
|
|
"1l_pad", // 5
|
|
"1l_reshape", //6
|
|
"1l_eltwise_div", //7
|
|
"1l_sigmoid", //8
|
|
"1l_sqrt", //9
|
|
"1l_softmax", //10
|
|
// "1l_instance_norm",
|
|
"1l_batch_norm", //11
|
|
"1l_prelu", //12
|
|
"1l_leakyrelu", //13
|
|
"1l_gelu_noappx", //14
|
|
// "1l_gelu_tanh_appx",
|
|
"1l_relu", //15
|
|
"1l_downsample", //16
|
|
"1l_tanh", //17
|
|
"2l_relu_sigmoid_small", //18
|
|
"2l_relu_fc", //19
|
|
"2l_relu_small", //20
|
|
"2l_relu_sigmoid", //21
|
|
"1l_conv", //22
|
|
"2l_sigmoid_small", //23
|
|
"2l_relu_sigmoid_conv", //24
|
|
"3l_relu_conv_fc", //25
|
|
"4l_relu_conv_fc", //26
|
|
"1l_erf", //27
|
|
"1l_var", //28
|
|
"1l_elu", //29
|
|
"min", //30
|
|
"max", //31
|
|
"1l_max_pool", //32
|
|
"1l_conv_transpose", //33
|
|
"1l_upsample", //34
|
|
"1l_identity", //35
|
|
"idolmodel", // too big evm
|
|
"trig", // too big evm
|
|
"prelu_gmm", //38
|
|
"lstm", //39
|
|
"rnn", //40
|
|
"quantize_dequantize", //41
|
|
"1l_where", //42
|
|
"boolean", //43
|
|
"boolean_identity", //44
|
|
"decision_tree", // 45
|
|
"random_forest", //46
|
|
"gradient_boosted_trees", //47
|
|
"1l_topk", //48
|
|
"xgboost", //49
|
|
"lightgbm", //50
|
|
"hummingbird_decision_tree", //51
|
|
"oh_decision_tree",
|
|
"linear_svc",
|
|
"gather_elements",
|
|
"less", //55
|
|
"xgboost_reg",
|
|
"1l_powf",
|
|
"scatter_elements",
|
|
"1l_linear",
|
|
"linear_regression", //60
|
|
"sklearn_mlp",
|
|
"1l_mean",
|
|
"rounding_ops",
|
|
// "mean_as_constrain",
|
|
"arange",
|
|
"layernorm", //65
|
|
"bitwise_ops",
|
|
"blackman_window",
|
|
"softsign", //68
|
|
"softplus",
|
|
"selu", //70
|
|
"hard_sigmoid",
|
|
"log_softmax",
|
|
"eye",
|
|
"ltsf",
|
|
"remainder", //75
|
|
"bitshift",
|
|
"gather_nd",
|
|
"scatter_nd",
|
|
"celu",
|
|
"gru", // 80
|
|
"hard_swish", // 81
|
|
"hard_max",
|
|
"tril", // 83
|
|
"triu", // 84
|
|
"logsumexp", // 85
|
|
"clip",
|
|
"mish",
|
|
"reducel1",
|
|
"reducel2", // 89
|
|
"1l_lppool",
|
|
"lstm_large", // 91
|
|
"lstm_medium", // 92
|
|
"lenet_5", // 93
|
|
"rsqrt", // 94
|
|
"log", // 95
|
|
"exp", // 96
|
|
"general_exp", // 97
|
|
"integer_div", // 98
|
|
];
|
|
|
|
const WASM_TESTS: [&str; 46] = [
|
|
"1l_mlp",
|
|
"1l_slice",
|
|
"1l_concat",
|
|
"1l_flatten",
|
|
// "1l_average",
|
|
"1l_div",
|
|
"1l_pad",
|
|
"1l_reshape",
|
|
"1l_eltwise_div",
|
|
"1l_sigmoid",
|
|
"1l_sqrt",
|
|
"1l_softmax",
|
|
// "1l_instance_norm",
|
|
"1l_batch_norm",
|
|
"1l_prelu",
|
|
"1l_leakyrelu",
|
|
"1l_gelu_noappx",
|
|
// "1l_gelu_tanh_appx",
|
|
"1l_relu",
|
|
"1l_downsample",
|
|
"1l_tanh",
|
|
"2l_relu_sigmoid_small",
|
|
"2l_relu_fc",
|
|
"2l_relu_small",
|
|
"2l_relu_sigmoid",
|
|
"1l_conv",
|
|
"2l_sigmoid_small",
|
|
"2l_relu_sigmoid_conv",
|
|
"3l_relu_conv_fc",
|
|
"4l_relu_conv_fc",
|
|
"1l_erf",
|
|
"1l_var",
|
|
"1l_elu",
|
|
"min",
|
|
"max",
|
|
"1l_max_pool",
|
|
"1l_conv_transpose",
|
|
"1l_upsample",
|
|
"1l_identity",
|
|
// "idolmodel",
|
|
"trig",
|
|
"prelu_gmm",
|
|
"lstm",
|
|
"rnn",
|
|
"quantize_dequantize",
|
|
"1l_where",
|
|
"boolean",
|
|
"boolean_identity",
|
|
"gradient_boosted_trees",
|
|
"1l_topk",
|
|
// "xgboost",
|
|
// "lightgbm",
|
|
// "hummingbird_decision_tree",
|
|
];
|
|
|
|
#[cfg(not(feature = "icicle"))]
|
|
const TESTS_AGGR: [&str; 21] = [
|
|
"1l_mlp",
|
|
"1l_flatten",
|
|
"1l_average",
|
|
"1l_reshape",
|
|
"1l_div",
|
|
"1l_pad",
|
|
"1l_sigmoid",
|
|
"1l_gelu_noappx",
|
|
"1l_sqrt",
|
|
"1l_prelu",
|
|
"1l_var",
|
|
"1l_leakyrelu",
|
|
"1l_relu",
|
|
"1l_tanh",
|
|
"2l_relu_fc",
|
|
"2l_relu_sigmoid_small",
|
|
"2l_relu_small",
|
|
"1l_conv",
|
|
"min",
|
|
"max",
|
|
"1l_max_pool",
|
|
];
|
|
|
|
#[cfg(feature = "icicle")]
|
|
const TESTS_AGGR: [&str; 3] = ["1l_mlp", "1l_flatten", "1l_average"];
|
|
|
|
const TESTS_EVM: [&str; 23] = [
|
|
"1l_mlp", // 0
|
|
"1l_flatten", // 1
|
|
"1l_average", // 2
|
|
"1l_reshape", // 3
|
|
"1l_sigmoid", // 4
|
|
"1l_div", // 5
|
|
"1l_sqrt", // 6
|
|
"1l_prelu", // 7
|
|
"1l_var", // 8
|
|
"1l_leakyrelu", // 9
|
|
"1l_gelu_noappx", // 10
|
|
"1l_relu", // 11
|
|
"1l_tanh", // 12
|
|
"2l_relu_sigmoid_small", // 13
|
|
"2l_relu_small", // 14
|
|
"min", // 15
|
|
"max", // 16
|
|
"1l_max_pool", // 17
|
|
"idolmodel", // 18
|
|
"1l_identity", // 19
|
|
"lstm", // 20
|
|
"rnn", // 21
|
|
"quantize_dequantize", // 22
|
|
];
|
|
|
|
const TESTS_EVM_AGGR: [&str; 18] = [
|
|
"1l_mlp",
|
|
"1l_reshape",
|
|
"1l_sigmoid",
|
|
"1l_div",
|
|
"1l_sqrt",
|
|
"1l_prelu",
|
|
"1l_var",
|
|
"1l_leakyrelu",
|
|
"1l_gelu_noappx",
|
|
"1l_relu",
|
|
"1l_tanh",
|
|
"2l_relu_sigmoid_small",
|
|
"2l_relu_small",
|
|
"2l_relu_fc",
|
|
"min",
|
|
"max",
|
|
"idolmodel",
|
|
"1l_identity",
|
|
];
|
|
|
|
const EXAMPLES: [&str; 2] = ["mlp_4d_einsum", "conv2d_mnist"];
|
|
|
|
macro_rules! test_func_aggr {
|
|
() => {
|
|
#[cfg(test)]
|
|
mod tests_aggr {
|
|
use seq_macro::seq;
|
|
use crate::native_tests::TESTS_AGGR;
|
|
use test_case::test_case;
|
|
use crate::native_tests::aggr_prove_and_verify;
|
|
use crate::native_tests::kzg_aggr_mock_prove_and_verify;
|
|
use tempdir::TempDir;
|
|
use ezkl::Commitments;
|
|
|
|
#[cfg(not(feature="icicle"))]
|
|
seq!(N in 0..=20 {
|
|
|
|
#(#[test_case(TESTS_AGGR[N])])*
|
|
fn kzg_aggr_mock_prove_and_verify_(test: &str) {
|
|
crate::native_tests::init_binary();
|
|
let test_dir = TempDir::new(test).unwrap();
|
|
let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test);
|
|
kzg_aggr_mock_prove_and_verify(path, test.to_string());
|
|
test_dir.close().unwrap();
|
|
}
|
|
|
|
|
|
|
|
#(#[test_case(TESTS_AGGR[N])])*
|
|
fn kzg_aggr_prove_and_verify_(test: &str) {
|
|
crate::native_tests::init_binary();
|
|
let test_dir = TempDir::new(test).unwrap();
|
|
let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test);
|
|
aggr_prove_and_verify(path, test.to_string(), "private", "private", "public", Commitments::KZG);
|
|
test_dir.close().unwrap();
|
|
}
|
|
|
|
#(#[test_case(TESTS_AGGR[N])])*
|
|
fn ipa_aggr_prove_and_verify_(test: &str) {
|
|
crate::native_tests::init_binary();
|
|
let test_dir = TempDir::new(test).unwrap();
|
|
let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test);
|
|
aggr_prove_and_verify(path, test.to_string(), "private", "private", "public", Commitments::IPA);
|
|
test_dir.close().unwrap();
|
|
}
|
|
|
|
});
|
|
|
|
#[cfg(feature="icicle")]
|
|
seq!(N in 0..=2 {
|
|
#(#[test_case(TESTS_AGGR[N])])*
|
|
fn kzg_aggr_prove_and_verify_(test: &str) {
|
|
crate::native_tests::init_binary();
|
|
let test_dir = TempDir::new(test).unwrap();
|
|
let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(test_dir.path().to_str().unwrap(), test);
|
|
aggr_prove_and_verify(path, test.to_string(), "private", "private", "public", Commitments::KZG);
|
|
test_dir.close().unwrap();
|
|
}
|
|
});
|
|
}
|
|
};
|
|
}
|
|
|
|
macro_rules! test_func {
|
|
() => {
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use seq_macro::seq;
|
|
use crate::native_tests::TESTS;
|
|
use crate::native_tests::WASM_TESTS;
|
|
use crate::native_tests::ACCURACY_CAL_TESTS;
|
|
use crate::native_tests::LARGE_TESTS;
|
|
use test_case::test_case;
|
|
use crate::native_tests::mock;
|
|
use crate::native_tests::accuracy_measurement;
|
|
use crate::native_tests::prove_and_verify;
|
|
use crate::native_tests::run_js_tests;
|
|
use crate::native_tests::render_circuit;
|
|
use crate::native_tests::model_serialization_different_binaries;
|
|
|
|
use tempdir::TempDir;
|
|
use ezkl::Commitments;
|
|
|
|
#[test]
|
|
fn model_serialization_different_binaries_() {
|
|
let test = "1l_mlp";
|
|
let test_dir = TempDir::new(test).unwrap();
|
|
let path = test_dir.path().to_str().unwrap();
|
|
crate::native_tests::mv_test_(path, test);
|
|
// percent tolerance test
|
|
model_serialization_different_binaries(path, test.to_string());
|
|
test_dir.close().unwrap();
|
|
}
|
|
|
|
seq!(N in 0..=5 {
|
|
#(#[test_case(ACCURACY_CAL_TESTS[N])])*
|
|
fn mock_accuracy_cal_tests(test: &str) {
|
|
crate::native_tests::init_binary();
|
|
let test_dir = TempDir::new(test).unwrap();
|
|
let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test);
|
|
mock(path, test.to_string(), "public", "fixed", "public", 1, "accuracy", None, false, None, None);
|
|
test_dir.close().unwrap();
|
|
}
|
|
});
|
|
|
|
seq!(N in 0..=98 {
|
|
|
|
#(#[test_case(TESTS[N])])*
|
|
#[ignore]
|
|
fn render_circuit_(test: &str) {
|
|
crate::native_tests::init_binary();
|
|
let test_dir = TempDir::new(test).unwrap();
|
|
let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test);
|
|
render_circuit(path, test.to_string());
|
|
test_dir.close().unwrap();
|
|
}
|
|
|
|
|
|
|
|
#(#[test_case(TESTS[N])])*
|
|
fn accuracy_measurement_public_outputs_(test: &str) {
|
|
crate::native_tests::init_binary();
|
|
crate::native_tests::setup_py_env();
|
|
let test_dir = TempDir::new(test).unwrap();
|
|
let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test);
|
|
accuracy_measurement(path, test.to_string(), "private", "private", "public", 1, "accuracy", 2.6);
|
|
test_dir.close().unwrap();
|
|
}
|
|
|
|
#(#[test_case(TESTS[N])])*
|
|
fn accuracy_measurement_fixed_params_(test: &str) {
|
|
crate::native_tests::init_binary();
|
|
crate::native_tests::setup_py_env();
|
|
let test_dir = TempDir::new(test).unwrap();
|
|
let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test);
|
|
accuracy_measurement(path, test.to_string(), "private", "fixed", "private", 1, "accuracy", 2.6 );
|
|
test_dir.close().unwrap();
|
|
}
|
|
|
|
#(#[test_case(TESTS[N])])*
|
|
fn accuracy_measurement_public_inputs_(test: &str) {
|
|
crate::native_tests::init_binary();
|
|
crate::native_tests::setup_py_env();
|
|
let test_dir = TempDir::new(test).unwrap();
|
|
let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test);
|
|
accuracy_measurement(path, test.to_string(), "public", "private", "private", 1, "accuracy", 2.6);
|
|
test_dir.close().unwrap();
|
|
}
|
|
|
|
|
|
#(#[test_case(TESTS[N])])*
|
|
fn resources_accuracy_measurement_public_outputs_(test: &str) {
|
|
crate::native_tests::init_binary();
|
|
crate::native_tests::setup_py_env();
|
|
let test_dir = TempDir::new(test).unwrap();
|
|
let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test);
|
|
accuracy_measurement(path, test.to_string(), "private", "private", "public", 1, "resources", 3.1);
|
|
test_dir.close().unwrap();
|
|
}
|
|
|
|
#(#[test_case(TESTS[N])])*
|
|
fn mock_public_outputs_(test: &str) {
|
|
crate::native_tests::init_binary();
|
|
let test_dir = TempDir::new(test).unwrap();
|
|
let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test);
|
|
mock(path, test.to_string(), "private", "private", "public", 1, "resources", None, false, None, None);
|
|
test_dir.close().unwrap();
|
|
}
|
|
|
|
|
|
#(#[test_case(TESTS[N])])*
|
|
fn mock_bounded_lookup_log(test: &str) {
|
|
crate::native_tests::init_binary();
|
|
let test_dir = TempDir::new(test).unwrap();
|
|
let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test);
|
|
mock(path, test.to_string(), "private", "private", "public", 1, "resources", None, true, Some(8194), Some(4));
|
|
test_dir.close().unwrap();
|
|
}
|
|
|
|
|
|
#(#[test_case(TESTS[N])])*
|
|
fn mock_large_batch_public_outputs_(test: &str) {
|
|
// currently variable output rank is not supported in ONNX
|
|
if test != "gather_nd" && test != "lstm_large" && test != "lstm_medium" && test != "scatter_nd" {
|
|
crate::native_tests::init_binary();
|
|
let test_dir = TempDir::new(test).unwrap();
|
|
let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test);
|
|
let large_batch_dir = &format!("large_batches_{}", test);
|
|
crate::native_tests::mk_data_batches_(path, test, &large_batch_dir, 10);
|
|
mock(path, large_batch_dir.to_string(), "private", "private", "public", 10, "resources", None, false, None, None);
|
|
test_dir.close().unwrap();
|
|
}
|
|
}
|
|
|
|
#(#[test_case(TESTS[N])])*
|
|
fn mock_public_inputs_(test: &str) {
|
|
crate::native_tests::init_binary();
|
|
let test_dir = TempDir::new(test).unwrap();
|
|
let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test);
|
|
mock(path, test.to_string(), "public", "private", "private", 1, "resources", None, false, None, None);
|
|
test_dir.close().unwrap();
|
|
}
|
|
|
|
#(#[test_case(TESTS[N])])*
|
|
fn mock_hashed_params_public_inputs_(test: &str) {
|
|
crate::native_tests::init_binary();
|
|
let test_dir = TempDir::new(test).unwrap();
|
|
let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test);
|
|
mock(path, test.to_string(), "public", "hashed", "private", 1, "resources", None, false, None, None);
|
|
test_dir.close().unwrap();
|
|
}
|
|
|
|
#(#[test_case(TESTS[N])])*
|
|
fn mock_fixed_inputs_(test: &str) {
|
|
crate::native_tests::init_binary();
|
|
let test_dir = TempDir::new(test).unwrap();
|
|
let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test);
|
|
mock(path, test.to_string(), "fixed", "private", "private", 1, "resources", None, false, None, None);
|
|
test_dir.close().unwrap();
|
|
}
|
|
|
|
#(#[test_case(TESTS[N])])*
|
|
fn mock_fixed_outputs_(test: &str) {
|
|
crate::native_tests::init_binary();
|
|
let test_dir = TempDir::new(test).unwrap();
|
|
let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test);
|
|
mock(path, test.to_string(), "private", "private", "fixed", 1, "resources", None, false, None, None);
|
|
test_dir.close().unwrap();
|
|
}
|
|
|
|
#(#[test_case(TESTS[N])])*
|
|
fn mock_fixed_params_(test: &str) {
|
|
crate::native_tests::init_binary();
|
|
let test_dir = TempDir::new(test).unwrap();
|
|
let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test);
|
|
mock(path, test.to_string(), "private", "fixed", "private", 1, "resources", None, false, None, None);
|
|
test_dir.close().unwrap();
|
|
}
|
|
|
|
#(#[test_case(TESTS[N])])*
|
|
fn mock_hashed_input_(test: &str) {
|
|
crate::native_tests::init_binary();
|
|
let test_dir = TempDir::new(test).unwrap();
|
|
let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test);
|
|
mock(path, test.to_string(), "hashed", "private", "public", 1, "resources", None, false, None, None);
|
|
test_dir.close().unwrap();
|
|
}
|
|
|
|
#(#[test_case(TESTS[N])])*
|
|
fn mock_kzg_input_(test: &str) {
|
|
crate::native_tests::init_binary();
|
|
let test_dir = TempDir::new(test).unwrap();
|
|
let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test);
|
|
mock(path, test.to_string(), "polycommit", "private", "public", 1, "resources", None, false, None, None);
|
|
test_dir.close().unwrap();
|
|
}
|
|
|
|
|
|
#(#[test_case(TESTS[N])])*
|
|
fn mock_hashed_params_(test: &str) {
|
|
crate::native_tests::init_binary();
|
|
let test_dir = TempDir::new(test).unwrap();
|
|
let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test);
|
|
mock(path, test.to_string(), "private", "hashed", "public", 1, "resources", None, false, None, None);
|
|
test_dir.close().unwrap();
|
|
}
|
|
|
|
|
|
#(#[test_case(TESTS[N])])*
|
|
fn mock_kzg_params_(test: &str) {
|
|
crate::native_tests::init_binary();
|
|
let test_dir = TempDir::new(test).unwrap();
|
|
let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test);
|
|
mock(path, test.to_string(), "private", "polycommit", "public", 1, "resources", None, false, None, None);
|
|
test_dir.close().unwrap();
|
|
}
|
|
|
|
#(#[test_case(TESTS[N])])*
|
|
fn mock_hashed_output_(test: &str) {
|
|
crate::native_tests::init_binary();
|
|
let test_dir = TempDir::new(test).unwrap();
|
|
let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test);
|
|
mock(path, test.to_string(), "public", "private", "hashed", 1, "resources", None, false, None, None);
|
|
test_dir.close().unwrap();
|
|
}
|
|
|
|
|
|
#(#[test_case(TESTS[N])])*
|
|
fn mock_kzg_output_(test: &str) {
|
|
crate::native_tests::init_binary();
|
|
let test_dir = TempDir::new(test).unwrap();
|
|
let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test);
|
|
mock(path, test.to_string(), "public", "private", "polycommit", 1, "resources", None, false, None, None);
|
|
test_dir.close().unwrap();
|
|
}
|
|
|
|
#(#[test_case(TESTS[N])])*
|
|
fn mock_hashed_output_fixed_params_(test: &str) {
|
|
crate::native_tests::init_binary();
|
|
let test_dir = TempDir::new(test).unwrap();
|
|
let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test);
|
|
mock(path, test.to_string(), "public", "fixed", "hashed", 1, "resources", None, false, None, None);
|
|
test_dir.close().unwrap();
|
|
}
|
|
|
|
|
|
#(#[test_case(TESTS[N])])*
|
|
fn mock_hashed_output_kzg_params_(test: &str) {
|
|
crate::native_tests::init_binary();
|
|
let test_dir = TempDir::new(test).unwrap();
|
|
let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test);
|
|
mock(path, test.to_string(), "public", "polycommit", "hashed", 1, "resources", None, false, None, None);
|
|
test_dir.close().unwrap();
|
|
}
|
|
|
|
|
|
#(#[test_case(TESTS[N])])*
|
|
fn mock_kzg_all_(test: &str) {
|
|
crate::native_tests::init_binary();
|
|
let test_dir = TempDir::new(test).unwrap();
|
|
let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test);
|
|
mock(path, test.to_string(), "polycommit", "polycommit", "polycommit", 1, "resources", None, false, None, None);
|
|
test_dir.close().unwrap();
|
|
}
|
|
|
|
|
|
#(#[test_case(TESTS[N])])*
|
|
fn mock_hashed_input_output_(test: &str) {
|
|
crate::native_tests::init_binary();
|
|
let test_dir = TempDir::new(test).unwrap();
|
|
let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test);
|
|
mock(path, test.to_string(), "hashed", "private", "hashed", 1, "resources", None, false, None, None);
|
|
test_dir.close().unwrap();
|
|
}
|
|
|
|
#(#[test_case(TESTS[N])])*
|
|
fn mock_hashed_input_params_(test: &str) {
|
|
crate::native_tests::init_binary();
|
|
let test_dir = TempDir::new(test).unwrap();
|
|
let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test);
|
|
// needs an extra row for the large model
|
|
mock(path, test.to_string(),"hashed", "hashed", "public", 1, "resources", None, false, None, None);
|
|
test_dir.close().unwrap();
|
|
}
|
|
|
|
#(#[test_case(TESTS[N])])*
|
|
fn mock_hashed_all_(test: &str) {
|
|
crate::native_tests::init_binary();
|
|
let test_dir = TempDir::new(test).unwrap();
|
|
let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test);
|
|
// needs an extra row for the large model
|
|
mock(path, test.to_string(),"hashed", "hashed", "hashed", 1, "resources", None, false, None, None);
|
|
test_dir.close().unwrap();
|
|
}
|
|
|
|
#(#[test_case(TESTS[N])])*
|
|
fn kzg_prove_and_verify_single_col(test: &str) {
|
|
crate::native_tests::init_binary();
|
|
let test_dir = TempDir::new(test).unwrap();
|
|
let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test);
|
|
prove_and_verify(path, test.to_string(), "safe", "private", "private", "public", 1, None, false, "single", Commitments::KZG, 2);
|
|
test_dir.close().unwrap();
|
|
}
|
|
|
|
#(#[test_case(TESTS[N])])*
|
|
fn kzg_prove_and_verify_triple_col(test: &str) {
|
|
crate::native_tests::init_binary();
|
|
let test_dir = TempDir::new(test).unwrap();
|
|
let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test);
|
|
prove_and_verify(path, test.to_string(), "safe", "private", "private", "public", 3, None, false, "single", Commitments::KZG, 2);
|
|
test_dir.close().unwrap();
|
|
}
|
|
|
|
#(#[test_case(TESTS[N])])*
|
|
fn kzg_prove_and_verify_quadruple_col(test: &str) {
|
|
crate::native_tests::init_binary();
|
|
let test_dir = TempDir::new(test).unwrap();
|
|
let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test);
|
|
prove_and_verify(path, test.to_string(), "safe", "private", "private", "public", 4, None, false, "single", Commitments::KZG, 2);
|
|
test_dir.close().unwrap();
|
|
}
|
|
|
|
#(#[test_case(TESTS[N])])*
|
|
fn kzg_prove_and_verify_octuple_col(test: &str) {
|
|
crate::native_tests::init_binary();
|
|
let test_dir = TempDir::new(test).unwrap();
|
|
let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test);
|
|
prove_and_verify(path, test.to_string(), "safe", "private", "private", "public", 8, None, false, "single", Commitments::KZG, 2);
|
|
test_dir.close().unwrap();
|
|
}
|
|
|
|
#(#[test_case(TESTS[N])])*
|
|
fn kzg_prove_and_verify_(test: &str) {
|
|
crate::native_tests::init_binary();
|
|
let test_dir = TempDir::new(test).unwrap();
|
|
let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test);
|
|
prove_and_verify(path, test.to_string(), "safe", "private", "private", "public", 1, None, false, "single", Commitments::KZG, 2);
|
|
test_dir.close().unwrap();
|
|
}
|
|
|
|
#(#[test_case(TESTS[N])])*
|
|
fn kzg_prove_and_verify_tight_lookup_(test: &str) {
|
|
crate::native_tests::init_binary();
|
|
let test_dir = TempDir::new(test).unwrap();
|
|
let path = test_dir.into_path();
|
|
let path = path.to_str().unwrap();
|
|
crate::native_tests::mv_test_(path, test);
|
|
prove_and_verify(path, test.to_string(), "safe", "private", "private", "public", 1, None, false, "single", Commitments::KZG, 1);
|
|
// test_dir.close().unwrap();
|
|
}
|
|
|
|
#(#[test_case(TESTS[N])])*
|
|
fn ipa_prove_and_verify_(test: &str) {
|
|
crate::native_tests::init_binary();
|
|
let test_dir = TempDir::new(test).unwrap();
|
|
let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test);
|
|
prove_and_verify(path, test.to_string(), "safe", "private", "private", "public", 1, None, false, "single", Commitments::IPA, 2);
|
|
test_dir.close().unwrap();
|
|
}
|
|
|
|
#(#[test_case(TESTS[N])])*
|
|
fn kzg_prove_and_verify_public_input_(test: &str) {
|
|
crate::native_tests::init_binary();
|
|
let test_dir = TempDir::new(test).unwrap();
|
|
let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test);
|
|
prove_and_verify(path, test.to_string(), "safe", "public", "private", "public", 1, None, false, "single", Commitments::KZG, 2);
|
|
test_dir.close().unwrap();
|
|
}
|
|
|
|
#(#[test_case(TESTS[N])])*
|
|
fn kzg_prove_and_verify_fixed_params_(test: &str) {
|
|
crate::native_tests::init_binary();
|
|
let test_dir = TempDir::new(test).unwrap();
|
|
let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test);
|
|
prove_and_verify(path, test.to_string(), "safe", "private", "fixed", "public", 1, None, false, "single", Commitments::KZG, 2);
|
|
test_dir.close().unwrap();
|
|
}
|
|
|
|
#(#[test_case(TESTS[N])])*
|
|
fn kzg_prove_and_verify_hashed_output(test: &str) {
|
|
crate::native_tests::init_binary();
|
|
let test_dir = TempDir::new(test).unwrap();
|
|
let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test);
|
|
prove_and_verify(path, test.to_string(), "safe", "private", "private", "hashed", 1, None, false, "single", Commitments::KZG, 2);
|
|
test_dir.close().unwrap();
|
|
}
|
|
|
|
#(#[test_case(TESTS[N])])*
|
|
fn kzg_prove_and_verify_kzg_output(test: &str) {
|
|
crate::native_tests::init_binary();
|
|
let test_dir = TempDir::new(test).unwrap();
|
|
let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test);
|
|
prove_and_verify(path, test.to_string(), "safe", "private", "private", "polycommit", 1, None, false, "single", Commitments::KZG, 2);
|
|
test_dir.close().unwrap();
|
|
}
|
|
|
|
#(#[test_case(TESTS[N])])*
|
|
fn ipa_prove_and_verify_ipa_output(test: &str) {
|
|
crate::native_tests::init_binary();
|
|
let test_dir = TempDir::new(test).unwrap();
|
|
let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test);
|
|
prove_and_verify(path, test.to_string(), "safe", "private", "private", "polycommit", 1, None, false, "single", Commitments::IPA, 2);
|
|
test_dir.close().unwrap();
|
|
}
|
|
|
|
});
|
|
|
|
seq!(N in 0..=45 {
|
|
|
|
#(#[test_case(WASM_TESTS[N])])*
|
|
fn kzg_prove_and_verify_with_overflow_(test: &str) {
|
|
crate::native_tests::init_binary();
|
|
// crate::native_tests::init_wasm();
|
|
let test_dir = TempDir::new(test).unwrap();
|
|
env_logger::init();
|
|
let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test);
|
|
prove_and_verify(path, test.to_string(), "safe", "private", "private", "public", 1, None, true, "single", Commitments::KZG, 2);
|
|
#[cfg(not(feature = "icicle"))]
|
|
run_js_tests(path, test.to_string(), "testWasm", false);
|
|
test_dir.close().unwrap();
|
|
}
|
|
|
|
#(#[test_case(WASM_TESTS[N])])*
|
|
fn kzg_prove_and_verify_with_overflow_hashed_inputs_(test: &str) {
|
|
crate::native_tests::init_binary();
|
|
// crate::native_tests::init_wasm();
|
|
let test_dir = TempDir::new(test).unwrap();
|
|
env_logger::init();
|
|
let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test);
|
|
prove_and_verify(path, test.to_string(), "safe", "hashed", "private", "public", 1, None, true, "single", Commitments::KZG, 2);
|
|
#[cfg(not(feature = "icicle"))]
|
|
run_js_tests(path, test.to_string(), "testWasm", false);
|
|
test_dir.close().unwrap();
|
|
}
|
|
|
|
#(#[test_case(WASM_TESTS[N])])*
|
|
fn kzg_prove_and_verify_with_overflow_fixed_params_(test: &str) {
|
|
crate::native_tests::init_binary();
|
|
// crate::native_tests::init_wasm();
|
|
let test_dir = TempDir::new(test).unwrap();
|
|
env_logger::init();
|
|
let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test);
|
|
prove_and_verify(path, test.to_string(), "safe", "private", "fixed", "public", 1, None, true, "single", Commitments::KZG, 2);
|
|
#[cfg(not(feature = "icicle"))]
|
|
run_js_tests(path, test.to_string(), "testWasm", false);
|
|
test_dir.close().unwrap();
|
|
}
|
|
|
|
});
|
|
|
|
seq!(N in 0..=7 {
|
|
|
|
#(#[test_case(LARGE_TESTS[N])])*
|
|
#[ignore]
|
|
fn large_prove_and_verify_(test: &str) {
|
|
crate::native_tests::init_binary();
|
|
let test_dir = TempDir::new(test).unwrap();
|
|
let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test);
|
|
prove_and_verify(path, test.to_string(), "unsafe", "private", "fixed", "public", 1, None, false, "single", Commitments::KZG, 2);
|
|
test_dir.close().unwrap();
|
|
}
|
|
|
|
#(#[test_case(LARGE_TESTS[N])])*
|
|
#[ignore]
|
|
fn large_mock_(test: &str) {
|
|
crate::native_tests::init_binary();
|
|
let test_dir = TempDir::new(test).unwrap();
|
|
let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test);
|
|
mock(path, test.to_string(), "private", "fixed", "public", 1, "resources", None, false, None, Some(5));
|
|
test_dir.close().unwrap();
|
|
}
|
|
});
|
|
}
|
|
};
|
|
}
|
|
|
|
macro_rules! test_func_evm {
|
|
() => {
|
|
#[cfg(test)]
|
|
mod tests_evm {
|
|
use seq_macro::seq;
|
|
use crate::native_tests::TESTS_EVM;
|
|
use crate::native_tests::TESTS;
|
|
use crate::native_tests::TESTS_EVM_AGGR;
|
|
use test_case::test_case;
|
|
use crate::native_tests::kzg_evm_prove_and_verify;
|
|
use crate::native_tests::kzg_evm_prove_and_verify_reusable_verifier;
|
|
|
|
use crate::native_tests::kzg_evm_on_chain_input_prove_and_verify;
|
|
use crate::native_tests::kzg_evm_aggr_prove_and_verify;
|
|
use tempdir::TempDir;
|
|
use crate::native_tests::Hardfork;
|
|
use crate::native_tests::run_js_tests;
|
|
use ezkl::logger::init_logger;
|
|
use crate::native_tests::lazy_static;
|
|
|
|
// Global variables to store verifier hashes and identical verifiers
|
|
lazy_static! {
|
|
// create a new variable of type
|
|
static ref REUSABLE_VERIFIER_ADDR: std::sync::Mutex<Option<String>> = std::sync::Mutex::new(None);
|
|
}
|
|
|
|
|
|
/// Currently only on chain inputs that return a non-negative value are supported.
|
|
const TESTS_ON_CHAIN_INPUT: [&str; 17] = [
|
|
"1l_mlp",
|
|
"1l_average",
|
|
"1l_reshape",
|
|
"1l_sigmoid",
|
|
"1l_div",
|
|
"1l_sqrt",
|
|
"1l_prelu",
|
|
"1l_var",
|
|
"1l_leakyrelu",
|
|
"1l_gelu_noappx",
|
|
"1l_relu",
|
|
"1l_tanh",
|
|
"2l_relu_sigmoid_small",
|
|
"2l_relu_small",
|
|
"2l_relu_fc",
|
|
"min",
|
|
"max"
|
|
];
|
|
|
|
seq!(N in 0..=16 {
|
|
#(#[test_case((TESTS_ON_CHAIN_INPUT[N],Hardfork::Latest))])*
|
|
#(#[test_case((TESTS_ON_CHAIN_INPUT[N],Hardfork::Paris))])*
|
|
#(#[test_case((TESTS_ON_CHAIN_INPUT[N],Hardfork::London))])*
|
|
#(#[test_case((TESTS_ON_CHAIN_INPUT[N],Hardfork::Shanghai))])*
|
|
fn kzg_evm_on_chain_input_prove_and_verify_(test: (&str,Hardfork)) {
|
|
let (test,hardfork) = test;
|
|
crate::native_tests::init_binary();
|
|
let test_dir = TempDir::new(test).unwrap();
|
|
let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test);
|
|
let _anvil_child = crate::native_tests::start_anvil(true, hardfork);
|
|
kzg_evm_on_chain_input_prove_and_verify(path, test.to_string(), "on-chain", "file", "public", "private", "private");
|
|
// test_dir.close().unwrap();
|
|
}
|
|
|
|
#(#[test_case(TESTS_ON_CHAIN_INPUT[N])])*
|
|
fn kzg_evm_on_chain_output_prove_and_verify_(test: &str) {
|
|
crate::native_tests::init_binary();
|
|
let test_dir = TempDir::new(test).unwrap();
|
|
let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test);
|
|
let _anvil_child = crate::native_tests::start_anvil(true, Hardfork::Latest);
|
|
kzg_evm_on_chain_input_prove_and_verify(path, test.to_string(), "file", "on-chain", "private", "public", "private");
|
|
// test_dir.close().unwrap();
|
|
}
|
|
|
|
#(#[test_case(TESTS_ON_CHAIN_INPUT[N])])*
|
|
fn kzg_evm_on_chain_input_output_prove_and_verify_(test: &str) {
|
|
crate::native_tests::init_binary();
|
|
let test_dir = TempDir::new(test).unwrap();
|
|
let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test);
|
|
let _anvil_child = crate::native_tests::start_anvil(true, Hardfork::Latest);
|
|
kzg_evm_on_chain_input_prove_and_verify(path, test.to_string(), "on-chain", "on-chain", "public", "public", "private");
|
|
test_dir.close().unwrap();
|
|
}
|
|
|
|
#(#[test_case(TESTS_ON_CHAIN_INPUT[N])])*
|
|
fn kzg_evm_on_chain_input_output_hashed_prove_and_verify_(test: &str) {
|
|
crate::native_tests::init_binary();
|
|
let test_dir = TempDir::new(test).unwrap();
|
|
let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test);
|
|
let _anvil_child = crate::native_tests::start_anvil(true, Hardfork::Latest);
|
|
kzg_evm_on_chain_input_prove_and_verify(path, test.to_string(), "on-chain", "on-chain", "hashed", "hashed", "private");
|
|
test_dir.close().unwrap();
|
|
}
|
|
#(#[test_case(TESTS_ON_CHAIN_INPUT[N])])*
|
|
fn kzg_evm_on_chain_input_kzg_output_kzg_params_prove_and_verify_(test: &str) {
|
|
crate::native_tests::init_binary();
|
|
let test_dir = TempDir::new(test).unwrap();
|
|
let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test);
|
|
let _anvil_child = crate::native_tests::start_anvil(true, Hardfork::Latest);
|
|
kzg_evm_on_chain_input_prove_and_verify(path, test.to_string(), "on-chain", "file", "public", "polycommit", "polycommit");
|
|
test_dir.close().unwrap();
|
|
}
|
|
#(#[test_case(TESTS_ON_CHAIN_INPUT[N])])*
|
|
fn kzg_evm_on_chain_output_kzg_input_kzg_params_prove_and_verify_(test: &str) {
|
|
crate::native_tests::init_binary();
|
|
let test_dir = TempDir::new(test).unwrap();
|
|
let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test);
|
|
let _anvil_child = crate::native_tests::start_anvil(true, Hardfork::Latest);
|
|
kzg_evm_on_chain_input_prove_and_verify(path, test.to_string(), "file", "on-chain", "polycommit", "public", "polycommit");
|
|
test_dir.close().unwrap();
|
|
}
|
|
#(#[test_case(TESTS_ON_CHAIN_INPUT[N])])*
|
|
fn kzg_evm_on_chain_all_kzg_params_prove_and_verify_(test: &str) {
|
|
crate::native_tests::init_binary();
|
|
let test_dir = TempDir::new(test).unwrap();
|
|
let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test);
|
|
let _anvil_child = crate::native_tests::start_anvil(true, Hardfork::Latest);
|
|
kzg_evm_on_chain_input_prove_and_verify(path, test.to_string(), "file", "file", "polycommit", "polycommit", "polycommit");
|
|
test_dir.close().unwrap();
|
|
}
|
|
});
|
|
|
|
|
|
seq!(N in 0..=17 {
|
|
// these take a particularly long time to run
|
|
#(#[test_case(TESTS_EVM_AGGR[N])])*
|
|
#[ignore]
|
|
fn kzg_evm_aggr_prove_and_verify_(test: &str) {
|
|
crate::native_tests::init_binary();
|
|
let test_dir = TempDir::new(test).unwrap();
|
|
let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test);
|
|
let _anvil_child = crate::native_tests::start_anvil(false, Hardfork::Latest);
|
|
kzg_evm_aggr_prove_and_verify(path, test.to_string(), "private", "private", "public");
|
|
test_dir.close().unwrap();
|
|
}
|
|
|
|
});
|
|
|
|
seq!(N in 0..4 {
|
|
#(#[test_case(TESTS[N])])*
|
|
fn kzg_evm_prove_and_verify_reusable_verifier_(test: &str) {
|
|
crate::native_tests::init_binary();
|
|
let test_dir = TempDir::new(test).unwrap();
|
|
let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test);
|
|
let _anvil_child = crate::native_tests::start_anvil(false, Hardfork::Latest);
|
|
init_logger();
|
|
log::error!("Running kzg_evm_prove_and_verify_reusable_verifier_ for test: {}", test);
|
|
// default vis
|
|
let reusable_verifier_address: String = kzg_evm_prove_and_verify_reusable_verifier(2, path, test.to_string(), "private", "private", "public", &mut REUSABLE_VERIFIER_ADDR.lock().unwrap(), false);
|
|
// public/public vis
|
|
let reusable_verifier_address: String = kzg_evm_prove_and_verify_reusable_verifier(2, path, test.to_string(), "public", "private", "public", &mut Some(reusable_verifier_address), false);
|
|
// hashed input
|
|
let reusable_verifier_address: String = kzg_evm_prove_and_verify_reusable_verifier(2, path, test.to_string(), "hashed", "private", "public", &mut Some(reusable_verifier_address), false);
|
|
|
|
match REUSABLE_VERIFIER_ADDR.try_lock() {
|
|
Ok(mut addr) => {
|
|
*addr = Some(reusable_verifier_address.clone());
|
|
log::error!("Reusing the same verifeir deployed at address: {}", reusable_verifier_address);
|
|
}
|
|
Err(_) => {
|
|
log::error!("Failed to acquire lock on REUSABLE_VERIFIER_ADDR");
|
|
}
|
|
}
|
|
|
|
test_dir.close().unwrap();
|
|
|
|
}
|
|
|
|
#(#[test_case(TESTS[N])])*
|
|
fn kzg_evm_prove_and_verify_reusable_verifier_with_overflow_(test: &str) {
|
|
// verifier too big to fit on chain with overflow calibration target
|
|
if test == "1l_eltwise_div" || test == "lenet_5" || test == "ltsf" || test == "lstm_large" {
|
|
return;
|
|
}
|
|
crate::native_tests::init_binary();
|
|
let test_dir = TempDir::new(test).unwrap();
|
|
let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test);
|
|
let _anvil_child = crate::native_tests::start_anvil(false, Hardfork::Latest);
|
|
init_logger();
|
|
log::error!("Running kzg_evm_prove_and_verify_reusable_verifier_with_overflow_ for test: {}", test);
|
|
// default vis
|
|
let reusable_verifier_address: String = kzg_evm_prove_and_verify_reusable_verifier(2, path, test.to_string(), "private", "private", "public", &mut REUSABLE_VERIFIER_ADDR.lock().unwrap(), true);
|
|
// public/public vis
|
|
let reusable_verifier_address: String = kzg_evm_prove_and_verify_reusable_verifier(2, path, test.to_string(), "public", "private", "public", &mut Some(reusable_verifier_address), true);
|
|
// hashed input
|
|
let reusable_verifier_address: String = kzg_evm_prove_and_verify_reusable_verifier(2, path, test.to_string(), "hashed", "private", "public", &mut Some(reusable_verifier_address), true);
|
|
|
|
match REUSABLE_VERIFIER_ADDR.try_lock() {
|
|
Ok(mut addr) => {
|
|
*addr = Some(reusable_verifier_address.clone());
|
|
log::error!("Reusing the same verifeir deployed at address: {}", reusable_verifier_address);
|
|
}
|
|
Err(_) => {
|
|
log::error!("Failed to acquire lock on REUSABLE_VERIFIER_ADDR");
|
|
}
|
|
}
|
|
|
|
test_dir.close().unwrap();
|
|
|
|
}
|
|
});
|
|
|
|
|
|
seq!(N in 0..=22 {
|
|
|
|
#(#[test_case(TESTS_EVM[N])])*
|
|
fn kzg_evm_prove_and_verify_(test: &str) {
|
|
crate::native_tests::init_binary();
|
|
let test_dir = TempDir::new(test).unwrap();
|
|
let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test);
|
|
let _anvil_child = crate::native_tests::start_anvil(false, Hardfork::Latest);
|
|
kzg_evm_prove_and_verify(2, path, test.to_string(), "private", "private", "public");
|
|
#[cfg(not(feature = "icicle"))]
|
|
run_js_tests(path, test.to_string(), "testBrowserEvmVerify", false);
|
|
test_dir.close().unwrap();
|
|
|
|
}
|
|
|
|
|
|
#(#[test_case(TESTS_EVM[N])])*
|
|
fn kzg_evm_hashed_input_prove_and_verify_(test: &str) {
|
|
crate::native_tests::init_binary();
|
|
let test_dir = TempDir::new(test).unwrap();
|
|
let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test);
|
|
let mut _anvil_child = crate::native_tests::start_anvil(false, Hardfork::Latest);
|
|
kzg_evm_prove_and_verify(2, path, test.to_string(), "hashed", "private", "private");
|
|
#[cfg(not(feature = "icicle"))]
|
|
run_js_tests(path, test.to_string(), "testBrowserEvmVerify", false);
|
|
test_dir.close().unwrap();
|
|
}
|
|
|
|
|
|
#(#[test_case((TESTS_EVM[N], Hardfork::Latest))])*
|
|
#(#[test_case((TESTS_EVM[N], Hardfork::Paris))])*
|
|
#(#[test_case((TESTS_EVM[N], Hardfork::London))])*
|
|
#(#[test_case((TESTS_EVM[N], Hardfork::Shanghai))])*
|
|
fn kzg_evm_kzg_input_prove_and_verify_(test: (&str, Hardfork)) {
|
|
let (test,hardfork) = test;
|
|
crate::native_tests::init_binary();
|
|
let test_dir = TempDir::new(test).unwrap();
|
|
let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test);
|
|
let mut _anvil_child = crate::native_tests::start_anvil(false, hardfork);
|
|
kzg_evm_prove_and_verify(2, path, test.to_string(), "polycommit", "private", "public");
|
|
#[cfg(not(feature = "icicle"))]
|
|
run_js_tests(path, test.to_string(), "testBrowserEvmVerify", false);
|
|
test_dir.close().unwrap();
|
|
}
|
|
|
|
|
|
#(#[test_case(TESTS_EVM[N])])*
|
|
fn kzg_evm_hashed_params_prove_and_verify_(test: &str) {
|
|
crate::native_tests::init_binary();
|
|
let test_dir = TempDir::new(test).unwrap();
|
|
let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test);
|
|
let _anvil_child = crate::native_tests::start_anvil(false, Hardfork::Latest);
|
|
kzg_evm_prove_and_verify(2, path, test.to_string(), "private", "hashed", "public");
|
|
#[cfg(not(feature = "icicle"))]
|
|
run_js_tests(path, test.to_string(), "testBrowserEvmVerify", false);
|
|
test_dir.close().unwrap();
|
|
|
|
}
|
|
|
|
#(#[test_case(TESTS_EVM[N])])*
|
|
fn kzg_evm_hashed_output_prove_and_verify_(test: &str) {
|
|
crate::native_tests::init_binary();
|
|
let test_dir = TempDir::new(test).unwrap();
|
|
let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test);
|
|
let _anvil_child = crate::native_tests::start_anvil(false, Hardfork::Latest);
|
|
kzg_evm_prove_and_verify(2, path, test.to_string(), "private", "private", "hashed");
|
|
#[cfg(not(feature = "icicle"))]
|
|
run_js_tests(path, test.to_string(), "testBrowserEvmVerify", false);
|
|
test_dir.close().unwrap();
|
|
}
|
|
|
|
|
|
#(#[test_case(TESTS_EVM[N])])*
|
|
fn kzg_evm_kzg_params_prove_and_verify_(test: &str) {
|
|
crate::native_tests::init_binary();
|
|
let test_dir = TempDir::new(test).unwrap();
|
|
let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test);
|
|
let _anvil_child = crate::native_tests::start_anvil(false, Hardfork::Latest);
|
|
kzg_evm_prove_and_verify(2, path, test.to_string(), "private", "polycommit", "public");
|
|
#[cfg(not(feature = "icicle"))]
|
|
run_js_tests(path, test.to_string(), "testBrowserEvmVerify", false);
|
|
test_dir.close().unwrap();
|
|
}
|
|
|
|
|
|
#(#[test_case(TESTS_EVM[N])])*
|
|
fn kzg_evm_kzg_output_prove_and_verify_(test: &str) {
|
|
crate::native_tests::init_binary();
|
|
let test_dir = TempDir::new(test).unwrap();
|
|
let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test);
|
|
let _anvil_child = crate::native_tests::start_anvil(false, Hardfork::Latest);
|
|
kzg_evm_prove_and_verify(2, path, test.to_string(), "private", "private", "polycommit");
|
|
#[cfg(not(feature = "icicle"))]
|
|
run_js_tests(path, test.to_string(), "testBrowserEvmVerify", false);
|
|
test_dir.close().unwrap();
|
|
}
|
|
|
|
#(#[test_case(TESTS_EVM[N])])*
|
|
fn kzg_evm_kzg_all_prove_and_verify_(test: &str) {
|
|
crate::native_tests::init_binary();
|
|
let test_dir = TempDir::new(test).unwrap();
|
|
let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test);
|
|
let _anvil_child = crate::native_tests::start_anvil(false, Hardfork::Latest);
|
|
kzg_evm_prove_and_verify(2, path, test.to_string(), "polycommit", "polycommit", "polycommit");
|
|
#[cfg(not(feature = "icicle"))]
|
|
run_js_tests(path, test.to_string(), "testBrowserEvmVerify", false);
|
|
test_dir.close().unwrap();
|
|
}
|
|
|
|
|
|
|
|
|
|
});
|
|
}
|
|
};
|
|
}
|
|
|
|
macro_rules! test_func_examples {
|
|
() => {
|
|
#[cfg(test)]
|
|
mod tests_examples {
|
|
use seq_macro::seq;
|
|
use crate::native_tests::EXAMPLES;
|
|
use test_case::test_case;
|
|
use crate::native_tests::run_example as run;
|
|
seq!(N in 0..=1 {
|
|
#(#[test_case(EXAMPLES[N])])*
|
|
fn example_(test: &str) {
|
|
run(test.to_string());
|
|
}
|
|
});
|
|
}
|
|
};
|
|
}
|
|
|
|
test_func!();
|
|
test_func_aggr!();
|
|
test_func_evm!();
|
|
test_func_examples!();
|
|
|
|
fn model_serialization_different_binaries(test_dir: &str, example_name: String) {
|
|
let status = Command::new("cargo")
|
|
.args([
|
|
"run",
|
|
"--bin",
|
|
"ezkl",
|
|
"--",
|
|
"gen-settings",
|
|
"-M",
|
|
format!("{}/{}/network.onnx", test_dir, example_name).as_str(),
|
|
&format!(
|
|
"--settings-path={}/{}/settings.json",
|
|
test_dir, example_name
|
|
),
|
|
])
|
|
.status()
|
|
.expect("failed to execute process");
|
|
assert!(status.success());
|
|
|
|
let status = Command::new("cargo")
|
|
.args([
|
|
"run",
|
|
"--bin",
|
|
"ezkl",
|
|
"--",
|
|
"compile-circuit",
|
|
"-M",
|
|
format!("{}/{}/network.onnx", test_dir, example_name).as_str(),
|
|
"--compiled-circuit",
|
|
format!("{}/{}/network.compiled", test_dir, example_name).as_str(),
|
|
&format!(
|
|
"--settings-path={}/{}/settings.json",
|
|
test_dir, example_name
|
|
),
|
|
])
|
|
.status()
|
|
.expect("failed to execute process");
|
|
assert!(status.success());
|
|
|
|
// now alter binary slightly
|
|
// create new temp cargo.toml with a different version
|
|
// cpy old cargo.toml to cargo.toml.bak
|
|
let status = Command::new("cp")
|
|
.args(["Cargo.toml", "Cargo.toml.bak"])
|
|
.status()
|
|
.expect("failed to execute process");
|
|
assert!(status.success());
|
|
|
|
let mut cargo_toml = std::fs::File::open("Cargo.toml").unwrap();
|
|
let mut cargo_toml_contents = String::new();
|
|
cargo_toml.read_to_string(&mut cargo_toml_contents).unwrap();
|
|
let mut cargo_toml_contents = cargo_toml_contents.split('\n').collect::<Vec<_>>();
|
|
|
|
// draw a random version number from 0.0.0 to 0.100.100
|
|
let mut rng = rand::thread_rng();
|
|
let version = &format!(
|
|
"version = \"0.{}.{}-test\"",
|
|
rng.gen_range(0..100),
|
|
rng.gen_range(0..100)
|
|
);
|
|
let cargo_toml_contents = cargo_toml_contents
|
|
.iter_mut()
|
|
.map(|line| {
|
|
if line.starts_with("version") {
|
|
*line = version;
|
|
}
|
|
*line
|
|
})
|
|
.collect::<Vec<_>>();
|
|
let mut cargo_toml = std::fs::File::create("Cargo.toml").unwrap();
|
|
cargo_toml
|
|
.write_all(cargo_toml_contents.join("\n").as_bytes())
|
|
.unwrap();
|
|
|
|
let status = Command::new("cargo")
|
|
.args([
|
|
"run",
|
|
"--bin",
|
|
"ezkl",
|
|
"--",
|
|
"gen-witness",
|
|
"-D",
|
|
&format!("{}/{}/input.json", test_dir, example_name),
|
|
"-M",
|
|
&format!("{}/{}/network.compiled", test_dir, example_name),
|
|
"-O",
|
|
&format!("{}/{}/witness.json", test_dir, example_name),
|
|
])
|
|
.status()
|
|
.expect("failed to execute process");
|
|
assert!(status.success());
|
|
|
|
// now delete cargo.toml and move cargo.toml.bak to cargo.toml
|
|
let status = Command::new("rm")
|
|
.args(["Cargo.toml"])
|
|
.status()
|
|
.expect("failed to execute process");
|
|
assert!(status.success());
|
|
|
|
let status = Command::new("mv")
|
|
.args(["Cargo.toml.bak", "Cargo.toml"])
|
|
.status()
|
|
.expect("failed to execute process");
|
|
assert!(status.success());
|
|
}
|
|
|
|
// Mock prove (fast, but does not cover some potential issues)
|
|
fn run_example(example_name: String) {
|
|
let status = Command::new("cargo")
|
|
.args(["run", "--release", "--example", example_name.as_str()])
|
|
.status()
|
|
.expect("failed to execute process");
|
|
assert!(status.success());
|
|
}
|
|
|
|
// Mock prove (fast, but does not cover some potential issues)
|
|
#[allow(clippy::too_many_arguments)]
|
|
fn mock(
|
|
test_dir: &str,
|
|
example_name: String,
|
|
input_visibility: &str,
|
|
param_visibility: &str,
|
|
output_visibility: &str,
|
|
batch_size: usize,
|
|
cal_target: &str,
|
|
scales_to_use: Option<Vec<u32>>,
|
|
bounded_lookup_log: bool,
|
|
decomp_base: Option<usize>,
|
|
decomp_legs: Option<usize>,
|
|
) {
|
|
gen_circuit_settings_and_witness(
|
|
test_dir,
|
|
example_name.clone(),
|
|
input_visibility,
|
|
param_visibility,
|
|
output_visibility,
|
|
batch_size,
|
|
cal_target,
|
|
scales_to_use,
|
|
2,
|
|
Commitments::KZG,
|
|
2,
|
|
bounded_lookup_log,
|
|
decomp_base,
|
|
decomp_legs,
|
|
);
|
|
|
|
let status = Command::new(format!("{}/{}", *CARGO_TARGET_DIR, TEST_BINARY))
|
|
.args([
|
|
"mock",
|
|
"-W",
|
|
format!("{}/{}/witness.json", test_dir, example_name).as_str(),
|
|
"-M",
|
|
format!("{}/{}/network.compiled", test_dir, example_name).as_str(),
|
|
])
|
|
.status()
|
|
.expect("failed to execute process");
|
|
assert!(status.success());
|
|
}
|
|
|
|
#[allow(clippy::too_many_arguments)]
|
|
fn gen_circuit_settings_and_witness(
|
|
test_dir: &str,
|
|
example_name: String,
|
|
input_visibility: &str,
|
|
param_visibility: &str,
|
|
output_visibility: &str,
|
|
batch_size: usize,
|
|
cal_target: &str,
|
|
scales_to_use: Option<Vec<u32>>,
|
|
num_inner_columns: usize,
|
|
commitment: Commitments,
|
|
lookup_safety_margin: usize,
|
|
bounded_lookup_log: bool,
|
|
decomp_base: Option<usize>,
|
|
decomp_legs: Option<usize>,
|
|
) {
|
|
let mut args = vec![
|
|
"gen-settings".to_string(),
|
|
"-M".to_string(),
|
|
format!("{}/{}/network.onnx", test_dir, example_name),
|
|
format!(
|
|
"--settings-path={}/{}/settings.json",
|
|
test_dir, example_name
|
|
),
|
|
format!(
|
|
"--variables=batch_size->{},sequence_length->100,<Sym1>->1",
|
|
batch_size
|
|
),
|
|
format!("--input-visibility={}", input_visibility),
|
|
format!("--param-visibility={}", param_visibility),
|
|
format!("--output-visibility={}", output_visibility),
|
|
format!("--num-inner-cols={}", num_inner_columns),
|
|
format!("--commitment={}", commitment),
|
|
format!("--logrows={}", 22),
|
|
];
|
|
|
|
// if output-visibility is fixed set --range-check-inputs-outputs to False
|
|
if output_visibility == "fixed" {
|
|
args.push("--ignore-range-check-inputs-outputs".to_string());
|
|
}
|
|
|
|
if let Some(decomp_base) = decomp_base {
|
|
args.push(format!("--decomp-base={}", decomp_base));
|
|
}
|
|
|
|
if let Some(decomp_legs) = decomp_legs {
|
|
args.push(format!("--decomp-legs={}", decomp_legs));
|
|
}
|
|
|
|
if bounded_lookup_log {
|
|
args.push("--bounded-log-lookup".to_string());
|
|
}
|
|
|
|
let status = Command::new(format!("{}/{}", *CARGO_TARGET_DIR, TEST_BINARY))
|
|
.args(args)
|
|
.status()
|
|
.expect("failed to execute process");
|
|
assert!(status.success());
|
|
|
|
let mut calibrate_args = vec![
|
|
"calibrate-settings".to_string(),
|
|
"--data".to_string(),
|
|
format!("{}/{}/input.json", test_dir, example_name),
|
|
"-M".to_string(),
|
|
format!("{}/{}/network.onnx", test_dir, example_name),
|
|
format!(
|
|
"--settings-path={}/{}/settings.json",
|
|
test_dir, example_name
|
|
),
|
|
format!("--target={}", cal_target),
|
|
format!("--lookup-safety-margin={}", lookup_safety_margin),
|
|
];
|
|
|
|
if let Some(scales) = scales_to_use {
|
|
let scales = scales
|
|
.iter()
|
|
.map(|s| s.to_string())
|
|
.collect::<Vec<_>>()
|
|
.join(",");
|
|
calibrate_args.push("--scales".to_string());
|
|
calibrate_args.push(scales);
|
|
}
|
|
|
|
let status = Command::new(format!("{}/{}", *CARGO_TARGET_DIR, TEST_BINARY))
|
|
.args(calibrate_args)
|
|
.status()
|
|
.expect("failed to execute process");
|
|
assert!(status.success());
|
|
|
|
let status = Command::new(format!("{}/{}", *CARGO_TARGET_DIR, TEST_BINARY))
|
|
.args([
|
|
"compile-circuit",
|
|
"-M",
|
|
format!("{}/{}/network.onnx", test_dir, example_name).as_str(),
|
|
"--compiled-circuit",
|
|
format!("{}/{}/network.compiled", test_dir, example_name).as_str(),
|
|
&format!(
|
|
"--settings-path={}/{}/settings.json",
|
|
test_dir, example_name
|
|
),
|
|
])
|
|
.status()
|
|
.expect("failed to execute process");
|
|
assert!(status.success());
|
|
|
|
let status = Command::new(format!("{}/{}", *CARGO_TARGET_DIR, TEST_BINARY))
|
|
.args([
|
|
"gen-witness",
|
|
"-D",
|
|
&format!("{}/{}/input.json", test_dir, example_name),
|
|
"-M",
|
|
&format!("{}/{}/network.compiled", test_dir, example_name),
|
|
"-O",
|
|
&format!("{}/{}/witness.json", test_dir, example_name),
|
|
])
|
|
.stdout(std::process::Stdio::null())
|
|
.status()
|
|
.expect("failed to execute process");
|
|
assert!(status.success());
|
|
}
|
|
|
|
// Mock prove (fast, but does not cover some potential issues)
|
|
#[allow(clippy::too_many_arguments)]
|
|
fn accuracy_measurement(
|
|
test_dir: &str,
|
|
example_name: String,
|
|
input_visibility: &str,
|
|
param_visibility: &str,
|
|
output_visibility: &str,
|
|
batch_size: usize,
|
|
cal_target: &str,
|
|
target_perc: f32,
|
|
) {
|
|
gen_circuit_settings_and_witness(
|
|
test_dir,
|
|
example_name.clone(),
|
|
input_visibility,
|
|
param_visibility,
|
|
output_visibility,
|
|
batch_size,
|
|
cal_target,
|
|
None,
|
|
2,
|
|
Commitments::KZG,
|
|
2,
|
|
false,
|
|
None,
|
|
None,
|
|
);
|
|
|
|
println!(
|
|
" ------------ running accuracy measurement for {}",
|
|
example_name
|
|
);
|
|
// run python ./output_comparison.py in the test dir
|
|
let status = Command::new("python")
|
|
.args([
|
|
"tests/output_comparison.py",
|
|
&format!("{}/{}/network.onnx", test_dir, example_name),
|
|
&format!("{}/{}/input.json", test_dir, example_name),
|
|
&format!("{}/{}/witness.json", test_dir, example_name),
|
|
&format!("{}/{}/settings.json", test_dir, example_name),
|
|
&format!("{}", target_perc),
|
|
])
|
|
.status()
|
|
.expect("failed to execute process");
|
|
|
|
assert!(status.success());
|
|
}
|
|
|
|
// Mock prove (fast, but does not cover some potential issues)
|
|
fn render_circuit(test_dir: &str, example_name: String) {
|
|
let status = Command::new(format!("{}/{}", *CARGO_TARGET_DIR, TEST_BINARY))
|
|
.args([
|
|
"render-circuit",
|
|
"-M",
|
|
format!("{}/{}/network.onnx", test_dir, example_name).as_str(),
|
|
"-O",
|
|
format!("{}/{}/render.png", test_dir, example_name).as_str(),
|
|
"--lookup-range=-32768->32768",
|
|
"-K=17",
|
|
])
|
|
.status()
|
|
.expect("failed to execute process");
|
|
assert!(status.success());
|
|
}
|
|
|
|
// prove-serialize-verify, the usual full path
|
|
fn kzg_aggr_mock_prove_and_verify(test_dir: &str, example_name: String) {
|
|
prove_and_verify(
|
|
test_dir,
|
|
example_name.clone(),
|
|
"safe",
|
|
"private",
|
|
"private",
|
|
"public",
|
|
2,
|
|
None,
|
|
false,
|
|
"for-aggr",
|
|
Commitments::KZG,
|
|
2,
|
|
);
|
|
let status = Command::new(format!("{}/{}", *CARGO_TARGET_DIR, TEST_BINARY))
|
|
.args([
|
|
"mock-aggregate",
|
|
"--logrows=23",
|
|
"--aggregation-snarks",
|
|
&format!("{}/{}/proof.pf", test_dir, example_name),
|
|
])
|
|
.status()
|
|
.expect("failed to execute process");
|
|
assert!(status.success());
|
|
}
|
|
|
|
// prove-serialize-verify, the usual full path
|
|
fn aggr_prove_and_verify(
|
|
test_dir: &str,
|
|
example_name: String,
|
|
input_visibility: &str,
|
|
param_visibility: &str,
|
|
output_visibility: &str,
|
|
commitment: Commitments,
|
|
) {
|
|
prove_and_verify(
|
|
test_dir,
|
|
example_name.clone(),
|
|
"safe",
|
|
input_visibility,
|
|
param_visibility,
|
|
output_visibility,
|
|
2,
|
|
None,
|
|
false,
|
|
"for-aggr",
|
|
Commitments::KZG,
|
|
2,
|
|
);
|
|
|
|
download_srs(23, commitment);
|
|
// now setup-aggregate
|
|
let status = Command::new(format!("{}/{}", *CARGO_TARGET_DIR, TEST_BINARY))
|
|
.args([
|
|
"setup-aggregate",
|
|
"--sample-snarks",
|
|
&format!("{}/{}/proof.pf", test_dir, example_name),
|
|
"--logrows=23",
|
|
"--vk-path",
|
|
&format!("{}/{}/aggr.vk", test_dir, example_name),
|
|
"--pk-path",
|
|
&format!("{}/{}/aggr.pk", test_dir, example_name),
|
|
&format!("--commitment={}", commitment),
|
|
])
|
|
.status()
|
|
.expect("failed to execute process");
|
|
assert!(status.success());
|
|
|
|
let status = Command::new(format!("{}/{}", *CARGO_TARGET_DIR, TEST_BINARY))
|
|
.args([
|
|
"aggregate",
|
|
"--logrows=23",
|
|
"--aggregation-snarks",
|
|
&format!("{}/{}/proof.pf", test_dir, example_name),
|
|
"--proof-path",
|
|
&format!("{}/{}/aggr.pf", test_dir, example_name),
|
|
"--pk-path",
|
|
&format!("{}/{}/aggr.pk", test_dir, example_name),
|
|
&format!("--commitment={}", commitment),
|
|
])
|
|
.status()
|
|
.expect("failed to execute process");
|
|
assert!(status.success());
|
|
let status = Command::new(format!("{}/{}", *CARGO_TARGET_DIR, TEST_BINARY))
|
|
.args([
|
|
"verify-aggr",
|
|
"--logrows=23",
|
|
"--proof-path",
|
|
&format!("{}/{}/aggr.pf", test_dir, example_name),
|
|
"--vk-path",
|
|
&format!("{}/{}/aggr.vk", test_dir, example_name),
|
|
])
|
|
.status()
|
|
.expect("failed to execute process");
|
|
assert!(status.success());
|
|
}
|
|
|
|
// prove-serialize-verify, the usual full path
|
|
fn kzg_evm_aggr_prove_and_verify(
|
|
test_dir: &str,
|
|
example_name: String,
|
|
input_visibility: &str,
|
|
param_visibility: &str,
|
|
output_visibility: &str,
|
|
) {
|
|
aggr_prove_and_verify(
|
|
test_dir,
|
|
example_name.clone(),
|
|
input_visibility,
|
|
param_visibility,
|
|
output_visibility,
|
|
Commitments::KZG,
|
|
);
|
|
|
|
download_srs(23, Commitments::KZG);
|
|
|
|
let vk_arg = &format!("{}/{}/aggr.vk", test_dir, example_name);
|
|
|
|
fn build_args<'a>(base_args: Vec<&'a str>, sol_arg: &'a str) -> Vec<&'a str> {
|
|
let mut args = base_args;
|
|
|
|
args.push("--sol-code-path");
|
|
args.push(sol_arg);
|
|
args
|
|
}
|
|
|
|
let sol_arg = format!("{}/{}/kzg_aggr.sol", test_dir, example_name);
|
|
let addr_path_arg = format!("--addr-path={}/{}/addr.txt", test_dir, example_name);
|
|
let rpc_arg = format!("--rpc-url={}", *ANVIL_URL);
|
|
let settings_arg = format!("{}/{}/settings.json", test_dir, example_name);
|
|
let private_key = format!("--private-key={}", *ANVIL_DEFAULT_PRIVATE_KEY);
|
|
|
|
// create encoded calldata
|
|
let status = Command::new(format!("{}/{}", *CARGO_TARGET_DIR, TEST_BINARY))
|
|
.args([
|
|
"encode-evm-calldata",
|
|
"--proof-path",
|
|
&format!("{}/{}/aggr.pf", test_dir, example_name),
|
|
])
|
|
.status()
|
|
.expect("failed to execute process");
|
|
|
|
assert!(status.success());
|
|
|
|
let base_args = vec![
|
|
"create-evm-verifier-aggr",
|
|
"--vk-path",
|
|
vk_arg.as_str(),
|
|
"--aggregation-settings",
|
|
settings_arg.as_str(),
|
|
"--logrows=23",
|
|
];
|
|
|
|
let args = build_args(base_args, &sol_arg);
|
|
|
|
let status = Command::new(format!("{}/{}", *CARGO_TARGET_DIR, TEST_BINARY))
|
|
.args(args)
|
|
.status()
|
|
.expect("failed to execute process");
|
|
assert!(status.success());
|
|
|
|
// deploy the verifier
|
|
let args = vec![
|
|
"deploy-evm",
|
|
rpc_arg.as_str(),
|
|
addr_path_arg.as_str(),
|
|
"--sol-code-path",
|
|
sol_arg.as_str(),
|
|
private_key.as_str(),
|
|
];
|
|
|
|
let status = Command::new(format!("{}/{}", *CARGO_TARGET_DIR, TEST_BINARY))
|
|
.args(&args)
|
|
.status()
|
|
.expect("failed to execute process");
|
|
assert!(status.success());
|
|
|
|
// read in the address
|
|
let addr = std::fs::read_to_string(format!("{}/{}/addr.txt", test_dir, example_name))
|
|
.expect("failed to read address file");
|
|
|
|
let deployed_addr_arg = format!("--addr-verifier={}", addr);
|
|
|
|
let pf_arg = format!("{}/{}/aggr.pf", test_dir, example_name);
|
|
|
|
let mut base_args = vec![
|
|
"verify-evm",
|
|
"--proof-path",
|
|
pf_arg.as_str(),
|
|
deployed_addr_arg.as_str(),
|
|
rpc_arg.as_str(),
|
|
];
|
|
|
|
let status = Command::new(format!("{}/{}", *CARGO_TARGET_DIR, TEST_BINARY))
|
|
.args(&base_args)
|
|
.status()
|
|
.expect("failed to execute process");
|
|
assert!(status.success());
|
|
// As sanity check, add example that should fail.
|
|
base_args[2] = PF_FAILURE_AGGR;
|
|
let status = Command::new(format!("{}/{}", *CARGO_TARGET_DIR, TEST_BINARY))
|
|
.args(base_args)
|
|
.status()
|
|
.expect("failed to execute process");
|
|
assert!(!status.success());
|
|
}
|
|
|
|
// prove-serialize-verify, the usual full path
|
|
#[allow(clippy::too_many_arguments)]
|
|
fn prove_and_verify(
|
|
test_dir: &str,
|
|
example_name: String,
|
|
checkmode: &str,
|
|
input_visibility: &str,
|
|
param_visibility: &str,
|
|
output_visibility: &str,
|
|
num_inner_columns: usize,
|
|
scales_to_use: Option<Vec<u32>>,
|
|
overflow: bool,
|
|
proof_type: &str,
|
|
commitment: Commitments,
|
|
lookup_safety_margin: usize,
|
|
) {
|
|
let target_str = if overflow {
|
|
"resources/col-overflow"
|
|
} else {
|
|
"resources"
|
|
};
|
|
|
|
gen_circuit_settings_and_witness(
|
|
test_dir,
|
|
example_name.clone(),
|
|
input_visibility,
|
|
param_visibility,
|
|
output_visibility,
|
|
1,
|
|
target_str,
|
|
scales_to_use,
|
|
num_inner_columns,
|
|
commitment,
|
|
lookup_safety_margin,
|
|
false,
|
|
None,
|
|
None,
|
|
);
|
|
|
|
let settings_path = format!("{}/{}/settings.json", test_dir, example_name);
|
|
|
|
init_params(settings_path.clone().into());
|
|
|
|
let status = Command::new(format!("{}/{}", *CARGO_TARGET_DIR, TEST_BINARY))
|
|
.args([
|
|
"setup",
|
|
"-M",
|
|
&format!("{}/{}/network.compiled", test_dir, example_name),
|
|
"--pk-path",
|
|
&format!("{}/{}/key.pk", test_dir, example_name),
|
|
"--vk-path",
|
|
&format!("{}/{}/key.vk", test_dir, example_name),
|
|
"--disable-selector-compression",
|
|
])
|
|
.status()
|
|
.expect("failed to execute process");
|
|
assert!(status.success());
|
|
|
|
let status = Command::new(format!("{}/{}", *CARGO_TARGET_DIR, TEST_BINARY))
|
|
.args([
|
|
"prove",
|
|
"-W",
|
|
format!("{}/{}/witness.json", test_dir, example_name).as_str(),
|
|
"-M",
|
|
format!("{}/{}/network.compiled", test_dir, example_name).as_str(),
|
|
"--proof-path",
|
|
&format!("{}/{}/proof.pf", test_dir, example_name),
|
|
"--pk-path",
|
|
&format!("{}/{}/key.pk", test_dir, example_name),
|
|
&format!("--check-mode={}", checkmode),
|
|
&format!("--proof-type={}", proof_type),
|
|
])
|
|
.status()
|
|
.expect("failed to execute process");
|
|
assert!(status.success());
|
|
|
|
let status = Command::new(format!("{}/{}", *CARGO_TARGET_DIR, TEST_BINARY))
|
|
.args([
|
|
"swap-proof-commitments",
|
|
"--proof-path",
|
|
&format!("{}/{}/proof.pf", test_dir, example_name),
|
|
"--witness-path",
|
|
format!("{}/{}/witness.json", test_dir, example_name).as_str(),
|
|
])
|
|
.status()
|
|
.expect("failed to execute process");
|
|
assert!(status.success());
|
|
|
|
let status = Command::new(format!("{}/{}", *CARGO_TARGET_DIR, TEST_BINARY))
|
|
.args([
|
|
"verify",
|
|
format!("--settings-path={}", settings_path).as_str(),
|
|
"--proof-path",
|
|
&format!("{}/{}/proof.pf", test_dir, example_name),
|
|
"--vk-path",
|
|
&format!("{}/{}/key.vk", test_dir, example_name),
|
|
])
|
|
.status()
|
|
.expect("failed to execute process");
|
|
assert!(status.success());
|
|
|
|
// load settings file
|
|
let settings =
|
|
std::fs::read_to_string(settings_path.clone()).expect("failed to read settings file");
|
|
|
|
let graph_settings = serde_json::from_str::<GraphSettings>(&settings)
|
|
.expect("failed to parse settings file");
|
|
|
|
// get_srs for the graph_settings_num_instances
|
|
download_srs(1, graph_settings.run_args.commitment.into());
|
|
|
|
let status = Command::new(format!("{}/{}", *CARGO_TARGET_DIR, TEST_BINARY))
|
|
.args([
|
|
"verify",
|
|
format!("--settings-path={}", settings_path).as_str(),
|
|
"--proof-path",
|
|
&format!("{}/{}/proof.pf", test_dir, example_name),
|
|
"--vk-path",
|
|
&format!("{}/{}/key.vk", test_dir, example_name),
|
|
"--reduced-srs",
|
|
])
|
|
.status()
|
|
.expect("failed to execute process");
|
|
assert!(status.success());
|
|
}
|
|
|
|
// prove-serialize-verify, the usual full path
|
|
fn kzg_evm_prove_and_verify(
|
|
num_inner_columns: usize,
|
|
test_dir: &str,
|
|
example_name: String,
|
|
input_visibility: &str,
|
|
param_visibility: &str,
|
|
output_visibility: &str,
|
|
) {
|
|
let anvil_url = ANVIL_URL.as_str();
|
|
|
|
prove_and_verify(
|
|
test_dir,
|
|
example_name.clone(),
|
|
"safe",
|
|
input_visibility,
|
|
param_visibility,
|
|
output_visibility,
|
|
num_inner_columns,
|
|
None,
|
|
false,
|
|
"single",
|
|
Commitments::KZG,
|
|
2,
|
|
);
|
|
|
|
let settings_path = format!("{}/{}/settings.json", test_dir, example_name);
|
|
init_params(settings_path.clone().into());
|
|
|
|
let vk_arg = format!("{}/{}/key.vk", test_dir, example_name);
|
|
let rpc_arg = format!("--rpc-url={}", anvil_url);
|
|
let addr_path_arg = format!("--addr-path={}/{}/addr.txt", test_dir, example_name);
|
|
let settings_arg = format!("--settings-path={}", settings_path);
|
|
|
|
// create encoded calldata
|
|
let status = Command::new(format!("{}/{}", *CARGO_TARGET_DIR, TEST_BINARY))
|
|
.args([
|
|
"encode-evm-calldata",
|
|
"--proof-path",
|
|
&format!("{}/{}/proof.pf", test_dir, example_name),
|
|
])
|
|
.status()
|
|
.expect("failed to execute process");
|
|
|
|
assert!(status.success());
|
|
|
|
// create the verifier
|
|
let mut args = vec!["create-evm-verifier", "--vk-path", &vk_arg, &settings_arg];
|
|
|
|
let sol_arg = format!("{}/{}/kzg.sol", test_dir, example_name);
|
|
|
|
// create everything to test the pipeline
|
|
args.push("--sol-code-path");
|
|
args.push(sol_arg.as_str());
|
|
|
|
let status = Command::new(format!("{}/{}", *CARGO_TARGET_DIR, TEST_BINARY))
|
|
.args(&args)
|
|
.status()
|
|
.expect("failed to execute process");
|
|
assert!(status.success());
|
|
|
|
// deploy the verifier
|
|
let mut args = vec!["deploy-evm", rpc_arg.as_str(), addr_path_arg.as_str()];
|
|
|
|
args.push("--sol-code-path");
|
|
args.push(sol_arg.as_str());
|
|
|
|
let status = Command::new(format!("{}/{}", *CARGO_TARGET_DIR, TEST_BINARY))
|
|
.args(&args)
|
|
.status()
|
|
.expect("failed to execute process");
|
|
assert!(status.success());
|
|
|
|
// read in the address
|
|
let addr = std::fs::read_to_string(format!("{}/{}/addr.txt", test_dir, example_name))
|
|
.expect("failed to read address file");
|
|
|
|
let deployed_addr_arg = format!("--addr-verifier={}", addr);
|
|
|
|
// now verify the proof
|
|
let pf_arg = format!("{}/{}/proof.pf", test_dir, example_name);
|
|
let mut args = vec![
|
|
"verify-evm",
|
|
"--proof-path",
|
|
pf_arg.as_str(),
|
|
rpc_arg.as_str(),
|
|
deployed_addr_arg.as_str(),
|
|
];
|
|
|
|
let status = Command::new(format!("{}/{}", *CARGO_TARGET_DIR, TEST_BINARY))
|
|
.args(&args)
|
|
.status()
|
|
.expect("failed to execute process");
|
|
assert!(status.success());
|
|
// As sanity check, add example that should fail.
|
|
args[2] = PF_FAILURE;
|
|
let status = Command::new(format!("{}/{}", *CARGO_TARGET_DIR, TEST_BINARY))
|
|
.args(args)
|
|
.status()
|
|
.expect("failed to execute process");
|
|
assert!(!status.success());
|
|
}
|
|
|
|
// prove-serialize-verify, the usual full path
|
|
#[allow(clippy::too_many_arguments)]
|
|
fn kzg_evm_prove_and_verify_reusable_verifier(
|
|
num_inner_columns: usize,
|
|
test_dir: &str,
|
|
example_name: String,
|
|
input_visibility: &str,
|
|
param_visibility: &str,
|
|
output_visibility: &str,
|
|
reusable_verifier_address: &mut Option<String>,
|
|
overflow: bool,
|
|
) -> String {
|
|
let anvil_url = ANVIL_URL.as_str();
|
|
|
|
prove_and_verify(
|
|
test_dir,
|
|
example_name.clone(),
|
|
"safe",
|
|
input_visibility,
|
|
param_visibility,
|
|
output_visibility,
|
|
num_inner_columns,
|
|
None,
|
|
overflow,
|
|
"single",
|
|
Commitments::KZG,
|
|
2,
|
|
);
|
|
|
|
let settings_path = format!("{}/{}/settings.json", test_dir, example_name);
|
|
init_params(settings_path.clone().into());
|
|
|
|
let vk_arg = format!("{}/{}/key.vk", test_dir, example_name);
|
|
let rpc_arg = format!("--rpc-url={}", anvil_url);
|
|
let addr_path_arg = format!("--addr-path={}/{}/addr.txt", test_dir, example_name);
|
|
let settings_arg = format!("--settings-path={}", settings_path);
|
|
let sol_arg = format!("--sol-code-path={}/{}/kzg.sol", test_dir, example_name);
|
|
|
|
// if the reusable verifier address is not set, create the verifier
|
|
let deployed_addr_arg = match reusable_verifier_address {
|
|
Some(addr) => addr.clone(),
|
|
None => {
|
|
// create the reusable verifier
|
|
let args = vec![
|
|
"create-evm-verifier",
|
|
"--vk-path",
|
|
&vk_arg,
|
|
&settings_arg,
|
|
&sol_arg,
|
|
"--reusable",
|
|
];
|
|
|
|
let status = Command::new(format!("{}/{}", *CARGO_TARGET_DIR, TEST_BINARY))
|
|
.args(&args)
|
|
.status()
|
|
.expect("failed to execute process");
|
|
assert!(status.success());
|
|
|
|
// deploy the verifier
|
|
let args = vec![
|
|
"deploy-evm",
|
|
rpc_arg.as_str(),
|
|
addr_path_arg.as_str(),
|
|
sol_arg.as_str(),
|
|
"-C=verifier/reusable",
|
|
];
|
|
|
|
let status = Command::new(format!("{}/{}", *CARGO_TARGET_DIR, TEST_BINARY))
|
|
.args(&args)
|
|
.status()
|
|
.expect("failed to execute process");
|
|
assert!(status.success());
|
|
|
|
// read in the address
|
|
let addr =
|
|
std::fs::read_to_string(format!("{}/{}/addr.txt", test_dir, example_name))
|
|
.expect("failed to read address file");
|
|
|
|
let deployed_addr_arg = format!("--addr-verifier={}", addr);
|
|
// set the reusable verifier address
|
|
*reusable_verifier_address = Some(addr);
|
|
deployed_addr_arg
|
|
}
|
|
};
|
|
|
|
let addr_path_arg_vk = format!("--addr-path={}/{}/addr_vk.txt", test_dir, example_name);
|
|
let sol_arg_vk: String = format!("--sol-code-path={}/{}/vk.sol", test_dir, example_name);
|
|
// create the verifier
|
|
let args = vec![
|
|
"create-evm-vka",
|
|
"--vk-path",
|
|
&vk_arg,
|
|
&settings_arg,
|
|
&sol_arg_vk,
|
|
];
|
|
|
|
let status = Command::new(format!("{}/{}", *CARGO_TARGET_DIR, TEST_BINARY))
|
|
.args(&args)
|
|
.status()
|
|
.expect("failed to execute process");
|
|
assert!(status.success());
|
|
|
|
// deploy the vka
|
|
let args = vec![
|
|
"deploy-evm",
|
|
rpc_arg.as_str(),
|
|
addr_path_arg_vk.as_str(),
|
|
sol_arg_vk.as_str(),
|
|
"-C=vka",
|
|
];
|
|
|
|
let status = Command::new(format!("{}/{}", *CARGO_TARGET_DIR, TEST_BINARY))
|
|
.args(&args)
|
|
.status()
|
|
.expect("failed to execute process");
|
|
assert!(status.success());
|
|
|
|
// read in the address
|
|
let addr_vk = std::fs::read_to_string(format!("{}/{}/addr_vk.txt", test_dir, example_name))
|
|
.expect("failed to read address file");
|
|
|
|
let deployed_addr_arg_vk = format!("--addr-vk={}", addr_vk);
|
|
|
|
// create encoded calldata
|
|
let status = Command::new(format!("{}/{}", *CARGO_TARGET_DIR, TEST_BINARY))
|
|
.args([
|
|
"encode-evm-calldata",
|
|
"--proof-path",
|
|
&format!("{}/{}/proof.pf", test_dir, example_name),
|
|
&deployed_addr_arg_vk,
|
|
])
|
|
.status()
|
|
.expect("failed to execute process");
|
|
|
|
assert!(status.success());
|
|
|
|
// now verify the proof
|
|
let pf_arg = format!("{}/{}/proof.pf", test_dir, example_name);
|
|
let args = vec![
|
|
"verify-evm",
|
|
"--proof-path",
|
|
pf_arg.as_str(),
|
|
rpc_arg.as_str(),
|
|
deployed_addr_arg.as_str(),
|
|
deployed_addr_arg_vk.as_str(),
|
|
];
|
|
|
|
let status = Command::new(format!("{}/{}", *CARGO_TARGET_DIR, TEST_BINARY))
|
|
.args(&args)
|
|
.status()
|
|
.expect("failed to execute process");
|
|
assert!(status.success());
|
|
// Read the original proof file
|
|
let original_proof_data: ezkl::pfsys::Snark<
|
|
halo2curves::bn256::Fr,
|
|
halo2curves::bn256::G1Affine,
|
|
> = Snark::load::<KZGCommitmentScheme<Bn256>>(&PathBuf::from(format!(
|
|
"{}/{}/proof.pf",
|
|
test_dir, example_name
|
|
)))
|
|
.expect("Failed to read proof file");
|
|
|
|
for i in 0..1 {
|
|
// Create a copy of the original proof data
|
|
let mut modified_proof_data = original_proof_data.clone();
|
|
|
|
// Flip a random bit
|
|
let random_byte = rand::thread_rng().gen_range(0..modified_proof_data.proof.len());
|
|
let random_bit = rand::thread_rng().gen_range(0..8);
|
|
modified_proof_data.proof[random_byte] ^= 1 << random_bit;
|
|
|
|
// Write the modified proof to a new file
|
|
let modified_pf_arg = format!("{}/{}/modified_proof_{}.pf", test_dir, example_name, i);
|
|
modified_proof_data
|
|
.save(&PathBuf::from(modified_pf_arg.clone()))
|
|
.expect("Failed to save modified proof file");
|
|
|
|
// Verify the modified proof (should fail)
|
|
let mut args_mod = args.clone();
|
|
args_mod[2] = &modified_pf_arg;
|
|
let status = Command::new(format!("{}/{}", *CARGO_TARGET_DIR, TEST_BINARY))
|
|
.args(&args_mod)
|
|
.status()
|
|
.expect("failed to execute process");
|
|
|
|
if status.success() {
|
|
log::error!(
|
|
"Verification unexpectedly succeeded for modified proof {}. Flipped bit {} in byte {}",
|
|
i,
|
|
random_bit,
|
|
random_byte
|
|
);
|
|
}
|
|
|
|
assert!(
|
|
!status.success(),
|
|
"Modified proof {} should have failed verification",
|
|
i
|
|
);
|
|
}
|
|
|
|
// Returned deploy_addr_arg for reusable verifier
|
|
deployed_addr_arg
|
|
}
|
|
|
|
// run js browser evm verify tests for a given example
|
|
fn run_js_tests(test_dir: &str, example_name: String, js_test: &str, vk: bool) {
|
|
let example = format!("--example={}", example_name);
|
|
let dir = format!("--dir={}", test_dir);
|
|
let mut args = vec!["run", "test", js_test, &example, &dir];
|
|
let vk_string: String;
|
|
if vk {
|
|
vk_string = format!("--vk={}", vk);
|
|
args.push(&vk_string);
|
|
};
|
|
let status = Command::new("pnpm")
|
|
.args(&args)
|
|
.status()
|
|
.expect("failed to execute process");
|
|
assert!(status.success());
|
|
}
|
|
|
|
fn kzg_evm_on_chain_input_prove_and_verify(
|
|
test_dir: &str,
|
|
example_name: String,
|
|
input_source: &str,
|
|
output_source: &str,
|
|
input_visibility: &str,
|
|
output_visibility: &str,
|
|
param_visibility: &str,
|
|
) {
|
|
gen_circuit_settings_and_witness(
|
|
test_dir,
|
|
example_name.clone(),
|
|
input_visibility,
|
|
param_visibility,
|
|
output_visibility,
|
|
1,
|
|
"resources",
|
|
// we need the accuracy
|
|
Some(vec![4]),
|
|
1,
|
|
Commitments::KZG,
|
|
2,
|
|
false,
|
|
None,
|
|
None,
|
|
);
|
|
|
|
let model_path = format!("{}/{}/network.compiled", test_dir, example_name);
|
|
let settings_path = format!("{}/{}/settings.json", test_dir, example_name);
|
|
init_params(settings_path.clone().into());
|
|
|
|
let data_path = format!("{}/{}/input.json", test_dir, example_name);
|
|
let witness_path = format!("{}/{}/witness.json", test_dir, example_name);
|
|
let test_on_chain_data_path = format!("{}/{}/on_chain_input.json", test_dir, example_name);
|
|
let rpc_arg = format!("--rpc-url={}", LIMITLESS_ANVIL_URL.as_str());
|
|
let private_key = format!("--private-key={}", *ANVIL_DEFAULT_PRIVATE_KEY);
|
|
|
|
let test_input_source = format!("--input-source={}", input_source);
|
|
let test_output_source = format!("--output-source={}", output_source);
|
|
|
|
let status = Command::new(format!("{}/{}", *CARGO_TARGET_DIR, TEST_BINARY))
|
|
.args([
|
|
"setup",
|
|
"-M",
|
|
&model_path,
|
|
"--pk-path",
|
|
&format!("{}/{}/key.pk", test_dir, example_name),
|
|
"--vk-path",
|
|
&format!("{}/{}/key.vk", test_dir, example_name),
|
|
])
|
|
.status()
|
|
.expect("failed to execute process");
|
|
assert!(status.success());
|
|
|
|
// generate the witness, passing the vk path to generate the necessary kzg commits
|
|
let status = Command::new(format!("{}/{}", *CARGO_TARGET_DIR, TEST_BINARY))
|
|
.args([
|
|
"gen-witness",
|
|
"-D",
|
|
&data_path,
|
|
"-M",
|
|
&model_path,
|
|
"-O",
|
|
&witness_path,
|
|
"--vk-path",
|
|
&format!("{}/{}/key.vk", test_dir, example_name),
|
|
])
|
|
.status()
|
|
.expect("failed to execute process");
|
|
assert!(status.success());
|
|
|
|
// load witness
|
|
let witness: GraphWitness = GraphWitness::from_path(witness_path.clone().into()).unwrap();
|
|
// print out the witness
|
|
println!("WITNESS: {:?}", witness);
|
|
let mut input: GraphData = GraphData::from_path(data_path.clone().into()).unwrap();
|
|
if input_source != "file" || output_source != "file" {
|
|
println!("on chain input");
|
|
if input_visibility == "hashed" {
|
|
let hashes = witness.processed_inputs.unwrap().poseidon_hash.unwrap();
|
|
input.input_data = DataSource::File(
|
|
hashes
|
|
.iter()
|
|
.map(|h| vec![FileSourceInner::Field(*h)])
|
|
.collect(),
|
|
);
|
|
}
|
|
if output_visibility == "hashed" {
|
|
let hashes = witness.processed_outputs.unwrap().poseidon_hash.unwrap();
|
|
input.output_data = Some(DataSource::File(
|
|
hashes
|
|
.iter()
|
|
.map(|h| vec![FileSourceInner::Field(*h)])
|
|
.collect(),
|
|
));
|
|
} else {
|
|
input.output_data = Some(DataSource::File(
|
|
witness
|
|
.pretty_elements
|
|
.unwrap()
|
|
.rescaled_outputs
|
|
.iter()
|
|
.map(|o| {
|
|
o.iter()
|
|
.map(|f| FileSourceInner::Float(f.parse().unwrap()))
|
|
.collect()
|
|
})
|
|
.collect(),
|
|
));
|
|
}
|
|
input.save(data_path.clone().into()).unwrap();
|
|
|
|
let status = Command::new(format!("{}/{}", *CARGO_TARGET_DIR, TEST_BINARY))
|
|
.args([
|
|
"setup-test-evm-data",
|
|
"-D",
|
|
data_path.as_str(),
|
|
"-M",
|
|
&model_path,
|
|
"--test-data",
|
|
test_on_chain_data_path.as_str(),
|
|
rpc_arg.as_str(),
|
|
test_input_source.as_str(),
|
|
test_output_source.as_str(),
|
|
])
|
|
.status()
|
|
.expect("failed to execute process");
|
|
assert!(status.success());
|
|
}
|
|
|
|
let status = Command::new(format!("{}/{}", *CARGO_TARGET_DIR, TEST_BINARY))
|
|
.args([
|
|
"prove",
|
|
"-W",
|
|
&witness_path,
|
|
"-M",
|
|
&model_path,
|
|
"--proof-path",
|
|
&format!("{}/{}/proof.pf", test_dir, example_name),
|
|
"--pk-path",
|
|
&format!("{}/{}/key.pk", test_dir, example_name),
|
|
])
|
|
.status()
|
|
.expect("failed to execute process");
|
|
assert!(status.success());
|
|
|
|
let vk_arg = format!("{}/{}/key.vk", test_dir, example_name);
|
|
|
|
let settings_arg = format!("--settings-path={}", settings_path);
|
|
|
|
// create encoded calldata
|
|
let status = Command::new(format!("{}/{}", *CARGO_TARGET_DIR, TEST_BINARY))
|
|
.args([
|
|
"encode-evm-calldata",
|
|
"--proof-path",
|
|
&format!("{}/{}/proof.pf", test_dir, example_name),
|
|
])
|
|
.status()
|
|
.expect("failed to execute process");
|
|
|
|
assert!(status.success());
|
|
|
|
// create the verifier
|
|
let mut args = vec!["create-evm-verifier", "--vk-path", &vk_arg, &settings_arg];
|
|
|
|
let sol_arg = format!("{}/{}/kzg.sol", test_dir, example_name);
|
|
|
|
args.push("--sol-code-path");
|
|
args.push(sol_arg.as_str());
|
|
|
|
let status = Command::new(format!("{}/{}", *CARGO_TARGET_DIR, TEST_BINARY))
|
|
.args(&args)
|
|
.status()
|
|
.expect("failed to execute process");
|
|
assert!(status.success());
|
|
|
|
let addr_path_verifier_arg = format!(
|
|
"--addr-path={}/{}/addr_verifier.txt",
|
|
test_dir, example_name
|
|
);
|
|
|
|
// deploy the verifier
|
|
let mut args = vec![
|
|
"deploy-evm",
|
|
rpc_arg.as_str(),
|
|
addr_path_verifier_arg.as_str(),
|
|
];
|
|
|
|
args.push("--sol-code-path");
|
|
args.push(sol_arg.as_str());
|
|
|
|
let status = Command::new(format!("{}/{}", *CARGO_TARGET_DIR, TEST_BINARY))
|
|
.args(&args)
|
|
.status()
|
|
.expect("failed to execute process");
|
|
assert!(status.success());
|
|
|
|
let sol_arg = format!("{}/{}/kzg.sol", test_dir, example_name);
|
|
|
|
let mut create_da_args = vec![
|
|
"create-evm-da",
|
|
&settings_arg,
|
|
"--sol-code-path",
|
|
sol_arg.as_str(),
|
|
"-W",
|
|
&witness_path,
|
|
];
|
|
|
|
// if there is a on-chain source we add the data
|
|
if input_source != "file" || output_source != "file" {
|
|
create_da_args.push("-D");
|
|
create_da_args.push(test_on_chain_data_path.as_str());
|
|
}
|
|
|
|
let status = Command::new(format!("{}/{}", *CARGO_TARGET_DIR, TEST_BINARY))
|
|
.args(&create_da_args)
|
|
.status()
|
|
.expect("failed to execute process");
|
|
assert!(status.success());
|
|
|
|
let deploy_evm_data_path = if input_source != "file" || output_source != "file" {
|
|
test_on_chain_data_path.clone()
|
|
} else {
|
|
data_path.clone()
|
|
};
|
|
|
|
let addr_path_da_arg = format!("--addr-path={}/{}/addr_da.txt", test_dir, example_name);
|
|
let status = Command::new(format!("{}/{}", *CARGO_TARGET_DIR, TEST_BINARY))
|
|
.args([
|
|
"deploy-evm-da",
|
|
format!("--settings-path={}", settings_path).as_str(),
|
|
"-D",
|
|
deploy_evm_data_path.as_str(),
|
|
"--sol-code-path",
|
|
sol_arg.as_str(),
|
|
rpc_arg.as_str(),
|
|
addr_path_da_arg.as_str(),
|
|
private_key.as_str(),
|
|
])
|
|
.status()
|
|
.expect("failed to execute process");
|
|
assert!(status.success());
|
|
|
|
let pf_arg = format!("{}/{}/proof.pf", test_dir, example_name);
|
|
// read in the verifier address
|
|
let addr_verifier =
|
|
std::fs::read_to_string(format!("{}/{}/addr_verifier.txt", test_dir, example_name))
|
|
.expect("failed to read address file");
|
|
|
|
let deployed_addr_verifier_arg = format!("--addr-verifier={}", addr_verifier);
|
|
|
|
// read in the da address
|
|
let addr_da = std::fs::read_to_string(format!("{}/{}/addr_da.txt", test_dir, example_name))
|
|
.expect("failed to read address file");
|
|
|
|
let deployed_addr_da_arg = format!("--addr-da={}", addr_da);
|
|
|
|
let args = vec![
|
|
"verify-evm",
|
|
"--proof-path",
|
|
pf_arg.as_str(),
|
|
deployed_addr_verifier_arg.as_str(),
|
|
deployed_addr_da_arg.as_str(),
|
|
rpc_arg.as_str(),
|
|
];
|
|
let status = Command::new(format!("{}/{}", *CARGO_TARGET_DIR, TEST_BINARY))
|
|
.args(&args)
|
|
.status()
|
|
.expect("failed to execute process");
|
|
assert!(status.success());
|
|
// Create a new set of test on chain data only for the on-chain input source
|
|
if input_source != "file" || output_source != "file" {
|
|
let status = Command::new(format!("{}/{}", *CARGO_TARGET_DIR, TEST_BINARY))
|
|
.args([
|
|
"setup-test-evm-data",
|
|
"-D",
|
|
data_path.as_str(),
|
|
"-M",
|
|
&model_path,
|
|
"--test-data",
|
|
test_on_chain_data_path.as_str(),
|
|
rpc_arg.as_str(),
|
|
test_input_source.as_str(),
|
|
test_output_source.as_str(),
|
|
])
|
|
.status()
|
|
.expect("failed to execute process");
|
|
|
|
assert!(status.success());
|
|
|
|
let deployed_addr_arg = format!("--addr={}", addr_da);
|
|
|
|
let args: Vec<&str> = vec![
|
|
"test-update-account-calls",
|
|
deployed_addr_arg.as_str(),
|
|
"-D",
|
|
test_on_chain_data_path.as_str(),
|
|
rpc_arg.as_str(),
|
|
];
|
|
let status = Command::new(format!("{}/{}", *CARGO_TARGET_DIR, TEST_BINARY))
|
|
.args(&args)
|
|
.status()
|
|
.expect("failed to execute process");
|
|
|
|
assert!(status.success());
|
|
}
|
|
// As sanity check, add example that should fail.
|
|
let args = vec![
|
|
"verify-evm",
|
|
"--proof-path",
|
|
PF_FAILURE,
|
|
deployed_addr_verifier_arg.as_str(),
|
|
deployed_addr_da_arg.as_str(),
|
|
rpc_arg.as_str(),
|
|
];
|
|
let status = Command::new(format!("{}/{}", *CARGO_TARGET_DIR, TEST_BINARY))
|
|
.args(args)
|
|
.status()
|
|
.expect("failed to execute process");
|
|
assert!(!status.success());
|
|
}
|
|
|
|
fn build_ezkl() {
|
|
#[cfg(feature = "icicle")]
|
|
let args = [
|
|
"build",
|
|
"--profile=test-runs",
|
|
"--bin",
|
|
"ezkl",
|
|
"--features",
|
|
"icicle",
|
|
];
|
|
#[cfg(feature = "macos-metal")]
|
|
let args = [
|
|
"build",
|
|
"--profile=test-runs",
|
|
"--bin",
|
|
"ezkl",
|
|
"--features",
|
|
"macos-metal",
|
|
];
|
|
// not macos-metal and not icicle
|
|
#[cfg(all(not(feature = "icicle"), not(feature = "macos-metal")))]
|
|
let args = ["build", "--profile=test-runs", "--bin", "ezkl"];
|
|
#[cfg(not(feature = "mv-lookup"))]
|
|
let args = [
|
|
"build",
|
|
"--profile=test-runs",
|
|
"--bin",
|
|
"ezkl",
|
|
"--no-default-features",
|
|
"--features",
|
|
"ezkl",
|
|
];
|
|
|
|
let status = Command::new("cargo")
|
|
.args(args)
|
|
.status()
|
|
.expect("failed to execute process");
|
|
assert!(status.success());
|
|
}
|
|
|
|
#[allow(dead_code)]
|
|
fn build_wasm_ezkl() {
|
|
// wasm-pack build --target nodejs --out-dir ./tests/wasm/nodejs . -- -Z build-std="panic_abort,std"
|
|
let status = Command::new("wasm-pack")
|
|
.args([
|
|
"build",
|
|
"--profile=test-runs",
|
|
"--target",
|
|
"nodejs",
|
|
"--out-dir",
|
|
"./tests/wasm/nodejs",
|
|
".",
|
|
"--",
|
|
"-Z",
|
|
"build-std=panic_abort,std",
|
|
])
|
|
.status()
|
|
.expect("failed to execute process");
|
|
assert!(status.success());
|
|
// fix the memory size
|
|
// sed -i "3s|.*|imports['env'] = {memory: new WebAssembly.Memory({initial:20,maximum:65536,shared:true})}|" tests/wasm/nodejs/ezkl.js
|
|
let status = Command::new("sed")
|
|
.args([
|
|
"-i",
|
|
// is required on macos
|
|
// "\".js\"",
|
|
"3s|.*|imports['env'] = {memory: new WebAssembly.Memory({initial:20,maximum:65536,shared:true})}|",
|
|
"./tests/wasm/nodejs/ezkl.js",
|
|
])
|
|
.status()
|
|
.expect("failed to execute process");
|
|
assert!(status.success());
|
|
}
|
|
}
|