DoHoon Kim
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights New
    • Engagement control
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Note Insights Versions and GitHub Sync Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Engagement control Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       Owned this note    Owned this note      
    Published Linked with GitHub
    1
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    # Bringing recursive SN[T]ARK techniques for Semaphore protocol ## Introduction Hello, I'm Dohoon from Privacy & Scaling Explorations team. PSE team has been working for various applications of zkSNARK for years. They have made lots of applications including zkEVM, Semaphore-protocol and all other awesome projects. Throughout the development, we are always facing challenges of reducing proving time, and lower the verification cost. It seems that there is no killer-scheme yet that achieves everything better, however some people suggested some idea of composing different schemes that have different advantages into one. It is called **proof composition** in the field, and it was already explored by many people and proved quite powerful. A variety of composition strategies have emerged for constructing “hybrid” proof systems that combine components across the stack. There are several forms of proof composition, and today, I will talk about composing zkSTARK and zkSNARK proof systems. Motivation of this work was to make more fast, light prover and to reduce the verification cost using aggregation technique. Recursion & aggregation for zkSNARK proof system has been developed by several people, and shown that it has large *recursion overhead*. It requires the expensive pairing check inside the circuit, and also too many non-native field arithmetic inside the circuit. Some people have proven that the recursion & aggregation for zkSTARK is quite really fast, as zkSTARK operates on a single finite field, and does not require pairing.(instead a lot of hashing) We can make faster and lighter prover and aggregate multiple proofs cheaply with zkSTARK technology. zkSTARK has very fast proving time, it has a drawback that its proof size is too-large to be verified on-chain. This is where zkSNARK comes in. If we can prove the verification of zkSTARK proof inside zkSNARK circuit, the resulting proof will be much smaller and can be verified on-chain! It seems that we can obtain really nice proof system by combining them. Let's see more closely. ## Prerequisites ### How zkSTARK works? zkSTARK has quite different properties from zkSNARK, as they do not work on elliptic curves and do not require trusted setup. Let's see what makes the differences between zkSTARK and zkSNARK. For people who are already familiar with zkSNARK schemes(Groth16, PLONK, KZG, ...), it would be clear that zkSNARK is nothing more than proving about the knowledge of certain *polynomials*. In ZK argument systems, they usually brings the power of *polynomial commitment scheme* to prove the knowledge of polynomials without revealing the whole coefficients. For KZG commitment scheme, prover can *commit* to the polynomials which is represented as a elliptic curve point, and later *open* the polynomial at some point by providing another elliptic curve point as a opening proof. This proof can be verified in a single pairing check. In zkSTARK, they also use polynomials, and thus require polynomial commitment scheme, and is based on **FRI**. FRI protocol was originally used for *low-degree testing*, which shows that some codeword is close enough to the codeword of some polynomial that has low-degree. Here is how it works. ### FRI protocol Let’s say the following function as codeword. $$ f: D \rightarrow \mathbb{F} $$ We want to show the codeword is close to Reed-Solomon code defined as following: $$ RS_k[F, D] = \{p(x)|_{x \in D}:p(X) \in F[X], \;deg\; p(X) \le k-1\} $$ We say $\rho = k/|D|$ as **rate**, or $1/\rho$ as a **blowup factor**. Let’s say the initial domain of FRI as $L_0$, and want to show codeword $f: L_0 \rightarrow \mathbb{F}$ is close to some polynomial $p(X)$ of degree at most $k-1.$ $|L_0| = 2^n, k = 2^d$ Also, denote Merkle tree commitment of $f: L \rightarrow \mathbb{F}$ as $[f]$. Honest prover will proceed to prove that the interpolation of codeword $f$, which we call $f(X)$ has degree at most $k-1$. FRI protocol has two phases: *commit phase* and *query phase*. In **commit phase**, prover splits the domain size and the polynomial into half in each layer, and sends commitments of the polynomials in each layer. ![](https://i.imgur.com/8KlJmRb.png) Each domain $L_0, L_1, \dots$ are cyclic multiplicative subgroups of $\mathbb{F}^*$. 1. Prover sends $[f_0]$ to verifier. 2. Verifier samples random field value $\beta_0$ 3. Prover splits the polynomial as follows: $$ f_0(X) = f_{0, E}(X^2) + X \cdot f_{0, O}(X^2) $$ and computes $f_1(X)$ $$ f_1(X) = f_{0, E}(X) + \beta_0 \cdot f_{0, O}(X) $$ Note that $f_1(X)$ has half degree of the degree of $f_0(X)$, and is defined above $L_1 = \{x^2| x \in L_0 \}$ . $L_1$ size is half of the size of $L_0$ . 4. Prover recursively proceeds this for $\log(k)$ rounds. 5. Prover sends this constant to verifier. In **query** phase, verifier should check that the prover folded the polynomial correctly. This is called consistency check. ![](https://i.imgur.com/2v90WNQ.png) 1. Verifier queries random point $v, -v$ in $L_0$, and calculates the correct folded value as follows: $$ f_0(v) = f_{0, E}(v^2) + v \cdot f_{0, O}(v^2) \\ f_0(-v) = f_{0, E}(v^2) - v \cdot f_{0, O}(v^2) $$ From queried value $f_0(v), f_0(-v)$, verifier can obtain $f_{0, E}(v^2), f_{0, O}(v^2)$ and calculate $f_1(v^2)$ . $$ f_1(v^2) = f_{0, E}(v^2) + \beta_0 \cdot f_{0, O}(v^2) $$ 2. Verifier queries point $v^2$ in $L_1$, and checks the above equation holds. 3. Verifier checks consistencies between subsequent layers. Verifier repeats the query phase until it reaches the desired security level. ### Cost model of FRI It's quite important to have bird's-eye view on the cost model of FRI, because the cost is affected by the parameters of FRI. - Prover time For prover, the most dominant cost is to evaluate the polynomial over initial domain. It is the cost of FFT over initial domain. If rate parameter $\rho$ gets smaller, the prover time will increase. $$ O(|L_0|\log(|L_0|)) = O(\rho^{-1} \cdot k\log(\rho^{-1} \cdot k)) $$ - Proof length In query phase, prover should provide **merkle path** to decommit the evaluation on the queried point. This is the dominant cost for proof length. To achieve $\lambda$ bits of security, the verifier should repeat query phase at least $\lambda / \log(\rho^{-1})$ times. If we do many queries, then the proof length and verification cost will be bigger. We can configure the parameters for FRI to take achieve desirable property between proving time and proof size. ### DEEP FRI So, how can we use FRI as polynomial commitment scheme? I will re-ask the question. How can verifier query the point **outside** of the initial evaluation domain? Let’s assume the following case: $$ f: L_0 \rightarrow \mathbb{F}, \; r \in \mathbb{F} \backslash L_0 \\ f(r) $$ How can verifier verifies the opening at $f(r)$? Prover and verifier can simply proceed FRI on the quotient polynomial: $$ q(X) = {{f(X) - v} \over {X - r}}, \\ q : L_0 \rightarrow \mathbb{F} $$ If $q(X)$ has the degree at most $k-2$, then the verifier can accept the opening. [VP19] Prover should also send $f(x)$ to check the consistency between $q(x)$ and $f(x)$ (along with merkle proof) in every query round. Prover should also send $f(x)$ to check the consistency between $q(x)$ and $f(x)$ (along with merkle proof) in every query round. ### Optimizations There are some several techniques to reduce the proving time and the proof length of FRI. We will not deal with these techniques more deeply in this post, check out [here](https://oil-moustache-ffb.notion.site/FRI-workshop-b491d29bc6b846aaac451f206f23c012). ## Architecture ### STARK & SNARK proof composition As first proving system we use a STARK and our main idea of composition is to delegate the verification procedure of the STARK proof $\pi_{STARK}$ to a verification circuit $C$. In this case, if the prover provides a proof for the correct execution of the verification circuit $\pi_{circuit}$, then this is enough to verify the original STARK. In this case, the verifier entity just verifies the proof of the STARK verification circuit $\pi_{circuit}$. The advantage of this composition is that $\pi_{circuit}$ is smaller and faster to verify than $\pi_{STARK}$. ### Aggregation We used aggregation method to combine the original STARK proofs. Aggregation is a particular type of proof composition in which multiple valid proofs can be proven to be valid by comprising them all into one proof, called the *aggregated proof*, by validating only the aggregated one. In the architecture, aggregators are defined in intermediate circuits. Below describes how aggregation works: ![](https://i.imgur.com/vWXotQM.png) We should be able to aggregate the arbitrary number of proofs, so we make tree-like structure to aggregate all of them into one. We call this *aggregation tree*. Below describes how aggregation tree works. ![](https://i.imgur.com/olANx6K.png) In aggregation tree, we have three different parts, or phases. First, individual provers generate STARK proofs circuits. In this part, we do not need to care about aggregation. The remaining two phases are: aggregation phase and finalization phase. In aggregation phase, every adjacent proofs in aggregation tree are combined into one proof by the aggregators which are defined as the circuit that encodes STARK verification logic. Let's call this aggregator as *recursive STARK prover*. When the final proof is generated at the end, this proof should be verified inside SNARK circuit. The main purpose of the finalization phase is to compress the proof and make it verifiable on-chain(e.g. EVM). In aggregation phase, all the independent computations in each aggregation layer can be parallelized. ![](https://i.imgur.com/mJ8V5jH.png) Let's look more deeply into the details of each phases. ### Detail in each phase Let's look at the each layer of the phases. In aggregation phase, the base layer of the aggregation tree can be described as follows: ![](https://i.imgur.com/pk4iyx3.png) Users provide witness and public inputs for circuits, and the circuits generate STARK proof. This STARK proof should be verified inside the next layer's recursive STARK prover. Thus the recursive STARK prover should be witnessed by proofs, verification key of the previous layer's circuit, and the public inputs of the previous layer's circuits. In the above figure, recursive STARK prover generates new proof that attests to the correctness of $proof0$ and $proof1$. Recursive STARK prover should pass combined public inputs and the verification key of *its own circuit* to the next layer along with the proof. ## Applications ### Semaphore for large-scaled voting How about using Semaphore protocol for very large-scaled voting(e.g. nationwide presidential election)? Every voter should generate their proof in a short time. Also if we can aggregate all the proofs into one, we can make the gas fee charged on each voter negligible. Also, for voting case, the time spent for all the proofs to be finalized does not matter.(it would be much faster to get finalized than in the real-world voting) I tested this aggregation scheme with Semaphore proofs, and the following is the benchmark result. ## Benchmarks The code can be found [here](https://github.com/DoHoonKim8/stark-verifier). ### Without aggregation Proving time measured for group size $2^{20}$ on M1 mac pro is approximately 0.95s. FRI parameter setting is as follows: - $\rho = 2^{-3}$ (blowup factor 8) - 28 query rounds - proof of work bits: 16 bits We can see the proving time has decreased compared to current Semaphore protocol, which takes approximately [2.4s](https://benchmarks.semaphore.appliedzkp.org/) for group size $2^{20}$. ### Aggregation Following is the benchmark result for aggregating Semaphore proofs & finalizing. Measured gas cost is the cost for verifying only Halo2 proofs, without sending public inputs of Semaphore to on-chain.(this definitely should be done later) It was measured on r5.4xlarge ec2 instance. |number of proofs|aggregation time|Halo2 proving time|circuit size|gas| |---|---|---|---|---| |2|11s|505s|k=23|407142| |4|29s|507s|k=23|405109| |8|64s|511s|k=23|401021| |16|128s|509s|k=23|407388| |32|235s|509s|k=23|406783| |64|468s|511s|k=23|409911| |128|930s|510s|k=23|406226| Plonky2 library seems to be 2 times faster on M1 mac pro than on r5.4xlarge ec2 instance. (Aggregation time is much faster than on M1 mac pro) We can reduce the aggregation time more by changing machine stack and also by applying optimization techniques. ## Further works - I hope my work can be generalized to be the framework for zkSTARK aggregation. In Semaphore, we can test completely another model other than using Merkle tree. Instead of using merkle tree, devs can use lookup arguments(e.g. [Caulk+](https://github.com/geometryresearch/semacaulk/tree/main)), and whenever they want to aggregate membership proofs and verify them on-chain, I hope they can build Plonky2 circuit that verifies pairing and aggregate them using this POC.

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password

    or

    By clicking below, you agree to our terms of service.

    Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully