From 7cbf16a3c026e64706e6032b7914a589ed167c3b Mon Sep 17 00:00:00 2001 From: Arthur Paulino Date: Fri, 13 Mar 2026 08:53:17 -0300 Subject: [PATCH] chore: Update Plonky3 dependency and adapt to breaking API changes: - AirBuilder: replace type M with PreprocessedWindow, MainWindow, PublicVar - Use RowWindow/WindowAccess instead of VerticalPair for preprocessed traces - MerkleTreeMmcs: add arity generic parameter and cap_height constructor arg - FriParameters: add max_log_arity field - MerkleCap no longer Copy: add .clone() where needed - Remove PreprocessedBuilder, AirBuilderWithPublicValues, BaseAirWithPublicValues (functionality merged into AirBuilder/BaseAir) - Expose cap_height and max_log_arity in public CommitmentParameters/FriParameters - Add documentation to public types and fix stale doc comments --- Cargo.lock | 123 +++++++++++++++++++---------------- Cargo.toml | 26 ++++---- deny.toml | 3 +- src/builder/check.rs | 41 +++++------- src/builder/folder.rs | 66 +++++++++---------- src/builder/mod.rs | 13 ++-- src/builder/symbolic.rs | 33 ++++------ src/chips/blake3_circuit.rs | 20 ++++-- src/chips/byte_operations.rs | 6 +- src/chips/u32_add.rs | 12 ++-- src/lookup.rs | 41 +++++------- src/prover.rs | 23 +++++-- src/system.rs | 13 ++++ src/types.rs | 19 +++++- src/verifier.rs | 62 +++++++++++------- 15 files changed, 281 insertions(+), 220 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ed31b82..ce08f77 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -134,17 +134,18 @@ dependencies = [ [[package]] name = "p3-air" -version = "0.4.2" -source = "git+https://github.com/Plonky3/Plonky3?rev=0835481398d2b481bef0c6d0e8188b484ab9a636#0835481398d2b481bef0c6d0e8188b484ab9a636" +version = "0.5.0" +source = "git+https://github.com/Plonky3/Plonky3?rev=e52636ec09663fd7d3bd4eaabb21dba8698f129a#e52636ec09663fd7d3bd4eaabb21dba8698f129a" dependencies = [ "p3-field", "p3-matrix", + "tracing", ] [[package]] name = "p3-challenger" -version = "0.4.2" -source = "git+https://github.com/Plonky3/Plonky3?rev=0835481398d2b481bef0c6d0e8188b484ab9a636#0835481398d2b481bef0c6d0e8188b484ab9a636" +version = "0.5.0" +source = "git+https://github.com/Plonky3/Plonky3?rev=e52636ec09663fd7d3bd4eaabb21dba8698f129a#e52636ec09663fd7d3bd4eaabb21dba8698f129a" dependencies = [ "p3-field", "p3-maybe-rayon", @@ -156,8 +157,8 @@ dependencies = [ [[package]] name = "p3-commit" -version = "0.4.2" -source = "git+https://github.com/Plonky3/Plonky3?rev=0835481398d2b481bef0c6d0e8188b484ab9a636#0835481398d2b481bef0c6d0e8188b484ab9a636" +version = "0.5.0" +source = "git+https://github.com/Plonky3/Plonky3?rev=e52636ec09663fd7d3bd4eaabb21dba8698f129a#e52636ec09663fd7d3bd4eaabb21dba8698f129a" dependencies = [ "itertools", "p3-challenger", @@ -170,8 +171,8 @@ dependencies = [ [[package]] name = "p3-dft" -version = "0.4.2" -source = "git+https://github.com/Plonky3/Plonky3?rev=0835481398d2b481bef0c6d0e8188b484ab9a636#0835481398d2b481bef0c6d0e8188b484ab9a636" +version = "0.5.0" +source = "git+https://github.com/Plonky3/Plonky3?rev=e52636ec09663fd7d3bd4eaabb21dba8698f129a#e52636ec09663fd7d3bd4eaabb21dba8698f129a" dependencies = [ "itertools", "p3-field", @@ -184,8 +185,8 @@ dependencies = [ [[package]] name = "p3-field" -version = "0.4.2" -source = "git+https://github.com/Plonky3/Plonky3?rev=0835481398d2b481bef0c6d0e8188b484ab9a636#0835481398d2b481bef0c6d0e8188b484ab9a636" +version = "0.5.0" +source = "git+https://github.com/Plonky3/Plonky3?rev=e52636ec09663fd7d3bd4eaabb21dba8698f129a#e52636ec09663fd7d3bd4eaabb21dba8698f129a" dependencies = [ "itertools", "num-bigint", @@ -199,8 +200,8 @@ dependencies = [ [[package]] name = "p3-fri" -version = "0.4.2" -source = "git+https://github.com/Plonky3/Plonky3?rev=0835481398d2b481bef0c6d0e8188b484ab9a636#0835481398d2b481bef0c6d0e8188b484ab9a636" +version = "0.5.0" +source = "git+https://github.com/Plonky3/Plonky3?rev=e52636ec09663fd7d3bd4eaabb21dba8698f129a#e52636ec09663fd7d3bd4eaabb21dba8698f129a" dependencies = [ "itertools", "p3-challenger", @@ -213,20 +214,22 @@ dependencies = [ "p3-util", "rand", "serde", + "spin", "thiserror", "tracing", ] [[package]] name = "p3-goldilocks" -version = "0.4.2" -source = "git+https://github.com/Plonky3/Plonky3?rev=0835481398d2b481bef0c6d0e8188b484ab9a636#0835481398d2b481bef0c6d0e8188b484ab9a636" +version = "0.5.0" +source = "git+https://github.com/Plonky3/Plonky3?rev=e52636ec09663fd7d3bd4eaabb21dba8698f129a#e52636ec09663fd7d3bd4eaabb21dba8698f129a" dependencies = [ "num-bigint", "p3-challenger", "p3-dft", "p3-field", "p3-mds", + "p3-poseidon1", "p3-poseidon2", "p3-symmetric", "p3-util", @@ -237,8 +240,8 @@ dependencies = [ [[package]] name = "p3-interpolation" -version = "0.4.2" -source = "git+https://github.com/Plonky3/Plonky3?rev=0835481398d2b481bef0c6d0e8188b484ab9a636#0835481398d2b481bef0c6d0e8188b484ab9a636" +version = "0.5.0" +source = "git+https://github.com/Plonky3/Plonky3?rev=e52636ec09663fd7d3bd4eaabb21dba8698f129a#e52636ec09663fd7d3bd4eaabb21dba8698f129a" dependencies = [ "p3-field", "p3-matrix", @@ -248,10 +251,9 @@ dependencies = [ [[package]] name = "p3-keccak" -version = "0.4.2" -source = "git+https://github.com/Plonky3/Plonky3?rev=0835481398d2b481bef0c6d0e8188b484ab9a636#0835481398d2b481bef0c6d0e8188b484ab9a636" +version = "0.5.0" +source = "git+https://github.com/Plonky3/Plonky3?rev=e52636ec09663fd7d3bd4eaabb21dba8698f129a#e52636ec09663fd7d3bd4eaabb21dba8698f129a" dependencies = [ - "p3-field", "p3-symmetric", "p3-util", "tiny-keccak", @@ -259,8 +261,8 @@ dependencies = [ [[package]] name = "p3-matrix" -version = "0.4.2" -source = "git+https://github.com/Plonky3/Plonky3?rev=0835481398d2b481bef0c6d0e8188b484ab9a636#0835481398d2b481bef0c6d0e8188b484ab9a636" +version = "0.5.0" +source = "git+https://github.com/Plonky3/Plonky3?rev=e52636ec09663fd7d3bd4eaabb21dba8698f129a#e52636ec09663fd7d3bd4eaabb21dba8698f129a" dependencies = [ "itertools", "p3-field", @@ -269,21 +271,20 @@ dependencies = [ "rand", "serde", "tracing", - "transpose", ] [[package]] name = "p3-maybe-rayon" -version = "0.4.2" -source = "git+https://github.com/Plonky3/Plonky3?rev=0835481398d2b481bef0c6d0e8188b484ab9a636#0835481398d2b481bef0c6d0e8188b484ab9a636" +version = "0.5.0" +source = "git+https://github.com/Plonky3/Plonky3?rev=e52636ec09663fd7d3bd4eaabb21dba8698f129a#e52636ec09663fd7d3bd4eaabb21dba8698f129a" dependencies = [ "rayon", ] [[package]] name = "p3-mds" -version = "0.4.2" -source = "git+https://github.com/Plonky3/Plonky3?rev=0835481398d2b481bef0c6d0e8188b484ab9a636#0835481398d2b481bef0c6d0e8188b484ab9a636" +version = "0.5.0" +source = "git+https://github.com/Plonky3/Plonky3?rev=e52636ec09663fd7d3bd4eaabb21dba8698f129a#e52636ec09663fd7d3bd4eaabb21dba8698f129a" dependencies = [ "p3-dft", "p3-field", @@ -294,8 +295,8 @@ dependencies = [ [[package]] name = "p3-merkle-tree" -version = "0.4.2" -source = "git+https://github.com/Plonky3/Plonky3?rev=0835481398d2b481bef0c6d0e8188b484ab9a636#0835481398d2b481bef0c6d0e8188b484ab9a636" +version = "0.5.0" +source = "git+https://github.com/Plonky3/Plonky3?rev=e52636ec09663fd7d3bd4eaabb21dba8698f129a#e52636ec09663fd7d3bd4eaabb21dba8698f129a" dependencies = [ "itertools", "p3-commit", @@ -312,8 +313,8 @@ dependencies = [ [[package]] name = "p3-monty-31" -version = "0.4.2" -source = "git+https://github.com/Plonky3/Plonky3?rev=0835481398d2b481bef0c6d0e8188b484ab9a636#0835481398d2b481bef0c6d0e8188b484ab9a636" +version = "0.5.0" +source = "git+https://github.com/Plonky3/Plonky3?rev=e52636ec09663fd7d3bd4eaabb21dba8698f129a#e52636ec09663fd7d3bd4eaabb21dba8698f129a" dependencies = [ "itertools", "num-bigint", @@ -322,6 +323,7 @@ dependencies = [ "p3-matrix", "p3-maybe-rayon", "p3-mds", + "p3-poseidon1", "p3-poseidon2", "p3-symmetric", "p3-util", @@ -330,13 +332,22 @@ dependencies = [ "serde", "spin", "tracing", - "transpose", +] + +[[package]] +name = "p3-poseidon1" +version = "0.5.0" +source = "git+https://github.com/Plonky3/Plonky3?rev=e52636ec09663fd7d3bd4eaabb21dba8698f129a#e52636ec09663fd7d3bd4eaabb21dba8698f129a" +dependencies = [ + "p3-field", + "p3-symmetric", + "rand", ] [[package]] name = "p3-poseidon2" -version = "0.4.2" -source = "git+https://github.com/Plonky3/Plonky3?rev=0835481398d2b481bef0c6d0e8188b484ab9a636#0835481398d2b481bef0c6d0e8188b484ab9a636" +version = "0.5.0" +source = "git+https://github.com/Plonky3/Plonky3?rev=e52636ec09663fd7d3bd4eaabb21dba8698f129a#e52636ec09663fd7d3bd4eaabb21dba8698f129a" dependencies = [ "p3-field", "p3-mds", @@ -347,20 +358,22 @@ dependencies = [ [[package]] name = "p3-symmetric" -version = "0.4.2" -source = "git+https://github.com/Plonky3/Plonky3?rev=0835481398d2b481bef0c6d0e8188b484ab9a636#0835481398d2b481bef0c6d0e8188b484ab9a636" +version = "0.5.0" +source = "git+https://github.com/Plonky3/Plonky3?rev=e52636ec09663fd7d3bd4eaabb21dba8698f129a#e52636ec09663fd7d3bd4eaabb21dba8698f129a" dependencies = [ "itertools", "p3-field", + "p3-util", "serde", ] [[package]] name = "p3-util" -version = "0.4.2" -source = "git+https://github.com/Plonky3/Plonky3?rev=0835481398d2b481bef0c6d0e8188b484ab9a636#0835481398d2b481bef0c6d0e8188b484ab9a636" +version = "0.5.0" +source = "git+https://github.com/Plonky3/Plonky3?rev=e52636ec09663fd7d3bd4eaabb21dba8698f129a#e52636ec09663fd7d3bd4eaabb21dba8698f129a" dependencies = [ "serde", + "transpose", ] [[package]] @@ -371,42 +384,42 @@ checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" [[package]] name = "pin-project-lite" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" [[package]] name = "proc-macro2" -version = "1.0.104" +version = "1.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9695f8df41bb4f3d222c95a67532365f569318332d03d5f3f67f37b20e6ebdf0" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.42" +version = "1.0.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" dependencies = [ "proc-macro2", ] [[package]] name = "rand" -version = "0.9.2" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" +checksum = "bc266eb313df6c5c09c1c7b1fbe2510961e5bcd3add930c1e31f7ed9da0feff8" dependencies = [ "rand_core", ] [[package]] name = "rand_core" -version = "0.9.3" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +checksum = "0c8d0fd677905edcbeedbf2edb6494d676f0e98d54d5cf9bda0b061cb8fb8aba" [[package]] name = "rayon" @@ -481,9 +494,9 @@ checksum = "fe895eb47f22e2ddd4dabc02bce419d2e643c8e3b585c78158b349195bc24d82" [[package]] name = "syn" -version = "2.0.113" +version = "2.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "678faa00651c9eb72dd2020cbdf275d92eccb2400d568e419efdd64838145cb4" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" dependencies = [ "proc-macro2", "quote", @@ -492,18 +505,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.17" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "2.0.17" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" dependencies = [ "proc-macro2", "quote", @@ -559,9 +572,9 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.22" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" [[package]] name = "unty" diff --git a/Cargo.toml b/Cargo.toml index 793fc08..4aec777 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,19 +11,19 @@ rust-version = "1.88" [dependencies] serde = { version = "1", features = ["derive"] } bincode = { version = "2", features = ["serde"] } -p3-air = { git = "https://github.com/Plonky3/Plonky3", rev = "0835481398d2b481bef0c6d0e8188b484ab9a636" } -p3-goldilocks = { git = "https://github.com/Plonky3/Plonky3", rev = "0835481398d2b481bef0c6d0e8188b484ab9a636" } -p3-challenger = { git = "https://github.com/Plonky3/Plonky3", rev = "0835481398d2b481bef0c6d0e8188b484ab9a636" } -p3-commit = { git = "https://github.com/Plonky3/Plonky3", rev = "0835481398d2b481bef0c6d0e8188b484ab9a636" } -p3-dft = { git = "https://github.com/Plonky3/Plonky3", rev = "0835481398d2b481bef0c6d0e8188b484ab9a636" } -p3-field = { git = "https://github.com/Plonky3/Plonky3", rev = "0835481398d2b481bef0c6d0e8188b484ab9a636" } -p3-fri = { git = "https://github.com/Plonky3/Plonky3", rev = "0835481398d2b481bef0c6d0e8188b484ab9a636" } -p3-keccak = { git = "https://github.com/Plonky3/Plonky3", rev = "0835481398d2b481bef0c6d0e8188b484ab9a636" } -p3-matrix = { git = "https://github.com/Plonky3/Plonky3", rev = "0835481398d2b481bef0c6d0e8188b484ab9a636" } -p3-maybe-rayon = { git = "https://github.com/Plonky3/Plonky3", rev = "0835481398d2b481bef0c6d0e8188b484ab9a636" } -p3-merkle-tree = { git = "https://github.com/Plonky3/Plonky3", rev = "0835481398d2b481bef0c6d0e8188b484ab9a636" } -p3-symmetric = { git = "https://github.com/Plonky3/Plonky3", rev = "0835481398d2b481bef0c6d0e8188b484ab9a636" } -p3-util = { git = "https://github.com/Plonky3/Plonky3", rev = "0835481398d2b481bef0c6d0e8188b484ab9a636" } +p3-air = { git = "https://github.com/Plonky3/Plonky3", rev = "e52636ec09663fd7d3bd4eaabb21dba8698f129a" } +p3-goldilocks = { git = "https://github.com/Plonky3/Plonky3", rev = "e52636ec09663fd7d3bd4eaabb21dba8698f129a" } +p3-challenger = { git = "https://github.com/Plonky3/Plonky3", rev = "e52636ec09663fd7d3bd4eaabb21dba8698f129a" } +p3-commit = { git = "https://github.com/Plonky3/Plonky3", rev = "e52636ec09663fd7d3bd4eaabb21dba8698f129a" } +p3-dft = { git = "https://github.com/Plonky3/Plonky3", rev = "e52636ec09663fd7d3bd4eaabb21dba8698f129a" } +p3-field = { git = "https://github.com/Plonky3/Plonky3", rev = "e52636ec09663fd7d3bd4eaabb21dba8698f129a" } +p3-fri = { git = "https://github.com/Plonky3/Plonky3", rev = "e52636ec09663fd7d3bd4eaabb21dba8698f129a" } +p3-keccak = { git = "https://github.com/Plonky3/Plonky3", rev = "e52636ec09663fd7d3bd4eaabb21dba8698f129a" } +p3-matrix = { git = "https://github.com/Plonky3/Plonky3", rev = "e52636ec09663fd7d3bd4eaabb21dba8698f129a" } +p3-maybe-rayon = { git = "https://github.com/Plonky3/Plonky3", rev = "e52636ec09663fd7d3bd4eaabb21dba8698f129a" } +p3-merkle-tree = { git = "https://github.com/Plonky3/Plonky3", rev = "e52636ec09663fd7d3bd4eaabb21dba8698f129a" } +p3-symmetric = { git = "https://github.com/Plonky3/Plonky3", rev = "e52636ec09663fd7d3bd4eaabb21dba8698f129a" } +p3-util = { git = "https://github.com/Plonky3/Plonky3", rev = "e52636ec09663fd7d3bd4eaabb21dba8698f129a" } [features] parallel = ["p3-maybe-rayon/parallel"] diff --git a/deny.toml b/deny.toml index 92097af..8cf3ffe 100644 --- a/deny.toml +++ b/deny.toml @@ -71,6 +71,7 @@ feature-depth = 1 # output a note when they are encountered. ignore = [ "RUSTSEC-2024-0436", # `paste` crate is unmaintained + "RUSTSEC-2025-0141", # `bincode` crate is unmaintained #"RUSTSEC-0000-0000", #{ id = "RUSTSEC-0000-0000", reason = "you can specify a reason the advisory is ignored" }, #"a-crate-that-is-yanked@0.1.1", # you can also ignore yanked crate versions if you wish @@ -95,7 +96,7 @@ allow = [ "Unicode-3.0", "CC0-1.0", #"Apache-2.0 WITH LLVM-exception", - "BSD-2-Clause", + #"BSD-2-Clause", ] # The confidence threshold for detecting a license from license text. # The higher the value, the more closely the license text must be to the diff --git a/src/builder/check.rs b/src/builder/check.rs index e762a88..e0f82b3 100644 --- a/src/builder/check.rs +++ b/src/builder/check.rs @@ -1,4 +1,4 @@ -use p3_air::{Air, AirBuilder, AirBuilderWithPublicValues, ExtensionBuilder}; +use p3_air::{Air, AirBuilder, ExtensionBuilder, RowWindow}; use p3_field::PrimeCharacteristicRing; use p3_matrix::Matrix; use p3_matrix::dense::{RowMajorMatrix, RowMajorMatrixView}; @@ -6,7 +6,7 @@ use p3_matrix::stack::VerticalPair; use crate::types::{ExtVal, Val}; -use super::{PreprocessedBuilder, TwoStagedBuilder}; +use super::TwoStagedBuilder; pub fn check_constraints( air: &A, @@ -38,7 +38,7 @@ pub fn check_constraints( ); let mut builder = DebugConstraintBuilder { row_index: i, - preprocessed: None, + preprocessed: RowWindow::from_two_rows(&[], &[]), stage_1, stage_2, public_values, @@ -52,11 +52,8 @@ pub fn check_constraints( if let Some(preprocessed) = preprocessed { let preprocessed_local = preprocessed.row_slice(i).unwrap(); // i < height so unwrap should never fail. let preprocessed_next = preprocessed.row_slice(i_next).unwrap(); // i_next < height so unwrap should never fail. - let preprocessed = Some(VerticalPair::new( - RowMajorMatrixView::new_row(&*preprocessed_local), - RowMajorMatrixView::new_row(&*preprocessed_next), - )); - builder.preprocessed = preprocessed; + builder.preprocessed = + RowWindow::from_two_rows(&preprocessed_local, &preprocessed_next); air.eval(&mut builder); } else { air.eval(&mut builder); @@ -68,8 +65,8 @@ pub fn check_constraints( pub struct DebugConstraintBuilder<'a> { /// The index of the row currently being evaluated. row_index: usize, - /// A view of the current and next row as a vertical pair. - preprocessed: Option, RowMajorMatrixView<'a, Val>>>, + /// A two-row window over the preprocessed trace (current and next row). + preprocessed: RowWindow<'a, Val>, stage_1: VerticalPair, RowMajorMatrixView<'a, Val>>, stage_2: VerticalPair, RowMajorMatrixView<'a, ExtVal>>, /// The public values provided for constraint validation (e.g. inputs or outputs). @@ -87,10 +84,16 @@ impl<'a> AirBuilder for DebugConstraintBuilder<'a> { type F = Val; type Expr = Val; type Var = Val; - type M = VerticalPair, RowMajorMatrixView<'a, Val>>; + type PreprocessedWindow = RowWindow<'a, Val>; + type MainWindow = RowWindow<'a, Val>; + type PublicVar = Val; - fn main(&self) -> Self::M { - self.stage_1 + fn main(&self) -> Self::MainWindow { + RowWindow::from_two_rows(self.stage_1.top.values, self.stage_1.bottom.values) + } + + fn preprocessed(&self) -> &Self::PreprocessedWindow { + &self.preprocessed } fn is_first_row(&self) -> Self::Expr { @@ -129,22 +132,12 @@ impl<'a> AirBuilder for DebugConstraintBuilder<'a> { self.row_index, x, y ); } -} - -impl AirBuilderWithPublicValues for DebugConstraintBuilder<'_> { - type PublicVar = Self::F; - fn public_values(&self) -> &[Self::F] { + fn public_values(&self) -> &[Self::PublicVar] { self.public_values } } -impl PreprocessedBuilder for DebugConstraintBuilder<'_> { - fn preprocessed(&self) -> Option { - self.preprocessed - } -} - impl<'a> ExtensionBuilder for DebugConstraintBuilder<'a> { type EF = ExtVal; type ExprEF = ExtVal; diff --git a/src/builder/folder.rs b/src/builder/folder.rs index cc22c28..f8dfca9 100644 --- a/src/builder/folder.rs +++ b/src/builder/folder.rs @@ -1,16 +1,16 @@ -/// Adapted from Plonky3's `https://github.com/Plonky3/Plonky3/blob/main/uni-stark/src/folder.rs` -use p3_air::{AirBuilder, AirBuilderWithPublicValues, ExtensionBuilder}; +/// Constraint folders for the prover and verifier, adapted from Plonky3. +use p3_air::{AirBuilder, ExtensionBuilder, RowWindow}; use p3_field::{BasedVectorSpace, PackedField}; use p3_matrix::dense::RowMajorMatrixView; use p3_matrix::stack::VerticalPair; use crate::types::{ExtVal, PackedExtVal, PackedVal, Val}; -use super::{PreprocessedBuilder, TwoStagedBuilder}; +use super::TwoStagedBuilder; #[derive(Debug)] pub struct ProverConstraintFolder<'a> { - pub preprocessed: Option>, + pub preprocessed: RowWindow<'a, PackedVal>, pub stage_1: RowMajorMatrixView<'a, PackedVal>, pub stage_2: RowMajorMatrixView<'a, PackedExtVal>, pub stage_1_public_values: &'a [Val], @@ -28,7 +28,7 @@ type ViewPair<'a, T> = VerticalPair, RowMajorMatrixVie #[derive(Debug)] pub struct VerifierConstraintFolder<'a> { - pub preprocessed: Option>, + pub preprocessed: RowWindow<'a, ExtVal>, pub stage_1: ViewPair<'a, ExtVal>, pub stage_2: ViewPair<'a, ExtVal>, pub stage_1_public_values: &'a [Val], @@ -44,11 +44,17 @@ impl<'a> AirBuilder for ProverConstraintFolder<'a> { type F = Val; type Expr = PackedVal; type Var = PackedVal; - type M = RowMajorMatrixView<'a, PackedVal>; + type PreprocessedWindow = RowWindow<'a, PackedVal>; + type MainWindow = RowWindow<'a, PackedVal>; + type PublicVar = Val; #[inline] - fn main(&self) -> Self::M { - self.stage_1 + fn main(&self) -> Self::MainWindow { + RowWindow::from_view(&self.stage_1) + } + + fn preprocessed(&self) -> &Self::PreprocessedWindow { + &self.preprocessed } #[inline] @@ -90,6 +96,11 @@ impl<'a> AirBuilder for ProverConstraintFolder<'a> { }); self.constraint_index += N; } + + #[inline] + fn public_values(&self) -> &[Self::PublicVar] { + self.stage_1_public_values + } } impl<'a> ExtensionBuilder for ProverConstraintFolder<'a> { @@ -109,21 +120,6 @@ impl<'a> ExtensionBuilder for ProverConstraintFolder<'a> { } } -impl AirBuilderWithPublicValues for ProverConstraintFolder<'_> { - type PublicVar = Self::F; - - #[inline] - fn public_values(&self) -> &[Self::F] { - self.stage_1_public_values - } -} - -impl<'a> PreprocessedBuilder for ProverConstraintFolder<'a> { - fn preprocessed(&self) -> Option { - self.preprocessed - } -} - impl<'a> TwoStagedBuilder for ProverConstraintFolder<'a> { type MP = RowMajorMatrixView<'a, PackedExtVal>; @@ -142,10 +138,16 @@ impl<'a> AirBuilder for VerifierConstraintFolder<'a> { type F = Val; type Expr = ExtVal; type Var = ExtVal; - type M = ViewPair<'a, ExtVal>; + type PreprocessedWindow = RowWindow<'a, ExtVal>; + type MainWindow = RowWindow<'a, ExtVal>; + type PublicVar = Val; + + fn main(&self) -> Self::MainWindow { + RowWindow::from_two_rows(self.stage_1.top.values, self.stage_1.bottom.values) + } - fn main(&self) -> Self::M { - self.stage_1 + fn preprocessed(&self) -> &Self::PreprocessedWindow { + &self.preprocessed } fn is_first_row(&self) -> Self::Expr { @@ -171,22 +173,12 @@ impl<'a> AirBuilder for VerifierConstraintFolder<'a> { self.accumulator *= self.alpha; self.accumulator += x; } -} - -impl AirBuilderWithPublicValues for VerifierConstraintFolder<'_> { - type PublicVar = Self::F; - fn public_values(&self) -> &[Self::F] { + fn public_values(&self) -> &[Self::PublicVar] { self.stage_1_public_values } } -impl<'a> PreprocessedBuilder for VerifierConstraintFolder<'a> { - fn preprocessed(&self) -> Option { - self.preprocessed - } -} - impl<'a> ExtensionBuilder for VerifierConstraintFolder<'a> { type EF = ExtVal; type ExprEF = ExtVal; diff --git a/src/builder/mod.rs b/src/builder/mod.rs index aff77fc..7c41c5b 100644 --- a/src/builder/mod.rs +++ b/src/builder/mod.rs @@ -1,20 +1,23 @@ -use p3_air::{AirBuilder, ExtensionBuilder}; +use p3_air::ExtensionBuilder; use p3_matrix::Matrix; pub mod check; pub mod folder; pub mod symbolic; -pub trait PreprocessedBuilder: AirBuilder { - fn preprocessed(&self) -> Option; -} - +/// Extension of [`ExtensionBuilder`] that provides access to a second-stage +/// trace and its associated public values (used by the lookup argument). pub trait TwoStagedBuilder: ExtensionBuilder { + /// Matrix type for the stage 2 trace window. type MP: Matrix; + /// Variable type for stage 2 public values. type Stage2PublicVar: Into + Copy; + /// Returns the stage 2 trace window. fn stage_2(&self) -> Self::MP; + /// Returns the stage 2 public values (lookup and fingerprint challenges, + /// current accumulator, next accumulator). fn stage_2_public_values(&self) -> &[Self::Stage2PublicVar]; } diff --git a/src/builder/symbolic.rs b/src/builder/symbolic.rs index d09ca04..b2d62d3 100644 --- a/src/builder/symbolic.rs +++ b/src/builder/symbolic.rs @@ -1,5 +1,5 @@ -/// Adapted from Plonky3's `https://github.com/Plonky3/Plonky3/blob/main/uni-stark/src/symbolic_builder.rs` -use p3_air::{Air, AirBuilder, AirBuilderWithPublicValues, ExtensionBuilder}; +/// Symbolic constraint builder and expressions, adapted from Plonky3. +use p3_air::{Air, AirBuilder, ExtensionBuilder}; use p3_field::{Algebra, Field, InjectiveMonomial, PrimeCharacteristicRing}; use p3_matrix::dense::RowMajorMatrix; use p3_util::log2_ceil_usize; @@ -10,7 +10,7 @@ use std::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign}; use crate::types::{ExtVal, Val}; -use super::{PreprocessedBuilder, TwoStagedBuilder}; +use super::TwoStagedBuilder; #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub enum Entry { @@ -365,7 +365,7 @@ pub fn get_log_quotient_degree(max_constraint_degree: usize, is_zk: bool) -> usi /// An `AirBuilder` for evaluating constraints symbolically, and recording them for later use. #[derive(Debug)] pub struct SymbolicAirBuilder { - preprocessed: Option>>, + preprocessed: RowMajorMatrix>, stage_1: RowMajorMatrix>, stage_2: RowMajorMatrix>, public_values: Vec>, @@ -409,11 +409,7 @@ impl SymbolicAirBuilder { .map(move |index| SymbolicVariable::new(Entry::Stage2Public, index)) .collect(); Self { - preprocessed: if preprocessed_width == 0 { - None - } else { - Some(RowMajorMatrix::new(prep_values, preprocessed_width)) - }, + preprocessed: RowMajorMatrix::new(prep_values, preprocessed_width), stage_1: RowMajorMatrix::new(stage_1_values, stage_1_width), stage_2: RowMajorMatrix::new(stage_2_values, stage_2_width), public_values, @@ -427,12 +423,18 @@ impl AirBuilder for SymbolicAirBuilder { type F = Val; type Expr = SymbolicExpression; type Var = SymbolicVariable; - type M = RowMajorMatrix; + type PreprocessedWindow = RowMajorMatrix; + type MainWindow = RowMajorMatrix; + type PublicVar = SymbolicVariable; - fn main(&self) -> Self::M { + fn main(&self) -> Self::MainWindow { self.stage_1.clone() } + fn preprocessed(&self) -> &Self::PreprocessedWindow { + &self.preprocessed + } + fn is_first_row(&self) -> Self::Expr { SymbolicExpression::IsFirstRow } @@ -454,21 +456,12 @@ impl AirBuilder for SymbolicAirBuilder { fn assert_zero>(&mut self, x: I) { self.constraints.push(x.into().into()); } -} -impl AirBuilderWithPublicValues for SymbolicAirBuilder { - type PublicVar = SymbolicVariable; fn public_values(&self) -> &[Self::PublicVar] { &self.public_values } } -impl PreprocessedBuilder for SymbolicAirBuilder { - fn preprocessed(&self) -> Option { - self.preprocessed.clone() - } -} - impl Algebra> for SymbolicExpression {} impl From> for SymbolicExpression { diff --git a/src/chips/blake3_circuit.rs b/src/chips/blake3_circuit.rs index fbc0d46..2e7f672 100644 --- a/src/chips/blake3_circuit.rs +++ b/src/chips/blake3_circuit.rs @@ -5,7 +5,7 @@ mod tests { use crate::lookup::{Lookup, LookupAir}; use crate::system::{System, SystemWitness}; use crate::types::{CommitmentParameters, FriParameters, Val}; - use p3_air::{Air, AirBuilder, BaseAir}; + use p3_air::{Air, AirBuilder, BaseAir, WindowAccess}; use p3_field::{Field, PrimeCharacteristicRing, PrimeField64}; use p3_matrix::Matrix; use p3_matrix::dense::RowMajorMatrix; @@ -162,7 +162,7 @@ mod tests { | Self::GFunction => {} Self::U32Add => { let main = builder.main(); - let local = main.row_slice(0).unwrap(); + let local = main.current_slice(); let x = &local[0..4]; let y = &local[4..8]; let z = &local[8..12]; @@ -187,7 +187,7 @@ mod tests { } Self::U32RightRotate12 | Self::U32RightRotate7 => { let main = builder.main(); - let local = main.row_slice(0).unwrap(); + let local = main.current_slice(); let input = local[1] + local[2] * AB::Expr::from_u32(256) @@ -227,7 +227,7 @@ mod tests { } Self::Compression => { let main = builder.main(); - let columns = main.row_slice(0).unwrap(); + let columns = main.current_slice(); let mut offset = 1usize; let indices: [usize; 128] = array::from_fn(|i| i + 1); @@ -1915,7 +1915,10 @@ mod tests { assert_eq!(actual, expected.to_vec()); // circuit testing - let commitment_parameters = CommitmentParameters { log_blowup: 1 }; + let commitment_parameters = CommitmentParameters { + log_blowup: 1, + cap_height: 0, + }; let u8_circuit = LookupAir::new( Blake3CompressionChips::U8Xor, Blake3CompressionChips::U8Xor.lookups(), @@ -1989,6 +1992,7 @@ mod tests { let fri_parameters = FriParameters { log_final_poly_len: 0, + max_log_arity: 1, num_queries: 64, commit_proof_of_work_bits: 0, query_proof_of_work_bits: 0, @@ -2099,7 +2103,10 @@ mod tests { fn run_test(claims: &Blake3CompressionClaims) { // circuit testing - let commitment_parameters = CommitmentParameters { log_blowup: 1 }; + let commitment_parameters = CommitmentParameters { + log_blowup: 1, + cap_height: 0, + }; let u8_circuit = LookupAir::new( Blake3CompressionChips::U8Xor, Blake3CompressionChips::U8Xor.lookups(), @@ -2160,6 +2167,7 @@ mod tests { let fri_parameters = FriParameters { log_final_poly_len: 0, + max_log_arity: 1, num_queries: 64, commit_proof_of_work_bits: 0, query_proof_of_work_bits: 0, diff --git a/src/chips/byte_operations.rs b/src/chips/byte_operations.rs index cd0daeb..da68c7e 100644 --- a/src/chips/byte_operations.rs +++ b/src/chips/byte_operations.rs @@ -124,7 +124,10 @@ mod tests { #[test] #[ignore] fn byte_test() { - let commitment_parameters = CommitmentParameters { log_blowup: 1 }; + let commitment_parameters = CommitmentParameters { + log_blowup: 1, + cap_height: 0, + }; let circuit = LookupAir::new(ByteCS {}, ByteCS {}.lookups()); let (system, key) = System::new(commitment_parameters, vec![circuit]); let calls = ByteCalls { @@ -144,6 +147,7 @@ mod tests { let claims: &[&[Val]] = &[claim1, claim2, claim3, claim4]; let fri_parameters = FriParameters { log_final_poly_len: 0, + max_log_arity: 1, num_queries: 64, commit_proof_of_work_bits: 0, query_proof_of_work_bits: 0, diff --git a/src/chips/u32_add.rs b/src/chips/u32_add.rs index a72dfc0..0224095 100644 --- a/src/chips/u32_add.rs +++ b/src/chips/u32_add.rs @@ -1,8 +1,8 @@ #[cfg(test)] mod tests { - use p3_air::{Air, AirBuilder, BaseAir}; + use p3_air::{Air, AirBuilder, BaseAir, WindowAccess}; use p3_field::{Field, PrimeCharacteristicRing}; - use p3_matrix::{Matrix, dense::RowMajorMatrix}; + use p3_matrix::dense::RowMajorMatrix; use crate::chips::SymbExpr; use crate::{ @@ -57,7 +57,7 @@ mod tests { Self::ByteChip => {} Self::U32AddChip => { let main = builder.main(); - let local = main.row_slice(0).unwrap(); + let local = main.current_slice(); let x = &local[0..4]; let y = &local[4..8]; let z = &local[8..12]; @@ -183,7 +183,10 @@ mod tests { #[test] fn u32_add_proof() { - let commitment_parameters = CommitmentParameters { log_blowup: 1 }; + let commitment_parameters = CommitmentParameters { + log_blowup: 1, + cap_height: 0, + }; let (system, key) = byte_system(commitment_parameters); let calls = AddCalls { calls: vec![(10, 5), (30, 20), (100, 100), (8000, 10000)], @@ -197,6 +200,7 @@ mod tests { let claims: &[&[Val]] = &[claim1, claim2, claim3, claim4]; let fri_parameters = FriParameters { log_final_poly_len: 0, + max_log_arity: 1, num_queries: 64, commit_proof_of_work_bits: 0, query_proof_of_work_bits: 0, diff --git a/src/lookup.rs b/src/lookup.rs index fecd998..bb1a654 100644 --- a/src/lookup.rs +++ b/src/lookup.rs @@ -1,9 +1,9 @@ -use p3_air::{Air, BaseAir, BaseAirWithPublicValues, ExtensionBuilder}; +use p3_air::{Air, BaseAir, ExtensionBuilder, WindowAccess}; use p3_field::{PrimeCharacteristicRing, batch_multiplicative_inverse}; use p3_matrix::{Matrix, dense::RowMajorMatrix}; use crate::{ - builder::{PreprocessedBuilder, TwoStagedBuilder, symbolic::SymbolicExpression}, + builder::{TwoStagedBuilder, symbolic::SymbolicExpression}, types::{ExtVal, Val}, }; @@ -201,25 +201,16 @@ where } } -impl BaseAirWithPublicValues for LookupAir -where - A: BaseAirWithPublicValues, -{ - fn num_public_values(&self) -> usize { - self.inner_air.num_public_values() - } -} - impl Air for LookupAir where A: Air, - AB: PreprocessedBuilder + TwoStagedBuilder, + AB: TwoStagedBuilder, { fn eval(&self, builder: &mut AB) { - if let Some(preprocessed) = builder.preprocessed() { - let preprocessed_row = preprocessed.row_slice(0); - debug_assert!(preprocessed_row.is_some()); - self.eval_with_preprocessed_row(builder, preprocessed_row.as_deref()) + if self.preprocessed.is_some() { + let preprocessed = builder.preprocessed().clone(); + let preprocessed_row = preprocessed.current_slice(); + self.eval_with_preprocessed_row(builder, Some(preprocessed_row)) } else { self.eval_with_preprocessed_row(builder, None) } @@ -230,7 +221,7 @@ impl LookupAir { fn eval_with_preprocessed_row(&self, builder: &mut AB, preprocessed_row: Option<&[AB::Var]>) where A: Air, - AB: PreprocessedBuilder + TwoStagedBuilder, + AB: TwoStagedBuilder, { // Call `eval` for regular stage 1 constraints. self.inner_air.eval(builder); @@ -258,15 +249,15 @@ impl LookupAir { // inverses are indeed the inverses of the messages computed on the main // trace. let main = builder.main(); - let row = main.row_slice(0).unwrap(); + let row = main.current_slice(); let mut acc_expr = acc_col.into(); for (lookup, &message_inverse) in lookups.iter().zip(messages_inverses) { let multiplicity: AB::ExprEF = - lookup.multiplicity.interpret(&row, preprocessed_row).into(); + lookup.multiplicity.interpret(row, preprocessed_row).into(); let args = lookup .args .iter() - .map(|arg| arg.interpret(&row, preprocessed_row)); + .map(|arg| arg.interpret(row, preprocessed_row)); let fingerprint = fingerprint(&fingerprint_challenge, args); let message: AB::ExprEF = lookup_challenge.clone() + fingerprint; let message_inverse = message_inverse.into(); @@ -290,7 +281,7 @@ impl LookupAir { #[cfg(test)] mod tests { - use p3_air::AirBuilder; + use p3_air::{AirBuilder, WindowAccess}; use p3_field::Field; use crate::{ @@ -361,7 +352,7 @@ mod tests { fn eval(&self, builder: &mut AB) { // both even and odd have the same constraints, they only differ on the lookups let main = builder.main(); - let local = main.row_slice(0).unwrap(); + let local = main.current_slice(); let multiplicity = local[0]; let input = local[1]; let input_inverse = local[2]; @@ -385,7 +376,10 @@ mod tests { #[test] fn lookup_test() { - let commitment_parameters = CommitmentParameters { log_blowup: 1 }; + let commitment_parameters = CommitmentParameters { + log_blowup: 1, + cap_height: 0, + }; let (system, key) = system(commitment_parameters); let f = Val::from_u32; #[rustfmt::skip] @@ -423,6 +417,7 @@ mod tests { let claim = &[f(0), f(4), f(1)]; let fri_parameters = FriParameters { log_final_poly_len: 0, + max_log_arity: 1, num_queries: 64, commit_proof_of_work_bits: 0, query_proof_of_work_bits: 0, diff --git a/src/prover.rs b/src/prover.rs index 4020512..1626434 100644 --- a/src/prover.rs +++ b/src/prover.rs @@ -14,7 +14,7 @@ use bincode::{ error::{DecodeError, EncodeError}, serde::{decode_from_slice, encode_to_vec}, }; -use p3_air::{Air, BaseAir}; +use p3_air::{Air, BaseAir, RowWindow}; use p3_challenger::{CanObserve, FieldChallenger}; use p3_commit::{LagrangeSelectors, OpenedValuesForRound, Pcs as PcsTrait, PolynomialSpace}; use p3_field::{ @@ -26,18 +26,26 @@ use p3_maybe_rayon::prelude::*; use p3_util::log2_strict_usize; use serde::{Deserialize, Serialize}; +/// Polynomial commitments included in the proof. #[derive(Serialize, Deserialize)] pub struct Commitments { + /// Commitment to the stage 1 (main) execution traces. pub stage_1_trace: Commitment, + /// Commitment to the stage 2 (lookup) execution traces. pub stage_2_trace: Commitment, + /// Commitment to the quotient polynomial chunks. pub quotient_chunks: Commitment, } +/// A STARK proof for a multi-circuit system. #[derive(Serialize, Deserialize)] pub struct Proof { pub commitments: Commitments, + /// Per-circuit intermediate accumulator values for the lookup argument. pub intermediate_accumulators: Vec, + /// Log2 of the trace degree for each circuit. pub log_degrees: Vec, + /// PCS opening proof covering all rounds. pub opening_proof: PcsProof, pub quotient_opened_values: OpenedValuesForRound, pub preprocessed_opened_values: Option>, @@ -98,10 +106,10 @@ impl + for<'a> Air>> System { let (stage_1_trace_commit, stage_1_trace_data) = >::commit(pcs, evaluations); - if let Some(commit) = self.preprocessed_commit { + if let Some(commit) = &self.preprocessed_commit { challenger.observe(commit); } - challenger.observe(stage_1_trace_commit); + challenger.observe(stage_1_trace_commit.clone()); // observe the traces' heights. TODO: is this necessary? for log_degree in &log_degrees { @@ -144,7 +152,7 @@ impl + for<'a> Air>> System { }); let (stage_2_trace_commit, stage_2_trace_data) = >::commit(pcs, evaluations); - challenger.observe(stage_2_trace_commit); + challenger.observe(stage_2_trace_commit.clone()); // generate constraint challenge let constraint_challenge: ExtVal = challenger.sample_algebra_element(); @@ -233,7 +241,7 @@ impl + for<'a> Air>> System { }); let (quotient_commit, quotient_data) = >::commit(pcs, quotient_evaluations); - challenger.observe(quotient_commit); + challenger.observe(quotient_commit.clone()); // save the commitments let commitments = Commitments { @@ -449,7 +457,10 @@ where let accumulator = PackedExtVal::ZERO; let mut folder = ProverConstraintFolder { - preprocessed: preprocessed.as_ref().map(|mat| mat.as_view()), + preprocessed: match preprocessed.as_ref() { + Some(mat) => RowWindow::from_view(&mat.as_view()), + None => RowWindow::from_two_rows(&[], &[]), + }, stage_1: stage_1.as_view(), stage_2: stage_2.as_view(), stage_1_public_values, diff --git a/src/system.rs b/src/system.rs index 06a90f4..fb11dc0 100644 --- a/src/system.rs +++ b/src/system.rs @@ -6,14 +6,21 @@ use crate::{ use p3_air::{Air, BaseAir}; use p3_matrix::{Matrix, dense::RowMajorMatrix}; +/// A multi-circuit STARK system. Contains all circuits together with their +/// shared preprocessed commitment and commitment parameters. pub struct System { pub commitment_parameters: CommitmentParameters, pub circuits: Vec>, + /// Commitment to all preprocessed traces (if any circuit has one). pub preprocessed_commit: Option, + /// Maps each circuit index to its position within the preprocessed commitment. + /// `None` if that circuit has no preprocessed trace. pub preprocessed_indices: Vec>, } +/// Prover-side data that must be retained between system setup and proving. pub struct ProverKey { + /// PCS prover data for the preprocessed traces. pub preprocessed_data: Option, } @@ -55,6 +62,8 @@ impl + Air> System { } } +/// A single circuit within the system, wrapping an AIR together with +/// precomputed metadata used by the prover and verifier. pub struct Circuit { pub air: LookupAir, pub constraint_count: usize, @@ -65,9 +74,13 @@ pub struct Circuit { pub stage_2_width: usize, } +/// Witness data for the multi-circuit system, comprising stage 1 traces and +/// the concrete lookup values derived from them. #[derive(Clone)] pub struct SystemWitness { + /// Stage 1 (main) execution traces, one per circuit. pub traces: Vec>, + /// Lookup values per circuit, per row, per lookup. pub lookups: Vec>>>, } diff --git a/src/types.rs b/src/types.rs index a15926c..893b31f 100644 --- a/src/types.rs +++ b/src/types.rs @@ -19,11 +19,14 @@ pub type Mmcs = MerkleTreeMmcs< [u64; p3_keccak::VECTOR_LEN], SerializingHasher>, KeccakCompressionFunction, + 2, 4, >; pub type ExtMmcs = ExtensionMmcs; pub type Pcs = TwoAdicFriPcs; +/// Configuration for the STARK prover and verifier, bundling the PCS and an +/// initial challenger state. #[derive(Debug)] pub struct StarkConfig { /// The PCS used to commit polynomials and prove opening proofs. @@ -64,6 +67,7 @@ impl Committer { pub fn new(commitment_parameters: CommitmentParameters) -> Self { let dummy_parameters = FriParameters { log_final_poly_len: 0, + max_log_arity: 1, num_queries: 0, commit_proof_of_work_bits: 0, query_proof_of_work_bits: 0, @@ -87,11 +91,19 @@ impl Committer { #[derive(Clone, Copy)] pub struct CommitmentParameters { pub log_blowup: usize, + /// Height of the Merkle cap (number of top layers included in the commitment). + /// A cap height of 0 means only the root is committed. + pub cap_height: usize, } +/// Parameters controlling the FRI protocol. #[derive(Clone, Copy)] pub struct FriParameters { + /// Log2 of the degree of the final polynomial (0 means a constant). pub log_final_poly_len: usize, + /// Maximum folding arity per FRI round (log2). A value of 1 means binary folding. + pub max_log_arity: usize, + /// Number of query repetitions for soundness amplification. pub num_queries: usize, /// Number of bits for the PoW phase before sampling _each_ batching challenge. pub commit_proof_of_work_bits: usize, @@ -103,19 +115,20 @@ type KeccakCompressionFunction = CompressionFunctionFromHasher, 2, 4>; type Dft = Radix2DitParallel; -fn new_mmcs() -> Mmcs { +fn new_mmcs(cap_height: usize) -> Mmcs { let u64_hash = PaddingFreeSponge::::new(KeccakF {}); let field_hash = SerializingHasher::new(u64_hash); let compress = KeccakCompressionFunction::new(u64_hash); - Mmcs::new(field_hash, compress) + Mmcs::new(field_hash, compress, cap_height) } fn new_pcs(commitment_parameters: CommitmentParameters, fri_parameters: FriParameters) -> Pcs { - let val_mmcs = new_mmcs(); + let val_mmcs = new_mmcs(commitment_parameters.cap_height); let mmcs = ExtensionMmcs::new(val_mmcs.clone()); let inner_parameters = InnerFriParameters { log_blowup: commitment_parameters.log_blowup, log_final_poly_len: fri_parameters.log_final_poly_len, + max_log_arity: fri_parameters.max_log_arity, num_queries: fri_parameters.num_queries, commit_proof_of_work_bits: fri_parameters.commit_proof_of_work_bits, query_proof_of_work_bits: fri_parameters.query_proof_of_work_bits, diff --git a/src/verifier.rs b/src/verifier.rs index ef63a21..36162d8 100644 --- a/src/verifier.rs +++ b/src/verifier.rs @@ -6,20 +6,27 @@ use crate::{ system::System, types::{Challenger, ExtVal, FriParameters, Pcs, PcsError, StarkConfig, Val}, }; -use p3_air::{Air, BaseAir}; +use p3_air::{Air, BaseAir, RowWindow}; use p3_challenger::{CanObserve, FieldChallenger}; use p3_commit::{Pcs as PcsTrait, PolynomialSpace}; use p3_field::{BasedVectorSpace, Field, PrimeCharacteristicRing}; use p3_matrix::{dense::RowMajorMatrixView, stack::VerticalPair}; use p3_util::log2_strict_usize; +/// Errors that can occur during proof verification. #[derive(Debug)] pub enum VerificationError { + /// A provided claim is invalid. InvalidClaim, + /// The PCS opening proof failed to verify. InvalidOpeningArgument(PcsErr), + /// The proof has an unexpected shape (wrong number of opened values, etc.). InvalidProofShape, + /// The system configuration is invalid (e.g. no circuits). InvalidSystem, + /// The recomputed composition polynomial does not match the quotient. OodEvaluationMismatch, + /// The lookup accumulator did not balance to zero. UnbalancedChannel, } @@ -65,10 +72,10 @@ impl + for<'a> Air>> System { let mut challenger = config.initialise_challenger(); // observe preprocessed and stage_1 commitment - if let Some(commit) = self.preprocessed_commit { + if let Some(commit) = &self.preprocessed_commit { challenger.observe(commit); } - challenger.observe(commitments.stage_1_trace); + challenger.observe(commitments.stage_1_trace.clone()); // observe the traces' heights. TODO: is this necessary? for log_degree in log_degrees { @@ -87,7 +94,7 @@ impl + for<'a> Air>> System { challenger.observe_algebra_element(fingerprint_challenge); // observe stage_2 commitment - challenger.observe(commitments.stage_2_trace); + challenger.observe(commitments.stage_2_trace.clone()); // construct the accumulator from the claims let mut acc = ExtVal::ZERO; @@ -101,7 +108,7 @@ impl + for<'a> Air>> System { let constraint_challenge: ExtVal = challenger.sample_algebra_element(); // observe quotient commitment - challenger.observe(commitments.quotient_chunks); + challenger.observe(commitments.quotient_chunks.clone()); // generate out of domain points and verify the PCS opening let zeta: ExtVal = challenger.sample_algebra_element(); @@ -166,12 +173,18 @@ impl + for<'a> Air>> System { last_quotient_i += quotient_degree; } let mut coms_to_verify = vec![ - (commitments.stage_1_trace, stage_1_trace_evaluations), - (commitments.stage_2_trace, stage_2_trace_evaluations), - (commitments.quotient_chunks, quotient_chunks_evaluations), + (commitments.stage_1_trace.clone(), stage_1_trace_evaluations), + (commitments.stage_2_trace.clone(), stage_2_trace_evaluations), + ( + commitments.quotient_chunks.clone(), + quotient_chunks_evaluations, + ), ]; - if let Some(preprocessed_commitment) = self.preprocessed_commit { - coms_to_verify.extend([(preprocessed_commitment, preprocessed_trace_evaluations)]) + if let Some(preprocessed_commitment) = &self.preprocessed_commit { + coms_to_verify.extend([( + preprocessed_commitment.clone(), + preprocessed_trace_evaluations, + )]) } pcs.verify(coms_to_verify, opening_proof, &mut challenger) .map_err(VerificationError::InvalidOpeningArgument)?; @@ -203,12 +216,9 @@ impl + for<'a> Air>> System { let preprocessed_opened_values = preprocessed_opened_values.as_ref().unwrap(); let preprocessed_row = &preprocessed_opened_values[i][0]; let preprocessed_next_row = &preprocessed_opened_values[i][1]; - Some(VerticalPair::new( - RowMajorMatrixView::new_row(preprocessed_row), - RowMajorMatrixView::new_row(preprocessed_next_row), - )) + RowWindow::from_two_rows(preprocessed_row, preprocessed_next_row) } else { - None + RowWindow::from_two_rows(&[], &[]) }; let stage_1 = VerticalPair::new( RowMajorMatrixView::new_row(stage_1_row), @@ -420,8 +430,8 @@ mod tests { system::{ProverKey, SystemWitness}, types::{CommitmentParameters, FriParameters}, }; - use p3_air::{AirBuilderWithPublicValues, BaseAir}; - use p3_matrix::{Matrix, dense::RowMajorMatrix}; + use p3_air::{AirBuilder, BaseAir, WindowAccess}; + use p3_matrix::dense::RowMajorMatrix; enum CS { Pythagorean, @@ -437,14 +447,14 @@ mod tests { } impl Air for CS where - AB: AirBuilderWithPublicValues, + AB: AirBuilder, AB::Var: Copy, { fn eval(&self, builder: &mut AB) { match self { Self::Pythagorean => { let main = builder.main(); - let local = main.row_slice(0).unwrap(); + let local = main.current_slice(); let expr1 = local[0] * local[0] + local[1] * local[1]; let expr2 = local[2] * local[2]; // this extra `local[0]` multiplication is there to increase the maximum constraint degree @@ -452,7 +462,7 @@ mod tests { } Self::Complex => { let main = builder.main(); - let local = main.row_slice(0).unwrap(); + let local = main.current_slice(); // (a + ib)(c + id) = (ac - bd) + i(ad + bc) let expr1 = local[0] * local[2] - local[1] * local[3]; let expr2 = local[4]; @@ -475,7 +485,10 @@ mod tests { #[test] fn multi_stark_test() { - let commitment_parameters = CommitmentParameters { log_blowup: 1 }; + let commitment_parameters = CommitmentParameters { + log_blowup: 1, + cap_height: 0, + }; let (system, key) = system(commitment_parameters); let f = Val::from_u32; let witness = SystemWitness::from_stage_1( @@ -490,6 +503,7 @@ mod tests { ); let fri_parameters = FriParameters { log_final_poly_len: 0, + max_log_arity: 1, num_queries: 64, commit_proof_of_work_bits: 0, query_proof_of_work_bits: 0, @@ -507,7 +521,10 @@ mod tests { // To run this benchmark effectively, run the following command // RUSTFLAGS="-Ctarget-cpu=native" cargo test multi_stark_benchmark_test --release --features parallel -- --include-ignored --nocapture const LOG_HEIGHT: usize = 20; - let commitment_parameters = CommitmentParameters { log_blowup: 1 }; + let commitment_parameters = CommitmentParameters { + log_blowup: 1, + cap_height: 0, + }; let (system, key) = system(commitment_parameters); let f = Val::from_u32; let mut pythagorean_trace = [3, 4, 5].map(f).to_vec(); @@ -525,6 +542,7 @@ mod tests { ); let fri_parameters = FriParameters { log_final_poly_len: 0, + max_log_arity: 1, num_queries: 100, commit_proof_of_work_bits: 10, query_proof_of_work_bits: 10,