This commit is contained in:
Mengran Lan
2024-05-09 19:14:20 +08:00
parent a1a7f25921
commit 107aa5792b
18 changed files with 5952 additions and 0 deletions

4966
prover_rust/Cargo.lock generated Normal file

File diff suppressed because it is too large Load Diff

36
prover_rust/Cargo.toml Normal file
View File

@@ -0,0 +1,36 @@
[package]
name = "prover_rust"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[patch.crates-io]
ethers-signers = { git = "https://github.com/scroll-tech/ethers-rs.git", branch = "v2.0.7" }
halo2curves = { git = "https://github.com/scroll-tech/halo2curves", branch = "v0.1.0" }
[patch."https://github.com/privacy-scaling-explorations/halo2.git"]
halo2_proofs = { git = "https://github.com/scroll-tech/halo2.git", branch = "v1.1" }
[patch."https://github.com/privacy-scaling-explorations/poseidon.git"]
poseidon = { git = "https://github.com/scroll-tech/poseidon.git", branch = "main" }
[patch."https://github.com/privacy-scaling-explorations/bls12_381"]
bls12_381 = { git = "https://github.com/scroll-tech/bls12_381", branch = "feat/impl_scalar_field" }
[dependencies]
anyhow = "1.0"
log = "0.4"
serde = { version = "1.0.198", features = ["derive"] }
serde_json = "1.0.116"
futures = "0.3.30"
ethers-core = { git = "https://github.com/scroll-tech/ethers-rs.git", branch = "v2.0.7" }
ethers-providers = { git = "https://github.com/scroll-tech/ethers-rs.git", branch = "v2.0.7" }
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 = { git = "https://github.com/scroll-tech/zkevm-circuits.git", tag = "v0.10.3", default-features = false, features = ["parallel_syn", "scroll", "shanghai"] }
eth-types = { git = "https://github.com/scroll-tech/zkevm-circuits.git", tag = "v0.10.3" }
base64 = "0.13.1"
reqwest = "0.12.4"

22
prover_rust/config.json Normal file
View File

@@ -0,0 +1,22 @@
{
"prover_name": "prover-1",
"hard_fork_name": "homestead",
"keystore_path": "keystore.json",
"keystore_password": "prover-pwd",
"db_path": "unique-db-path-for-prover-1",
"core": {
"params_path": "params",
"assets_path": "assets",
"proof_type": 2
},
"coordinator": {
"base_url": "http://localhost:8555",
"retry_count": 10,
"retry_wait_time_sec": 10,
"connection_timeout_sec": 30
},
"l2geth": {
"endpoint": "http://localhost:9999",
"confirmations": "0x1"
}
}

View File

@@ -0,0 +1 @@
nightly-2023-12-03

9
prover_rust/rustfmt.toml Normal file
View File

@@ -0,0 +1,9 @@
edition = "2021"
comment_width = 100
imports_granularity = "Crate"
max_width = 100
newline_style = "Unix"
# normalize_comments = true
reorder_imports = true
wrap_comments = true

65
prover_rust/src/config.rs Normal file
View File

@@ -0,0 +1,65 @@
use ethers_core::types::BlockNumber;
use serde::{Deserialize, Serialize};
// use serde_json::Error;
use std::error::Error;
use std::fs::File;
use crate::types::ProofType;
#[derive(Debug)]
#[derive(Serialize, Deserialize)]
pub struct ProverCoreConfig {
pub params_path: String,
pub assets_path: String,
#[serde(default)]
pub proof_type: ProofType,
#[serde(default)]
pub dump_dir: String,
}
#[derive(Debug)]
#[derive(Serialize, Deserialize)]
pub struct CoordinatorConfig{
pub base_url: String,
pub retry_count: u16,
pub retry_wait_time_sec: u32,
pub connection_timeout_sec: u32,
}
#[derive(Debug)]
#[derive(Serialize, Deserialize)]
pub struct L2GethConfig{
pub endpoint: String,
pub confirmations: BlockNumber,
}
#[derive(Debug)]
#[derive(Serialize, Deserialize)]
pub struct Config {
pub prover_name: String,
pub hard_fork_name: String,
pub keystore_path: String,
pub keystore_password: String,
pub db_path: String,
pub core: ProverCoreConfig,
pub coordinator: CoordinatorConfig,
pub l2geth: L2GethConfig,
}
impl Config {
pub fn from_reader<R>(reader: R) -> Result<Self, Box<dyn Error>>
where
R: std::io::Read,
{
serde_json::from_reader(reader).map_err( |e| Box::new(e) as Box<dyn Error>)
}
pub fn from_file(file_name: String) -> Result<Self, Box<dyn Error>>
{
let file = File::open(file_name)?;
Config::from_reader(&file)
}
}

View File

@@ -0,0 +1,99 @@
mod errors;
pub mod types;
mod api;
use anyhow::{bail, Context, Ok, Result};
use types::*;
use errors::*;
use api::API;
use futures::executor::block_on;
use log;
pub struct Config {
pub endpoint: String,
pub prover_name: String,
pub prover_version: String,
pub hard_fork_name: String,
}
pub struct CoordinatorClient {
api: API,
token: Option<String>,
config: Config,
}
impl CoordinatorClient {
pub fn new(config: Config) -> Result<Self> {
let mut client = Self {
api: API::new(config.endpoint)?,
token: None,
config: config,
};
client.login()?;
Ok(client)
}
fn login(&mut self) -> Result<()> {
let api = self.api;
let challenge_response = block_on(api.challenge())?;
if challenge_response.errcode != Success {
bail!("challenge failed: {}", challenge_response.errmsg)
}
let mut token: String;
if let Some(r) = challenge_response.data {
token = r.token;
} else {
bail!("challenge failed: got empty token")
}
let login_message = LoginMessage {
challenge: token,
prover_name: self.config.prover_name,
prover_version: self.config.prover_version,
hard_fork_name: self.config.hard_fork_name,
};
let login_request = LoginRequest {
message: login_message,
signature: login_message.sign_with_key(),
};
let login_response = block_on(api.login(&login_request, &token));
if login_response.errcode != Success {
bail!("login failed: {}", login_response.errmsg)
}
if let Some(r) = login_response.data {
token = r.token;
} else {
bail!("login failed: got empty token")
}
self.token = Some(token);
Ok(())
}
pub fn get_task(&mut self, req: GetTaskRequest) -> Result<Response<GetTaskResponseData>> {
let response = block_on(self.api.get_task(&req, &self.token))?;
if response.errcode == ErrJWTTokenExpired {
log::info!("JWT expired, attempting to re-login");
self.login().context("JWT expired, re-login failed")?;
log::info!("re-login success");
} else if response.errcode != Success {
bail!("get task failed: {}", response.errmsg)
}
Ok(response)
}
pub fn submit_proof(&mut self, req: SubmitProofRequest) -> Result<Response<SubmitProofResponseData>> {
let response = block_on(self.api.get_task(&req, &self.token))?;
if response.errcode == ErrJWTTokenExpired {
log::info!("JWT expired, attempting to re-login");
self.login().context("JWT expired, re-login failed")?;
log::info!("re-login success");
} else if response.errcode != Success {
bail!("get task failed: {}", response.errmsg)
}
Ok(response)
}
}

View File

@@ -0,0 +1,92 @@
use super::types::*;
use anyhow::Result;
use reqwest::{header::{self, CONTENT_TYPE}, Url};
pub struct API {
url_base: Url,
pub client: reqwest::Client,
}
impl API {
pub fn new(url_base: String) -> Result<Self> {
let mut headers = header::HeaderMap::new();
Ok(Self {
url_base: Url::parse(&url_base)?,
client: reqwest::Client::new(),
})
}
pub async fn challenge(&self) -> Result<Response<ChallengeResponseData>> {
let method = "/coordinator/v1/challenge";
let url = self.build_url(method)?;
let response = self.client
.get(url)
.header(CONTENT_TYPE, "application/json")
.send()
.await?;
let response_body = response.text().await?;
serde_json::from_str(&response_body).map_err(|e| anyhow::anyhow!(e))
}
pub async fn login(&self, req: &LoginRequest, token: &String) -> Result<Response<LoginResponseData>> {
let method = "/coordinator/v1/login";
let url = self.build_url(method)?;
let request_body = serde_json::to_string(&req)?;
let response = self.client
.post(url)
.header(CONTENT_TYPE, "application/json")
.bearer_auth(token)
.body(request_body)
.send()
.await?;
let response_body = response.text().await?;
serde_json::from_str(&response_body).map_err(|e| anyhow::anyhow!(e))
}
pub async fn get_task(&self, req: &GetTaskRequest, token: &String) -> Result<Response<GetTaskResponseData>> {
let method = "/coordinator/v1/get_task";
let url = self.build_url(method)?;
let request_body = serde_json::to_string(&req)?;
let response = self.client
.post(url)
.header(CONTENT_TYPE, "application/json")
.bearer_auth(token)
.body(request_body)
.send()
.await?;
let response_body = response.text().await?;
serde_json::from_str(&response_body).map_err(|e| anyhow::anyhow!(e))
}
pub async fn submit_proof(&self, req: SubmitProofRequest, token: &String) -> Result<Response<SubmitProofResponseData>> {
let method = "/coordinator/v1/submit_proof";
let url = self.build_url(method)?;
let request_body = serde_json::to_string(&req)?;
let response = self.client
.post(url)
.header(CONTENT_TYPE, "application/json")
.bearer_auth(token)
.body(request_body)
.send()
.await?;
let response_body = response.text().await?;
serde_json::from_str(&response_body).map_err(|e| anyhow::anyhow!(e))
}
fn build_url(&self, method: &str) -> Result<Url> {
self.url_base.join(method).map_err(|e| anyhow::anyhow!(e))
}
}

View File

@@ -0,0 +1,20 @@
// TODO: refactor using enum
pub type ErrorCode = i32;
pub const Success: ErrorCode = 0;
pub const InternalServerError: ErrorCode = 500;
pub const ErrJWTCommonErr: ErrorCode = 50000;
pub const ErrJWTTokenExpired: ErrorCode = 50001;
pub const ErrProverStatsAPIParameterInvalidNo: ErrorCode = 10001;
pub const ErrProverStatsAPIProverTaskFailure: ErrorCode = 10002;
pub const ErrProverStatsAPIProverTotalRewardFailure: ErrorCode = 10003;
pub const ErrCoordinatorParameterInvalidNo: ErrorCode = 20001;
pub const ErrCoordinatorGetTaskFailure: ErrorCode = 20002;
pub const ErrCoordinatorHandleZkProofFailure: ErrorCode = 20003;
pub const ErrCoordinatorEmptyProofData: ErrorCode = 20004;

View File

@@ -0,0 +1,69 @@
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize)]
pub struct Response<T> {
pub errcode: i32,
pub errmsg: String,
pub data: Option<T>,
}
#[derive(Serialize, Deserialize)]
pub struct LoginMessage {
pub challenge: String,
pub prover_name: String,
pub prover_version: String,
pub hard_fork_name: String,
}
impl LoginMessage {
pub fn hash() -> Result<Vec<u8>> {
}
pub fn sign_with_key() -> Result<String> {
}
}
#[derive(Serialize, Deserialize)]
pub struct LoginRequest {
pub message: LoginMessage,
pub signature: String,
}
#[derive(Serialize, Deserialize)]
pub struct LoginResponseData {
pub time: String,
pub token: String,
}
pub type ChallengeResponseData = LoginResponseData;
#[derive(Default, Serialize, Deserialize)]
pub struct GetTaskRequest {
pub task_type: crate::types::ProofType,
pub prover_height: Option<u64>,
pub vks: Vec<String>,
}
#[derive(Serialize, Deserialize)]
pub struct GetTaskResponseData {
pub uuid: String,
pub task_id: String,
pub task_type: crate::types::ProofType,
pub task_data: String,
}
#[derive(Serialize, Deserialize)]
pub struct SubmitProofRequest {
pub uuid: String,
pub task_id: String,
pub task_type: i32,
pub status: i32,
pub proof: String,
pub failure_type: Option<i32>,
pub failure_msg: Option<String>,
}
#[derive(Serialize, Deserialize)]
pub struct SubmitProofResponseData {}

View File

@@ -0,0 +1,79 @@
mod types;
use anyhow::Result;
use crate::types::CommonHash;
use ethers_core::types::BlockNumber;
use types::{BlockTrace, Header};
use futures::executor;
use ethers_providers::{Http, Provider};
/// Serialize a type.
///
/// # Panics
///
/// If the type returns an error during serialization.
pub fn serialize<T: serde::Serialize>(t: &T) -> serde_json::Value {
serde_json::to_value(t).expect("Types never fail to serialize.")
}
pub struct GethClient {
id: String,
provider: Provider<Http>,
}
impl GethClient {
pub fn new(id: &str, api_url: &str) -> Result<Self> {
let provider = Provider::<Http>::try_from(api_url)?;
Ok(Self {
id: id.to_string(),
provider,
})
}
pub fn get_block_trace_by_hash(&self, hash: CommonHash) -> Result<BlockTrace> {
log::info!("{}: calling get_block_trace_by_hash, hash: {}", self.id, hash);
let trace_future = self
.provider
.request(
"scroll_getBlockTraceByNumberOrHash",
[format!("{hash:#x}")],
);
let trace = executor::block_on(trace_future)?;
Ok(trace)
}
pub fn header_by_number(&self, block_number: &BlockNumber) -> Result<Header> {
log::info!("{}: calling header_by_number, hash: {}", self.id, block_number);
let hash = serialize(block_number);
let include_txs = serialize(&false);
let trace_future = self
.provider
.request(
"eth_getBlockByNumber",
[hash, include_txs],
);
let trace = executor::block_on(trace_future)?;
Ok(trace)
}
pub fn block_number(&self) -> Result<BlockNumber> {
log::info!("{}: calling block_number", self.id);
let trace_future = self
.provider
.request(
"eth_blockNumber",
(),
);
let trace = executor::block_on(trace_future)?;
Ok(trace)
}
}

View File

@@ -0,0 +1,37 @@
use eth_types::{H256, U64};
use serde::{Deserialize, Serialize};
use crate::types::CommonHash;
use prover::BlockTrace as ProverBlockTrace;
/// l2 block full trace
#[derive(Deserialize, Serialize, Default, Debug, Clone)]
pub struct BlockTrace {
#[serde(flatten)]
pub block_trace: ProverBlockTrace,
pub version: String,
pub withdraw_trie_root: Option<CommonHash>,
#[serde(rename = "mptwitness", default)]
pub mpt_witness: Vec<u8>,
}
pub type TxHash = H256;
/// this struct is tracked to https://github.com/scroll-tech/go-ethereum/blob/0f0cd99f7a2e/core/types/block.go#Header
/// the detail fields of struct are not 100% same as eth_types::Block so this needs to be changed in some time
/// currently only the `number` field is required
#[derive(Debug, Deserialize, Serialize, Default)]
pub struct Header {
#[serde(flatten)]
block: eth_types::Block<TxHash>,
}
impl Header {
pub fn get_number(&self) -> Option<U64> {
self.block.number
}
}

59
prover_rust/src/main.rs Normal file
View File

@@ -0,0 +1,59 @@
mod types;
mod config;
mod prover;
mod zk_circuits_handler;
mod coordinator_client;
mod geth_client;
use config::Config;
use prover::Prover;
use anyhow::Result;
use log;
struct TaskProcesser<'a> {
prover: &'a Prover<'a>,
}
impl<'a> TaskProcesser<'a> {
pub fn new(prover: &'a Prover) -> Self {
TaskProcesser {
prover: prover,
}
}
pub fn start(&self) {
loop {
log::info!("start a new round.");
if let Err(err) = self.prove_and_submit() {
log::error!("encounter error: {err}");
} else {
log::info!("prove & submit succeed.");
}
}
}
fn prove_and_submit(&self) -> Result<()> {
let task = self.prover.fetch_task()?;
let proof_detail = self.prover.prove_task(&task)?;
self.prover.submit_proof(&proof_detail, task.uuid)
}
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let file_name = "config.json";
let config: Config = Config::from_file(file_name.to_string())?;
println!("{:?}", config);
let prover = Prover::new(&config)?;
let task_processer = TaskProcesser::new(&prover);
task_processer.start();
Ok(())
}

105
prover_rust/src/prover.rs Normal file
View File

