mirror of
https://github.com/scroll-tech/scroll.git
synced 2026-04-23 03:00:50 -04:00
tmp save
This commit is contained in:
4966
prover_rust/Cargo.lock
generated
Normal file
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
36
prover_rust/Cargo.toml
Normal 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
22
prover_rust/config.json
Normal 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"
|
||||
}
|
||||
}
|
||||
1
prover_rust/rust-toolchain
Normal file
1
prover_rust/rust-toolchain
Normal file
@@ -0,0 +1 @@
|
||||
nightly-2023-12-03
|
||||
9
prover_rust/rustfmt.toml
Normal file
9
prover_rust/rustfmt.toml
Normal 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
65
prover_rust/src/config.rs
Normal 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)
|
||||
}
|
||||
}
|
||||
99
prover_rust/src/coordinator_client.rs
Normal file
99
prover_rust/src/coordinator_client.rs
Normal 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)
|
||||
}
|
||||
}
|
||||
92
prover_rust/src/coordinator_client/api.rs
Normal file
92
prover_rust/src/coordinator_client/api.rs
Normal 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))
|
||||
}
|
||||
}
|
||||
20
prover_rust/src/coordinator_client/errors.rs
Normal file
20
prover_rust/src/coordinator_client/errors.rs
Normal 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;
|
||||
69
prover_rust/src/coordinator_client/types.rs
Normal file
69
prover_rust/src/coordinator_client/types.rs
Normal 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 {}
|
||||
79
prover_rust/src/geth_client.rs
Normal file
79
prover_rust/src/geth_client.rs
Normal 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)
|
||||
}
|
||||
}
|
||||
37
prover_rust/src/geth_client/types.rs
Normal file
37
prover_rust/src/geth_client/types.rs
Normal 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
59
prover_rust/src/main.rs
Normal 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
105
prover_rust/src/prover.rs
Normal 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, ¶ms_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
135
prover_rust/src/types.rs
Normal 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,
|
||||
}
|
||||
77
prover_rust/src/zk_circuits_handler.rs
Normal file
77
prover_rust/src/zk_circuits_handler.rs
Normal 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!()
|
||||
}
|
||||
}
|
||||
}
|
||||
80
prover_rust/src/zk_circuits_handler/base.rs
Normal file
80
prover_rust/src/zk_circuits_handler/base.rs
Normal 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!()
|
||||
}
|
||||
}
|
||||
1
prover_rust/src/zk_circuits_handler/types.rs
Normal file
1
prover_rust/src/zk_circuits_handler/types.rs
Normal file
@@ -0,0 +1 @@
|
||||
pub use prover::{ChunkProof, BatchProof, BlockTrace, ChunkHash};
|
||||
Reference in New Issue
Block a user