GitShow/facebook/winterfell
facebook

winterfell

A STARK prover and verifier for arbitrary computations

by facebook
Star on GitHubFork

Rust

901 stars232 forks38 contributorsQuiet · 1y agoSince 2021v0.13.1MIT

Meet the team

See all 38 on GitHub →
irakliyk
irakliyk489 contributions
Nashtare
Nashtare52 contributions
Al-Kindi-0
Al-Kindi-043 contributions
0xkanekiken
0xkanekiken21 contributions
plafer
plafer12 contributions
hackaugusto
hackaugusto11 contributions
grjte
grjte10 contributions
andrewmilson
andrewmilson5 contributions

Languages

View on GitHub →
Rust99.7%
HTML0.1%
Makefile0.1%
Shell0%

Commit activity

Last 12 weeks · 0 commits

Full graph →

Community health

4 of 6 standards met

Community profile →
75
✓README✓License✓Contributing✓Code of Conduct○Issue Template○PR Template

Recent PRs & issues

Quiet · Last activity 1y ago
See all on GitHub →
atoranzo
Docs: constraint degree calculation and constant-column edge caseOpenIssue

While implementing several application circuits with Winterfell I hit the "transition constraint degrees didn't match" assertion repeatedly, and worked out two things that took me a while and are not in the docs. Sharing in case they're useful for the documentation, or in case I've misunderstood something. 1. The relationship between the declared degree and the expected value From comparing the and arrays across several failures on a 512-row trace, the expected degree appears to be: So a cyclic column effectively contributes one degree. Once I worked this out I could translate a mismatch directly into the correct declaration instead of guessing, which saved a lot of iterations. If that's accurate, having it stated in the docs — or in the assertion message itself — would help. The current message gives the two arrays but not the mapping back to the declaration. 2. Constraints over columns that are constant by construction This one surprised me. Consider: I declared this as degree 2, reasoning that it multiplies two trace columns. Winterfell rejected it: actual degree 0. The reason is that all four columns are constant — the transport constraints force them to be — so the product of two constant polynomials is constant, and the whole expression has degree 0 regardless of its algebraic form. Declaring is correct. The contrast that made it click: a boolean check also multiplies two columns and is degree 2, because the bit varies across rows. So the degree depends on whether the columns vary, not on the shape of the expression. That's obvious in hindsight but I didn't find it stated anywhere, and it cost me a couple of debugging cycles. Context Encountered while building settlement circuits for a comparative study of five proof systems, and a follow-up on digital euro privacy requirements. Both are public if the concrete cases are useful: https://github.com/atoranzo/ZK-SSL-ZK-Sovereign-Settlement-Layer- https://github.com/atoranzo/euro-digital-zk Happy to open a PR against the docs if either of these is worth writing up and I've got them right.

atoranzo · 4w ago
nzengi
Out-of-core proving over f64OpenIssue

Quick heads up first: I built this on plonky2, not Winterfell. But it runs over the same field (your is the 2^64 - 2^32 + 1 Goldilocks prime I use), and the moving parts line up with what , , and the Merkle tree in do, so this felt like the right place to ask. The idea: a DEEP-FRI STARK where none of the stages that normally hold the whole trace actually keep it in RAM. They stream to disk instead, so peak memory ends up tracking a tile size rather than the trace length. Roughly how each stage goes: NTT/LDE uses the four-step (Bailey) split, N = n1*n2: transform the rows, apply twiddles, transform the columns, transpose. Every pass only touches one row or column, so the working set is O(sqrt N). The matrix sits on NVMe and tiles move through a fixed buffer. The Merkle tree is built bottom-up off a leaf file, one chunk per pread, so it never fully lives in memory the way a does. Leaves are batched, one leaf hashing a group of columns at a row. FRI reads each round's file and writes the next. I commit every other layer and let the verifier recompute the skipped one. There's a page-cache flusher too, because under a hard cgroup with swap off the dirty pages alone will OOM you even when the heap is flat. The thing I was careful about: the out-of-core proof comes out byte-for-byte identical to an in-core run, and a test checks that on every AIR (the in-core path is itself checked against plonky2). So streaming only moves where the work happens. And every memory number is measured under a real systemd cgroup with swap off, so "it survived" is something I watched, not a model. Some numbers under a 256 MB cgroup: 2^28 NTT, 2 GB of data: in-core gets killed, out-of-core runs in 40 MB with the same checksum. A full FRI low-degree proof from 2^26 to 2^28 (512 MB up to 2 GB): in-core OOMs every time, out-of-core stays flat at 34 MB. A Fibonacci STARK at 2^22, around 7 GB in core: killed in core, 45 MB and 61 s out of core. A sponge hash proving Sponge(public msg) = digest, 54 columns: killed in core, 121 MB out of core. The resident set follows the tile, not N. The CPU side is already parallel (a 2^24 self-proof drops from 65.7 s to 11.2 s on 16 cores), and the real cost is the Poseidon hashing in the commitment, not the I/O. What I actually want to know: I'm Goldilocks-only and on plonky2, so this is a design question, not a PR. Winterfell's and assume the trace lives in memory with random row access, and the is fully resident. Is there room in that abstraction for a disk-backed trace and a streaming commitment, or do the trait signatures bake the in-memory assumption in too deeply? And if it did fit, would a streaming prover ever belong in Winterfell, or only as an external thing built on the traits? Upfront about the gaps: it's a research artifact. Small AIRs (they do go up to the sponge), Goldilocks only, a research Poseidon rather than your Rescue, and since the bottleneck is the hash, the obvious next step is GPU hashing, which is the one part I haven't had the hardware to try. Writeup with diagrams and a recording of the cgroup run: https://dev.to/nzengi/a-zk-provers-ram-is-a-dial-not-a-wall-3blg Code: https://github.com/nzengi/zk-stream

nzengi · 2mo ago
YichiZhang0613
fix(air): fix inconsistent assertionOpenPR

In winterfell/air/src/proof/table.rs, the comment and assertion's message requires num_rows and num_cols Result { assert!(num_rows > 0, "number of rows must be greater than 0"); assert!( num_rows 0, "number of columns must be greater than 0"); assert!( num_cols < MAX_ROWS, "number of columns cannot exceed {MAX_COLS}, but was {num_cols}" ); let mut reader = SliceReader::new(bytes); let num_elements = num_rows * num_cols; Ok(Self { data: reader.read_many(num_elements)?, row_width: num_cols, }) } ```

YichiZhang0613 · 3mo ago
Structured data for AI agents

Repository: facebook/winterfell. Description: A STARK prover and verifier for arbitrary computations Stars: 901, Forks: 232. Primary language: Rust. Languages: Rust (99.7%), HTML (0.1%), Makefile (0.1%), Shell (0%). License: MIT. Latest release: v0.13.1 (1y ago). Open PRs: 19, open issues: 49. Last activity: 1y ago. Community health: 75%. Top contributors: irakliyk, Nashtare, Al-Kindi-0, 0xkanekiken, plafer, hackaugusto, grjte, andrewmilson, Jasleen1, Fumuran and others.

·@ofershap

Replace github.com with gitshow.dev