@@ -0,0 +1,105 @@
use anyhow::{Ok, Result};
use ethers_core::types::BlockNumber;
use eth_types::U64;
use crate::{config::Config, types::ProofType};
use crate::zk_circuits_handler::CircuitsHandlerProvider;
use crate::coordinator_client::CoordinatorClient;
use crate::coordinator_client::types::*;
use crate::geth_client::GethClient;
use super::types::{Task, ProofDetail};
pub struct Prover<'a> {
config: &'a Config,
circuits_client_provider: CircuitsHandlerProvider,
coordinator_client: CoordinatorClient,
geth_client: GethClient,
}
// a u64 is positive when it's 0 index bit not set
fn is_positive(n: &U64) -> bool {
!n.bit(0)
}
impl<'a> Prover<'a> {
pub fn new(config: &'a Config) -> Result<Self> {
let proof_type = config.core.proof_type;
let params_path = config.core.params_path;
let assets_path = config.core.assets_path;
let prover = Prover {
config: config,
circuits_client_provider: CircuitsHandlerProvider::new(proof_type, &params_path, &assets_path)?,
coordinator_client: CoordinatorClient::new(),
geth_client: GethClient::new("test", &config.l2geth.endpoint)?,
};
Ok(prover)
}
pub fn get_proof_type(&self) -> ProofType {
self.config.core.proof_type
}
pub fn get_public_key(&self) -> String {
"".to_string()
}
pub fn fetch_task(&self) -> Result<Task> {
let mut req = GetTaskRequest {
task_type: self.get_proof_type(),
prover_height: None,
vks: self.circuits_client_provider.get_vks(),
};
if self.get_proof_type() == ProofType::ProofTypeChunk {
let latest_block_number = self.get_configured_block_number_value()?;
if let Some(v) = latest_block_number {
if v.as_u64() == 0 {
unreachable!()
}
req.prover_height = Some(v.as_u64());
}
unreachable!()
}
let resp = self.coordinator_client.get_task(req)?;
Task::try_from(&resp.data.unwrap()).map_err(|e| anyhow::anyhow!(e))
}
pub fn prove_task(&self, task: &Task) -> Result<ProofDetail> {
}
pub fn submit_proof(&self, proof_detail: &ProofDetail, uuid: String) -> Result<()> {
Ok(())
}
fn get_configured_block_number_value(&self) -> Result<Option<U64>> {
self.get_block_number_value(&self.config.l2geth.confirmations)
}
fn get_block_number_value(&self, block_number: &BlockNumber) -> Result<Option<U64>> {
match block_number {
BlockNumber::Safe | BlockNumber::Finalized => {
let header = self.geth_client.header_by_number(block_number)?;
Ok(header.get_number())
},
BlockNumber::Latest => {
let number = self.geth_client.block_number()?;
Ok(number.as_number())
},
BlockNumber::Number(n) if is_positive(n) => {
let number = self.geth_client.block_number()?;
let diff = number.as_number()
.filter(|m| m.as_u64() >= n.as_u64())
.map(|m| U64::from(m.as_u64() - n.as_u64()));
Ok(diff)
},
_ => unreachable!(),
}
}
}

135
prover_rust/src/types.rs Normal file
View File

