first compile-ready version

This commit is contained in:
Mengran Lan
2024-05-16 11:17:16 +08:00
parent 94bd5917ba
commit 173cbc4dc4
11 changed files with 135 additions and 79 deletions

25
prover_rust/Makefile Normal file
View File

@@ -0,0 +1,25 @@
.PHONY: prover
ifeq (4.3,$(firstword $(sort $(MAKE_VERSION) 4.3)))
ZKEVM_VERSION=$(shell grep -m 1 "zkevm-circuits" ./Cargo.lock | cut -d "#" -f2 | cut -c-7)
HALO2_VERSION=$(shell grep -m 1 "halo2.git" ./Cargo.lock | cut -d "#" -f2 | cut -c-7)
else
ZKEVM_VERSION=$(shell grep -m 1 "zkevm-circuits" ./Cargo.lock | cut -d "\#" -f2 | cut -c-7)
HALO2_VERSION=$(shell grep -m 1 "halo2.git" ./Cargo.lock | cut -d "\#" -f2 | cut -c-7)
endif
HALO2_GPU_VERSION=$(shell ./print_halo2gpu_version.sh | sed -n '2p')
GIT_REV=$(shell git rev-parse --short HEAD)
ifeq (${HALO2_GPU_VERSION},)
# use halo2_proofs with CPU
ZK_VERSION=${ZKEVM_VERSION}-${HALO2_VERSION}
else
# use halo2_gpu
ZK_VERSION=${ZKEVM_VERSION}-${HALO2_GPU_VERSION}
endif
prover:
GIT_REV=${GIT_REV} ZK_VERSION=${ZK_VERSION} cargo build

View File

@@ -0,0 +1,21 @@
#!/bin/bash
config_file="$HOME/.cargo/config"
if [ ! -e "$config_file" ]; then
exit 0
fi
if [[ $(head -n 1 "$config_file") == "#"* ]]; then
exit 0
fi
halo2gpu_path=$(grep -Po '(?<=paths = \[")([^"]*)' $config_file)
pushd $halo2gpu_path
commit_hash=$(git log --pretty=format:%h -n 1)
echo "${commit_hash:0:7}"
popd

View File

