diff --git a/common/libzkp/e2e-test.sh b/common/libzkp/e2e-test.sh index 2ba3d88460..a46a979f53 100644 --- a/common/libzkp/e2e-test.sh +++ b/common/libzkp/e2e-test.sh @@ -7,7 +7,7 @@ export RUST_LOG=debug export RUST_MIN_STACK=100000000 export PROVER_OUTPUT_DIR=test_zkp_test export SCROLL_PROVER_ASSETS_DIR=/assets/test_assets -export EDISON_TEST_DIR=/assets +export DARWIN_V2_TEST_DIR=/assets #export LD_LIBRARY_PATH=/:/usr/local/cuda/lib64 mkdir -p $PROVER_OUTPUT_DIR @@ -26,5 +26,5 @@ function build_test_bins() { build_test_bins rm -rf $PROVER_OUTPUT_DIR/* #rm -rf prover.log verifier.log -$REPO/prover/prover.test --exact zk_circuits_handler::edison::tests::test_circuits 2>&1 | tee prover.log +$REPO/prover/prover.test --exact zk_circuits_handler::darwin_v2::tests::test_circuits 2>&1 | tee prover.log $REPO/coordinator/verifier.test -test.v 2>&1 | tee verifier.log diff --git a/common/libzkp/impl/Cargo.lock b/common/libzkp/impl/Cargo.lock index caae228080..2df231e2b5 100644 --- a/common/libzkp/impl/Cargo.lock +++ b/common/libzkp/impl/Cargo.lock @@ -171,9 +171,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.72" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b13c32d80ecc7ab747b80c3784bce54ee8a7a0cc4fbda9bf4cda2cf6fe90854" +checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" [[package]] name = "arc-swap" @@ -4628,6 +4628,7 @@ dependencies = [ name = "zkp" version = "0.1.0" dependencies = [ + "anyhow", "base64 0.13.1", "env_logger 0.9.3", "halo2_proofs", diff --git a/common/libzkp/impl/Cargo.toml b/common/libzkp/impl/Cargo.toml index 8927f41cbf..6d4447bb54 100644 --- a/common/libzkp/impl/Cargo.toml +++ b/common/libzkp/impl/Cargo.toml @@ -26,7 +26,7 @@ snark-verifier-sdk = { git = "https://github.com/scroll-tech/snark-verifier", br # darwin prover_v4 = { git = "https://github.com/scroll-tech/zkevm-circuits.git", tag = "v0.12.0", package = "prover", default-features = false, features = ["parallel_syn", "scroll"] } -# edison +# darwin_v2 prover_v5 = { git = "https://github.com/scroll-tech/zkevm-circuits.git", tag = "v0.13.0", package = "prover", default-features = false, features = ["parallel_syn", "scroll"] } base64 = "0.13.0" @@ -37,6 +37,7 @@ once_cell = "1.19" serde = "1.0" serde_derive = "1.0" serde_json = "1.0.66" +anyhow = "1.0.86" [profile.test] opt-level = 3 diff --git a/common/libzkp/impl/src/batch.rs b/common/libzkp/impl/src/batch.rs deleted file mode 100644 index 61d248fb89..0000000000 --- a/common/libzkp/impl/src/batch.rs +++ /dev/null @@ -1,64 +0,0 @@ -use crate::utils::{c_char_to_str, c_char_to_vec, panic_catch}; -use libc::c_char; -use prover_v4::BatchProof as BatchProofLoVersion; -use prover_v5::{ - aggregator::Verifier as VerifierHiVersion, utils::init_env_and_log, - BatchProof as BatchProofHiVersion, BundleProof, -}; -use snark_verifier_sdk::verify_evm_calldata; -use std::{cell::OnceCell, env}; - -static mut VERIFIER: OnceCell = OnceCell::new(); - -/// # Safety -#[no_mangle] -pub unsafe extern "C" fn init_batch_verifier(params_dir: *const c_char, assets_dir: *const c_char) { - init_env_and_log("ffi_batch_verify"); - - let params_dir = c_char_to_str(params_dir); - let assets_dir = c_char_to_str(assets_dir); - - // TODO: add a settings in scroll-prover. - env::set_var("SCROLL_PROVER_ASSETS_DIR", assets_dir); - let verifier_hi = VerifierHiVersion::from_dirs(params_dir, assets_dir); - - VERIFIER.set(verifier_hi).unwrap(); -} - -/// # Safety -#[no_mangle] -pub unsafe extern "C" fn verify_batch_proof( - proof: *const c_char, - fork_name: *const c_char, -) -> c_char { - let proof = c_char_to_vec(proof); - let fork_name_str = c_char_to_str(fork_name); - let fork_id = match fork_name_str { - "darwin" => 4, - "edison" => 5, - _ => { - log::warn!("unexpected fork_name {fork_name_str}, treated as edison"); - 5 - } - }; - let verified = panic_catch(|| { - if fork_id == 4 { - unimplemented!("todo"); - } else { - // Post upgrade #4 (Darwin), batch proofs are not EVM-verifiable. Instead they are - // halo2 proofs meant to be bundled recursively. - let proof = serde_json::from_slice::(proof.as_slice()).unwrap(); - VERIFIER.get().unwrap().verify_batch_proof(&proof) - } - }); - verified.unwrap_or(false) as c_char -} - -/// # Safety -#[no_mangle] -pub unsafe extern "C" fn verify_bundle_proof(proof: *const c_char) -> c_char { - let proof = c_char_to_vec(proof); - let proof = serde_json::from_slice::(proof.as_slice()).unwrap(); - let verified = panic_catch(|| VERIFIER.get().unwrap().verify_bundle_proof(proof)); - verified.unwrap_or(false) as c_char -} diff --git a/common/libzkp/impl/src/chunk.rs b/common/libzkp/impl/src/chunk.rs deleted file mode 100644 index cb781f3898..0000000000 --- a/common/libzkp/impl/src/chunk.rs +++ /dev/null @@ -1,63 +0,0 @@ -use crate::utils::{c_char_to_str, c_char_to_vec, panic_catch}; -use libc::c_char; -use prover_v4::{zkevm::Verifier as VerifierLoVersion, ChunkProof as ChunkProofLoVersion}; -use prover_v5::{ - utils::init_env_and_log, zkevm::Verifier as VerifierHiVersion, - ChunkProof as ChunkProofHiVersion, -}; -use std::{cell::OnceCell, env}; - -static mut VERIFIER_LO_VERSION: OnceCell = OnceCell::new(); -static mut VERIFIER_HI_VERSION: OnceCell = OnceCell::new(); - -/// # Safety -#[no_mangle] -pub unsafe extern "C" fn init_chunk_verifier( - params_dir: *const c_char, - v4_assets_dir: *const c_char, - v5_assets_dir: *const c_char, -) { - init_env_and_log("ffi_chunk_verify"); - - let params_dir = c_char_to_str(params_dir); - let v4_assets_dir = c_char_to_str(v4_assets_dir); - let v5_assets_dir = c_char_to_str(v5_assets_dir); - - // TODO: add a settings in scroll-prover. - env::set_var("SCROLL_PROVER_ASSETS_DIR", v4_assets_dir); - let verifier_lo = VerifierLoVersion::from_dirs(params_dir, v4_assets_dir); - env::set_var("SCROLL_PROVER_ASSETS_DIR", v5_assets_dir); - let verifier_hi = VerifierHiVersion::from_dirs(params_dir, v5_assets_dir); - - VERIFIER_LO_VERSION.set(verifier_lo).unwrap(); - VERIFIER_HI_VERSION.set(verifier_hi).unwrap(); -} - -/// # Safety -#[no_mangle] -pub unsafe extern "C" fn verify_chunk_proof( - proof: *const c_char, - fork_name: *const c_char, -) -> c_char { - let proof = c_char_to_vec(proof); - - let fork_name_str = c_char_to_str(fork_name); - let fork_id = match fork_name_str { - "darwin" => 4, - "edison" => 5, - _ => { - log::warn!("unexpected fork_name {fork_name_str}, treated as edison"); - 5 - } - }; - let verified = panic_catch(|| { - if fork_id == 4 { - let proof = serde_json::from_slice::(proof.as_slice()).unwrap(); - VERIFIER_LO_VERSION.get().unwrap().verify_chunk_proof(proof) - } else { - let proof = serde_json::from_slice::(proof.as_slice()).unwrap(); - VERIFIER_HI_VERSION.get().unwrap().verify_chunk_proof(proof) - } - }); - verified.unwrap_or(false) as c_char -} diff --git a/common/libzkp/impl/src/lib.rs b/common/libzkp/impl/src/lib.rs index 674b696b90..b15857d5a9 100644 --- a/common/libzkp/impl/src/lib.rs +++ b/common/libzkp/impl/src/lib.rs @@ -1,4 +1,63 @@ -mod batch; -mod chunk; -mod types; mod utils; +mod verifier; + +use crate::utils::{c_char_to_str, c_char_to_vec}; +use libc::c_char; +use prover_v5::utils::init_env_and_log; +use verifier::{TaskType, VerifierConfig}; + +/// # Safety +#[no_mangle] +pub unsafe extern "C" fn init(config: *const c_char) { + init_env_and_log("ffi_init"); + + let config_str = c_char_to_str(config); + let verifier_config = serde_json::from_str::(config_str).unwrap(); + verifier::init(verifier_config); +} + +/// # Safety +#[no_mangle] +pub unsafe extern "C" fn verify_chunk_proof( + proof: *const c_char, + fork_name: *const c_char, +) -> c_char { + verify_proof(proof, fork_name, TaskType::Chunk) +} + +fn verify_proof(proof: *const c_char, fork_name: *const c_char, task_type: TaskType) -> c_char { + let proof = c_char_to_vec(proof); + + let fork_name_str = c_char_to_str(fork_name); + let verifier = verifier::get_verifier(fork_name_str); + + if let Err(e) = verifier { + log::warn!("failed to get verifier, error: {:#}", e); + return 0 as c_char; + } + match verifier.unwrap().verify(task_type, proof) { + Err(e) => { + log::error!("{:?} verify failed, error: {:#}", task_type, e); + false as c_char + } + Ok(result) => result as c_char, + } +} + +/// # Safety +#[no_mangle] +pub unsafe extern "C" fn verify_batch_proof( + proof: *const c_char, + fork_name: *const c_char, +) -> c_char { + verify_proof(proof, fork_name, TaskType::Batch) +} + +/// # Safety +#[no_mangle] +pub unsafe extern "C" fn verify_bundle_proof( + proof: *const c_char, + fork_name: *const c_char, +) -> c_char { + verify_proof(proof, fork_name, TaskType::Bundle) +} diff --git a/common/libzkp/impl/src/types.rs b/common/libzkp/impl/src/types.rs deleted file mode 100644 index 1d066a4282..0000000000 --- a/common/libzkp/impl/src/types.rs +++ /dev/null @@ -1,22 +0,0 @@ -use serde::{Deserialize, Serialize}; - -// Represents the result of a chunk proof checking operation. -// `ok` indicates whether the proof checking was successful. -// `error` provides additional details in case the check failed. -#[derive(Debug, Clone, Deserialize, Serialize)] -pub struct CheckChunkProofsResponse { - pub ok: bool, - #[serde(skip_serializing_if = "Option::is_none")] - pub error: Option, -} - -// Encapsulates the result from generating a proof. -// `message` holds the generated proof in byte slice format. -// `error` provides additional details in case the proof generation failed. -#[derive(Debug, Clone, Deserialize, Serialize)] -pub struct ProofResult { - #[serde(skip_serializing_if = "Option::is_none")] - pub message: Option>, - #[serde(skip_serializing_if = "Option::is_none")] - pub error: Option, -} diff --git a/common/libzkp/impl/src/verifier.rs b/common/libzkp/impl/src/verifier.rs new file mode 100644 index 0000000000..a25e42123b --- /dev/null +++ b/common/libzkp/impl/src/verifier.rs @@ -0,0 +1,80 @@ +mod darwin; +mod darwin_v2; + +use anyhow::{bail, Result}; +use darwin::DarwinVerifier; +use darwin_v2::DarwinV2Verifier; +use serde::{Deserialize, Serialize}; +use std::{cell::OnceCell, rc::Rc}; + +#[derive(Debug, Clone, Copy, PartialEq)] +pub enum TaskType { + Chunk, + Batch, + Bundle, +} + +pub trait ProofVerifier { + fn verify(&self, task_type: TaskType, proof: Vec) -> Result; +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct CircuitConfig { + pub fork_name: String, + pub params_path: String, + pub assets_path: String, +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct VerifierConfig { + pub low_version_circuit: CircuitConfig, + pub high_version_circuit: CircuitConfig, +} + +type HardForkName = String; + +struct VerifierPair(HardForkName, Rc>); + +static mut VERIFIER_HIGH: OnceCell = OnceCell::new(); +static mut VERIFIER_LOW: OnceCell = OnceCell::new(); + +pub fn init(config: VerifierConfig) { + let low_conf = config.low_version_circuit; + let verifier = DarwinVerifier::new(&low_conf.params_path, &low_conf.assets_path); + + unsafe { + VERIFIER_LOW + .set(VerifierPair( + low_conf.fork_name, + Rc::new(Box::new(verifier)), + )) + .unwrap_unchecked(); + } + let high_conf = config.high_version_circuit; + let verifier = DarwinV2Verifier::new(&high_conf.params_path, &high_conf.assets_path); + unsafe { + VERIFIER_HIGH + .set(VerifierPair( + high_conf.fork_name, + Rc::new(Box::new(verifier)), + )) + .unwrap_unchecked(); + } +} + +pub fn get_verifier(fork_name: &str) -> Result>> { + unsafe { + if let Some(verifier) = VERIFIER_LOW.get() { + if verifier.0 == fork_name { + return Ok(verifier.1.clone()); + } + } + + if let Some(verifier) = VERIFIER_HIGH.get() { + if verifier.0 == fork_name { + return Ok(verifier.1.clone()); + } + } + } + bail!("failed to get verifier, key not found, {}", fork_name) +} diff --git a/common/libzkp/impl/src/verifier/darwin.rs b/common/libzkp/impl/src/verifier/darwin.rs new file mode 100644 index 0000000000..9119b9b03d --- /dev/null +++ b/common/libzkp/impl/src/verifier/darwin.rs @@ -0,0 +1,48 @@ +use super::{ProofVerifier, TaskType}; + +use anyhow::Result; + +use crate::utils::panic_catch; +use prover_v4::{ + aggregator::Verifier as AggVerifier, zkevm::Verifier, BatchProof, BundleProof, ChunkProof, +}; +use std::env; + +pub struct DarwinVerifier { + verifier: Verifier, + agg_verifier: AggVerifier, +} + +impl DarwinVerifier { + pub fn new(params_dir: &str, assets_dir: &str) -> Self { + env::set_var("SCROLL_PROVER_ASSETS_DIR", assets_dir); + let verifier = Verifier::from_dirs(params_dir, assets_dir); + + let agg_verifier = AggVerifier::from_dirs(params_dir, assets_dir); + + Self { + verifier, + agg_verifier, + } + } +} + +impl ProofVerifier for DarwinVerifier { + fn verify(&self, task_type: super::TaskType, proof: Vec) -> Result { + let result = panic_catch(|| match task_type { + TaskType::Chunk => { + let proof = serde_json::from_slice::(proof.as_slice()).unwrap(); + self.verifier.verify_chunk_proof(proof) + } + TaskType::Batch => { + let proof = serde_json::from_slice::(proof.as_slice()).unwrap(); + self.agg_verifier.verify_batch_proof(&proof) + } + TaskType::Bundle => { + let proof = serde_json::from_slice::(proof.as_slice()).unwrap(); + self.agg_verifier.verify_bundle_proof(proof) + } + }); + result.map_err(|e| anyhow::anyhow!(e)) + } +} diff --git a/common/libzkp/impl/src/verifier/darwin_v2.rs b/common/libzkp/impl/src/verifier/darwin_v2.rs new file mode 100644 index 0000000000..dadc075890 --- /dev/null +++ b/common/libzkp/impl/src/verifier/darwin_v2.rs @@ -0,0 +1,48 @@ +use super::{ProofVerifier, TaskType}; + +use anyhow::Result; + +use crate::utils::panic_catch; +use prover_v5::{ + aggregator::Verifier as AggVerifier, zkevm::Verifier, BatchProof, BundleProof, ChunkProof, +}; +use std::env; + +pub struct DarwinV2Verifier { + verifier: Verifier, + agg_verifier: AggVerifier, +} + +impl DarwinV2Verifier { + pub fn new(params_dir: &str, assets_dir: &str) -> Self { + env::set_var("SCROLL_PROVER_ASSETS_DIR", assets_dir); + let verifier = Verifier::from_dirs(params_dir, assets_dir); + + let agg_verifier = AggVerifier::from_dirs(params_dir, assets_dir); + + Self { + verifier, + agg_verifier, + } + } +} + +impl ProofVerifier for DarwinV2Verifier { + fn verify(&self, task_type: super::TaskType, proof: Vec) -> Result { + let result = panic_catch(|| match task_type { + TaskType::Chunk => { + let proof = serde_json::from_slice::(proof.as_slice()).unwrap(); + self.verifier.verify_chunk_proof(proof) + } + TaskType::Batch => { + let proof = serde_json::from_slice::(proof.as_slice()).unwrap(); + self.agg_verifier.verify_batch_proof(&proof) + } + TaskType::Bundle => { + let proof = serde_json::from_slice::(proof.as_slice()).unwrap(); + self.agg_verifier.verify_bundle_proof(proof) + } + }); + result.map_err(|e| anyhow::anyhow!(e)) + } +} diff --git a/common/libzkp/interface/libzkp.h b/common/libzkp/interface/libzkp.h index 3b8c359a60..51fee4f2ed 100644 --- a/common/libzkp/interface/libzkp.h +++ b/common/libzkp/interface/libzkp.h @@ -1,11 +1,10 @@ // BatchVerifier is used to: // - Verify a batch proof // - Verify a bundle proof -void init_batch_verifier(char* params_dir, char* assets_dir); +void init(char* config); char verify_batch_proof(char* proof, char* fork_name); -char verify_bundle_proof(char* proof); +char verify_bundle_proof(char* proof, char* fork_name); -void init_chunk_verifier(char* params_dir, char* v3_assets_dir, char* v4_assets_dir); char verify_chunk_proof(char* proof, char* fork_name); diff --git a/coordinator/conf/config.json b/coordinator/conf/config.json index 15ae708f8d..f3abe6c786 100644 --- a/coordinator/conf/config.json +++ b/coordinator/conf/config.json @@ -6,11 +6,17 @@ "batch_collection_time_sec": 180, "chunk_collection_time_sec": 180, "verifier": { - "fork_name": "bernoulli", "mock_mode": true, - "params_path": "", - "assets_path_lo": "", - "assets_path_hi": "" + "low_version_circuit": { + "params_path": "params", + "assets_path": "assets", + "fork_name": "" + }, + "high_version_circuit": { + "params_path": "params", + "assets_path": "assets", + "fork_name": "" + } }, "max_verifier_workers": 4, "min_prover_version": "v1.0.0" diff --git a/coordinator/internal/config/config.go b/coordinator/internal/config/config.go index cbe9ca02d8..60fc481bd7 100644 --- a/coordinator/internal/config/config.go +++ b/coordinator/internal/config/config.go @@ -50,13 +50,18 @@ type Config struct { Auth *Auth `json:"auth"` } +// CircuitConfig circuit items. +type CircuitConfig struct { + ParamsPath string `json:"params_path"` + AssetsPath string `json:"assets_path"` + ForkName string `json:"fork_name"` +} + // VerifierConfig load zk verifier config. type VerifierConfig struct { - ForkName string `json:"fork_name"` - MockMode bool `json:"mock_mode"` - ParamsPath string `json:"params_path"` - AssetsPathLo string `json:"assets_path_lo"` // lower version Verifier - AssetsPathHi string `json:"assets_path_hi"` // higher version Verifier + MockMode bool `json:"mock_mode"` + LowVersionCircuit *CircuitConfig `json:"low_version_circuit"` + HighVersionCircuit *CircuitConfig `json:"high_version_circuit"` } // NewConfig returns a new instance of Config. diff --git a/coordinator/internal/logic/auth/login.go b/coordinator/internal/logic/auth/login.go index aa4268380e..6e2eda84f9 100644 --- a/coordinator/internal/logic/auth/login.go +++ b/coordinator/internal/logic/auth/login.go @@ -27,27 +27,13 @@ type LoginLogic struct { // NewLoginLogic new a LoginLogic func NewLoginLogic(db *gorm.DB, cfg *config.Config, vf *verifier.Verifier) *LoginLogic { - l := &LoginLogic{ + return &LoginLogic{ cfg: cfg, - chunkVks: make(map[string]struct{}), - batchVKs: make(map[string]struct{}), - bundleVks: make(map[string]struct{}), + chunkVks: vf.ChunkVKMap, + batchVKs: vf.BatchVKMap, + bundleVks: vf.BundleVkMap, challengeOrm: orm.NewChallenge(db), } - - for _, vk := range vf.ChunkVKMap { - l.chunkVks[vk] = struct{}{} - } - - for _, vk := range vf.BatchVKMap { - l.batchVKs[vk] = struct{}{} - } - - for _, vk := range vf.BundleVkMap { - l.bundleVks[vk] = struct{}{} - } - - return l } // InsertChallengeString insert and check the challenge string is existed diff --git a/coordinator/internal/logic/submitproof/proof_receiver.go b/coordinator/internal/logic/submitproof/proof_receiver.go index c8450a7d54..5daaf9e520 100644 --- a/coordinator/internal/logic/submitproof/proof_receiver.go +++ b/coordinator/internal/logic/submitproof/proof_receiver.go @@ -187,7 +187,7 @@ func (m *ProofReceiverLogic) HandleZkProof(ctx *gin.Context, proofParameter coor if unmarshalErr := json.Unmarshal([]byte(proofParameter.Proof), &bundleProof); unmarshalErr != nil { return unmarshalErr } - success, verifyErr = m.verifier.VerifyBundleProof(&bundleProof) + success, verifyErr = m.verifier.VerifyBundleProof(&bundleProof, hardForkName) } if verifyErr != nil || !success { diff --git a/coordinator/internal/logic/verifier/legacy_vk/agg_vk.vkey b/coordinator/internal/logic/verifier/legacy_vk/agg_vk.vkey deleted file mode 100644 index 0b4ab2657c..0000000000 Binary files a/coordinator/internal/logic/verifier/legacy_vk/agg_vk.vkey and /dev/null differ diff --git a/coordinator/internal/logic/verifier/legacy_vk/chunk_vk.vkey b/coordinator/internal/logic/verifier/legacy_vk/chunk_vk.vkey deleted file mode 100644 index 7318195ddf..0000000000 Binary files a/coordinator/internal/logic/verifier/legacy_vk/chunk_vk.vkey and /dev/null differ diff --git a/coordinator/internal/logic/verifier/legacy_vk/upgrade_vks.sh b/coordinator/internal/logic/verifier/legacy_vk/upgrade_vks.sh deleted file mode 100755 index bc5fad9bd4..0000000000 --- a/coordinator/internal/logic/verifier/legacy_vk/upgrade_vks.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash - -work_dir="$(dirname -- "${BASH_SOURCE[0]}")" -work_dir="$(cd -- "$work_dir" && pwd)" -echo $work_dir - -rm $work_dir/*.vkey - -version=release-v0.11.4 -wget https://circuit-release.s3.us-west-2.amazonaws.com/${version}/chunk_vk.vkey -O $work_dir/chunk_vk.vkey -wget https://circuit-release.s3.us-west-2.amazonaws.com/${version}/agg_vk.vkey -O $work_dir/agg_vk.vkey \ No newline at end of file diff --git a/coordinator/internal/logic/verifier/mock.go b/coordinator/internal/logic/verifier/mock.go index 7615c51b6e..5c4f1326ba 100644 --- a/coordinator/internal/logic/verifier/mock.go +++ b/coordinator/internal/logic/verifier/mock.go @@ -10,8 +10,8 @@ import ( // NewVerifier Sets up a mock verifier. func NewVerifier(cfg *config.VerifierConfig) (*Verifier, error) { - batchVKMap := map[string]string{cfg.ForkName: "mock_vk"} - chunkVKMap := map[string]string{cfg.ForkName: "mock_vk"} + batchVKMap := map[string]struct{}{"mock_vk": {}} + chunkVKMap := map[string]struct{}{"mock_vk": {}} return &Verifier{cfg: cfg, ChunkVKMap: chunkVKMap, BatchVKMap: batchVKMap}, nil } @@ -32,7 +32,7 @@ func (v *Verifier) VerifyBatchProof(proof *message.BatchProof, forkName string) } // VerifyBundleProof return a mock verification result for a BundleProof. -func (v *Verifier) VerifyBundleProof(proof *message.BundleProof) (bool, error) { +func (v *Verifier) VerifyBundleProof(proof *message.BundleProof, forkName string) (bool, error) { if string(proof.Proof) == InvalidTestProof { return false, nil } diff --git a/coordinator/internal/logic/verifier/types.go b/coordinator/internal/logic/verifier/types.go index 9d4fdba931..2d831d53ed 100644 --- a/coordinator/internal/logic/verifier/types.go +++ b/coordinator/internal/logic/verifier/types.go @@ -10,7 +10,7 @@ const InvalidTestProof = "this is a invalid proof" // Verifier represents a rust ffi to a halo2 verifier. type Verifier struct { cfg *config.VerifierConfig - ChunkVKMap map[string]string - BatchVKMap map[string]string - BundleVkMap map[string]string + ChunkVKMap map[string]struct{} + BatchVKMap map[string]struct{} + BundleVkMap map[string]struct{} } diff --git a/coordinator/internal/logic/verifier/verifier.go b/coordinator/internal/logic/verifier/verifier.go index b394bfba92..aecc87ef87 100644 --- a/coordinator/internal/logic/verifier/verifier.go +++ b/coordinator/internal/logic/verifier/verifier.go @@ -11,11 +11,9 @@ package verifier import "C" //nolint:typecheck import ( - "embed" "encoding/base64" "encoding/json" "io" - "io/fs" "os" "path" "unsafe" @@ -27,50 +25,61 @@ import ( "scroll-tech/coordinator/internal/config" ) +type rustVerifierConfig struct { + LowVersionCircuit *config.CircuitConfig `json:"low_version_circuit"` + HighVersionCircuit *config.CircuitConfig `json:"high_version_circuit"` +} + // NewVerifier Sets up a rust ffi to call verify. func NewVerifier(cfg *config.VerifierConfig) (*Verifier, error) { if cfg.MockMode { - chunkVKMap := map[string]string{cfg.ForkName: "mock_vk"} - batchVKMap := map[string]string{cfg.ForkName: "mock_vk"} - bundleVKMap := map[string]string{cfg.ForkName: "mock_vk"} + chunkVKMap := map[string]struct{}{"mock_vk": {}} + batchVKMap := map[string]struct{}{"mock_vk": {}} + bundleVKMap := map[string]struct{}{"mock_vk": {}} return &Verifier{cfg: cfg, ChunkVKMap: chunkVKMap, BatchVKMap: batchVKMap, BundleVkMap: bundleVKMap}, nil } - paramsPathStr := C.CString(cfg.ParamsPath) - assetsPathLoStr := C.CString(cfg.AssetsPathLo) - assetsPathHiStr := C.CString(cfg.AssetsPathHi) + verifierConfig := rustVerifierConfig{ + LowVersionCircuit: cfg.LowVersionCircuit, + HighVersionCircuit: cfg.HighVersionCircuit, + } + configBytes, err := json.Marshal(verifierConfig) + if err != nil { + return nil, err + } + + configStr := C.CString(string(configBytes)) + assetsPathHiStr := C.CString(cfg.HighVersionCircuit.AssetsPath) defer func() { - C.free(unsafe.Pointer(paramsPathStr)) - C.free(unsafe.Pointer(assetsPathLoStr)) + C.free(unsafe.Pointer(configStr)) C.free(unsafe.Pointer(assetsPathHiStr)) }() - C.init_batch_verifier(paramsPathStr, assetsPathHiStr) - C.init_chunk_verifier(paramsPathStr, assetsPathLoStr, assetsPathHiStr) + C.init(configStr) v := &Verifier{ cfg: cfg, - ChunkVKMap: make(map[string]string), - BatchVKMap: make(map[string]string), - BundleVkMap: make(map[string]string), + ChunkVKMap: make(map[string]struct{}), + BatchVKMap: make(map[string]struct{}), + BundleVkMap: make(map[string]struct{}), } - bundleVK, err := v.readVK(path.Join(cfg.AssetsPathHi, "vk_bundle.vkey")) + bundleVK, err := v.readVK(path.Join(cfg.HighVersionCircuit.AssetsPath, "vk_bundle.vkey")) if err != nil { return nil, err } - batchVK, err := v.readVK(path.Join(cfg.AssetsPathHi, "vk_batch.vkey")) + batchVK, err := v.readVK(path.Join(cfg.HighVersionCircuit.AssetsPath, "vk_batch.vkey")) if err != nil { return nil, err } - chunkVK, err := v.readVK(path.Join(cfg.AssetsPathHi, "vk_chunk.vkey")) + chunkVK, err := v.readVK(path.Join(cfg.HighVersionCircuit.AssetsPath, "vk_chunk.vkey")) if err != nil { return nil, err } - v.BundleVkMap[cfg.ForkName] = bundleVK - v.BatchVKMap[cfg.ForkName] = batchVK - v.ChunkVKMap[cfg.ForkName] = chunkVK + v.BundleVkMap[bundleVK] = struct{}{} + v.BatchVKMap[batchVK] = struct{}{} + v.ChunkVKMap[chunkVK] = struct{}{} - if err := v.loadEmbedVK(); err != nil { + if err := v.loadLowVersionVKs(cfg); err != nil { return nil, err } return v, nil @@ -131,7 +140,7 @@ func (v *Verifier) VerifyChunkProof(proof *message.ChunkProof, forkName string) } // VerifyBundleProof Verify a ZkProof for a bundle of batches, by marshaling it and verifying it via the EVM verifier. -func (v *Verifier) VerifyBundleProof(proof *message.BundleProof) (bool, error) { +func (v *Verifier) VerifyBundleProof(proof *message.BundleProof, forkName string) (bool, error) { if v.cfg.MockMode { log.Info("Mock mode, verifier disabled") if string(proof.Proof) == InvalidTestProof { @@ -146,12 +155,14 @@ func (v *Verifier) VerifyBundleProof(proof *message.BundleProof) (bool, error) { } proofStr := C.CString(string(buf)) + forkNameStr := C.CString(forkName) defer func() { C.free(unsafe.Pointer(proofStr)) + C.free(unsafe.Pointer(forkNameStr)) }() log.Info("Start to verify bundle proof ...") - verified := C.verify_bundle_proof(proofStr) + verified := C.verify_bundle_proof(proofStr, forkNameStr) return verified != 0, nil } @@ -167,23 +178,22 @@ func (v *Verifier) readVK(filePat string) (string, error) { return base64.StdEncoding.EncodeToString(byt), nil } -//go:embed legacy_vk/* -var legacyVKFS embed.FS - -func (v *Verifier) loadEmbedVK() error { - batchVKBytes, err := fs.ReadFile(legacyVKFS, "legacy_vk/agg_vk.vkey") +// load low version vks, current is darwin +func (v *Verifier) loadLowVersionVKs(cfg *config.VerifierConfig) error { + bundleVK, err := v.readVK(path.Join(cfg.LowVersionCircuit.AssetsPath, "vk_bundle.vkey")) if err != nil { - log.Error("load embed batch vk failure", "err", err) return err } - - chunkVkBytes, err := fs.ReadFile(legacyVKFS, "legacy_vk/chunk_vk.vkey") + batchVK, err := v.readVK(path.Join(cfg.LowVersionCircuit.AssetsPath, "vk_batch.vkey")) if err != nil { - log.Error("load embed chunk vk failure", "err", err) return err } - - v.BatchVKMap["curie"] = base64.StdEncoding.EncodeToString(batchVKBytes) - v.ChunkVKMap["curie"] = base64.StdEncoding.EncodeToString(chunkVkBytes) + chunkVK, err := v.readVK(path.Join(cfg.LowVersionCircuit.AssetsPath, "vk_chunk.vkey")) + if err != nil { + return err + } + v.BundleVkMap[bundleVK] = struct{}{} + v.BatchVKMap[batchVK] = struct{}{} + v.ChunkVKMap[chunkVK] = struct{}{} return nil } diff --git a/coordinator/internal/logic/verifier/verifier_test.go b/coordinator/internal/logic/verifier/verifier_test.go index 5e254bd35c..ed57a8f0ce 100644 --- a/coordinator/internal/logic/verifier/verifier_test.go +++ b/coordinator/internal/logic/verifier/verifier_test.go @@ -39,19 +39,19 @@ func TestFFI(t *testing.T) { as.NoError(err) chunkProof1 := readChunkProof(*chunkProofPath1, as) - chunkOk1, err := v.VerifyChunkProof(chunkProof1, "edison") + chunkOk1, err := v.VerifyChunkProof(chunkProof1, "darwin_v2") as.NoError(err) as.True(chunkOk1) t.Log("Verified chunk proof 1") chunkProof2 := readChunkProof(*chunkProofPath2, as) - chunkOk2, err := v.VerifyChunkProof(chunkProof2, "edison") + chunkOk2, err := v.VerifyChunkProof(chunkProof2, "darwin_v2") as.NoError(err) as.True(chunkOk2) t.Log("Verified chunk proof 2") batchProof := readBatchProof(*batchProofPath, as) - batchOk, err := v.VerifyBatchProof(batchProof, "edison") + batchOk, err := v.VerifyBatchProof(batchProof, "darwin_v2") as.NoError(err) as.True(batchOk) t.Log("Verified batch proof") diff --git a/prover/Cargo.toml b/prover/Cargo.toml index 295a67ab36..96b60de9b9 100644 --- a/prover/Cargo.toml +++ b/prover/Cargo.toml @@ -30,7 +30,7 @@ ethers-providers = { git = "https://github.com/scroll-tech/ethers-rs.git", branc halo2_proofs = { git = "https://github.com/scroll-tech/halo2.git", branch = "v1.1" } snark-verifier-sdk = { git = "https://github.com/scroll-tech/snark-verifier", branch = "develop", default-features = false, features = ["loader_halo2", "loader_evm", "halo2-pse"] } prover_darwin = { git = "https://github.com/scroll-tech/zkevm-circuits.git", tag = "v0.12.0", package = "prover", default-features = false, features = ["parallel_syn", "scroll"] } -prover_edison = { git = "https://github.com/scroll-tech/zkevm-circuits.git", tag = "v0.13.0", package = "prover", default-features = false, features = ["parallel_syn", "scroll"] } +prover_darwin_v2 = { git = "https://github.com/scroll-tech/zkevm-circuits.git", tag = "v0.13.0", package = "prover", default-features = false, features = ["parallel_syn", "scroll"] } base64 = "0.13.1" reqwest = { version = "0.12.4", features = ["gzip"] } reqwest-middleware = "0.3" diff --git a/prover/config.json b/prover/config.json index daaf989f53..0a816360d5 100644 --- a/prover/config.json +++ b/prover/config.json @@ -3,7 +3,7 @@ "keystore_path": "keystore.json", "keystore_password": "prover-pwd", "db_path": "unique-db-path-for-prover-1", - "proof_type": 2, + "prover_type": 2, "low_version_circuit": { "hard_fork_name": "bernoulli", "params_path": "params", diff --git a/prover/src/zk_circuits_handler.rs b/prover/src/zk_circuits_handler.rs index ab79cd765c..491feca415 100644 --- a/prover/src/zk_circuits_handler.rs +++ b/prover/src/zk_circuits_handler.rs @@ -1,5 +1,5 @@ mod darwin; -mod edison; +mod darwin_v2; use super::geth_client::GethClient; use crate::{ @@ -9,7 +9,7 @@ use crate::{ }; use anyhow::{bail, Result}; use darwin::DarwinHandler; -use edison::EdisonHandler; +use darwin_v2::DarwinV2Handler; use std::{cell::RefCell, collections::HashMap, rc::Rc}; type HardForkName = String; @@ -38,7 +38,7 @@ pub struct CircuitsHandlerProvider<'a> { geth_client: Option>>, circuits_handler_builder_map: HashMap, - current_hard_fork_name: Option, + current_fork_name: Option, current_circuit: Option>>, } @@ -83,7 +83,7 @@ impl<'a> CircuitsHandlerProvider<'a> { &config.high_version_circuit.hard_fork_name ); AssetsDirEnvConfig::enable_second(); - EdisonHandler::new( + DarwinV2Handler::new( prover_type, &config.high_version_circuit.params_path, &config.high_version_circuit.assets_path, @@ -102,7 +102,7 @@ impl<'a> CircuitsHandlerProvider<'a> { config, geth_client, circuits_handler_builder_map: m, - current_hard_fork_name: None, + current_fork_name: None, current_circuit: None, }; @@ -113,8 +113,8 @@ impl<'a> CircuitsHandlerProvider<'a> { &mut self, hard_fork_name: &String, ) -> Result>> { - match &self.current_hard_fork_name { - Some(name) if name == hard_fork_name => { + match &self.current_fork_name { + Some(fork_name) if fork_name == hard_fork_name => { log::info!("get circuits handler from cache"); if let Some(handler) = &self.current_circuit { Ok(handler.clone()) @@ -131,7 +131,7 @@ impl<'a> CircuitsHandlerProvider<'a> { log::info!("building circuits handler for {hard_fork_name}"); let handler = builder(self.prover_type, self.config, self.geth_client.clone()) .expect("failed to build circuits handler"); - self.current_hard_fork_name = Some(hard_fork_name.clone()); + self.current_fork_name = Some(hard_fork_name.clone()); let rc_handler = Rc::new(handler); self.current_circuit = Some(rc_handler.clone()); Ok(rc_handler) diff --git a/prover/src/zk_circuits_handler/edison.rs b/prover/src/zk_circuits_handler/darwin_v2.rs similarity index 97% rename from prover/src/zk_circuits_handler/edison.rs rename to prover/src/zk_circuits_handler/darwin_v2.rs index 6f3428540d..9c7ce6910f 100644 --- a/prover/src/zk_circuits_handler/edison.rs +++ b/prover/src/zk_circuits_handler/darwin_v2.rs @@ -10,7 +10,7 @@ use serde::Deserialize; use crate::types::{CommonHash, Task}; use std::{cell::RefCell, cmp::Ordering, env, rc::Rc}; -use prover_edison::{ +use prover_darwin_v2::{ aggregator::Prover as BatchProver, check_chunk_hashes, zkevm::Prover as ChunkProver, BatchProof, BatchProvingTask, BlockTrace, BundleProof, BundleProvingTask, ChunkInfo, ChunkProof, ChunkProvingTask, @@ -38,14 +38,14 @@ fn get_block_number(block_trace: &BlockTrace) -> Option { } #[derive(Default)] -pub struct EdisonHandler { +pub struct DarwinV2Handler { chunk_prover: Option>, batch_prover: Option>, geth_client: Option>>, } -impl EdisonHandler { +impl DarwinV2Handler { pub fn new( prover_type: ProverType, params_dir: &str, @@ -207,7 +207,7 @@ impl EdisonHandler { } } -impl CircuitsHandler for EdisonHandler { +impl CircuitsHandler for DarwinV2Handler { fn get_vk(&self, task_type: TaskType) -> Option> { match task_type { TaskType::Chunk => self @@ -243,8 +243,7 @@ mod tests { use super::*; use crate::zk_circuits_handler::utils::encode_vk; use ethers_core::types::H256; - use prover_darwin::zkevm_circuits::witness::Block; - use prover_edison::{ + use prover_darwin_v2::{ aggregator::eip4844, utils::chunk_trace_to_witness_block, BatchData, BatchHeader, MAX_AGG_SNARKS, }; @@ -258,7 +257,7 @@ mod tests { static DEFAULT_WORK_DIR: &str = "/assets"; static WORK_DIR: LazyLock = LazyLock::new(|| { - std::env::var("EDISON_TEST_DIR") + std::env::var("DARWIN_V2_TEST_DIR") .unwrap_or(String::from(DEFAULT_WORK_DIR)) .trim_end_matches('/') .to_string() @@ -283,7 +282,7 @@ mod tests { #[test] fn test_circuits() -> Result<()> { let chunk_handler = - EdisonHandler::new(ProverType::Chunk, &PARAMS_PATH, &ASSETS_PATH, None)?; + DarwinV2Handler::new(ProverType::Chunk, &PARAMS_PATH, &ASSETS_PATH, None)?; let chunk_vk = chunk_handler.get_vk(TaskType::Chunk).unwrap(); @@ -309,7 +308,7 @@ mod tests { } let batch_handler = - EdisonHandler::new(ProverType::Batch, &PARAMS_PATH, &ASSETS_PATH, None)?; + DarwinV2Handler::new(ProverType::Batch, &PARAMS_PATH, &ASSETS_PATH, None)?; let batch_vk = batch_handler.get_vk(TaskType::Batch).unwrap(); check_vk(TaskType::Batch, batch_vk, "batch vk must be available"); let batch_task_detail = make_batch_task_detail(chunk_traces, chunk_proofs, None);