mirror of
https://github.com/scroll-tech/scroll.git
synced 2026-04-23 03:00:50 -04:00
finish most logic, leaving some rust-style compiler issue to be solved
This commit is contained in:
6
prover_rust/Cargo.lock
generated
6
prover_rust/Cargo.lock
generated
@@ -2991,17 +2991,23 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"base64 0.13.1",
|
||||
"eth-keystore",
|
||||
"eth-types",
|
||||
"ethers-core 2.0.7 (git+https://github.com/scroll-tech/ethers-rs.git?branch=v2.0.7)",
|
||||
"ethers-providers 2.0.7 (git+https://github.com/scroll-tech/ethers-rs.git?branch=v2.0.7)",
|
||||
"futures",
|
||||
"halo2_proofs",
|
||||
"hex",
|
||||
"log",
|
||||
"once_cell",
|
||||
"prover",
|
||||
"rand",
|
||||
"reqwest 0.12.4",
|
||||
"rlp",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"snark-verifier-sdk",
|
||||
"tiny-keccak",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
@@ -34,3 +34,9 @@ prover = { git = "https://github.com/scroll-tech/zkevm-circuits.git", tag = "v0.
|
||||
eth-types = { git = "https://github.com/scroll-tech/zkevm-circuits.git", tag = "v0.10.3" }
|
||||
base64 = "0.13.1"
|
||||
reqwest = "0.12.4"
|
||||
once_cell = "1.19.0"
|
||||
hex = "0.4.3"
|
||||
tiny-keccak = { version = "2.0.0", features = ["sha3", "keccak"] }
|
||||
rand = "0.8.5"
|
||||
eth-keystore = "0.5.0"
|
||||
rlp = "0.5.2"
|
||||
|
||||
@@ -10,25 +10,28 @@ use api::API;
|
||||
use futures::executor::block_on;
|
||||
use log;
|
||||
|
||||
use crate::key_signer::KeySigner;
|
||||
|
||||
pub struct Config {
|
||||
pub endpoint: String,
|
||||
pub prover_name: String,
|
||||
pub prover_version: String,
|
||||
pub hard_fork_name: String,
|
||||
}
|
||||
|
||||
pub struct CoordinatorClient {
|
||||
pub struct CoordinatorClient<'a> {
|
||||
api: API,
|
||||
token: Option<String>,
|
||||
config: Config,
|
||||
key_signer: &'a KeySigner,
|
||||
}
|
||||
|
||||
impl CoordinatorClient {
|
||||
pub fn new(config: Config) -> Result<Self> {
|
||||
impl<'a> CoordinatorClient<'a> {
|
||||
pub fn new(config: Config, key_signer: &'a KeySigner) -> Result<Self> {
|
||||
let mut client = Self {
|
||||
api: API::new(config.endpoint)?,
|
||||
token: None,
|
||||
config: config,
|
||||
config,
|
||||
key_signer,
|
||||
};
|
||||
client.login()?;
|
||||
Ok(client)
|
||||
@@ -54,11 +57,13 @@ impl CoordinatorClient {
|
||||
hard_fork_name: self.config.hard_fork_name,
|
||||
};
|
||||
|
||||
let buffer = login_message.rlp();
|
||||
let signature = self.key_signer.sign_buffer(&buffer)?;
|
||||
let login_request = LoginRequest {
|
||||
message: login_message,
|
||||
signature: login_message.sign_with_key(),
|
||||
signature: signature,
|
||||
};
|
||||
let login_response = block_on(api.login(&login_request, &token));
|
||||
let login_response = block_on(api.login(&login_request, &token))?;
|
||||
if login_response.errcode != Success {
|
||||
bail!("login failed: {}", login_response.errmsg)
|
||||
}
|
||||
@@ -71,8 +76,8 @@ impl CoordinatorClient {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn get_task(&mut self, req: GetTaskRequest) -> Result<Response<GetTaskResponseData>> {
|
||||
let response = block_on(self.api.get_task(&req, &self.token))?;
|
||||
pub fn get_task(&mut self, req: &GetTaskRequest) -> Result<Response<GetTaskResponseData>> {
|
||||
let response = block_on(self.api.get_task(req, &self.token.unwrap()))?;
|
||||
|
||||
if response.errcode == ErrJWTTokenExpired {
|
||||
log::info!("JWT expired, attempting to re-login");
|
||||
@@ -84,15 +89,15 @@ impl CoordinatorClient {
|
||||
Ok(response)
|
||||
}
|
||||
|
||||
pub fn submit_proof(&mut self, req: SubmitProofRequest) -> Result<Response<SubmitProofResponseData>> {
|
||||
let response = block_on(self.api.get_task(&req, &self.token))?;
|
||||
pub fn submit_proof(&mut self, req: &SubmitProofRequest) -> Result<Response<SubmitProofResponseData>> {
|
||||
let response = block_on(self.api.submit_proof(req, &self.token.unwrap()))?;
|
||||
|
||||
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)
|
||||
bail!("submit proof failed: {}", response.errmsg)
|
||||
}
|
||||
Ok(response)
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ impl API {
|
||||
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 request_body = serde_json::to_string(req)?;
|
||||
|
||||
let response = self.client
|
||||
.post(url)
|
||||
@@ -67,11 +67,11 @@ impl API {
|
||||
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>> {
|
||||
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 request_body = serde_json::to_string(req)?;
|
||||
|
||||
let response = self.client
|
||||
.post(url)
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
use eth_types::Bytes;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use crate::types::{ProofStatus, ProofFailureType};
|
||||
use rlp::RlpStream;
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct Response<T> {
|
||||
@@ -16,12 +19,15 @@ pub struct LoginMessage {
|
||||
}
|
||||
|
||||
impl LoginMessage {
|
||||
pub fn hash() -> Result<Vec<u8>> {
|
||||
|
||||
}
|
||||
|
||||
pub fn sign_with_key() -> Result<String> {
|
||||
|
||||
pub fn rlp(&self) -> Vec<u8> {
|
||||
let mut rlp = RlpStream::new();
|
||||
let num_fields = 4;
|
||||
rlp.begin_list(num_fields);
|
||||
rlp.append(&self.prover_name);
|
||||
rlp.append(&self.prover_version);
|
||||
rlp.append(&self.challenge);
|
||||
rlp.append(&self.hard_fork_name);
|
||||
rlp.out().freeze().into()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,16 +58,17 @@ pub struct GetTaskResponseData {
|
||||
pub task_id: String,
|
||||
pub task_type: crate::types::ProofType,
|
||||
pub task_data: String,
|
||||
pub hard_fork_name: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Serialize, Deserialize, Default)]
|
||||
pub struct SubmitProofRequest {
|
||||
pub uuid: String,
|
||||
pub task_id: String,
|
||||
pub task_type: i32,
|
||||
pub status: i32,
|
||||
pub task_type: crate::types::ProofType,
|
||||
pub status: ProofStatus,
|
||||
pub proof: String,
|
||||
pub failure_type: Option<i32>,
|
||||
pub failure_type: Option<ProofFailureType>,
|
||||
pub failure_msg: Option<String>,
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
mod types;
|
||||
pub mod types;
|
||||
|
||||
use anyhow::Result;
|
||||
use crate::types::CommonHash;
|
||||
|
||||
@@ -19,6 +19,10 @@ pub struct BlockTrace {
|
||||
pub mpt_witness: Vec<u8>,
|
||||
}
|
||||
|
||||
pub fn get_block_number(block_trace: &ProverBlockTrace) -> Option<u64> {
|
||||
block_trace.header.number.map(|n| n.as_u64())
|
||||
}
|
||||
|
||||
pub type TxHash = H256;
|
||||
|
||||
/// this struct is tracked to https://github.com/scroll-tech/go-ethereum/blob/0f0cd99f7a2e/core/types/block.go#Header
|
||||
|
||||
108
prover_rust/src/key_signer.rs
Normal file
108
prover_rust/src/key_signer.rs
Normal file
@@ -0,0 +1,108 @@
|
||||
use std::path::Path;
|
||||
|
||||
use anyhow::Result;
|
||||
use ethers_core::k256::{
|
||||
ecdsa::{signature::hazmat::PrehashSigner, RecoveryId, Signature, SigningKey},
|
||||
elliptic_curve::{sec1::ToEncodedPoint, FieldBytes},
|
||||
Secp256k1,
|
||||
PublicKey,
|
||||
SecretKey
|
||||
};
|
||||
|
||||
use hex::ToHex;
|
||||
use tiny_keccak::{Hasher, Keccak};
|
||||
use eth_types::{H256, U256};
|
||||
|
||||
use ethers_core::types::Signature as EthSignature;
|
||||
|
||||
|
||||
pub struct KeySigner {
|
||||
public_key: PublicKey,
|
||||
signer: SigningKey,
|
||||
}
|
||||
|
||||
impl KeySigner {
|
||||
pub fn new(key_path: &str, passwd: &str) -> Result<Self> {
|
||||
let p = Path::new(key_path);
|
||||
|
||||
let secret = if !p.exists() {
|
||||
let dir = p.parent().unwrap();
|
||||
let name = p.file_name().and_then(|s| s.to_str());
|
||||
let mut rng = rand::thread_rng();
|
||||
let (secret, _) = eth_keystore::new(dir, &mut rng, passwd, name)?;
|
||||
secret
|
||||
} else {
|
||||
eth_keystore::decrypt_key(key_path, passwd).map_err(|e| anyhow::anyhow!(e))?
|
||||
};
|
||||
|
||||
|
||||
let secret_key = SecretKey::from_bytes(secret.as_slice().into())?;
|
||||
|
||||
let signer = SigningKey::from(secret_key.clone());
|
||||
|
||||
Ok(Self{
|
||||
public_key: secret_key.public_key(),
|
||||
signer: signer,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn get_public_key(&self) -> String {
|
||||
let v: Vec<u8> = Vec::from(self.public_key.to_encoded_point(true).as_bytes());
|
||||
buffer_to_hex(&v, false)
|
||||
}
|
||||
|
||||
/// Signs the provided hash.
|
||||
pub fn sign_hash(&self, hash: H256) -> Result<EthSignature> {
|
||||
let signer = &self.signer as &dyn PrehashSigner<(Signature, RecoveryId)>;
|
||||
let (recoverable_sig, recovery_id) = signer.sign_prehash(hash.as_ref())?;
|
||||
|
||||
let v = u8::from(recovery_id) as u64;
|
||||
|
||||
let r_bytes: FieldBytes<Secp256k1> = recoverable_sig.r().into();
|
||||
let s_bytes: FieldBytes<Secp256k1> = recoverable_sig.s().into();
|
||||
let r = U256::from_big_endian(r_bytes.as_slice());
|
||||
let s = U256::from_big_endian(s_bytes.as_slice());
|
||||
|
||||
Ok(EthSignature { r, s, v })
|
||||
}
|
||||
|
||||
pub fn sign_buffer<T>(&self, buffer: &T) -> Result<String>
|
||||
where
|
||||
T: AsRef<[u8]>,
|
||||
{
|
||||
let pre_hash = keccak256(buffer);
|
||||
|
||||
let hash_str = buffer_to_hex(&pre_hash, true);
|
||||
println!("hash is {hash_str}");
|
||||
|
||||
let hash = H256::from(pre_hash);
|
||||
let sig = self.sign_hash(hash)?;
|
||||
|
||||
Ok(buffer_to_hex(&sig.to_vec(), true))
|
||||
}
|
||||
}
|
||||
|
||||
fn buffer_to_hex<T>(buffer: &T, has_prefix: bool) -> String
|
||||
where
|
||||
T: AsRef<[u8]>,
|
||||
{
|
||||
if has_prefix {
|
||||
format!("0x{}", buffer.encode_hex::<String>())
|
||||
} else {
|
||||
buffer.encode_hex::<String>()
|
||||
}
|
||||
}
|
||||
|
||||
/// Compute the Keccak-256 hash of input bytes.
|
||||
///
|
||||
/// Note that strings are interpreted as UTF-8 bytes,
|
||||
// TODO: Add Solidity Keccak256 packing support
|
||||
pub fn keccak256<T: AsRef<[u8]>>(bytes: T) -> [u8; 32] {
|
||||
let mut output = [0u8; 32];
|
||||
|
||||
let mut hasher = Keccak::v256();
|
||||
hasher.update(bytes.as_ref());
|
||||
hasher.finalize(&mut output);
|
||||
|
||||
output
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
|
||||
mod version;
|
||||
mod types;
|
||||
mod config;
|
||||
mod key_signer;
|
||||
mod prover;
|
||||
mod zk_circuits_handler;
|
||||
mod coordinator_client;
|
||||
@@ -36,9 +37,14 @@ impl<'a> TaskProcesser<'a> {
|
||||
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)
|
||||
match self.prover.prove_task(&task) {
|
||||
Ok(proof_detail) => {
|
||||
self.prover.submit_proof(&proof_detail, task.uuid)
|
||||
},
|
||||
Err(error) => {
|
||||
self.prover.submit_error(&task, types::ProofFailureType::NoPanic, error)
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,19 +1,30 @@
|
||||
use anyhow::{Ok, Result};
|
||||
use anyhow::{bail, Error, Ok, Result};
|
||||
use ethers_core::types::BlockNumber;
|
||||
use eth_types::U64;
|
||||
use once_cell::sync::Lazy;
|
||||
use std::cmp::Ordering;
|
||||
use std::env;
|
||||
|
||||
use crate::types::{CommonHash, ProofFailureType, ProofStatus};
|
||||
use crate::{config::Config, types::ProofType};
|
||||
use crate::zk_circuits_handler::CircuitsHandlerProvider;
|
||||
use crate::coordinator_client::CoordinatorClient;
|
||||
use crate::zk_circuits_handler::{CircuitsHandler, CircuitsHandlerProvider};
|
||||
use crate::coordinator_client::{CoordinatorClient, Config as CoordinatorConfig};
|
||||
use crate::coordinator_client::types::*;
|
||||
use crate::geth_client::GethClient;
|
||||
use crate::geth_client::{types::get_block_number, GethClient};
|
||||
use crate::key_signer::KeySigner;
|
||||
|
||||
use super::types::{Task, ProofDetail};
|
||||
use prover::{ChunkProof, ChunkHash, BlockTrace};
|
||||
|
||||
// Only used for debugging.
|
||||
pub(crate) static OUTPUT_DIR: Lazy<Option<String>> =
|
||||
Lazy::new(|| env::var("PROVER_OUTPUT_DIR").ok());
|
||||
|
||||
pub struct Prover<'a> {
|
||||
config: &'a Config,
|
||||
circuits_client_provider: CircuitsHandlerProvider,
|
||||
coordinator_client: CoordinatorClient,
|
||||
key_signer: KeySigner,
|
||||
circuits_handler_provider: CircuitsHandlerProvider,
|
||||
coordinator_client: CoordinatorClient<'a>,
|
||||
geth_client: GethClient,
|
||||
}
|
||||
|
||||
@@ -27,11 +38,23 @@ impl<'a> Prover<'a> {
|
||||
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 coordinator_config = CoordinatorConfig {
|
||||
endpoint: config.coordinator.base_url,
|
||||
prover_name: config.prover_name,
|
||||
prover_version: crate::version::get_version(),
|
||||
hard_fork_name: config.hard_fork_name,
|
||||
};
|
||||
|
||||
let key_signer = KeySigner::new(&keystore_path, &keystore_password)?;
|
||||
|
||||
let prover = Prover {
|
||||
config: config,
|
||||
circuits_client_provider: CircuitsHandlerProvider::new(proof_type, ¶ms_path, &assets_path)?,
|
||||
coordinator_client: CoordinatorClient::new(),
|
||||
config,
|
||||
key_signer,
|
||||
circuits_handler_provider: CircuitsHandlerProvider::new(proof_type, ¶ms_path, &assets_path)?,
|
||||
coordinator_client: CoordinatorClient::new(coordinator_config, &key_signer)?,
|
||||
geth_client: GethClient::new("test", &config.l2geth.endpoint)?,
|
||||
};
|
||||
|
||||
@@ -43,14 +66,14 @@ impl<'a> Prover<'a> {
|
||||
}
|
||||
|
||||
pub fn get_public_key(&self) -> String {
|
||||
"".to_string()
|
||||
self.key_signer.get_public_key()
|
||||
}
|
||||
|
||||
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(),
|
||||
vks: self.circuits_handler_provider.get_vks(),
|
||||
};
|
||||
|
||||
if self.get_proof_type() == ProofType::ProofTypeChunk {
|
||||
@@ -64,17 +87,89 @@ impl<'a> Prover<'a> {
|
||||
|
||||
unreachable!()
|
||||
}
|
||||
|
||||
let resp = self.coordinator_client.get_task(req)?;
|
||||
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> {
|
||||
let version = task.get_version();
|
||||
if let Some(handler) = self.circuits_handler_provider.get_circuits_client(version) {
|
||||
self.do_prove(task, handler)
|
||||
} else {
|
||||
bail!("failed to get a circuit handler")
|
||||
}
|
||||
}
|
||||
|
||||
fn do_prove(&self, task: &Task, handler: &Box<dyn CircuitsHandler>) -> Result<ProofDetail> {
|
||||
let mut proof_detail = ProofDetail {
|
||||
id: task.id,
|
||||
proof_type: task.task_type,
|
||||
status: ProofStatus::Error,
|
||||
..Default::default()
|
||||
};
|
||||
match task.task_type {
|
||||
ProofType::ProofTypeBatch => {
|
||||
let chunk_hashes_proofs = self.gen_chunk_hashes_proofs(task)?;
|
||||
let batch_proof = handler.aggregator_gen_agg_evm_proof(chunk_hashes_proofs,
|
||||
None,
|
||||
self.get_output_dir())?;
|
||||
|
||||
proof_detail.batch_proof = Some(batch_proof);
|
||||
Ok(proof_detail)
|
||||
},
|
||||
ProofType::ProofTypeChunk => {
|
||||
let chunk_trace = self.gen_chunk_traces(task)?;
|
||||
let chunk_proof = handler.prover_gen_chunk_proof(chunk_trace,
|
||||
None,
|
||||
None,
|
||||
self.get_output_dir())?;
|
||||
|
||||
proof_detail.chunk_proof = Some(chunk_proof);
|
||||
Ok(proof_detail)
|
||||
},
|
||||
_ => bail!("task type invalid")
|
||||
}
|
||||
}
|
||||
|
||||
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())?
|
||||
},
|
||||
ProofType::ProofTypeChunk => {
|
||||
serde_json::to_string(&proof_detail.chunk_proof.unwrap())?
|
||||
},
|
||||
_ => unreachable!()
|
||||
};
|
||||
|
||||
let request = SubmitProofRequest {
|
||||
uuid,
|
||||
task_id: proof_detail.id,
|
||||
task_type: proof_detail.proof_type,
|
||||
status: proof_detail.status,
|
||||
proof: proof_data,
|
||||
..Default::default()
|
||||
};
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn submit_error(&self, task: &Task, failure_type: ProofFailureType, error: Error) -> Result<()> {
|
||||
let request = SubmitProofRequest {
|
||||
uuid: task.uuid,
|
||||
task_id: task.id,
|
||||
task_type: task.task_type,
|
||||
status: ProofStatus::Error,
|
||||
proof: todo!(),
|
||||
failure_type: todo!(),
|
||||
failure_msg: todo!(),
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
fn do_submit(&self, request: &SubmitProofRequest) -> Result<()> {
|
||||
self.coordinator_client.submit_proof(request)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -102,4 +197,62 @@ impl<'a> Prover<'a> {
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
fn get_output_dir(&self) -> Option<&str> {
|
||||
OUTPUT_DIR.as_deref()
|
||||
}
|
||||
|
||||
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)
|
||||
} 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())
|
||||
} else {
|
||||
bail!("invalid task")
|
||||
}
|
||||
}
|
||||
|
||||
fn get_sorted_traces_by_hashes(&self, block_hashes: Vec<CommonHash>) -> Result<Vec<BlockTrace>> {
|
||||
if block_hashes.len() == 0 {
|
||||
bail!("blockHashes is empty")
|
||||
}
|
||||
|
||||
let mut block_traces = Vec::new();
|
||||
for (_, hash) in block_hashes.into_iter().enumerate() {
|
||||
let trace = self.geth_client.get_block_trace_by_hash(hash)?;
|
||||
block_traces.push(trace.block_trace);
|
||||
}
|
||||
|
||||
block_traces.sort_by(|a, b| {
|
||||
if get_block_number(a) == None {
|
||||
Ordering::Less
|
||||
} else if get_block_number(b) == None {
|
||||
Ordering::Greater
|
||||
} else {
|
||||
get_block_number(a).unwrap().cmp(&get_block_number(b).unwrap())
|
||||
}
|
||||
});
|
||||
|
||||
let block_numbers: Vec<u64> = block_traces.iter().map(|trace| {
|
||||
match get_block_number(trace) {
|
||||
Some(v) => v,
|
||||
None => 0
|
||||
}
|
||||
}).collect();
|
||||
let mut i = 0;
|
||||
while i < block_numbers.len() - 1 {
|
||||
if block_numbers[i] + 1 != block_numbers[i+1] {
|
||||
bail!("block numbers are not continuous, got {} and {}", block_numbers[i], block_numbers[i+1])
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
|
||||
Ok(block_traces)
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
use prover::BatchProof;
|
||||
use prover::{BatchProof, ChunkProof, ChunkHash};
|
||||
use serde::{Deserialize, Serialize, Serializer, Deserializer};
|
||||
use eth_types::H256;
|
||||
|
||||
@@ -54,37 +54,15 @@ impl Default for ProofType {
|
||||
}
|
||||
}
|
||||
|
||||
#[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>,
|
||||
pub chunk_infos: Vec<ChunkHash>,
|
||||
pub chunk_proofs: Vec<ChunkProof>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct ChunkTaskDetail {
|
||||
block_hashes: Vec<CommonHash>,
|
||||
pub block_hashes: Vec<CommonHash>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Default)]
|
||||
@@ -97,6 +75,17 @@ pub struct Task {
|
||||
pub batch_task_detail: Option<BatchTaskDetail>,
|
||||
#[serde(default)]
|
||||
pub chunk_task_detail: Option<ChunkTaskDetail>,
|
||||
#[serde(default)]
|
||||
pub hard_fork_name: Option<String>,
|
||||
}
|
||||
|
||||
impl Task {
|
||||
pub fn get_version(&self) -> String {
|
||||
match self.hard_fork_name {
|
||||
Some(v) => v,
|
||||
None => "".to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&GetTaskResponseData> for Task {
|
||||
@@ -109,6 +98,7 @@ impl TryFrom<&GetTaskResponseData> for Task {
|
||||
task_type: value.task_type,
|
||||
chunk_task_detail: None,
|
||||
batch_task_detail: None,
|
||||
hard_fork_name: None,
|
||||
};
|
||||
match task.task_type {
|
||||
ProofType::ProofTypeBatch => {
|
||||
@@ -123,13 +113,102 @@ impl TryFrom<&GetTaskResponseData> for Task {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Serialize, Deserialize, Default)]
|
||||
pub struct ProofDetail {
|
||||
pub id: String,
|
||||
#[serde(rename = "type", default)]
|
||||
pub proof_type: ProofType,
|
||||
pub status: u32,
|
||||
pub status: ProofStatus,
|
||||
pub chunk_proof: Option<ChunkProof>,
|
||||
pub batch_proof: Option<BatchProof>,
|
||||
pub error: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub enum ProofFailureType {
|
||||
Undefined,
|
||||
Panic,
|
||||
NoPanic
|
||||
}
|
||||
|
||||
impl ProofFailureType {
|
||||
fn from_u8(v: u8) -> Self {
|
||||
match v {
|
||||
1 => ProofFailureType::Panic,
|
||||
2 => ProofFailureType::NoPanic,
|
||||
_ => ProofFailureType::Undefined,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for ProofFailureType {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
match *self {
|
||||
ProofFailureType::Undefined => serializer.serialize_u8(0),
|
||||
ProofFailureType::Panic => serializer.serialize_u8(1),
|
||||
ProofFailureType::NoPanic => serializer.serialize_u8(2),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for ProofFailureType {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let v: u8 = u8::deserialize(deserializer)?;
|
||||
Ok(ProofFailureType::from_u8(v))
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for ProofFailureType {
|
||||
fn default() -> Self {
|
||||
Self::Undefined
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub enum ProofStatus {
|
||||
Ok,
|
||||
Error,
|
||||
}
|
||||
|
||||
impl ProofStatus {
|
||||
fn from_u8(v: u8) -> Self {
|
||||
match v {
|
||||
0 => ProofStatus::Ok,
|
||||
_ => ProofStatus::Error,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for ProofStatus {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
match *self {
|
||||
ProofStatus::Ok => serializer.serialize_u8(0),
|
||||
ProofStatus::Error => serializer.serialize_u8(1),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for ProofStatus {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let v: u8 = u8::deserialize(deserializer)?;
|
||||
Ok(ProofStatus::from_u8(v))
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for ProofStatus {
|
||||
fn default() -> Self {
|
||||
Self::Ok
|
||||
}
|
||||
}
|
||||
10
prover_rust/src/version.rs
Normal file
10
prover_rust/src/version.rs
Normal file
@@ -0,0 +1,10 @@
|
||||
|
||||
|
||||
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 fn get_version() -> String {
|
||||
VERSION
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
mod types;
|
||||
mod base;
|
||||
|
||||
|
||||
use types::{ChunkProof, BatchProof, BlockTrace, ChunkHash};
|
||||
use anyhow::Result;
|
||||
use std::collections::HashMap;
|
||||
|
||||
Reference in New Issue
Block a user