diff --git a/.github/labeler.yml b/.github/labeler.yml index d64cda1ec..baacbe1fa 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -13,11 +13,6 @@ - changed-files: - any-glob-to-any-file: trace_decoder/** -# Add 'crate: proof_gen' label to any changes within 'proof_gen' folder. -'crate: proof_gen': -- changed-files: - - any-glob-to-any-file: proof_gen/** - # Add 'crate: zero_bin' label to any changes within 'zero' folder. 'crate: zero_bin': - changed-files: diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 066789eea..8e8ea6aee 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -71,31 +71,6 @@ jobs: - name: test run: cargo test --release --manifest-path trace_decoder/Cargo.toml -- --nocapture - test_proof_gen: - name: Test proof_gen - runs-on: ubuntu-latest - timeout-minutes: 30 - if: ${{ ! contains(toJSON(github.event.commits.*.message), '[skip-ci]') }} - steps: - - name: Checkout sources - uses: actions/checkout@v4 - - - name: Install nightly toolchain - uses: dtolnay/rust-toolchain@nightly - - - name: Set up rust cache - uses: Swatinem/rust-cache@v2 - with: - cache-on-failure: true - - - name: Test in proof_gen subdirectory - run: cargo test --manifest-path proof_gen/Cargo.toml - env: - RUSTFLAGS: -Copt-level=3 -Cdebug-assertions -Coverflow-checks=y -Cdebuginfo=0 - RUST_LOG: 1 - CARGO_INCREMENTAL: 1 - RUST_BACKTRACE: 1 - test_evm_arithmetization: name: Test evm_arithmetization runs-on: ubuntu-latest diff --git a/Cargo.lock b/Cargo.lock index dcd3ec2b7..770f7253f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3853,19 +3853,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "proof_gen" -version = "0.4.0" -dependencies = [ - "evm_arithmetization", - "hashbrown", - "log", - "paste", - "plonky2", - "serde", - "zk_evm_common", -] - [[package]] name = "proptest" version = "1.5.0" @@ -5790,6 +5777,7 @@ dependencies = [ "dotenvy", "evm_arithmetization", "futures", + "hashbrown", "hex", "itertools 0.13.0", "jemallocator", @@ -5802,7 +5790,6 @@ dependencies = [ "plonky2", "plonky2_maybe_rayon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "primitive-types 0.12.2", - "proof_gen", "ruint", "serde", "serde_json", diff --git a/Cargo.toml b/Cargo.toml index 45f521447..9cbc60fd4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,6 @@ members = [ "evm_arithmetization", "mpt_trie", "proc_macro", - "proof_gen", "smt_trie", "trace_decoder", "zero", @@ -104,7 +103,6 @@ winnow = "0.6.13" # local dependencies evm_arithmetization = { path = "evm_arithmetization", version = "0.4.0", default-features = false } mpt_trie = { path = "mpt_trie", version = "0.4.1" } -proof_gen = { path = "proof_gen", version = "0.4.0", default-features = false } smt_trie = { path = "smt_trie", version = "0.1.1" } trace_decoder = { path = "trace_decoder", version = "0.6.0", default-features = false } zk_evm_common = { path = "common", version = "0.1.0" } diff --git a/README.md b/README.md index b7bd2208e..69fbc79a2 100644 --- a/README.md +++ b/README.md @@ -18,9 +18,7 @@ understood by the zkEVM prover. * [evm_arithmetization](./evm_arithmetization/README.md): Defines all the STARK constraints and recursive circuits to generate succinct proofs of EVM execution. It uses starky and plonky2 as proving backend: https://github.com/0xPolygonZero/plonky2. -* [proof_gen](./proof_gen/README.md): A convenience library for generating proofs from inputs already in Intermediate Representation (IR) format. - -* [zero_bin](./zero_bin/README.md): A composition of [`paladin`](https://github.com/0xPolygonZero/paladin) and [`proof_gen`](./proof_gen/README.md) to generate +* [zero_bin](./zero_bin/README.md): A composition of [`paladin`](https://github.com/0xPolygonZero/paladin) and [`evm_arithmetization`](./evm_arithmetization/README.md) to generate EVM block proofs. ## Dependency graph @@ -44,18 +42,14 @@ flowchart LR B[mpt_trie] C[evm_arithmetization] D[trace_decoder] - E[proof_gen] B --> C B ---> D C ---> D - C --> E - D --> E F{zero-bin} C --> F D --> F - E --> F end ``` diff --git a/evm_arithmetization/src/fixed_recursive_verifier.rs b/evm_arithmetization/src/fixed_recursive_verifier.rs index cb3cec8a8..94a658685 100644 --- a/evm_arithmetization/src/fixed_recursive_verifier.rs +++ b/evm_arithmetization/src/fixed_recursive_verifier.rs @@ -2157,7 +2157,7 @@ where /// This method outputs a tuple of [`ProofWithPublicInputs`] and /// its [`PublicValues`]. Only the proof with public inputs is necessary /// for a verifier to assert correctness of the computation. - pub fn prove_transaction_aggregation( + pub fn prove_batch_aggregation( &self, lhs_is_agg: bool, lhs_proof: &ProofWithPublicInputs, diff --git a/evm_arithmetization/tests/global_exit_root.rs b/evm_arithmetization/tests/global_exit_root.rs index 193255622..b7e82c7a0 100644 --- a/evm_arithmetization/tests/global_exit_root.rs +++ b/evm_arithmetization/tests/global_exit_root.rs @@ -13,7 +13,7 @@ use evm_arithmetization::testing_utils::{ ADDRESS_SCALABLE_L2_ADDRESS_HASHED, GLOBAL_EXIT_ROOT_ACCOUNT, GLOBAL_EXIT_ROOT_ADDRESS_HASHED, }; use evm_arithmetization::verifier::testing::verify_all_proofs; -use evm_arithmetization::{AllStark, Node, StarkConfig}; +use evm_arithmetization::{AllStark, Node, StarkConfig, EMPTY_CONSOLIDATED_BLOCKHASH}; use keccak_hash::keccak; use mpt_trie::partial_trie::{HashedPartialTrie, PartialTrie}; use plonky2::field::goldilocks_field::GoldilocksField; diff --git a/evm_arithmetization/tests/two_to_one_block.rs b/evm_arithmetization/tests/two_to_one_block.rs index a420a223b..9c4eb7f29 100644 --- a/evm_arithmetization/tests/two_to_one_block.rs +++ b/evm_arithmetization/tests/two_to_one_block.rs @@ -124,7 +124,7 @@ fn get_test_block_proof( let dummy0_proof = all_circuits.prove_segment_aggregation(false, &dummy1_proof[0], false, &dummy1_proof[1])?; - let (agg_proof, pv) = all_circuits.prove_transaction_aggregation( + let (agg_proof, pv) = all_circuits.prove_batch_aggregation( false, &inputs0_proof.proof_with_pis, inputs0_proof.public_values, diff --git a/proof_gen/Cargo.toml b/proof_gen/Cargo.toml deleted file mode 100644 index 1e2f595b9..000000000 --- a/proof_gen/Cargo.toml +++ /dev/null @@ -1,36 +0,0 @@ -[package] -name = "proof_gen" -description = "Generates block proofs from zero proof IR." -version = "0.4.0" -authors = ["Polygon Zero "] -edition.workspace = true -license.workspace = true -repository.workspace = true -homepage.workspace = true -keywords.workspace = true - -[dependencies] -log = { workspace = true } -paste = { workspace = true } -plonky2 = { workspace = true } -serde = { workspace = true } -hashbrown = { workspace = true } - -# Local dependencies -evm_arithmetization = { workspace = true } -zk_evm_common = { workspace = true } - -[features] -default = ["eth_mainnet"] -eth_mainnet = [ - "evm_arithmetization/eth_mainnet" -] -cdk_erigon = [ - "evm_arithmetization/cdk_erigon" -] -polygon_pos = [ - "evm_arithmetization/polygon_pos" -] - -[lints] -workspace = true diff --git a/proof_gen/README.md b/proof_gen/README.md deleted file mode 100644 index 09730359a..000000000 --- a/proof_gen/README.md +++ /dev/null @@ -1,43 +0,0 @@ -# Proof generator - -Library for generating proofs from proof IR. - - -# General Usage (Extremely rough, will change) - -In [proof_gen.rs](https://github.com/0xPolygonZero/zk_evm/proof-gen/blob/main/src/proof_gen.rs), there are three core functions: - -- `generate_txn_proof` -- `generate_agg_proof` -- `generate_block_proof` - -Both libraries are currently targeting the latest [plonky2](https://github.com/0xPolygonZero/plonky2). One noteworthy piece of data that all proofs need is this: - -```rust -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct BlockHashes { - pub prev_hashes: Vec, - pub cur_hash: H256, -} -``` -Note that `prev_hashes` is going to be `256` elements long (!) most of the time. - -`generate_txn_proof` takes in the output from the parser lib (`GenerationInputs`). - -`generate_agg_proof` takes in the two child proofs (wrapped in `AggregatableProof`` to support txn or agg proofs). - -`generate_block_proof` is a bit less obvious. You give it an agg proof that contains all txns in the entire block, but also pass in an optional previous block proof. The previous block proof is able to be `None` on checkpoint heights. - -## License - -Licensed under either of - -* Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) -* MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) - -at your option. - - -### Contribution - -Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/proof_gen/src/constants.rs b/proof_gen/src/constants.rs deleted file mode 100644 index 9e00a93eb..000000000 --- a/proof_gen/src/constants.rs +++ /dev/null @@ -1,27 +0,0 @@ -//! Hardcoded circuit constants to be used when generating the prover circuits. - -use core::ops::Range; - -/// Default range to be used for the `ArithmeticStark` table. -pub(crate) const DEFAULT_ARITHMETIC_RANGE: Range = 16..28; -/// Default range to be used for the `BytePackingStark` table. -pub(crate) const DEFAULT_BYTE_PACKING_RANGE: Range = 9..28; -/// Default range to be used for the `CpuStark` table. -pub(crate) const DEFAULT_CPU_RANGE: Range = 12..28; -/// Default range to be used for the `KeccakStark` table. -pub(crate) const DEFAULT_KECCAK_RANGE: Range = 14..25; -/// Default range to be used for the `KeccakSpongeStark` table. -pub(crate) const DEFAULT_KECCAK_SPONGE_RANGE: Range = 9..25; -/// Default range to be used for the `LogicStark` table. -pub(crate) const DEFAULT_LOGIC_RANGE: Range = 12..28; -/// Default range to be used for the `MemoryStark` table. -pub(crate) const DEFAULT_MEMORY_RANGE: Range = 17..30; -// TODO: adapt the ranges once we have a better idea of the more common ranges -// for the next two STARKs. -/// Default range to be used for the `MemoryBeforeStark` table. -pub(crate) const DEFAULT_MEMORY_BEFORE_RANGE: Range = 8..20; -/// Default range to be used for the `MemoryAfterStark` table. -pub(crate) const DEFAULT_MEMORY_AFTER_RANGE: Range = 16..30; -#[cfg(feature = "cdk_erigon")] -/// Default range to be used for the `PoseidonStark` table. -pub(crate) const DEFAULT_POSEIDON_RANGE: Range = 4..25; diff --git a/proof_gen/src/lib.rs b/proof_gen/src/lib.rs deleted file mode 100644 index bb08f59f3..000000000 --- a/proof_gen/src/lib.rs +++ /dev/null @@ -1,147 +0,0 @@ -//! This library is intended to generate proofs with the [plonky2 zkEVM](https://github.com/0xPolygonZero/plonky2/evm), given -//! transactions provided in Intermediate Representation (IR) format. -//! -//! The exact format of this IR is defined by the [GenerationInputs](https://github.com/0xPolygonZero/plonky2/evm/src/generation/mod.rs) -//! used by the zkEVM prover, containing an RLP-encoded transaction along with -//! state metadata prior and post execution of this transaction. -//! -//! # Usage -//! -//! First, a prover needs to initialize its `ProverState`. For this, one can -//! use the `ProverStateBuilder`, which contains the ranges to be used by all -//! internal STARK tables of the zkEVM. -//! -//! The default method contains an initial set of ranges for each table, that -//! can be overridden at will by calling -//! `ProverStateBuilder::set_foo_circuit_size` where `foo` is the name of the -//! targeted table. At the moment, plonky2 zkEVM contains seven tables: -//! `arithmetic`, `byte_packing`, `cpu`, `keccak`, `keccak_sponge`, `logic` and -//! `memory`. -//! -//! ```no_run -//! # use proof_gen::prover_state::ProverStateBuilder; -//! let mut builder = ProverStateBuilder::default(); -//! -//! // Change Cpu and Memory tables supported ranges. -//! let builder = builder -//! .set_cpu_circuit_size(12..25) -//! .set_memory_circuit_size(18..28); -//! -//! // Generate a `ProverState` from the builder. -//! let prover_state = builder.build(); -//! ``` -//! -//! ***NOTE***: All the circuits to generate the different kind of proofs, from -//! transaction proofs to block proofs, are specific to the initial set of -//! ranges selected for each table. Changing one of them will require building a -//! new `ProverState`, and will make all previously generated proofs -//! incompatible with the new state. Make sure you select sufficiently large -//! ranges for your application! -//! -//! Once all circuits have been pre-processed, a prover can now generate proofs -//! from inputs passed as Intermediary Representation. -//! -//! This library handles the 3 kinds of proof generations necessary for the -//! zkEVM: -//! -//! ### Segment proofs -//! -//! From a `ProverState` and a transaction processed with some metadata in -//! Intermediate Representation, one can obtain a segment proof by calling -//! the method below: -//! -//! ```compile_fail -//! pub fn generate_txn_proof( -//! p_state: &ProverState, -//! gen_inputs: GenerationInputs, -//! abort_signal: Option>, -//! ) -> ProofGenResult { ... } -//! ``` -//! -//! The obtained `GeneratedTxnProof` contains the actual proof and some -//! additional data to be used when aggregating this transaction with others. -//! -//! ### Segment Aggregation proofs -//! -//! Two proofs can be aggregated together with a `ProverState`. These `child` -//! proofs can either be segment proofs, or aggregated proofs themselves. -//! This library abstracts their type behind an `AggregatableProof` enum. -//! -//! ```compile_fail -//! pub fn generate_agg_proof( -//! p_state: &ProverState, -//! lhs_child: &AggregatableProof, -//! rhs_child: &AggregatableProof, -//! ) -> ProofGenResult { ... } -//! ``` -//! -//! ### Transaction Aggregation proofs -//! -//! Given a `GeneratedAggProof` corresponding to the entire set of segment -//! proofs within one transaction proof, the prover can wrap it into a -//! `GeneratedBlockProof`. The prover can pass an optional previous transaction -//! proof as argument to the `generate_transaction_agg_proof` method, to combine -//! both statements into one. -//! -//! ```compile_fail -//! pub fn generate_transaction_agg_proof( -//! p_state: &ProverState, -//! prev_opt_parent_b_proof: Option<&GeneratedBlockProof>, -//! curr_block_agg_proof: &GeneratedAggProof, -//! ) -> ProofGenResult { ... } -//! ``` -//! -//! ### Block proofs -//! -//! Once the prover has obtained a `GeneratedBlockProof` corresponding to the -//! entire set of transactions within a block, they can then wrap it into a -//! final `GeneratedBlockProof`. The prover can pass an optional previous -//! block proof as argument to the `generate_block_proof` method, to combine -//! both statement into one, effectively proving an entire chain from genesis -//! through a single final proof. -//! -//! ```compile_fail -//! pub fn generate_block_proof( -//! p_state: &ProverState, -//! prev_opt_parent_b_proof: Option<&GeneratedBlockProof>, -//! curr_block_agg_proof: &GeneratedAggProof, -//! ) -> ProofGenResult { ... } -//! ``` -//! -//! ## Verifying block proofs -//! -//! The `ProverState` can be used to verify any block proofs emitted with the -//! same set of circuits. -//! However, because the prover state can be quite heavy, the necessary verifier -//! data to verify block proofs can be saved independently into a -//! `VerifierState`, to allow anyone to easily verify block proofs. -//! -//! ```compile_fail -//! # use proof_gen::prover_state::ProverStateBuilder; -//! # use proof_gen::verifier_state::VerifierState; -//! let mut builder = ProverStateBuilder::default(); -//! -//! // Generate a `ProverState` from the builder. -//! let prover_state = builder.build(); -//! -//! // Derive a `VerifierState` from the `ProverState`. -//! let verifier_state: VerifierState = prover_state.into(); -//! -//! // The prover generates some block proof. -//! let block_proof = prover_state.generate_block_proof(...); -//! -//! // Have the verifier attest validity of the proof. -//! assert!(verifier_state.verify(block_proof.intern).is_ok()); -//! ``` - -zk_evm_common::check_chain_features!(); - -pub(crate) mod constants; -pub mod proof_gen; -pub mod proof_types; -pub mod prover_state; -pub mod verifier_state; - -// Re-exports - -pub use verifier_state::VerifierState; diff --git a/proof_gen/src/proof_gen.rs b/proof_gen/src/proof_gen.rs deleted file mode 100644 index 8e713de27..000000000 --- a/proof_gen/src/proof_gen.rs +++ /dev/null @@ -1,206 +0,0 @@ -//! This module defines the proof generation methods corresponding to the three -//! types of proofs the zkEVM internally handles. - -use std::sync::{atomic::AtomicBool, Arc}; - -use evm_arithmetization::{ - fixed_recursive_verifier::ProverOutputData, AllStark, GenerationSegmentData, - ProofWithPublicInputs, StarkConfig, TrimmedGenerationInputs, -}; -use hashbrown::HashMap; -use plonky2::{ - gates::noop::NoopGate, - plonk::{circuit_builder::CircuitBuilder, circuit_data::CircuitConfig}, - util::timing::TimingTree, -}; - -use crate::{ - proof_types::{ - AggregatableBlockProof, BatchAggregatableProof, GeneratedAggBlockProof, - GeneratedBlockProof, GeneratedSegmentAggProof, GeneratedSegmentProof, GeneratedTxnAggProof, - SegmentAggregatableProof, - }, - prover_state::ProverState, -}; - -/// A type alias for `Result`. -pub type ProofGenResult = Result; - -/// A custom error type to handle failure cases during proof generation. -// Plonky2 is still using `anyhow` for proof gen, and since this is a library, -// it's probably best if we at least convert it to a `String`. -#[derive(Debug)] -pub struct ProofGenError(pub String); - -impl std::fmt::Display for ProofGenError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{:#?}", self.0) - } -} - -impl std::error::Error for ProofGenError {} - -impl From for ProofGenError { - fn from(v: String) -> Self { - Self(v) - } -} - -/// Generates a transaction proof from some IR data. -pub fn generate_segment_proof( - p_state: &ProverState, - gen_inputs: TrimmedGenerationInputs, - segment_data: &mut GenerationSegmentData, - abort_signal: Option>, -) -> ProofGenResult { - let output_data = p_state - .state - .prove_segment( - &AllStark::default(), - &StarkConfig::standard_fast_config(), - gen_inputs, - segment_data, - &mut TimingTree::default(), - abort_signal, - ) - .map_err(|err| err.to_string())?; - - let p_vals = output_data.public_values; - let intern = output_data.proof_with_pis; - Ok(GeneratedSegmentProof { p_vals, intern }) -} - -/// Generates an aggregation proof from two child proofs. -/// -/// Note that the child proofs may be either transaction or aggregation proofs. -/// -/// If a transaction only contains a single segment, this function must still be -/// called to generate a `GeneratedSegmentAggProof`. In that case, you can set -/// `has_dummy` to `true`, and provide an arbitrary proof for the right child. -pub fn generate_segment_agg_proof( - p_state: &ProverState, - lhs_child: &SegmentAggregatableProof, - rhs_child: &SegmentAggregatableProof, - has_dummy: bool, -) -> ProofGenResult { - if has_dummy { - assert!( - !lhs_child.is_agg(), - "Cannot have a dummy segment with an aggregation." - ); - } - - let lhs_prover_output_data = ProverOutputData { - is_dummy: false, - proof_with_pis: lhs_child.intern().clone(), - public_values: lhs_child.public_values(), - }; - let rhs_prover_output_data = ProverOutputData { - is_dummy: has_dummy, - proof_with_pis: rhs_child.intern().clone(), - public_values: rhs_child.public_values(), - }; - let agg_output_data = p_state - .state - .prove_segment_aggregation( - lhs_child.is_agg(), - &lhs_prover_output_data, - rhs_child.is_agg(), - &rhs_prover_output_data, - ) - .map_err(|err| err.to_string())?; - - let p_vals = agg_output_data.public_values; - let intern = agg_output_data.proof_with_pis; - - Ok(GeneratedSegmentAggProof { p_vals, intern }) -} - -/// Generates a transaction aggregation proof from two child proofs. -/// -/// Note that the child proofs may be either transaction or aggregation proofs. -pub fn generate_transaction_agg_proof( - p_state: &ProverState, - lhs_child: &BatchAggregatableProof, - rhs_child: &BatchAggregatableProof, -) -> ProofGenResult { - let (b_proof_intern, p_vals) = p_state - .state - .prove_transaction_aggregation( - lhs_child.is_agg(), - lhs_child.intern(), - lhs_child.public_values(), - rhs_child.is_agg(), - rhs_child.intern(), - rhs_child.public_values(), - ) - .map_err(|err| err.to_string())?; - - Ok(GeneratedTxnAggProof { - p_vals, - intern: b_proof_intern, - }) -} - -/// Generates a block proof. -/// -/// It takes an optional argument, `prev_opt_parent_b_proof`, that can be set to -/// `None` on checkpoint heights. -pub fn generate_block_proof( - p_state: &ProverState, - prev_opt_parent_b_proof: Option<&GeneratedBlockProof>, - curr_block_agg_proof: &GeneratedTxnAggProof, -) -> ProofGenResult { - let b_height = curr_block_agg_proof - .p_vals - .block_metadata - .block_number - .low_u64(); - let parent_intern = prev_opt_parent_b_proof.map(|p| &p.intern); - - let (b_proof_intern, _) = p_state - .state - .prove_block( - parent_intern, - &curr_block_agg_proof.intern, - curr_block_agg_proof.p_vals.clone(), - ) - .map_err(|err| err.to_string())?; - - Ok(GeneratedBlockProof { - b_height, - intern: b_proof_intern, - }) -} - -/// Generates an aggregation block proof from two child proofs. -/// -/// Note that the child proofs may be either block or aggregation proofs. -pub fn generate_agg_block_proof( - p_state: &ProverState, - lhs_child: &AggregatableBlockProof, - rhs_child: &AggregatableBlockProof, -) -> ProofGenResult { - let intern = p_state - .state - .prove_two_to_one_block( - lhs_child.intern(), - lhs_child.is_agg(), - rhs_child.intern(), - rhs_child.is_agg(), - ) - .map_err(|err| err.to_string())?; - - Ok(GeneratedAggBlockProof { intern }) -} - -/// Generates a dummy proof for a dummy circuit doing nothing. -/// This is useful for testing purposes only. -pub fn dummy_proof() -> ProofGenResult { - let mut builder = CircuitBuilder::new(CircuitConfig::default()); - builder.add_gate(NoopGate, vec![]); - let circuit_data = builder.build::<_>(); - - plonky2::recursion::dummy_circuit::dummy_proof(&circuit_data, HashMap::default()) - .map_err(|e| ProofGenError(e.to_string())) -} diff --git a/proof_gen/src/prover_state.rs b/proof_gen/src/prover_state.rs deleted file mode 100644 index c5e1a88a4..000000000 --- a/proof_gen/src/prover_state.rs +++ /dev/null @@ -1,116 +0,0 @@ -//! This module defines the `ProverState`, that contains all pre-processed -//! circuits necessary to handle arbitrary transaction proving and proof -//! aggregation to generate succinct block proofs attesting validity of an -//! entire EVM-based chain. - -use std::ops::Range; - -use evm_arithmetization::{AllRecursiveCircuits, AllStark, StarkConfig}; -use log::info; -use paste::paste; - -use crate::constants::*; - -/// Plonky2 proving state. Note that this is generally going to be massive in -/// terms of memory and has a long spin-up time, -pub struct ProverState { - /// The set of pre-processed circuits to recursively prove transactions. - pub state: AllRecursiveCircuits, -} - -/// Builder for the prover state. -#[derive(Debug)] -pub struct ProverStateBuilder { - pub(crate) arithmetic_circuit_size: Range, - pub(crate) byte_packing_circuit_size: Range, - pub(crate) cpu_circuit_size: Range, - pub(crate) keccak_circuit_size: Range, - pub(crate) keccak_sponge_circuit_size: Range, - pub(crate) logic_circuit_size: Range, - pub(crate) memory_circuit_size: Range, - pub(crate) memory_before_circuit_size: Range, - pub(crate) memory_after_circuit_size: Range, - #[cfg(feature = "cdk_erigon")] - pub(crate) poseidon_circuit_size: Range, -} - -impl Default for ProverStateBuilder { - /// Generates a new builder from a set of default ranges. - /// These ranges should be sufficient to prove any transaction, - /// but will require a significant amount of RAM (around 30GB). - /// - /// Specifying shorter ranges will allow for a lower memory - /// consumption, with the drawback of possibly not being sufficient - /// for some transactions. - fn default() -> Self { - Self { - arithmetic_circuit_size: DEFAULT_ARITHMETIC_RANGE, - byte_packing_circuit_size: DEFAULT_BYTE_PACKING_RANGE, - cpu_circuit_size: DEFAULT_CPU_RANGE, - keccak_circuit_size: DEFAULT_KECCAK_RANGE, - keccak_sponge_circuit_size: DEFAULT_KECCAK_SPONGE_RANGE, - logic_circuit_size: DEFAULT_LOGIC_RANGE, - memory_circuit_size: DEFAULT_MEMORY_RANGE, - memory_before_circuit_size: DEFAULT_MEMORY_BEFORE_RANGE, - memory_after_circuit_size: DEFAULT_MEMORY_AFTER_RANGE, - #[cfg(feature = "cdk_erigon")] - poseidon_circuit_size: DEFAULT_POSEIDON_RANGE, - } - } -} - -macro_rules! define_set_circuit_size_method { - ($name:ident) => { - paste! { - /// Specifies a range of degrees to be supported for this STARK - /// table's associated recursive circuits. - pub const fn [](mut self, size: Range) -> Self { - self.[<$name _circuit_size>] = size; - self - } - } - }; -} - -impl ProverStateBuilder { - define_set_circuit_size_method!(arithmetic); - define_set_circuit_size_method!(byte_packing); - define_set_circuit_size_method!(cpu); - define_set_circuit_size_method!(keccak); - define_set_circuit_size_method!(keccak_sponge); - define_set_circuit_size_method!(logic); - define_set_circuit_size_method!(memory); - define_set_circuit_size_method!(memory_before); - define_set_circuit_size_method!(memory_after); - #[cfg(feature = "cdk_erigon")] - define_set_circuit_size_method!(poseidon); - - // TODO: Consider adding async version? - /// Instantiate the prover state from the builder. Note that this is a very - /// expensive call! - pub fn build(self) -> ProverState { - info!("Initializing Plonky2 aggregation prover state (This may take a while)..."); - - let state = AllRecursiveCircuits::new( - &AllStark::default(), - &[ - self.arithmetic_circuit_size, - self.byte_packing_circuit_size, - self.cpu_circuit_size, - self.keccak_circuit_size, - self.keccak_sponge_circuit_size, - self.logic_circuit_size, - self.memory_circuit_size, - self.memory_before_circuit_size, - self.memory_after_circuit_size, - #[cfg(feature = "cdk_erigon")] - self.poseidon_circuit_size, - ], - &StarkConfig::standard_fast_config(), - ); - - info!("Finished initializing Plonky2 aggregation prover state!"); - - ProverState { state } - } -} diff --git a/proof_gen/src/verifier_state.rs b/proof_gen/src/verifier_state.rs deleted file mode 100644 index f5b4f7c27..000000000 --- a/proof_gen/src/verifier_state.rs +++ /dev/null @@ -1,72 +0,0 @@ -//! This module defines the `VerifierState`, that contains the necessary data to -//! handle succinct block proofs verification. - -use core::borrow::Borrow; - -use evm_arithmetization::{ProofWithPublicInputs, VerifierData}; -use log::info; -use plonky2::recursion::cyclic_recursion::check_cyclic_proof_verifier_data; - -use crate::proof_gen::ProofGenResult; -use crate::prover_state::ProverState; -use crate::prover_state::ProverStateBuilder; - -/// Plonky2 verifier state. -/// -/// The default generation requires generating all the prover data before -/// extracting the verifier-related data, which can take a long time and require -/// a large amount of memory. -pub struct VerifierState { - /// The verification circuit data associated to the block proof layer of the - /// plonky2 prover state. - pub state: VerifierData, -} - -/// Builder for the verifier state. -/// This is essentially the same as the [`ProverStateBuilder`], in that we need -/// to first generate the entire prover state before extracting the verifier -/// data. -pub type VerifierStateBuilder = ProverStateBuilder; - -impl VerifierStateBuilder { - /// Instantiate the verifier state from the builder. Note that this is a - /// very expensive call! - pub fn build_verifier(self) -> VerifierState { - info!("Initializing Plonky2 aggregation verifier state (This may take a while)..."); - let ProverState { state } = self.build(); - info!("Finished initializing Plonky2 aggregation verifier state!"); - - VerifierState { - state: state.final_verifier_data(), - } - } -} - -/// Extracts the verifier state from the entire prover state. -impl> From for VerifierState { - fn from(prover_state: T) -> Self { - VerifierState { - state: prover_state.borrow().state.final_verifier_data(), - } - } -} - -impl VerifierState { - /// Verifies a `block_proof`. - pub fn verify(&self, block_proof: &ProofWithPublicInputs) -> ProofGenResult<()> { - // Proof verification - self.state - .verify(block_proof.clone()) - .map_err(|err| err.to_string())?; - - // Verifier data verification - check_cyclic_proof_verifier_data( - block_proof, - &self.state.verifier_only, - &self.state.common, - ) - .map_err(|err| err.to_string())?; - - Ok(()) - } -} diff --git a/zero/Cargo.toml b/zero/Cargo.toml index 3f8023313..7bc42709c 100644 --- a/zero/Cargo.toml +++ b/zero/Cargo.toml @@ -20,6 +20,7 @@ clap = { workspace = true, features = ["derive", "string"] } directories = "5.0.1" dotenvy = { workspace = true } futures = { workspace = true } +hashbrown = { workspace = true } hex = { workspace = true } itertools = { workspace = true } keccak-hash = { workspace = true } @@ -45,7 +46,6 @@ url = { workspace = true } compat = { workspace = true } evm_arithmetization = { workspace = true } mpt_trie = { workspace = true } -proof_gen = { workspace = true } trace_decoder = { workspace = true } zk_evm_common = { workspace = true } @@ -61,9 +61,9 @@ vergen-git2 = { version = "1.0.0", features = ["build"] } [features] default = ["eth_mainnet"] -eth_mainnet = ["evm_arithmetization/eth_mainnet", "proof_gen/eth_mainnet", "trace_decoder/eth_mainnet"] -cdk_erigon = ["evm_arithmetization/cdk_erigon", "proof_gen/cdk_erigon", "trace_decoder/cdk_erigon"] -polygon_pos = ["evm_arithmetization/polygon_pos", "proof_gen/polygon_pos", "trace_decoder/polygon_pos"] +eth_mainnet = ["evm_arithmetization/eth_mainnet", "trace_decoder/eth_mainnet"] +cdk_erigon = ["evm_arithmetization/cdk_erigon", "trace_decoder/cdk_erigon"] +polygon_pos = ["evm_arithmetization/polygon_pos", "trace_decoder/polygon_pos"] [lints] workspace = true diff --git a/zero/README.md b/zero/README.md index dda10a95b..936a73c91 100644 --- a/zero/README.md +++ b/zero/README.md @@ -1,6 +1,6 @@ # Zero Bin -A composition of [`paladin`](https://github.com/0xPolygonZero/paladin) and [`proof_gen`](../proof_gen/README.md). +A composition of [`paladin`](https://github.com/0xPolygonZero/paladin) and [`evm_arithmetization`](../evm_arithmetization/README.md). Given the [proof generation protocol](./prover/src/lib.rs) as input, generate a proof. The project is instrumented with [`paladin`](https://github.com/0xPolygonZero/paladin), and as such can distribute proof generation across multiple worker machines. diff --git a/zero/src/bin/leader/client.rs b/zero/src/bin/leader/client.rs index c4ddedd63..455cceb8b 100644 --- a/zero/src/bin/leader/client.rs +++ b/zero/src/bin/leader/client.rs @@ -4,11 +4,11 @@ use alloy::rpc::types::{BlockId, BlockNumberOrTag}; use alloy::transports::http::reqwest::Url; use anyhow::{anyhow, Result}; use paladin::runtime::Runtime; -use proof_gen::proof_types::GeneratedBlockProof; use tokio::sync::mpsc; use tracing::info; use zero::block_interval::{BlockInterval, BlockIntervalStream}; use zero::pre_checks::check_previous_proof_and_checkpoint; +use zero::proof_types::GeneratedBlockProof; use zero::prover::{self, BlockProverInput, ProverConfig}; use zero::rpc; use zero::rpc::{retry::build_http_retry_provider, RpcType}; diff --git a/zero/src/bin/leader/http.rs b/zero/src/bin/leader/http.rs index 3ebcbdaec..02e968ec0 100644 --- a/zero/src/bin/leader/http.rs +++ b/zero/src/bin/leader/http.rs @@ -4,10 +4,10 @@ use alloy::primitives::U256; use anyhow::{bail, Result}; use axum::{http::StatusCode, routing::post, Json, Router}; use paladin::runtime::Runtime; -use proof_gen::proof_types::GeneratedBlockProof; use serde::{Deserialize, Serialize}; use serde_json::to_writer; use tracing::{debug, error, info}; +use zero::proof_types::GeneratedBlockProof; use zero::prover::{BlockProverInput, ProverConfig}; /// The main function for the HTTP mode. diff --git a/zero/src/bin/leader/stdio.rs b/zero/src/bin/leader/stdio.rs index 2bef3ceff..306a08c65 100644 --- a/zero/src/bin/leader/stdio.rs +++ b/zero/src/bin/leader/stdio.rs @@ -3,9 +3,9 @@ use std::sync::Arc; use anyhow::{anyhow, Result}; use paladin::runtime::Runtime; -use proof_gen::proof_types::GeneratedBlockProof; use tokio::sync::mpsc; use tracing::info; +use zero::proof_types::GeneratedBlockProof; use zero::prover::{self, BlockProverInput, ProverConfig}; /// The main function for the stdio mode. diff --git a/zero/src/bin/verifier.rs b/zero/src/bin/verifier.rs index 7c5a671be..d306eed10 100644 --- a/zero/src/bin/verifier.rs +++ b/zero/src/bin/verifier.rs @@ -5,9 +5,9 @@ use std::fs::File; use anyhow::Result; use clap::Parser; use dotenvy::dotenv; -use proof_gen::proof_types::GeneratedBlockProof; use serde_json::Deserializer; use tracing::info; +use zero::proof_types::GeneratedBlockProof; use zero::prover_state::persistence::set_circuit_cache_dir_env_if_not_set; use self::verifier::*; diff --git a/zero/src/fs.rs b/zero/src/fs.rs index 7576cf20f..c53a676d0 100644 --- a/zero/src/fs.rs +++ b/zero/src/fs.rs @@ -2,7 +2,8 @@ use std::fs::File; use std::path::PathBuf; use anyhow::anyhow; -use proof_gen::proof_types::GeneratedBlockProof; + +use crate::proof_types::GeneratedBlockProof; pub fn generate_block_proof_file_name(directory: &Option<&str>, block_height: u64) -> PathBuf { let mut path = PathBuf::from(directory.unwrap_or("")); diff --git a/zero/src/lib.rs b/zero/src/lib.rs index 88f376fc7..066ecc87e 100644 --- a/zero/src/lib.rs +++ b/zero/src/lib.rs @@ -7,6 +7,7 @@ pub mod fs; pub mod ops; pub mod parsing; pub mod pre_checks; +pub mod proof_types; pub mod prover; pub mod prover_state; pub mod provider; diff --git a/zero/src/ops.rs b/zero/src/ops.rs index 2c0eb557a..b08b5a925 100644 --- a/zero/src/ops.rs +++ b/zero/src/ops.rs @@ -2,22 +2,22 @@ zk_evm_common::check_chain_features!(); use std::time::Instant; +use evm_arithmetization::fixed_recursive_verifier::ProverOutputData; use evm_arithmetization::{prover::testing::simulate_execution_all_segments, GenerationInputs}; use evm_arithmetization::{Field, PublicValues, TrimmedGenerationInputs}; use paladin::{ operation::{FatalError, FatalStrategy, Monoid, Operation, Result}, registry, RemoteExecute, }; -use proof_gen::{ - proof_gen::{generate_block_proof, generate_segment_agg_proof, generate_transaction_agg_proof}, - proof_types::{ - BatchAggregatableProof, GeneratedBlockProof, GeneratedTxnAggProof, SegmentAggregatableProof, - }, -}; use serde::{Deserialize, Serialize}; use tracing::error; use tracing::{event, info_span, Level}; +use crate::proof_types::{ + BatchAggregatableProof, GeneratedBlockProof, GeneratedSegmentAggProof, GeneratedTxnAggProof, + SegmentAggregatableProof, +}; +use crate::prover_state::ProverState; use crate::{debug_utils::save_inputs_to_disk, prover_state::p_state}; registry!(); @@ -29,11 +29,11 @@ pub struct SegmentProof { impl Operation for SegmentProof { type Input = evm_arithmetization::AllData; - type Output = proof_gen::proof_types::SegmentAggregatableProof; + type Output = crate::proof_types::SegmentAggregatableProof; fn execute(&self, all_data: Self::Input) -> Result { let all_data = - all_data.map_err(|err| FatalError::from_str(&err.0, FatalStrategy::Terminate))?; + all_data.map_err(|e| FatalError::from_str(&e.to_string(), FatalStrategy::Terminate))?; let input = all_data.0.clone(); let segment_index = all_data.1.segment_index(); @@ -41,7 +41,7 @@ impl Operation for SegmentProof { let proof = if self.save_inputs_on_error { crate::prover_state::p_manager() .generate_segment_proof(all_data) - .map_err(|err| { + .map_err(|e| { if let Err(write_err) = save_inputs_to_disk( format!( "b{}_txns_{}..{}-({})_input.json", @@ -55,12 +55,12 @@ impl Operation for SegmentProof { error!("Failed to save txn proof input to disk: {:?}", write_err); } - FatalError::from_anyhow(err, FatalStrategy::Terminate) + FatalError::from_str(&e.to_string(), FatalStrategy::Terminate) })? } else { crate::prover_state::p_manager() .generate_segment_proof(all_data) - .map_err(|err| FatalError::from_anyhow(err, FatalStrategy::Terminate))? + .map_err(|e| FatalError::from_str(&e.to_string(), FatalStrategy::Terminate))? }; Ok(proof.into()) @@ -78,7 +78,7 @@ impl Operation for SegmentProofTestOnly { fn execute(&self, inputs: Self::Input) -> Result { if self.save_inputs_on_error { - simulate_execution_all_segments::(inputs.0.clone(), inputs.1).map_err(|err| { + simulate_execution_all_segments::(inputs.0.clone(), inputs.1).map_err(|e| { if let Err(write_err) = save_inputs_to_disk( format!( "b{}_txns_{}..{}_input.json", @@ -91,11 +91,11 @@ impl Operation for SegmentProofTestOnly { error!("Failed to save txn proof input to disk: {:?}", write_err); } - FatalError::from_anyhow(err, FatalStrategy::Terminate) + FatalError::from_str(&e.to_string(), FatalStrategy::Terminate) })? } else { simulate_execution_all_segments::(inputs.0, inputs.1) - .map_err(|err| FatalError::from_anyhow(err, FatalStrategy::Terminate))?; + .map_err(|e| FatalError::from_str(&e.to_string(), FatalStrategy::Terminate))?; } Ok(()) @@ -194,6 +194,49 @@ fn get_seg_agg_proof_public_values(elem: SegmentAggregatableProof) -> PublicValu } } +/// Generates an aggregation proof from two child proofs. +/// +/// Note that the child proofs may be either transaction or aggregation proofs. +/// +/// If a transaction only contains a single segment, this function must still be +/// called to generate a `GeneratedSegmentAggProof`. In that case, you can set +/// `has_dummy` to `true`, and provide an arbitrary proof for the right child. +pub fn generate_segment_agg_proof( + p_state: &ProverState, + lhs_child: &SegmentAggregatableProof, + rhs_child: &SegmentAggregatableProof, + has_dummy: bool, +) -> anyhow::Result { + if has_dummy { + assert!( + !lhs_child.is_agg(), + "Cannot have a dummy segment with an aggregation." + ); + } + + let lhs_prover_output_data = ProverOutputData { + is_dummy: false, + proof_with_pis: lhs_child.intern().clone(), + public_values: lhs_child.public_values(), + }; + let rhs_prover_output_data = ProverOutputData { + is_dummy: has_dummy, + proof_with_pis: rhs_child.intern().clone(), + public_values: rhs_child.public_values(), + }; + let agg_output_data = p_state.state.prove_segment_aggregation( + lhs_child.is_agg(), + &lhs_prover_output_data, + rhs_child.is_agg(), + &rhs_prover_output_data, + )?; + + let p_vals = agg_output_data.public_values; + let intern = agg_output_data.proof_with_pis; + + Ok(GeneratedSegmentAggProof { p_vals, intern }) +} + impl Monoid for SegmentAggProof { type Elem = SegmentAggregatableProof; @@ -215,7 +258,7 @@ impl Monoid for SegmentAggProof { } } - FatalError::from(e) + FatalError::from_str(&e.to_string(), FatalStrategy::Terminate) })?; Ok(result.into()) @@ -251,7 +294,7 @@ impl Monoid for BatchAggProof { &SegmentAggregatableProof::from(segment), true, ) - .map_err(FatalError::from)?, + .map_err(|e| FatalError::from_str(&e.to_string(), FatalStrategy::Terminate))?, ), _ => a, }; @@ -264,32 +307,46 @@ impl Monoid for BatchAggProof { &SegmentAggregatableProof::from(segment), true, ) - .map_err(FatalError::from)?, + .map_err(|e| FatalError::from_str(&e.to_string(), FatalStrategy::Terminate))?, ), _ => b, }; - let result = generate_transaction_agg_proof(p_state(), &lhs, &rhs).map_err(|e| { - if self.save_inputs_on_error { - let pv = vec![ - get_agg_proof_public_values(lhs), - get_agg_proof_public_values(rhs), - ]; - if let Err(write_err) = save_inputs_to_disk( - format!( - "b{}_agg_lhs_rhs_inputs.json", - pv[0].block_metadata.block_number - ), - pv, - ) { - error!("Failed to save agg proof inputs to disk: {:?}", write_err); + let (proof, p_vals) = p_state() + .state + .prove_batch_aggregation( + lhs.is_agg(), + lhs.intern(), + lhs.public_values(), + rhs.is_agg(), + rhs.intern(), + rhs.public_values(), + ) + .map_err(|e| { + if self.save_inputs_on_error { + let pv = vec![ + get_agg_proof_public_values(lhs), + get_agg_proof_public_values(rhs), + ]; + if let Err(write_err) = save_inputs_to_disk( + format!( + "b{}_agg_lhs_rhs_inputs.json", + pv[0].block_metadata.block_number + ), + pv, + ) { + error!("Failed to save agg proof inputs to disk: {:?}", write_err); + } } - } - FatalError::from(e) - })?; + FatalError::from_str(&e.to_string(), FatalStrategy::Terminate) + })?; - Ok(result.into()) + Ok(GeneratedTxnAggProof { + p_vals, + intern: proof, + } + .into()) } fn empty(&self) -> Self::Elem { @@ -309,8 +366,13 @@ impl Operation for BlockProof { type Output = GeneratedBlockProof; fn execute(&self, input: Self::Input) -> Result { - Ok( - generate_block_proof(p_state(), self.prev.as_ref(), &input).map_err(|e| { + let b_height = input.p_vals.block_metadata.block_number.low_u64(); + let parent_intern = self.prev.as_ref().map(|p| &p.intern); + + let (b_proof_intern, _) = p_state() + .state + .prove_block(parent_intern, &input.intern, input.p_vals.clone()) + .map_err(|e| { if self.save_inputs_on_error { if let Err(write_err) = save_inputs_to_disk( format!( @@ -323,8 +385,12 @@ impl Operation for BlockProof { } } - FatalError::from(e) - })?, - ) + FatalError::from_str(&e.to_string(), FatalStrategy::Terminate) + })?; + + Ok(GeneratedBlockProof { + b_height, + intern: b_proof_intern, + }) } } diff --git a/zero/src/pre_checks.rs b/zero/src/pre_checks.rs index 6621f99e6..2a37d7154 100644 --- a/zero/src/pre_checks.rs +++ b/zero/src/pre_checks.rs @@ -1,4 +1,4 @@ -use proof_gen::proof_types::GeneratedBlockProof; +use crate::proof_types::GeneratedBlockProof; pub fn check_previous_proof_and_checkpoint( checkpoint_block_number: u64, diff --git a/proof_gen/src/proof_types.rs b/zero/src/proof_types.rs similarity index 97% rename from proof_gen/src/proof_types.rs rename to zero/src/proof_types.rs index 6dc5d0749..55ab492d0 100644 --- a/proof_gen/src/proof_types.rs +++ b/zero/src/proof_types.rs @@ -194,6 +194,8 @@ impl AggregatableBlockProof { } } + // TODO(Robin): https://github.com/0xPolygonZero/zk_evm/issues/387 + #[allow(unused)] pub(crate) const fn is_agg(&self) -> bool { match self { AggregatableBlockProof::Block(_) => false, @@ -201,6 +203,8 @@ impl AggregatableBlockProof { } } + // TODO(Robin): https://github.com/0xPolygonZero/zk_evm/issues/387 + #[allow(unused)] pub(crate) const fn intern(&self) -> &ProofWithPublicInputs { match self { AggregatableBlockProof::Block(info) => &info.intern, diff --git a/zero/src/prover.rs b/zero/src/prover.rs index 33c21c7bd..1625752b9 100644 --- a/zero/src/prover.rs +++ b/zero/src/prover.rs @@ -10,9 +10,12 @@ use alloy::primitives::U256; use anyhow::{Context, Result}; use evm_arithmetization::Field; use futures::{future::BoxFuture, FutureExt, TryFutureExt, TryStreamExt}; +use hashbrown::HashMap; use num_traits::ToPrimitive as _; use paladin::runtime::Runtime; -use proof_gen::proof_types::GeneratedBlockProof; +use plonky2::gates::noop::NoopGate; +use plonky2::plonk::circuit_builder::CircuitBuilder; +use plonky2::plonk::circuit_data::CircuitConfig; use serde::{Deserialize, Serialize}; use tokio::io::AsyncWriteExt; use tokio::sync::mpsc::Receiver; @@ -22,6 +25,7 @@ use tracing::{error, info}; use crate::fs::generate_block_proof_file_name; use crate::ops; +use crate::proof_types::GeneratedBlockProof; // All proving tasks are executed concurrently, which can cause issues for large // block intervals, where distant future blocks may be proven first. @@ -108,7 +112,7 @@ impl BlockProverInput { .fold(&seg_agg_ops) .run(&runtime) .map(move |e| { - e.map(|p| (idx, proof_gen::proof_types::BatchAggregatableProof::from(p))) + e.map(|p| (idx, crate::proof_types::BatchAggregatableProof::from(p))) }) }) .collect(); @@ -119,7 +123,7 @@ impl BlockProverInput { .run(&runtime) .await?; - if let proof_gen::proof_types::BatchAggregatableProof::Agg(proof) = final_batch_proof { + if let crate::proof_types::BatchAggregatableProof::Agg(proof) = final_batch_proof { let block_number = block_number .to_u64() .context("block number overflows u64")?; @@ -195,12 +199,21 @@ impl BlockProverInput { None => None, }; + // Build a dummy proof for output type consistency + let dummy_proof = { + let mut builder = CircuitBuilder::new(CircuitConfig::default()); + builder.add_gate(NoopGate, vec![]); + let circuit_data = builder.build::<_>(); + + plonky2::recursion::dummy_circuit::dummy_proof(&circuit_data, HashMap::default())? + }; + // Dummy proof to match expected output type. Ok(GeneratedBlockProof { b_height: block_number .to_u64() .expect("Block number should fit in a u64"), - intern: proof_gen::proof_gen::dummy_proof()?, + intern: dummy_proof, }) } } diff --git a/zero/src/prover_state/mod.rs b/zero/src/prover_state/mod.rs index 8cfa3f013..5dc34a53d 100644 --- a/zero/src/prover_state/mod.rs +++ b/zero/src/prover_state/mod.rs @@ -11,18 +11,22 @@ //! [`evm_arithmetization::fixed_recursive_verifier::AllRecursiveCircuits`]. //! - Global prover state management via the [`P_STATE`] static and the //! [`set_prover_state_from_config`] function. +use std::borrow::Borrow; use std::{fmt::Display, sync::OnceLock}; use clap::ValueEnum; use evm_arithmetization::{ - fixed_recursive_verifier::ProverOutputData, prover::prove, AllProof, AllStark, - GenerationSegmentData, RecursiveCircuitsForTableSize, StarkConfig, TrimmedGenerationInputs, + fixed_recursive_verifier::ProverOutputData, prover::prove, AllProof, AllRecursiveCircuits, + AllStark, GenerationSegmentData, RecursiveCircuitsForTableSize, StarkConfig, + TrimmedGenerationInputs, }; +use evm_arithmetization::{ProofWithPublicInputs, VerifierData}; +use plonky2::recursion::cyclic_recursion::check_cyclic_proof_verifier_data; use plonky2::util::timing::TimingTree; -use proof_gen::{proof_types::GeneratedSegmentProof, prover_state::ProverState, VerifierState}; use tracing::info; use self::circuit::{CircuitConfig, NUM_TABLES}; +use crate::proof_types::GeneratedSegmentProof; use crate::prover_state::persistence::{ BaseProverResource, DiskResource, MonolithicProverResource, RecursiveCircuitResource, VerifierResource, @@ -32,6 +36,42 @@ pub mod circuit; pub mod cli; pub mod persistence; +/// zkEVM proving state, needed to generate succinct block proofs for EVM-based +/// chains. +pub struct ProverState { + /// The set of pre-processed circuits to recursively prove blocks. + pub state: AllRecursiveCircuits, +} + +/// zkEVM verifier state, useful for verifying generated block proofs. +/// +/// This requires much less memory than its prover counterpart. +pub struct VerifierState { + /// The verification circuit data associated to the block proof layer of the + /// zkEVM prover state. + pub state: VerifierData, +} + +/// Extracts the verifier state from the entire prover state. +impl> From for VerifierState { + fn from(prover_state: T) -> Self { + VerifierState { + state: prover_state.borrow().state.final_verifier_data(), + } + } +} + +impl VerifierState { + /// Verifies a `block_proof`. + pub fn verify(&self, block_proof: &ProofWithPublicInputs) -> anyhow::Result<()> { + // Proof verification + self.state.verify(block_proof.clone())?; + + // Verifier data verification + check_cyclic_proof_verifier_data(block_proof, &self.state.verifier_only, &self.state.common) + } +} + /// The global prover state. /// /// It is specified as a `OnceLock` for the following reasons: