Skip to content

Commit

Permalink
added images
Browse files Browse the repository at this point in the history
  • Loading branch information
mimoo committed Oct 16, 2024
1 parent a78f0f9 commit 7158b91
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 4 deletions.
Binary file added img/starknet/fri/folding.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/starknet/fri/queries.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/starknet/fri/skipped_layers.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions source/starknet/fri.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ assert find_gen2(3)^8 == 1

#### Reduction

![folding](/img/starknet/fri/folding.png)

A reduction in the FRI protocol is obtained by interpreting an input polynomial $p$ as a polynomial of degree $2n$ and splitting it into two polynomials $g$ and $h$ of degree $n$ such that $p(x) = g(x^2) + x h(x^2)$.

Then, with the help of a verifier's random challenge $\zeta$, we can produce a random linear combination of these polynomials to obtain a new polynomial $g(x) + \zeta h(x)$ of degree $n$:
Expand Down Expand Up @@ -122,6 +124,8 @@ assert p3.degree() == 0

#### Queries

![queries](/img/starknet/fri/queries.png)

In the real FRI protocol, each layer's polynomial would be sent using a hash-based commitment (e.g. a Merkle tree of its evaluations over a large domain). As such, the verifier must ensure that each commitment consistently represent the proper reduction of the previous layer's polynomial. To do that, they "query" commitments of the different polynomials of the different layers at points/evaluations. Let's see how this works.

Given a polynomial $p_0(x) = g_0(x^2) + x h_0(x^2)$ and two of its evaluations at some points $v$ and $-v$, we can see that the verifier can recover the two halves by computing:
Expand Down Expand Up @@ -172,6 +176,8 @@ assert p3 == g2_square + zeta2 * h2_square # we already received p3 at the end o

#### Skipping FRI layers

![skipped layers](/img/starknet/fri/skipped_layers.png)

Section 3.11.1 "Skipping FRI Layers" of the ethSTARK paper describes an optimization which skips some of the layers/rounds. The intuition is the following: if we removed the first round commitment (to the polynomial $p_1$), then the verifier would not be able to:

- query $p_1(v^2)$ to verify that layer
Expand Down
46 changes: 42 additions & 4 deletions source/starknet/stark.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: "Starknet STARK Verifier"
abstract: "TKTK"
abstract: "In this document we specify the STARK verifier used in Starknet."
sotd: "none"
---

Expand All @@ -10,6 +10,16 @@ In this section we give an overview of the STARK protocol.

<aside class="note">Note that the protocol implemented closely resembles the high-level explanations of the <a href="https://eprint.iacr.org/2021/582">ethSTARK paper</a>, as such we refer to it in places.</aside>

<aside class="note">
This protocol is instantiated in several places to our knowledge:
<ul>
<li><a href="https://github.com/starkware-libs/stone-prover/blob/main/src/starkware/main/cpu/cpu_air_verifier_main.cc">C++ implementation</a></li>
<li><a href="https://zksecurity.github.io/stark-book/starkex/cairo.html">Solidity implementation</a></li>
<li><a href="https://github.com/starkware-libs/cairo-lang/tree/9e6e0e96d208608d98635ccfad5b26285c4936e1/src/starkware/cairo/stark_verifier">Cairo0 implementation</a></li>
<li><a href="https://github.com/HerodotusDev/integrity">Cairo1 implementation</a></li>
</ul>
</aside>

### AIR Arithmetization

TKTK
Expand Down Expand Up @@ -69,6 +79,34 @@ struct StarkConfig {
}
```

To validate:

* proof of work is validated as part of the FRI configuration validation
* compute the log of the evaluation domain size as the log of the trace domain size plus the log of the number of cosets
* if every coset is of size $2^{n_e}$ with $n_e$ the `log_trace_domain_size`, and there is $2^{n_c}$ cosets, then the evaluation domain size is expected to be $2^{n_e + n_c}$
* traces.validate() (TODO)
* composition.vector.validate()
* the FRI configuration is validated as part of the FRI configuration validation

```rust
self
.composition
.vector
.validate(log_eval_domain_size, *self.n_verifier_friendly_commitment_layers);

// Validate Fri config.
self.fri.validate(*self.log_n_cosets, *self.n_verifier_friendly_commitment_layers);

// Security bits.
let n_queries: u32 = (*self.n_queries).try_into().unwrap();
let log_n_cosets: u32 = (*self.log_n_cosets).try_into().unwrap();
let proof_of_work_bits: u32 = (*self.proof_of_work.n_bits).try_into().unwrap();

n_queries * log_n_cosets + proof_of_work_bits
}
}
```



## Main STARK functions / Buiding blocks
Expand Down Expand Up @@ -150,9 +188,9 @@ The protocol is split into 3 core functions:
One can successively call them in the following order to verify a proof:

1. Call `verify_initial` on the proof and return:
1. the FriVerificationStateConstant object
2. the FriVerificationStateVariable object
3. the last_layer_coefficients
1. the `FriVerificationStateConstant` object
2. the `FriVerificationStateVariable` object
3. the `last_layer_coefficients`
4. the security bits <-- TODO: remove this?
2. Call verify_step in a loop on each layer of the proof (`n_layers` of them according to the StateConstant returned) and pass the FriVerificationStateVariable in between each calls
3. Call verify_final on the StateConstant and StateVariable objects
Expand Down

0 comments on commit 7158b91

Please sign in to comment.