Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(prover): File-info tool to help prover debugging #1216

Merged
merged 8 commits into from
Mar 18, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions prover/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions prover/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ members = [
"witness_vector_generator",
"prover_fri_gateway",
"proof_fri_compressor",
"tools",
]

resolver = "2"
Expand Down
17 changes: 17 additions & 0 deletions prover/tools/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[package]
name = "tools"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]

clap = { version = "4.4.6", features = ["derive"] }
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
zksync_prover_fri_types = {path = "../prover_fri_types"}
bincode = "1.0"
colored = "2.0"
zksync_prover_interface = { path = "../../core/lib/prover_interface" }
hex = "0.4"
37 changes: 37 additions & 0 deletions prover/tools/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Tool to better understand and debug provers

For now, it has only one command 'file-info'

```
cargo run --release file-info /ksync-era/prover/artifacts/proofs_fri/l1_batch_proof_1.bin
```

Example outputs:

```
L1 proof
AUX info:
L1 msg linear hash: [163, 243, 172, 16, 189, 59, 100, 227, 249, 46, 226, 220, 82, 135, 213, 208, 221, 228, 49, 46, 121, 136, 78, 163, 15, 155, 199, 82, 64, 24, 172, 198]
Rollup_state_diff_for_compression: [157, 150, 29, 193, 105, 162, 176, 61, 83, 241, 72, 206, 68, 20, 143, 69, 119, 162, 138, 101, 80, 139, 193, 211, 188, 250, 156, 86, 254, 148, 117, 60]
bootloader_heap_initial_content: [112, 2, 120, 255, 156, 227, 172, 92, 134, 48, 247, 243, 148, 241, 11, 122, 6, 189, 46, 164, 89, 78, 209, 118, 115, 239, 195, 15, 225, 143, 97, 204]
events_queue_state: [202, 78, 244, 233, 150, 17, 247, 25, 183, 51, 245, 110, 135, 31, 115, 109, 84, 193, 17, 1, 153, 32, 39, 199, 102, 25, 63, 216, 220, 68, 212, 233]
Inputs: [Fr(0x00000000775db828700e0ebbe0384f8a017598a271dfb6c96ebb2baf22a7a572)]
```

```
== Circuit ==
Type: basic. Id: 1 (Scheduler)
Geometry: CSGeometry { num_columns_under_copy_permutation: 130, num_witness_columns: 0, num_constant_columns: 4, max_allowed_constraint_degree: 8 }
Circuit size: trace length: Some(1048576) something??: Some(100663296)
Scheduler witness info
Previous block data:
Enumeration counter: 25
State root: [107, 233, 138, 154, 21, 134, 189, 220, 183, 250, 117, 243, 103, 124, 71, 221, 160, 136, 249, 25, 197, 109, 8, 75, 26, 12, 81, 109, 36, 56, 30, 17]
Block meta parameters
bootloader code hash: 452367551810219221093730953379759186922674186246309239546886848509599206765
aa code hash: 452349823575802367618424269668644286404749728714566974110193150711820505769
Previous block meta hash: [63, 236, 0, 236, 23, 236, 175, 242, 75, 187, 203, 193, 88, 80, 202, 53, 40, 206, 28, 40, 125, 58, 53, 254, 233, 122, 108, 101, 101, 88, 102, 193]
Previous block aux hash: [200, 12, 70, 33, 103, 13, 251, 174, 96, 165, 135, 138, 34, 75, 249, 81, 93, 86, 110, 52, 30, 172, 198, 51, 155, 82, 86, 137, 156, 215, 11, 119]
EIP 4844 - witnesses: None
EIP 4844 - proofs: 0
```
251 changes: 251 additions & 0 deletions prover/tools/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,251 @@
use std::fs;

use clap::{Parser, Subcommand};
use colored::Colorize;
use tracing::level_filters::LevelFilter;
use zksync_prover_fri_types::{
circuit_definitions::{
boojum::{
field::goldilocks::{GoldilocksExt2, GoldilocksField},
gadgets::recursion::recursive_tree_hasher::CircuitGoldilocksPoseidon2Sponge,
},
circuit_definitions::{
base_layer::ZkSyncBaseLayerCircuit, recursion_layer::ZkSyncRecursiveLayerCircuit,
},
zkevm_circuits::scheduler::input::SchedulerCircuitInstanceWitness,
},
CircuitWrapper, FriProofWrapper,
};
use zksync_prover_interface::outputs::L1BatchProofForL1;

#[derive(Debug, Parser)]
#[command(
author = "Matter Labs",
version,
about = "Debugging tools for prover related things",
long_about = None
)]

struct Cli {
#[command(subcommand)]
command: Command,
}

#[derive(Debug, Subcommand)]
enum Command {
#[command(name = "file-info")]
FileInfo { file_path: String },
}

fn pretty_print_size_hint(size_hint: (Option<usize>, Option<usize>)) {
println!(
"Circuit size: trace length: {:?} something??: {:?}",
size_hint.0, size_hint.1
);
}

fn pretty_print_scheduler_witness(
witness: &SchedulerCircuitInstanceWitness<
GoldilocksField,
CircuitGoldilocksPoseidon2Sponge,
GoldilocksExt2,
>,
) {
println!("Scheduler witness info");
println!(" Previous block data: ");
println!(
" Enumeration counter: {:?}",
witness.prev_block_data.per_shard_states[0].enumeration_counter[0]
);
println!(
" State root: 0x{}",
hex::encode(witness.prev_block_data.per_shard_states[0].state_root)
);

println!(" Block meta parameters");
println!(
" bootloader code hash: {:?}",
witness.block_meta_parameters.bootloader_code_hash
);
println!(
" aa code hash: {:?}",
witness.block_meta_parameters.default_aa_code_hash
);

println!(
" Previous block meta hash: 0x{}",
hex::encode(witness.previous_block_meta_hash)
);
println!(
" Previous block aux hash: 0x{}",
hex::encode(witness.previous_block_aux_hash)
);

println!(" EIP 4844 - witnesses: {:?}", witness.eip4844_witnesses);
println!(" EIP 4844 - proofs: {:?}", witness.eip4844_proofs.len());
}

fn pretty_print_circuit_wrapper(circuit: &CircuitWrapper) {
println!(" == Circuit ==");
match circuit {
CircuitWrapper::Base(circuit) => {
println!(
"Type: basic. Id: {:?} ({})",
circuit.numeric_circuit_type(),
circuit.short_description().bold()
);
println!("Geometry: {:?}", circuit.geometry());
pretty_print_size_hint(circuit.size_hint());

match circuit {
ZkSyncBaseLayerCircuit::MainVM(_) => todo!(),
ZkSyncBaseLayerCircuit::CodeDecommittmentsSorter(_) => todo!(),
ZkSyncBaseLayerCircuit::CodeDecommitter(_) => todo!(),
ZkSyncBaseLayerCircuit::LogDemuxer(_) => todo!(),
ZkSyncBaseLayerCircuit::KeccakRoundFunction(_) => todo!(),
ZkSyncBaseLayerCircuit::Sha256RoundFunction(_) => todo!(),
ZkSyncBaseLayerCircuit::ECRecover(circuit) => {
//circuit.debug_witness()
println!("Expected public input: {:?}", circuit.expected_public_input);
println!("Max ECRecovers per circuit: {:?}", circuit.config);
}
ZkSyncBaseLayerCircuit::RAMPermutation(_) => todo!(),
ZkSyncBaseLayerCircuit::StorageSorter(_) => todo!(),
ZkSyncBaseLayerCircuit::StorageApplication(circuit) => circuit.debug_witness(),
ZkSyncBaseLayerCircuit::EventsSorter(_) => todo!(),
ZkSyncBaseLayerCircuit::L1MessagesSorter(_) => todo!(),
ZkSyncBaseLayerCircuit::L1MessagesHasher(_) => todo!(),
}
}
CircuitWrapper::Recursive(circuit) => {
println!(
"Type: basic. Id: {:?} ({})",
circuit.numeric_circuit_type(),
circuit.short_description().bold()
);
println!("Geometry: {:?}", circuit.geometry());
pretty_print_size_hint(circuit.size_hint());
match circuit {
ZkSyncRecursiveLayerCircuit::SchedulerCircuit(circuit) => {
//println!("Expected public input: {:?}", circuit.witness);
pretty_print_scheduler_witness(&circuit.witness);
}
ZkSyncRecursiveLayerCircuit::NodeLayerCircuit(_) => todo!(),
ZkSyncRecursiveLayerCircuit::LeafLayerCircuitForMainVM(_) => todo!(),
ZkSyncRecursiveLayerCircuit::LeafLayerCircuitForCodeDecommittmentsSorter(_) => {
todo!()
}
ZkSyncRecursiveLayerCircuit::LeafLayerCircuitForCodeDecommitter(_) => todo!(),
ZkSyncRecursiveLayerCircuit::LeafLayerCircuitForLogDemuxer(_) => todo!(),
ZkSyncRecursiveLayerCircuit::LeafLayerCircuitForKeccakRoundFunction(_) => todo!(),
ZkSyncRecursiveLayerCircuit::LeafLayerCircuitForSha256RoundFunction(_) => todo!(),
ZkSyncRecursiveLayerCircuit::LeafLayerCircuitForECRecover(_) => todo!(),
ZkSyncRecursiveLayerCircuit::LeafLayerCircuitForRAMPermutation(_) => todo!(),
ZkSyncRecursiveLayerCircuit::LeafLayerCircuitForStorageSorter(_) => todo!(),
ZkSyncRecursiveLayerCircuit::LeafLayerCircuitForStorageApplication(_) => todo!(),
ZkSyncRecursiveLayerCircuit::LeafLayerCircuitForEventsSorter(_) => todo!(),
ZkSyncRecursiveLayerCircuit::LeafLayerCircuitForL1MessagesSorter(_) => todo!(),
ZkSyncRecursiveLayerCircuit::LeafLayerCircuitForL1MessagesHasher(_) => todo!(),
}
}
CircuitWrapper::Eip4844(_) => {
println!("Type: eip4844")
}
}
}

fn pretty_print_proof(result: &FriProofWrapper) {
println!("{}", "== FRI proof ==".to_string().bold());
match result {
FriProofWrapper::Base(proof) => {
println!(
"Basic proof {} {}",
proof.numeric_circuit_type(),
proof.short_description()
);
}
FriProofWrapper::Recursive(proof) => {
println!(
"Recursive proof {} {}",
proof.numeric_circuit_type(),
proof.short_description()
);

let proof = proof.clone().into_inner();
println!("Proof config: {:?}", proof.proof_config);
println!("Proof public inputs: {:?}", proof.public_inputs);
}
FriProofWrapper::Eip4844(_) => {
println!("4844 blob proof",);
}
}
}

fn pretty_print_l1_proof(result: &L1BatchProofForL1) {
println!("{}", "== Snark wrapped L1 proof ==".to_string().bold());
println!("AUX info:");
println!(
" L1 msg linear hash: 0x{}",
hex::encode(result.aggregation_result_coords[0])
);
println!(
" Rollup_state_diff_for_compression: 0x{}",
hex::encode(result.aggregation_result_coords[1])
);
println!(
" bootloader_heap_initial_content: 0x{}",
hex::encode(result.aggregation_result_coords[2])
);
println!(
" events_queue_state: 0x{}",
hex::encode(result.aggregation_result_coords[3])
);

println!("Inputs: {:?}", result.scheduler_proof.inputs);
println!(" This proof will pass on L1, if L1 executor computes the block commitment that is matching exactly the Inputs value above");
}

fn file_info(path: String) {
println!("Reading file {} and guessing the type.", path.bold());

let bytes = fs::read(path).unwrap();

// Parsing stuff from 'prover_jobs_fri' directory.
let maybe_circuit: Option<CircuitWrapper> = bincode::deserialize(&bytes).ok();
if let Some(circuit) = maybe_circuit {
println!(" Parsing file as CircuitWrapper.");
pretty_print_circuit_wrapper(&circuit);
return;
}
println!(" NOT a CircuitWrapper.");
let maybe_fri_proof: Option<FriProofWrapper> = bincode::deserialize(&bytes).ok();
if let Some(fri_proof) = maybe_fri_proof {
println!(" Parsing file as FriProofWrapper.");
pretty_print_proof(&fri_proof);
return;
}
println!(" NOT a FriProofWrapper.");

let maybe_snark_proof: Option<L1BatchProofForL1> = bincode::deserialize(&bytes).ok();
if let Some(snark_proof) = maybe_snark_proof {
println!(" Parsing file as L1BatchProofForL1.");
pretty_print_l1_proof(&snark_proof)
} else {
println!(" NOT a L1BatchProof.");
}
}

fn main() {
tracing_subscriber::fmt()
.with_env_filter(
tracing_subscriber::EnvFilter::builder()
.with_default_directive(LevelFilter::INFO.into())
.from_env_lossy(),
)
.init();

let opt = Cli::parse();
match opt.command {
Command::FileInfo { file_path } => file_info(file_path),
}
}
Loading