@@ -0,0 +1,135 @@
use prover::BatchProof;
use serde::{Deserialize, Serialize, Serializer, Deserializer};
use eth_types::H256;
use crate::coordinator_client::types::GetTaskResponseData;
pub type CommonHash = H256;
pub type Bytes = Vec<u8>;
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum ProofType {
ProofTypeUndefined,
ProofTypeChunk,
ProofTypeBatch,
}
impl ProofType {
fn from_u8(v: u8) -> Self {
match v {
1 => ProofType::ProofTypeChunk,
2 => ProofType::ProofTypeBatch,
_ => ProofType::ProofTypeUndefined,
}
}
}
impl Serialize for ProofType {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
match *self {
ProofType::ProofTypeUndefined => serializer.serialize_i8(0),
ProofType::ProofTypeChunk => serializer.serialize_i8(1),
ProofType::ProofTypeBatch => serializer.serialize_i8(2),
}
}
}
impl<'de> Deserialize<'de> for ProofType {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let v: u8 = u8::deserialize(deserializer)?;
Ok(ProofType::from_u8(v))
}
}
impl Default for ProofType {
fn default() -> Self {
Self::ProofTypeUndefined
}
}
#[derive(Serialize, Deserialize)]
pub struct ChunkInfo {
pub chain_id: u64,
pub prev_state_root: CommonHash,
pub post_state_root: CommonHash,
pub withdraw_root: CommonHash,
pub data_hash: CommonHash,
pub is_padding: bool,
pub tx_bytes: Bytes,
}
#[derive(Serialize, Deserialize)]
pub struct ChunkProof {
pub storage_trace: Bytes,
pub protocol: Bytes,
pub proof: Bytes,
pub instances: Bytes,
pub vk: Bytes,
pub chunk_info: ChunkInfo,
pub git_version: String,
}
#[derive(Serialize, Deserialize)]
pub struct BatchTaskDetail {
chunk_infos: Vec<ChunkInfo>,
chunk_proofs: Vec<ChunkProof>,
}
#[derive(Serialize, Deserialize)]
pub struct ChunkTaskDetail {
block_hashes: Vec<CommonHash>,
}
#[derive(Serialize, Deserialize, Default)]
pub struct Task {
pub uuid: String,
pub id: String,
#[serde(rename = "type", default)]
pub task_type: ProofType,
#[serde(default)]
pub batch_task_detail: Option<BatchTaskDetail>,
#[serde(default)]
pub chunk_task_detail: Option<ChunkTaskDetail>,
}
impl TryFrom<&GetTaskResponseData> for Task {
type Error = serde_json::Error;
fn try_from(value: &GetTaskResponseData) -> Result<Self, Self::Error> {
let mut task = Task {
uuid: value.uuid,
id: value.task_id,
task_type: value.task_type,
chunk_task_detail: None,
batch_task_detail: None,
};
match task.task_type {
ProofType::ProofTypeBatch => {
task.batch_task_detail = serde_json::from_str(&value.task_data)?;
},
ProofType::ProofTypeChunk => {
task.chunk_task_detail = serde_json::from_str(&value.task_data)?;
},
_ => unreachable!()
}
Ok(task)
}
}
#[derive(Serialize, Deserialize)]
pub struct ProofDetail {
pub id: String,
#[serde(rename = "type", default)]
pub proof_type: ProofType,
pub status: u32,
pub chunk_proof: Option<ChunkProof>,
pub batch_proof: Option<BatchProof>,
pub error: String,
}

View File

@@ -0,0 +1,77 @@
mod types;
mod base;
use types::{ChunkProof, BatchProof, BlockTrace, ChunkHash};
use anyhow::Result;
use std::collections::HashMap;
use base::BaseCircuitsHandler;
use crate::types::ProofType;
type CiruitsVersion = String;
pub mod utils {
pub fn encode_vk(vk: Vec<u8>) -> String {
base64::encode(vk)
}
}
pub trait CircuitsHandler {
// api of zkevm::Prover
fn prover_get_vk(&self) -> Option<Vec<u8>>;
fn prover_gen_chunk_proof(&self,
chunk_trace: Vec<BlockTrace>,
name: Option<&str>,
inner_id: Option<&str>,
output_dir: Option<&str>) -> Result<ChunkProof>;
// api of aggregator::Prover
fn aggregator_get_vk(&self) -> Option<Vec<u8>>;
fn aggregator_gen_agg_evm_proof(&self,
chunk_hashes_proofs: Vec<(ChunkHash, ChunkProof)>,
name: Option<&str>,
output_dir: Option<&str>) -> Result<BatchProof>;
fn aggregator_check_chunk_proofs(&self,
chunk_proofs: &[ChunkProof]) -> bool;
}
pub struct CircuitsHandlerProvider {
proof_type: ProofType,
circuits_handler_map: HashMap<CiruitsVersion, Box<dyn CircuitsHandler>>,
}
impl CircuitsHandlerProvider {
pub fn new(proof_type: ProofType, params_dir: &str, assets_dir: &str) -> Result<Self> {
let mut m: HashMap<CiruitsVersion, Box<dyn CircuitsHandler>> = HashMap::new();
let handler = BaseCircuitsHandler::new(proof_type, params_dir, assets_dir)?;
m.insert("".to_string(), Box::new(handler));
Ok(CircuitsHandlerProvider {
proof_type: proof_type,
circuits_handler_map: m,
})
}
pub fn get_circuits_client(&self, version: String) -> Option<&Box<dyn CircuitsHandler>> {
self.circuits_handler_map.get(&version)
}
pub fn get_vks(&self) -> Vec<String> {
match self.proof_type {
ProofType::ProofTypeBatch => {
self.circuits_handler_map.values().map(|h| {
h.aggregator_get_vk()
.map_or("".to_string(), |vk| utils::encode_vk(vk))
}).collect::<Vec<String>>()
},
ProofType::ProofTypeChunk => {
self.circuits_handler_map.values().map(|h| {
h.prover_get_vk()
.map_or("".to_string(), |vk| utils::encode_vk(vk))
}).collect::<Vec<String>>()
},
_ => unreachable!()
}
}
}