@@ -3,6 +3,7 @@ pub mod types;
mod api;
use anyhow::{bail, Context, Ok, Result};
use std::rc::Rc;
use types::*;
use errors::*;
@@ -18,17 +19,18 @@ pub struct Config {
pub prover_version: String,
pub hard_fork_name: String,
}
pub struct CoordinatorClient<'a> {
pub struct CoordinatorClient {
api: API,
token: Option<String>,
config: Config,
key_signer: &'a KeySigner,
key_signer: Rc<KeySigner>,
}
impl<'a> CoordinatorClient<'a> {
pub fn new(config: Config, key_signer: &'a KeySigner) -> Result<Self> {
impl CoordinatorClient {
pub fn new(config: Config, key_signer: Rc<KeySigner>) -> Result<Self> {
let mut client = Self {
api: API::new(config.endpoint)?,
api: API::new(&config.endpoint)?,
token: None,
config,
key_signer,
@@ -38,7 +40,7 @@ impl<'a> CoordinatorClient<'a> {
}
fn login(&mut self) -> Result<()> {
let api = self.api;
let api = &self.api;
let challenge_response = block_on(api.challenge())?;
if challenge_response.errcode != Success {
bail!("challenge failed: {}", challenge_response.errmsg)
@@ -51,10 +53,10 @@ impl<'a> CoordinatorClient<'a> {
}
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,
challenge: token.clone(),
prover_name: self.config.prover_name.clone(),
prover_version: self.config.prover_version.clone(),
hard_fork_name: self.config.hard_fork_name.clone(),
};
let buffer = login_message.rlp();
@@ -77,7 +79,7 @@ impl<'a> CoordinatorClient<'a> {
}
pub fn get_task(&mut self, req: &GetTaskRequest) -> Result<Response<GetTaskResponseData>> {
let response = block_on(self.api.get_task(req, &self.token.unwrap()))?;
let response = block_on(self.api.get_task(req, self.token.as_ref().unwrap()))?;
if response.errcode == ErrJWTTokenExpired {
log::info!("JWT expired, attempting to re-login");
@@ -90,7 +92,7 @@ impl<'a> CoordinatorClient<'a> {
}
pub fn submit_proof(&mut self, req: &SubmitProofRequest) -> Result<Response<SubmitProofResponseData>> {
let response = block_on(self.api.submit_proof(req, &self.token.unwrap()))?;
let response = block_on(self.api.submit_proof(req, &self.token.as_ref().unwrap()))?;
if response.errcode == ErrJWTTokenExpired {
log::info!("JWT expired, attempting to re-login");

View File

@@ -8,8 +8,7 @@ pub struct API {
}
impl API {
pub fn new(url_base: String) -> Result<Self> {
let mut headers = header::HeaderMap::new();
pub fn new(url_base: &String) -> Result<Self> {
Ok(Self {
url_base: Url::parse(&url_base)?,
client: reqwest::Client::new(),

View File

@@ -58,7 +58,7 @@ pub struct GetTaskResponseData {
pub task_id: String,
pub task_type: crate::types::ProofType,
pub task_data: String,
pub hard_fork_name: String,
pub hard_fork_name: Option<String>,
}
#[derive(Serialize, Deserialize, Default)]

View File

@@ -32,7 +32,7 @@ impl GethClient {
})
}
pub fn get_block_trace_by_hash(&self, hash: CommonHash) -> Result<BlockTrace> {
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

View File

@@ -39,7 +39,7 @@ impl<'a> TaskProcesser<'a> {
match self.prover.prove_task(&task) {
Ok(proof_detail) => {
self.prover.submit_proof(&proof_detail, task.uuid)
self.prover.submit_proof(&proof_detail, task.uuid.clone())
},
Err(error) => {
self.prover.submit_error(&task, types::ProofFailureType::NoPanic, error)

View File

@@ -3,6 +3,8 @@ use ethers_core::types::BlockNumber;
use eth_types::U64;
use once_cell::sync::Lazy;
use std::cmp::Ordering;
use std::rc::Rc;
use std::cell::RefCell;
use std::env;
use crate::types::{CommonHash, ProofFailureType, ProofStatus};
@@ -22,9 +24,9 @@ pub(crate) static OUTPUT_DIR: Lazy<Option<String>> =
pub struct Prover<'a> {
config: &'a Config,
key_signer: KeySigner,
key_signer: Rc<KeySigner>,
circuits_handler_provider: CircuitsHandlerProvider,
coordinator_client: CoordinatorClient<'a>,
coordinator_client: RefCell<CoordinatorClient>,
geth_client: GethClient,
}
@@ -36,25 +38,26 @@ fn is_positive(n: &U64) -> bool {
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 keystore_path = config.keystore_path;
let keystore_password = config.keystore_password;
let params_path = &config.core.params_path;
let assets_path = &config.core.assets_path;
let keystore_path = &config.keystore_path;
let keystore_password = &config.keystore_password;
let coordinator_config = CoordinatorConfig {
endpoint: config.coordinator.base_url,
prover_name: config.prover_name,
endpoint: config.coordinator.base_url.clone(),
prover_name: config.prover_name.clone(),
prover_version: crate::version::get_version(),
hard_fork_name: config.hard_fork_name,
hard_fork_name: config.hard_fork_name.clone(),
};
let key_signer = KeySigner::new(&keystore_path, &keystore_password)?;
let key_signer = Rc::new(KeySigner::new(&keystore_path, &keystore_password)?);
let coordinator_client = CoordinatorClient::new(coordinator_config, Rc::clone(&key_signer))?;
let prover = Prover {
config,
key_signer,
circuits_handler_provider: CircuitsHandlerProvider::new(proof_type, &params_path, &assets_path)?,
coordinator_client: CoordinatorClient::new(coordinator_config, &key_signer)?,
key_signer: Rc::clone(&key_signer),
circuits_handler_provider: CircuitsHandlerProvider::new(proof_type, params_path, assets_path)?,
coordinator_client: RefCell::new(coordinator_client),
geth_client: GethClient::new("test", &config.l2geth.endpoint)?,
};
@@ -87,7 +90,7 @@ impl<'a> Prover<'a> {
unreachable!()
}
let resp = self.coordinator_client.get_task(&req)?;
let resp = self.coordinator_client.borrow_mut().get_task(&req)?;
Task::try_from(&resp.data.unwrap()).map_err(|e| anyhow::anyhow!(e))
}
@@ -103,7 +106,7 @@ impl<'a> Prover<'a> {
fn do_prove(&self, task: &Task, handler: &Box<dyn CircuitsHandler>) -> Result<ProofDetail> {
let mut proof_detail = ProofDetail {
id: task.id,
id: task.id.clone(),
proof_type: task.task_type,
status: ProofStatus::Error,
..Default::default()
@@ -135,41 +138,41 @@ impl<'a> Prover<'a> {
pub fn submit_proof(&self, proof_detail: &ProofDetail, uuid: String) -> Result<()> {
let proof_data = match proof_detail.proof_type {
ProofType::ProofTypeBatch => {
serde_json::to_string(&proof_detail.batch_proof.unwrap())?
serde_json::to_string(proof_detail.batch_proof.as_ref().unwrap())?
},
ProofType::ProofTypeChunk => {
serde_json::to_string(&proof_detail.chunk_proof.unwrap())?
serde_json::to_string(proof_detail.chunk_proof.as_ref().unwrap())?
},
_ => unreachable!()
};
let request = SubmitProofRequest {
uuid,
task_id: proof_detail.id,
task_id: proof_detail.id.clone(),
task_type: proof_detail.proof_type,
status: proof_detail.status,
proof: proof_data,
..Default::default()
};
Ok(())
self.do_submit(&request)
}
pub fn submit_error(&self, task: &Task, failure_type: ProofFailureType, error: Error) -> Result<()> {
let request = SubmitProofRequest {
uuid: task.uuid,
task_id: task.id,
uuid: task.uuid.clone(),
task_id: task.id.clone(),
task_type: task.task_type,
status: ProofStatus::Error,
proof: todo!(),
failure_type: todo!(),
failure_msg: todo!(),
failure_type: Some(failure_type),
failure_msg: Some(error.to_string()),
..Default::default()
};
self.do_submit(&request)
}
fn do_submit(&self, request: &SubmitProofRequest) -> Result<()> {
self.coordinator_client.submit_proof(request)?;
self.coordinator_client.borrow_mut().submit_proof(request)?;
Ok(())
}
@@ -203,22 +206,22 @@ impl<'a> Prover<'a> {
}
fn gen_chunk_traces(&self, task: &Task) -> Result<Vec<BlockTrace>> {
if let Some(chunk_detail) = task.chunk_task_detail {
self.get_sorted_traces_by_hashes(chunk_detail.block_hashes)
if let Some(chunk_detail) = task.chunk_task_detail.as_ref() {
self.get_sorted_traces_by_hashes(&chunk_detail.block_hashes)
} else {
bail!("invalid task")
}
}
fn gen_chunk_hashes_proofs(&self, task: &Task) -> Result<Vec<(ChunkHash, ChunkProof)>> {
if let Some(batch_detail) = task.batch_task_detail {
Ok(batch_detail.chunk_infos.into_iter().zip(batch_detail.chunk_proofs).collect())
if let Some(batch_detail) = task.batch_task_detail.as_ref() {
Ok(batch_detail.chunk_infos.clone().into_iter().zip(batch_detail.chunk_proofs.clone()).collect())
} else {
bail!("invalid task")
}
}
fn get_sorted_traces_by_hashes(&self, block_hashes: Vec<CommonHash>) -> Result<Vec<BlockTrace>> {
fn get_sorted_traces_by_hashes(&self, block_hashes: &Vec<CommonHash>) -> Result<Vec<BlockTrace>> {
if block_hashes.len() == 0 {
bail!("blockHashes is empty")
}

View File

@@ -81,8 +81,8 @@ pub struct Task {
impl Task {
pub fn get_version(&self) -> String {
match self.hard_fork_name {
Some(v) => v,
match self.hard_fork_name.as_ref() {
Some(v) => v.clone(),
None => "".to_string(),
}
}
@@ -93,19 +93,19 @@ impl TryFrom<&GetTaskResponseData> for Task {
fn try_from(value: &GetTaskResponseData) -> Result<Self, Self::Error> {
let mut task = Task {
uuid: value.uuid,
id: value.task_id,
uuid: value.uuid.clone(),
id: value.task_id.clone(),
task_type: value.task_type,
chunk_task_detail: None,
batch_task_detail: None,
hard_fork_name: None,
hard_fork_name: value.hard_fork_name.clone(),
};
match task.task_type {
ProofType::ProofTypeBatch => {
task.batch_task_detail = serde_json::from_str(&value.task_data)?;
task.batch_task_detail = Some(serde_json::from_str(&value.task_data)?);
},
ProofType::ProofTypeChunk => {
task.chunk_task_detail = serde_json::from_str(&value.task_data)?;
task.chunk_task_detail = Some(serde_json::from_str(&value.task_data)?);
},
_ => unreachable!()
}

View File

@@ -1,10 +1,19 @@
use std::cell::OnceCell;
static DEFAULT_COMMIT: &str = "unknown";
static mut VERSION: OnceCell<String> = OnceCell::new();
pub const TAG: &str = "v4.4.3";
pub const COMMIT: &str = "test";
pub const ZK_VERSION: &str = "000000-000000";
pub const VERSION: String = format!("{TAG}-{COMMIT}-{ZK_VERSION}");
pub const DEFAULT_ZK_VERSION: &str = "000000-000000";
fn init_version() -> String {
let commit = option_env!("GIT_REV").unwrap_or(DEFAULT_COMMIT);
let zk_version = option_env!("ZK_VERSION").unwrap_or(DEFAULT_ZK_VERSION);
format!("{TAG}-{commit}-{zk_version}")
}
pub fn get_version() -> String {
VERSION
unsafe {
VERSION.get_or_init(init_version).clone()
}
}

View File

@@ -4,30 +4,27 @@ 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};
use prover::zkevm::Prover as ChunkProver;
use prover::aggregator::Prover as BatchProver;
use std::cell::RefCell;
#[derive(Default)]
pub struct BaseCircuitsHandler {
chunk_prover: Option<ChunkProver>,
chunk_verifier: Option<ChunkVerifier>,
batch_prover: Option<BatchProver>,
batch_verifier: Option<BaatchVerifier>,
chunk_prover: Option<RefCell<ChunkProver>>,
batch_prover: Option<RefCell<BatchProver>>,
}
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)),
chunk_prover: Some(RefCell::new(ChunkProver::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)),
batch_prover: Some(RefCell::new(BatchProver::from_dirs(params_dir, assets_dir))),
..Default::default()
}),
// TODO: add custom error system and change unreachable to error
@@ -39,7 +36,7 @@ impl BaseCircuitsHandler {
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())
self.chunk_prover.as_ref().and_then(|prover| prover.borrow().get_vk())
}
fn prover_gen_chunk_proof(&self,
@@ -47,8 +44,8 @@ impl CircuitsHandler for BaseCircuitsHandler {
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)
if let Some(prover) = self.chunk_prover.as_ref() {
return prover.borrow_mut().gen_chunk_proof(chunk_trace, name, inner_id, output_dir)
}
// TODO: add custom error system and change unreachable to error
unreachable!()
@@ -56,23 +53,23 @@ impl CircuitsHandler for BaseCircuitsHandler {
// api of aggregator::Prover
fn aggregator_get_vk(&self) -> Option<Vec<u8>> {
self.batch_prover.and_then(|prover| prover.get_vk())
self.batch_prover.as_ref().and_then(|prover| prover.borrow().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)
if let Some(prover) = self.batch_prover.as_ref() {
return prover.borrow_mut().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)
if let Some(prover) = self.batch_prover.as_ref() {
return prover.borrow_mut().check_chunk_proofs(chunk_proofs)
}
// TODO: add custom error system and change unreachable to error
unreachable!()