diff --git a/.gitignore b/.gitignore index d808a4d..31d74ba 100644 --- a/.gitignore +++ b/.gitignore @@ -11,5 +11,6 @@ my_permanent_leveldb/ *level_db*/ *.json *DS_Store -*tar +*.tar /release/ +*.zip diff --git a/README.md b/README.md index 7f62f84..1ceb35c 100644 --- a/README.md +++ b/README.md @@ -22,8 +22,8 @@ file_num=10 per_file_account_num=131072 # multiple of 1024, the batch size # test data will be generated to ./test-data/user-data -rm -rf ./text-data/user-data -mkdir -p ./text-data/user-data +rm -rf ./test-data/user-data +mkdir -p ./test-data/user-data python3 scripts/gen_test_data.py ${file_num} ${per_file_account_num} ``` @@ -64,7 +64,7 @@ cargo run --features zk-por-core/verifier --release --package zk-por-cli --bin z - verify both the global proof and a user proof Note: -1. The cmd will NOT rebuild the circuit. Instead, it directly uses and trusts the circuit in the proof file. So the verification is fast, but not as secure as above. +1. The cmd will NOT rebuild the circuit. Instead, it directly uses and trusts the circuit in the proof file. So the verification is fast, but a user needs to incur a weaker trust assumption. 2. The cmd will auto-detect sum_proof_data.json and *_inclusion_proof.json in the same directory of the binary for the verification. ``` @@ -77,9 +77,9 @@ cp $global_proof_path tmp/sum_proof_data.json rm -rf tmp ``` -- print circuit verifier data +- print commit hash ``` -cargo run --release --package zk-por-cli --bin zk-por-cli print-root-circuit-verifier --proof-path ${global_proof_path} +cargo run --release --package zk-por-cli --bin zk-por-cli show-commit-hash ``` ## cli tool diff --git a/crates/zk-por-cli/src/main.rs b/crates/zk-por-cli/src/main.rs index 74414f5..de4b81c 100644 --- a/crates/zk-por-cli/src/main.rs +++ b/crates/zk-por-cli/src/main.rs @@ -9,7 +9,7 @@ use zk_por_cli::{ checker::check_non_neg_user, constant::{DEFAULT_USER_PROOF_FILE_PATTERN, GLOBAL_PROOF_FILENAME}, prover::prove, - verifier::{print_circuit_verifier_hex, verify_global, verify_user}, + verifier::{verify_global, verify_user}, }; use zk_por_core::error::PoRError; @@ -36,10 +36,6 @@ pub enum ZkPorCommands { #[arg(short, long)] cfg_path: String, // path to config file }, - PrintRootCircuitVerifier { - #[arg(short, long)] - proof_path: String, - }, VerifyGlobal { #[arg(short, long)] @@ -74,11 +70,6 @@ impl Execute for Option { check_non_neg_user(prover_cfg) } - Some(ZkPorCommands::PrintRootCircuitVerifier { proof_path }) => { - let global_proof_path = PathBuf::from_str(&proof_path).unwrap(); - print_circuit_verifier_hex(global_proof_path) - } - Some(ZkPorCommands::VerifyGlobal { proof_path: global_proof_path }) => { let global_proof_path = PathBuf::from_str(&global_proof_path).unwrap(); verify_global(global_proof_path, true, true) @@ -135,13 +126,15 @@ impl Execute for Option { fn main() { let cli = Cli::parse(); + let start = std::time::Instant::now(); let r = cli.command.execute(); + let duration = start.elapsed(); + println!("Execution result: {:?}, duration: {:?}", r, duration); + let is_prove_command = matches!(cli.command, Some(ZkPorCommands::Prove { cfg_path: _, output_path: _ })); - if is_prove_command { - println!("Execution result: {:?}", r); - } else { - println!("Execution result: {:?}. Press Enter to quit...", r); + if !is_prove_command { + println!("Press Enter to quit..."); stdin().read_exact(&mut [0]).unwrap(); } } diff --git a/crates/zk-por-cli/src/prover.rs b/crates/zk-por-cli/src/prover.rs index 06314f3..c6be474 100644 --- a/crates/zk-por-cli/src/prover.rs +++ b/crates/zk-por-cli/src/prover.rs @@ -3,7 +3,7 @@ use super::constant::{ USER_PROOF_DIRNAME, }; use indicatif::ProgressBar; -use plonky2::hash::hash_types::HashOut; +use plonky2::{hash::hash_types::HashOut, util::serialization::DefaultGateSerializer}; use plonky2_field::types::PrimeField64; use rayon::{iter::ParallelIterator, prelude::*}; @@ -30,7 +30,7 @@ use zk_por_core::{ parser::{AccountParser, FileAccountReader, FileManager, FilesCfg}, recursive_prover::recursive_circuit::RecursiveTargets, types::F, - CircuitConfigs, General, Info, Proof, + CircuitsInfo, General, Info, Proof, }; use zk_por_tracing::{init_tracing, TraceConfig}; @@ -317,6 +317,13 @@ pub fn prove(cfg: ProverConfig, proof_output_path: PathBuf) -> Result<(), PoRErr let root_vd_digest = circuit_registry.get_root_circuit().verifier_only.circuit_digest; + let root_circuit_verifier_data = circuit_registry.get_root_circuit().verifier_data(); + + let root_circuit_verifier_data_bytes = root_circuit_verifier_data + .to_bytes(&DefaultGateSerializer) + .expect("fail to serialize root circuit verifier data"); + let root_circuit_verifier_data_hex_str = hex::encode(root_circuit_verifier_data_bytes); + let proof = Proof { general: General { round_num: cfg.prover.round_no, @@ -324,11 +331,12 @@ pub fn prove(cfg: ProverConfig, proof_output_path: PathBuf) -> Result<(), PoRErr batch_size: batch_size, token_num: token_num, }, - root_vd_digest: root_vd_digest, - circuit_configs: Some(CircuitConfigs { + circuits_info: Some(CircuitsInfo { batch_circuit_config: batch_circuit_config, recursive_circuit_configs: recursive_circuit_configs, + root_verifier_data_hex: root_circuit_verifier_data_hex_str, }), + root_vd_digest: root_vd_digest, proof: root_proof, }; diff --git a/crates/zk-por-cli/src/verifier.rs b/crates/zk-por-cli/src/verifier.rs index f843bc5..806b909 100644 --- a/crates/zk-por-cli/src/verifier.rs +++ b/crates/zk-por-cli/src/verifier.rs @@ -8,22 +8,24 @@ use std::{fs::File, path::PathBuf}; use super::constant::RECURSION_BRANCHOUT_NUM; use zk_por_core::{ circuit_config::{STANDARD_CONFIG, STANDARD_ZK_CONFIG}, - circuit_registry::{precompiled_registry::get_verifier_for_round, registry::CircuitRegistry}, + circuit_registry::registry::CircuitRegistry, error::PoRError, merkle_proof::MerkleProof, recursive_prover::recursive_circuit::RecursiveTargets, - types::F, + types::{C, D, F}, Proof, }; -use plonky2::hash::hash_types::HashOut; +use plonky2::{hash::hash_types::HashOut, plonk::circuit_data::VerifierCircuitData}; use rayon::iter::ParallelIterator; use glob::glob; use std::io; -// some proof files may not contain the circuit_configs field, we hardcode the default config in this case. -fn default_circuit_configs() -> (CircuitConfig, Vec) { +static ROOT_CIRCUIT_HEX_FOR_508787475: &str = "0100000000000000e3370d1646daebec7fa045ddf1cc918706777cb88875ea173623eff57b773bc68f62cdf279612bd8c095eb7bad5feaf5209df02981e0b88ef5b178862e00694ba296ce1215562eabcac32a3b9a5aae1dcf6422a739a392ffc1b87f102bdf523d8700000000000000500000000000000002000000000000006400000000000000020000000000000008000000000000000101030000000000000001000000000000001c00000000000000100000000104000000000000000500000000000000030000000000000001000000000000001c00000000000000100000000104000000000000000500000000000000040000000000000004000000000000000400000000000000040000000000000004000000000000001300000000000000010e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000001000000000000000100000000000000010000000000000001000000000000000200000000000000020000000000000003000000000000000000000000000000070000000000000007000000000000000c000000000000000c000000000000000e0000000000000008000000000000007b0000000000000005000000000000000600000000000000500000000000000001000000000000000700000000000000310000000000000057010000000000006109000000000000a74100000000000091cb010000000000f7900c0000000000c1f657000000000047bf670200000000f13ad61000000000979cdb75000000002148013903000000e7f8088f1600000051ce3ee99d00000037a4b76051040000817d05a5391e0000876e268393d30000b1050d9608c90500d7275b1a3c7f2800e1167eb8a47a1b0127a0720b815ac007116122508779423676a7f030b452d17b37949456f042b9627f0d105e94d410b3755e709212d075e52d95120188b038463a148207b9d38ceb908d8e3415cad970eddee56f9786f4157b18490f24aeaf9959abff6a00c3cd336eaffdec0355a06a00ccef7a1d5362eafa938e5cd445b068d40be687d0e8d1dcc6524ab7b95dbd096a43080314902d44e5d739158df03edd3de79494e193b80cab5212102b0b0c59ab4280702f4e546faad281134f234e0ba6c28c8829f7224f8852d9bb24c2f429b741f122024fb12500cc98f40f29d90700942db06f1ff036ff0b3fd10edc9080f653b9b86a04f683b74b110dee1eba9bfd11795b86d81642ea7d4f80adeb9fce61712c82c3715fa6a319378f5c1c9c8c72b381ea8ac644d819e88b69d16de1e9a958d3e2bf002a659d6cc733410526c446f8736acd240a5de8c92be99f01478b55853260620bf1ce4ea561a1b54f97a81e85ab69fb2d239ccea3b0e3e341f644a17ad4393ccdbbe2615acf94ab9c2233a678ab11b248f265884cb07be0fc9fc9b317d26128ea5f83e2a5beac1d679f972a8936b9d3d15b2525c07d10cbbc8205034170738d29932614c71128df22060e8c717c181af42a62d21a67abb8ac2cafbabbd1af10b938ca1122bcce790f8d8709000000000000000e00000000000000090000000b0000000c000000020000003f000000000000000400000004000000000000000e0000000100000000000000140000000000000000000000000000000f0000002000000000000000100000002b00000000000000010000000a00000000000000000000001400000000000000080000000d000000000000000500000042000000000000000e0000000400000000000000040000000000000002000000000000000d000000"; + +// The proof file at round 508787475 on Sept 16th 2024 does not contain the circuit_infos, we hardcode in this case. +fn circuit_configs_for_508787475() -> (CircuitConfig, Vec) { (STANDARD_CONFIG, vec![STANDARD_CONFIG, STANDARD_CONFIG, STANDARD_ZK_CONFIG]) } @@ -116,14 +118,37 @@ pub fn verify_global( let proof_file = File::open(&global_proof_path).unwrap(); let reader = std::io::BufReader::new(proof_file); - // Parse the JSON as Proof let proof: Proof = from_reader(reader).unwrap(); if proof.general.recursion_branchout_num != RECURSION_BRANCHOUT_NUM { panic!("The recursion_branchout_num is not configured to be equal to 64"); } let round_num = proof.general.round_num; - let root_circuit_verifier_data = get_verifier_for_round(round_num); + let root_verifier_data_hex: String; + let (mut batch_circuit_config, mut recursive_circuit_configs) = + (CircuitConfig::default(), vec![]); + (_, _) = (batch_circuit_config, recursive_circuit_configs); // To quell the compiler, i.e., circuit configs are useless if not rebuilding the circuit. + + if let Some(circuits_info) = proof.circuits_info { + (batch_circuit_config, recursive_circuit_configs) = + (circuits_info.batch_circuit_config, circuits_info.recursive_circuit_configs); + root_verifier_data_hex = circuits_info.root_verifier_data_hex; + // only round number 508787475 does not contain the circuit_infos field, we hardcode in this case. + } else if round_num == 508787475 { + (batch_circuit_config, recursive_circuit_configs) = circuit_configs_for_508787475(); + root_verifier_data_hex = ROOT_CIRCUIT_HEX_FOR_508787475.to_string(); + } else { + return Err(PoRError::InvalidProof); + } + + let root_circuit_verifier_data_bytes = hex::decode(root_verifier_data_hex) + .expect("fail to decode root circuit verifier data hex string"); + + let root_circuit_verifier_data = VerifierCircuitData::::from_bytes( + root_circuit_verifier_data_bytes, + &DefaultGateSerializer, + ) + .expect("fail to parse root circuit verifier data"); let round_num = proof.general.round_num; if check_circuit { @@ -131,14 +156,6 @@ pub fn verify_global( let round_num = proof.general.round_num; let batch_size = proof.general.batch_size; - // There are cases that the proof file does not contain the circuit_configs field, we hardcode the default config in this case. - let (mut batch_circuit_config, mut recursive_circuit_configs) = default_circuit_configs(); - - if let Some(circuit_configs) = &proof.circuit_configs { - recursive_circuit_configs = circuit_configs.recursive_circuit_configs.clone(); - batch_circuit_config = circuit_configs.batch_circuit_config.clone(); - } - if verbose { println!( "start to reconstruct the circuit with {} recursive levels for round {}", @@ -192,44 +209,3 @@ pub fn verify_global( result.map_err(|_| PoRError::InvalidProof) } - -pub fn print_circuit_verifier_hex(global_proof_path: PathBuf) -> Result<(), PoRError> { - let proof_file = File::open(&global_proof_path).unwrap(); - let reader = std::io::BufReader::new(proof_file); - let proof: Proof = from_reader(reader).unwrap(); - - if proof.general.recursion_branchout_num != RECURSION_BRANCHOUT_NUM { - panic!("The recursion_branchout_num is not configured to be equal to 64"); - } - let token_num = proof.general.token_num; - let batch_size = proof.general.batch_size; - - let (mut batch_circuit_config, mut recursive_circuit_configs) = default_circuit_configs(); - - if let Some(circuit_configs) = &proof.circuit_configs { - recursive_circuit_configs = circuit_configs.recursive_circuit_configs.clone(); - batch_circuit_config = circuit_configs.batch_circuit_config.clone(); - } - - let circuit_registry = CircuitRegistry::::init( - batch_size, - token_num, - batch_circuit_config, - recursive_circuit_configs, - ); - - let root_circuit = circuit_registry.get_root_circuit(); - - let verifier_data = root_circuit.verifier_data().clone(); - - let gate_serializer = DefaultGateSerializer; - let verifier_data_bytes = verifier_data.to_bytes(&gate_serializer).unwrap(); - - if proof.root_vd_digest != verifier_data.verifier_only.circuit_digest { - return Err(PoRError::CircuitMismatch); - } - - println!("{}", hex::encode(verifier_data_bytes)); - - Ok(()) -} diff --git a/crates/zk-por-core/src/circuit_registry/mod.rs b/crates/zk-por-core/src/circuit_registry/mod.rs index 4880ba5..d108990 100644 --- a/crates/zk-por-core/src/circuit_registry/mod.rs +++ b/crates/zk-por-core/src/circuit_registry/mod.rs @@ -1,2 +1 @@ -pub mod precompiled_registry; pub mod registry; diff --git a/crates/zk-por-core/src/circuit_registry/precompiled_registry.rs b/crates/zk-por-core/src/circuit_registry/precompiled_registry.rs deleted file mode 100644 index 2cfc6c8..0000000 --- a/crates/zk-por-core/src/circuit_registry/precompiled_registry.rs +++ /dev/null @@ -1,85 +0,0 @@ -use crate::types::{C, D, F}; -use core::panic; -use once_cell::sync::Lazy; -use plonky2::{ - plonk::circuit_data::VerifierCircuitData, util::serialization::DefaultGateSerializer, -}; -use std::collections::{BTreeSet, HashMap, HashSet}; - -// Refer to README on how to generate the hex string for the root circuit. -static LATEST_ROOT_CIRCUIT_HEX: &str = "0100000000000000e3370d1646daebec7fa045ddf1cc918706777cb88875ea173623eff57b773bc68f62cdf279612bd8c095eb7bad5feaf5209df02981e0b88ef5b178862e00694ba296ce1215562eabcac32a3b9a5aae1dcf6422a739a392ffc1b87f102bdf523d8700000000000000500000000000000002000000000000006400000000000000020000000000000008000000000000000101030000000000000001000000000000001c00000000000000100000000104000000000000000500000000000000030000000000000001000000000000001c00000000000000100000000104000000000000000500000000000000040000000000000004000000000000000400000000000000040000000000000004000000000000001300000000000000010e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000001000000000000000100000000000000010000000000000001000000000000000200000000000000020000000000000003000000000000000000000000000000070000000000000007000000000000000c000000000000000c000000000000000e0000000000000008000000000000007b0000000000000005000000000000000600000000000000500000000000000001000000000000000700000000000000310000000000000057010000000000006109000000000000a74100000000000091cb010000000000f7900c0000000000c1f657000000000047bf670200000000f13ad61000000000979cdb75000000002148013903000000e7f8088f1600000051ce3ee99d00000037a4b76051040000817d05a5391e0000876e268393d30000b1050d9608c90500d7275b1a3c7f2800e1167eb8a47a1b0127a0720b815ac007116122508779423676a7f030b452d17b37949456f042b9627f0d105e94d410b3755e709212d075e52d95120188b038463a148207b9d38ceb908d8e3415cad970eddee56f9786f4157b18490f24aeaf9959abff6a00c3cd336eaffdec0355a06a00ccef7a1d5362eafa938e5cd445b068d40be687d0e8d1dcc6524ab7b95dbd096a43080314902d44e5d739158df03edd3de79494e193b80cab5212102b0b0c59ab4280702f4e546faad281134f234e0ba6c28c8829f7224f8852d9bb24c2f429b741f122024fb12500cc98f40f29d90700942db06f1ff036ff0b3fd10edc9080f653b9b86a04f683b74b110dee1eba9bfd11795b86d81642ea7d4f80adeb9fce61712c82c3715fa6a319378f5c1c9c8c72b381ea8ac644d819e88b69d16de1e9a958d3e2bf002a659d6cc733410526c446f8736acd240a5de8c92be99f01478b55853260620bf1ce4ea561a1b54f97a81e85ab69fb2d239ccea3b0e3e341f644a17ad4393ccdbbe2615acf94ab9c2233a678ab11b248f265884cb07be0fc9fc9b317d26128ea5f83e2a5beac1d679f972a8936b9d3d15b2525c07d10cbbc8205034170738d29932614c71128df22060e8c717c181af42a62d21a67abb8ac2cafbabbd1af10b938ca1122bcce790f8d8709000000000000000e00000000000000090000000b0000000c000000020000003f000000000000000400000004000000000000000e0000000100000000000000140000000000000000000000000000000f0000002000000000000000100000002b00000000000000010000000a00000000000000000000001400000000000000080000000d000000000000000500000042000000000000000e0000000400000000000000040000000000000002000000000000000d000000"; - -// key: a number of round numbers, value: the hex string of the root circuit verifier data. -static PREV_ROOT_CIRCUITS_HEX: Lazy, String>> = Lazy::new(|| { - let ret: HashMap, String> = HashMap::new(); - // later add previous root circuits here. - - // check no duplicates of round numbers in the keys - let mut existing_round_nums = HashSet::new(); - ret.iter().for_each(|(circuit_round_nums, _)| { - circuit_round_nums.iter().for_each(|&round_num| { - if existing_round_nums.contains(&round_num) { - panic!("duplicate round number found in the keys of PREV_ROOT_CIRCUITS_HEX"); - } - existing_round_nums.insert(round_num); - }); - }); - ret -}); - -pub fn get_verifier_for_round(round_num: usize) -> VerifierCircuitData { - let circuit_hex = - get_circuit_hex_str(LATEST_ROOT_CIRCUIT_HEX, &PREV_ROOT_CIRCUITS_HEX, round_num); - let root_circuit_verifier_data_bytes = hex::decode(circuit_hex).expect( - format!("fail to decode root circuit verifier data hex string for round {}", round_num) - .as_str(), - ); - - let root_circuit_verifier_data = VerifierCircuitData::::from_bytes( - root_circuit_verifier_data_bytes, - &DefaultGateSerializer, - ) - .expect(format!("fail to parse root circuit verifier data for round {}", round_num).as_str()); - - root_circuit_verifier_data -} - -fn get_circuit_hex_str( - latest_circuit_hex: &str, - prev_circuits_hex: &HashMap, String>, - round_num: usize, -) -> String { - let mut circuit_hex = latest_circuit_hex.to_owned(); - if let Some(prev_circuit_hex) = - (prev_circuits_hex.iter().find(|(k, _)| k.contains(&round_num))).map(|(_, v)| v) - { - tracing::info!("found previous circuit for round {}", round_num); - circuit_hex = prev_circuit_hex.clone(); - } - circuit_hex -} - -#[cfg(test)] -mod tests { - use super::*; - use std::collections::{BTreeSet, HashMap}; - - #[test] - fn test_get_circuit_hex_str_with_prev_circuit() { - let latest_circuit_hex = "latest_hex"; - let mut prev_circuits_hex = HashMap::new(); - - let round_num = 1; - let result = get_circuit_hex_str(latest_circuit_hex, &prev_circuits_hex, round_num); - - assert_eq!(result, latest_circuit_hex); - - let mut round_set = BTreeSet::new(); - round_set.insert(round_num); - prev_circuits_hex.insert(round_set, "prev_hex_for_round_1".to_string()); - - let result = get_circuit_hex_str(latest_circuit_hex, &prev_circuits_hex, round_num); - - assert_eq!(result, "prev_hex_for_round_1"); - } -} diff --git a/crates/zk-por-core/src/lib.rs b/crates/zk-por-core/src/lib.rs index 7ef180c..5ea0235 100644 --- a/crates/zk-por-core/src/lib.rs +++ b/crates/zk-por-core/src/lib.rs @@ -35,14 +35,15 @@ pub struct Proof { pub general: General, pub root_vd_digest: HashOut, #[serde(default)] // some proof files may not have this field. - pub circuit_configs: Option, + pub circuits_info: Option, pub proof: ProofWithPublicInputs, } #[derive(Serialize, Deserialize)] -pub struct CircuitConfigs { +pub struct CircuitsInfo { pub batch_circuit_config: CircuitConfig, pub recursive_circuit_configs: Vec, + pub root_verifier_data_hex: String, } #[derive(Serialize, Deserialize)] diff --git a/scripts/release/verifier/common.sh b/scripts/release/verifier/common.sh index a436b27..5e5769e 100755 --- a/scripts/release/verifier/common.sh +++ b/scripts/release/verifier/common.sh @@ -1,5 +1,4 @@ function build_and_package() { - mkdir -p validator/bin TARGET=$1 rustup target add $TARGET VERSION=$2 @@ -19,6 +18,5 @@ function build_and_package() { zip ./zk_STARK_Validator_V2_${TARGET}_${VERSION}.zip ./zk_STARK_Validator_V2_${TARGET}_${VERSION} rm ./zk_STARK_Validator_V2_${TARGET}_${VERSION} - mv ./zk_STARK_Validator_V2_${TARGET}_${VERSION}.zip validator/bin unset COMMIT_HASH } \ No newline at end of file