View File

@@ -0,0 +1,80 @@
use anyhow::{Ok, Result};
use crate::types::ProofType;
use super::CircuitsHandler;
use super::types::{ChunkProof, BatchProof, BlockTrace, ChunkHash};
use prover::zkevm::{Prover as ChunkProver, Verifier as ChunkVerifier};
use prover::aggregator::{Prover as BatchProver, Verifier as BaatchVerifier};
#[derive(Default)]
pub struct BaseCircuitsHandler {
chunk_prover: Option<ChunkProver>,
chunk_verifier: Option<ChunkVerifier>,
batch_prover: Option<BatchProver>,
batch_verifier: Option<BaatchVerifier>,
}
impl BaseCircuitsHandler {
pub fn new(proof_type: ProofType, params_dir: &str, assets_dir: &str) -> Result<Self> {
match proof_type {
ProofType::ProofTypeChunk => Ok(Self {
chunk_prover: Some(ChunkProver::from_dirs(params_dir, assets_dir)),
chunk_verifier: Some(ChunkVerifier::from_dirs(params_dir, assets_dir)),
..Default::default()
}),
ProofType::ProofTypeBatch => Ok(Self {
batch_prover: Some(BatchProver::from_dirs(params_dir, assets_dir)),
batch_verifier: Some(BaatchVerifier::from_dirs(params_dir, assets_dir)),
..Default::default()
}),
// TODO: add custom error system and change unreachable to error
_ => unreachable!()
}
}
}
impl CircuitsHandler for BaseCircuitsHandler {
// api of zkevm::Prover
fn prover_get_vk(&self) -> Option<Vec<u8>> {
self.chunk_prover.and_then(|prover| prover.get_vk())
}
fn prover_gen_chunk_proof(&self,
chunk_trace: Vec<BlockTrace>,
name: Option<&str>,
inner_id: Option<&str>,
output_dir: Option<&str>) -> Result<ChunkProof> {
if let Some(mut prover) = self.chunk_prover {
return prover.gen_chunk_proof(chunk_trace, name, inner_id, output_dir)
}
// TODO: add custom error system and change unreachable to error
unreachable!()
}
// api of aggregator::Prover
fn aggregator_get_vk(&self) -> Option<Vec<u8>> {
self.batch_prover.and_then(|prover| prover.get_vk())
}
fn aggregator_gen_agg_evm_proof(&self,
chunk_hashes_proofs: Vec<(ChunkHash, ChunkProof)>,
name: Option<&str>,
output_dir: Option<&str>) -> Result<BatchProof> {
if let Some(mut prover) = self.batch_prover {
return prover.gen_agg_evm_proof(chunk_hashes_proofs, name, output_dir)
}
// TODO: add custom error system and change unreachable to error
unreachable!()
}
fn aggregator_check_chunk_proofs(&self, chunk_proofs: &[ChunkProof]) -> bool {
if let Some(prover) = self.batch_prover {
return prover.check_chunk_proofs(chunk_proofs)
}
// TODO: add custom error system and change unreachable to error
unreachable!()
}
}

View File

@@ -0,0 +1 @@
pub use prover::{ChunkProof, BatchProof, BlockTrace, ChunkHash};