diff --git a/gen_index.py b/gen_index.py new file mode 100644 index 0000000..81c2eed --- /dev/null +++ b/gen_index.py @@ -0,0 +1,49 @@ +import os +import frontmatter +from jinja2 import Environment, FileSystemLoader +from datetime import datetime # Import datetime + + +def generate_rfc_page(): + """ + Generates an HTML page listing RFC documents using Jinja2 templating. + """ + + rfcs = [] + for root, _, files in os.walk("source/"): + for file in files: + if file.endswith(".md"): + filepath = os.path.join(root, file) + with open(filepath, "r") as f: + post = frontmatter.load(f) + # Get last modified date of the file + last_modified = os.path.getmtime(filepath) + rfcs.append( + { + "title": post.get("title"), + "abstract": post.get("abstract"), + "sotd": post.get("sotd"), + "shortName": post.get("shortName"), + "editor": post.get("editor"), + "link": filepath.replace("source/", "rfcs/").replace( + ".md", ".html" + ), + "updated": datetime.fromtimestamp(last_modified).strftime( + "%B %d, %Y" + ), + } + ) + + # Setup Jinja2 environment + env = Environment(loader=FileSystemLoader(".")) + template = env.get_template("index_template.html") + + # Render the template with the RFC data + html = template.render(rfcs=rfcs) + + with open("index.html", "w") as f: + f.write(html) + + +if __name__ == "__main__": + generate_rfc_page() diff --git a/index.html b/index.html index 159ce2f..792a296 100644 --- a/index.html +++ b/index.html @@ -9,45 +9,60 @@ -

Request for Comments (RFC) Documents

-
- + +
+

Starknet STARK Verifier

+

Short Name: starknet-stark

+ +

State of This Document: draft

+

Updated: October 16, 2024

+ + View RFC + +
+
-

FRI

-

Version: 0.1

-

Updated: October 14, 2024

+

Starknet FRI Verifier

+

Short Name: starknet-fri

+ +

State of This Document: draft

+

Updated: October 16, 2024

View RFC
- + - +
-

Channel

-

Version: 0.1

-

Updated: October 14, 2024

+

Starknet Channels for Fiat-Shamir Instantiation

+

Short Name: starknet-channel

+ +

State of This Document: draft

+

Updated: October 16, 2024

View RFC
- +
- \ No newline at end of file diff --git a/index_template.html b/index_template.html new file mode 100644 index 0000000..a4e7ae0 --- /dev/null +++ b/index_template.html @@ -0,0 +1,32 @@ + + + + + + + RFC Documents + + + + +
+

Request for Comments (RFC) Documents

+
+ {% for rfc in rfcs %} +
+

{{ rfc.title }}

+

Short Name: {{ rfc.shortName }}

+ +

State of This Document: {{ rfc.sotd }}

+

Updated: {{ rfc.updated }}

+ + View RFC + +
+ {% endfor %} +
+
+ + + \ No newline at end of file diff --git a/justfile b/justfile index d468edf..47084ee 100644 --- a/justfile +++ b/justfile @@ -5,6 +5,7 @@ setup: build: python md2respec.py --output-path rfcs/ --recursive ./source/ + python gen_index.py debug-build: python md2respec.py --pure-html source/starknet/fri.md @@ -13,4 +14,4 @@ serve: python -m http.server watch: - just serve & watchexec -w md2respec.py -w source/ -w template.html just build + just serve & watchexec -w md2respec.py -w source/ -w template.html -w index_template.html just build diff --git a/requirements.txt b/requirements.txt index dfb880e..266daef 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,4 @@ python-frontmatter Markdown latex2mathml +jinja2 diff --git a/rfcs/starknet/channel.html b/rfcs/starknet/channel.html index 5efcfeb..d5807e7 100644 --- a/rfcs/starknet/channel.html +++ b/rfcs/starknet/channel.html @@ -3,7 +3,7 @@ - Starknet Channel + Starknet Channels for Fiat-Shamir Instantiation @@ -73,7 +73,7 @@

TKTK

-

none

+

draft

Overview

diff --git a/rfcs/starknet/fri.html b/rfcs/starknet/fri.html index 7ade795..374d2d6 100644 --- a/rfcs/starknet/fri.html +++ b/rfcs/starknet/fri.html @@ -75,7 +75,7 @@

-

none

+

draft

Overview

@@ -140,7 +140,7 @@

Reduction

# at this point g and h are still around the same degree of p # we need to replace x^2 by x for FRI to (as we want to halve the degrees!) if remove_square: - g = g.parent(g.list()[::2]) # <-- (using python's <!--CODE_BLOCK_27--> syntax) + g = g.parent(g.list()[::2]) # <-- (using python's <!--CODE_BLOCK_24--> syntax) h = h.parent(h.list()[::2]) assert g.degree() == h.degree() == p.degree() // 2 assert p(7) == g(7^2) + 7 * h(7^2) @@ -337,10 +337,9 @@

Channel

See the Channel specification for more details.

-

Evaluation of the first FRI layer

-

As part of the protocol, the prover must provide a number of evaluations of the first layer polynomial p0. This is abstracted in this specification as the function eval_oods_polynomial which acts as an oracle from FRI's perspective.

-

TODO: not a very satisfying explanation

-

Note that this function is not fixed here, as the polynomial being "tested" could be computed in different ways. See the Starknet STARK verifier specification for a concrete example (and for an explanation of why the function is named this way).

+

Evaluations of the first FRI layer

+

As part of the protocol, the prover must provide a number of evaluations of the first layer polynomial p0 (based on the FRI queries that the verifier generates).

+

We abstract this here as an oracle that magically provides evaluations, it is the responsibility of the user of this protocol to ensure that the evaluations are correct. See the Starknet STARK verifier specification for a concrete usage example.

@@ -437,63 +436,6 @@

FRI configuration

-

Commitments

-

Commitments of polynomials are done using Merkle trees. The Merkle trees can be configured to hash some parameterized number of the lower layers using a circuit-friendly hash function (Poseidon).

- -
-

Table commitments

-

A table commitment in this context is a vector commitment where leaves are potentially hashes of several values (tables of multiple columns and a single row).

-
-
-

Vector commitments

-

A vector commitment is simply a Merkle tree.

-

TODO: diagram.

-

vector commit

-
-
-

Vector membership proofs

-

A vector decommitment/membership proof must provide a witness (the neighbor nodes missing to compute the root of the Merkle tree) ordered in a specific way. The following algorithm dictates in which order the nodes hash values provided in the proof are consumed:

-

vector decommit

-
-
-

Note on commitment multiple evaluations under the same leaf

- -
array![
-    0x1,
-    0x800000000000011000000000000000000000000000000000000000000000000,
-    0x625023929a2995b533120664329f8c7c5268e56ac8320da2a616626f41337e3,
-    0x1dafdc6d65d66b5accedf99bcd607383ad971a9537cdf25d59e99d90becc81e,
-    0x63365fe0de874d9c90adb1e2f9c676e98c62155e4412e873ada5e1dee6feebb,
-    0x1cc9a01f2178b3736f524e1d06398916739deaa1bbed178c525a1e211901146,
-    0x3b912c31d6a226e4a15988c6b7ec1915474043aac68553537192090b43635cd,
-    0x446ed3ce295dda2b5ea677394813e6eab8bfbc55397aacac8e6df6f4bc9ca34,
-    0x5ec467b88826aba4537602d514425f3b0bdf467bbf302458337c45f6021e539,
-    0x213b984777d9556bac89fd2aebbda0c4f420b98440cfdba7cc83ba09fde1ac8,
-    0x5ce3fa16c35cb4da537753675ca3276ead24059dddea2ca47c36587e5a538d1,
-    0x231c05e93ca34c35ac88ac98a35cd89152dbfa622215d35b83c9a781a5ac730,
-    0x00b54759e8c46e1258dc80f091e6f3be387888015452ce5f0ca09ce9e571f52,
-    0x7f4ab8a6173b92fda7237f0f6e190c41c78777feabad31a0f35f63161a8e0af,
-    0x23c12f3909539339b83645c1b8de3e14ebfee15c2e8b3ad2867e3a47eba558c,
-    0x5c3ed0c6f6ac6dd647c9ba3e4721c1eb14011ea3d174c52d7981c5b8145aa75,
-]
-
- -
-
-

Protocol

The FRI protocol is split into two phases:

    @@ -695,7 +637,7 @@

    Full Protocol

    We give more detail to each function below.

    -

    fri_commit(channel, cfg).

    +

    fri_commit(channel).

    1. Take a channel with a prologue (See the Channel section). A prologue contains any context relevant to this proof.
    2. Produce the FRI commits according to the Commit Phase section.
    3. @@ -705,12 +647,12 @@

      Full Protocol

    4. Evaluate the first layer at the queried points using the external dependency (see External Dependencies section), producing values.
    5. Produce the fri_decommitment as FriDecommitment { values, points }.
    -

    fri_verify_initial(queries, fri_commitment, decommitment).

    +

    fri_verify_initial(queries, fri_commitment, decommitment). Takes the FRI queries, the FRI commitments (each layer's committed polynomial), as well as the evaluation points and their associated evaluations of the first layer (in decommitment).

    (
         FriVerificationStateConstant {
    diff --git a/rfcs/starknet/polynomial_commitment.html b/rfcs/starknet/polynomial_commitment.html
    new file mode 100644
    index 0000000..ae024b5
    --- /dev/null
    +++ b/rfcs/starknet/polynomial_commitment.html
    @@ -0,0 +1,137 @@
    +
    +
    +
    +
    +    
    +    Starknet Merkle Tree Polynomial Commitments
    +    
    +
    +    
    +    
    +
    +
    +
    +
    +    
    +

    TKTK

    +
    +
    +

    none

    +
    +
    +

    Overview

    +

    Commitments of polynomials are done using Merkle trees. The Merkle trees can be configured to hash some parameterized number of the lower layers using a circuit-friendly hash function (Poseidon).

    +
      +
    • TODO: why montgomery form?
    • +
    +
    +

    Table commitments

    +

    A table commitment in this context is a vector commitment where leaves are potentially hashes of several values (tables of multiple columns and a single row).

    +
    +
    +

    Vector commitments

    +

    A vector commitment is simply a Merkle tree.

    +

    TODO: diagram.

    +

    vector commit

    +
    +
    +

    Vector membership proofs

    +

    A vector decommitment/membership proof must provide a witness (the neighbor nodes missing to compute the root of the Merkle tree) ordered in a specific way. The following algorithm dictates in which order the nodes hash values provided in the proof are consumed:

    +

    vector decommit

    +
    +
    +

    Note on commitment multiple evaluations under the same leaf

    +
      +
    • the following array contains all the 16-th roots of unity, handily ordered
    • +
    • that is, the first represents the subgroup of order 1, the two first values represent the subgroup of order 2, the four first values represent the subgroup of order 4, and so on
    • +
    • furthermore, these values are chosen in relation to how evaluations are ordered in a leaf of a commitment
    • +
    • each value tells you exactly what to multiply to 1/(something*x) to obtain 1/(x)
    • +
    • TODO: but wait, how is inv_x obtained... that doesn't make sense no?
    • +
    • it seems like the following values are used to "correct" the x value depending on where x pointed at
    • +
    +
    array![
    +    0x1,
    +    0x800000000000011000000000000000000000000000000000000000000000000,
    +    0x625023929a2995b533120664329f8c7c5268e56ac8320da2a616626f41337e3,
    +    0x1dafdc6d65d66b5accedf99bcd607383ad971a9537cdf25d59e99d90becc81e,
    +    0x63365fe0de874d9c90adb1e2f9c676e98c62155e4412e873ada5e1dee6feebb,
    +    0x1cc9a01f2178b3736f524e1d06398916739deaa1bbed178c525a1e211901146,
    +    0x3b912c31d6a226e4a15988c6b7ec1915474043aac68553537192090b43635cd,
    +    0x446ed3ce295dda2b5ea677394813e6eab8bfbc55397aacac8e6df6f4bc9ca34,
    +    0x5ec467b88826aba4537602d514425f3b0bdf467bbf302458337c45f6021e539,
    +    0x213b984777d9556bac89fd2aebbda0c4f420b98440cfdba7cc83ba09fde1ac8,
    +    0x5ce3fa16c35cb4da537753675ca3276ead24059dddea2ca47c36587e5a538d1,
    +    0x231c05e93ca34c35ac88ac98a35cd89152dbfa622215d35b83c9a781a5ac730,
    +    0x00b54759e8c46e1258dc80f091e6f3be387888015452ce5f0ca09ce9e571f52,
    +    0x7f4ab8a6173b92fda7237f0f6e190c41c78777feabad31a0f35f63161a8e0af,
    +    0x23c12f3909539339b83645c1b8de3e14ebfee15c2e8b3ad2867e3a47eba558c,
    +    0x5c3ed0c6f6ac6dd647c9ba3e4721c1eb14011ea3d174c52d7981c5b8145aa75,
    +]
    +
    +
      +
    • that is, if x pointed at the beginning of a coset, then we don't need to correct it (the first evaluation committed to contains x)
    • +
    • but if x pointed at the first value, it actually points to an evaluation of -x, so we need to correct the -x we have by multiplying with -1 again so that we get x (or -1/x becomes 1/x, same thing)
    • +
    • if x points to the 2 value, then
    • +
    +
    +
    + + + \ No newline at end of file diff --git a/rfcs/starknet/stark.html b/rfcs/starknet/stark.html index f4adfa1..a63e4a2 100644 --- a/rfcs/starknet/stark.html +++ b/rfcs/starknet/stark.html @@ -73,7 +73,7 @@

    In this document we specify the STARK verifier used in Starknet.

-

none

+

draft

Overview

@@ -95,7 +95,7 @@

AIR Arithmetization

TKTK

-

Interactive Arithemtization

+

Interactive Arithmetization

TKTK

@@ -203,6 +203,7 @@

Domain

STARK commit

+

The goal of the STARK commit is to process all of the commitments produced by the prover during the protocol (including the FRI commitments), as well as produce the verifier challenges:

  1. Absorb the original table with the channel.
  2. Sample the interaction challenges (e.g. z and alpha for the memory check argument (different alpha called memory_alpha to distinguish it from the alpha used to aggregate the different constraints into the composition polynomial)).
  3. @@ -218,32 +219,16 @@

    STARK commit

STARK verify (TODO: consolidate with above)

-

in src/stark/stark_verify.cairo:

-

stark_verify takes these inputs:

+

The goal of STARK verify is to verify evaluation queries (by checking that evaluations exist in the committed polynomials) and the FRI queries (by running the FRI verification).

+

To do this, we simply call the fri_verify_initial function contained in the FRI specification, and giving it the following oracle:

+

The oracle should provide the evaluations, under the same set of FRI queries (and specifically the point they are requesting the evaluations at) of the following polynomials:

-

algorithm:

-
    -
  1. traces_decommit()
  2. -
  3. table_decommit() (different depending on layout)
  4. -
  5. points = queries_to_points(queries, stark_domains)
  6. -
  7. eval_oods_boundary_poly_at_points()
  8. -
  9. fri_verify()
  10. -
-

actually, this is wrapped into StarKProofImpl::verify:

-
    -
  1. cfg.validate(security_bits)
  2. -
  3. cfg.public_input.validate(stark_domains)
  4. -
  5. digest = get_public_input_hash(public_input) <-- what is the public input exactly? (should be program + inputs (+outputs?))
  6. -
  7. channel = ChannelImpl::new(digest) <-- statement is a digest of the public_input
  8. -
  9. stark_commitment = stark_commit()
  10. -
  11. queries = generate_queries()
  12. -
  13. stark_verify()
  14. -
+

In addition the oracle should verify decommitment proofs (Merkle membership proofs) for each of these evaluations. We refer to the Merkle Tree Polynomial Commitments specification on how to verify evaluation proofs.

+ +
@@ -273,8 +258,7 @@

Full Protocol

  • Validate the public input (TODO: specify an external function for that?).
  • Compute the initial digest as get_public_input_hash(public_input, cfg.n_verifier_friendly_commitment_layers, settings) (TODO: define external function for that).
  • Initialize the channel using the digest as defined in the Channel section.
  • -
  • Call stark commit as defined in the STARK commit section.
  • -
  • Call fri_commit as defined in the FRI section.
  • +
  • Call STARK commit as defined in the STARK commit section.
  • Call STARK verify as defined in the STARK verify section.
  • diff --git a/source/starknet/channel.md b/source/starknet/channel.md index 3974790..1b3a874 100644 --- a/source/starknet/channel.md +++ b/source/starknet/channel.md @@ -1,9 +1,10 @@ --- -title: "Starknet Channel" +title: "Starknet Channels for Fiat-Shamir Instantiation" abstract: "TKTK" -sotd: "none" +sotd: "draft" shortName: "starknet-channel" editor: "David Wong" +tags: ["starknet", "fiat-shamir"] --- ## Overview diff --git a/source/starknet/fri.md b/source/starknet/fri.md index e4ac7e5..12a2072 100644 --- a/source/starknet/fri.md +++ b/source/starknet/fri.md @@ -5,9 +5,10 @@ abstract: "

    The Fast Reed-Solomon Interactive Oracle Proofs of Proximi

    For more information about the original construction, see Fast Reed-Solomon Interactive Oracle Proofs of Proximity. This document is about the specific instantiation of FRI and FRI-PCS as used by the StarkNet protocol.

    " -sotd: "none" +sotd: "draft" shortName: "starknet-fri" editor: "David Wong" +tags: ["starknet", "fri"] --- ## Overview @@ -331,13 +332,11 @@ TODO: why the alternate use of hash functions? See the [Channel](channel.html) specification for more details. -### Evaluation of the first FRI layer +### Evaluations of the first FRI layer -As part of the protocol, the prover must provide a number of evaluations of the first layer polynomial $p_0$. This is abstracted in this specification as the function `eval_oods_polynomial` which acts as an oracle from FRI's perspective. +As part of the protocol, the prover must provide a number of evaluations of the first layer polynomial $p_0$ (based on the FRI queries that the verifier generates). -TODO: not a very satisfying explanation - -Note that this function is not fixed here, as the polynomial being "tested" could be computed in different ways. See the [Starknet STARK verifier specification](stark.html) for a concrete example (and for an explanation of why the function is named this way). +We abstract this here as an oracle that magically provides evaluations, it is the responsibility of the user of this protocol to ensure that the evaluations are correct. See the [Starknet STARK verifier specification](stark.html) for a concrete usage example. ## Constants @@ -450,64 +449,6 @@ TODO: validate(cfg, log_n_cosets, n_verified_friendly_commitment_layers): * TODO: why is log_n_cosets passed? and what is it? (number of additional cosets with the blowup factor?) * where `log_expected_input_degree = sum_of_step_sizes + log_last_layer_degree_bound` -## Commitments - -Commitments of polynomials are done using [Merkle trees](). The Merkle trees can be configured to hash some parameterized number of the lower layers using a circuit-friendly hash function (Poseidon). - -* TODO: why montgomery form? - -### Table commitments - -A table commitment in this context is a vector commitment where leaves are potentially hashes of several values (tables of multiple columns and a single row). - -### Vector commitments - -A vector commitment is simply a Merkle tree. - -TODO: diagram. - -![vector commit](/img/starknet/fri/vector_commit.png) - -### Vector membership proofs - -A vector decommitment/membership proof must provide a witness (the neighbor nodes missing to compute the root of the Merkle tree) ordered in a specific way. The following algorithm dictates in which order the nodes hash values provided in the proof are consumed: - -![vector decommit](/img/starknet/fri/vector_decommit.png) - -### Note on commitment multiple evaluations under the same leaf - -* the following array contains all the 16-th roots of unity, handily ordered -* that is, the first represents the subgroup of order 1, the two first values represent the subgroup of order 2, the four first values represent the subgroup of order 4, and so on -* furthermore, these values are chosen in relation to how evaluations are ordered in a leaf of a commitment -* each value tells you exactly what to multiply to 1/(something*x) to obtain 1/(x) -* TODO: but wait, how is inv_x obtained... that doesn't make sense no? -* it seems like the following values are used to "correct" the x value depending on where x pointed at - -``` -array![ - 0x1, - 0x800000000000011000000000000000000000000000000000000000000000000, - 0x625023929a2995b533120664329f8c7c5268e56ac8320da2a616626f41337e3, - 0x1dafdc6d65d66b5accedf99bcd607383ad971a9537cdf25d59e99d90becc81e, - 0x63365fe0de874d9c90adb1e2f9c676e98c62155e4412e873ada5e1dee6feebb, - 0x1cc9a01f2178b3736f524e1d06398916739deaa1bbed178c525a1e211901146, - 0x3b912c31d6a226e4a15988c6b7ec1915474043aac68553537192090b43635cd, - 0x446ed3ce295dda2b5ea677394813e6eab8bfbc55397aacac8e6df6f4bc9ca34, - 0x5ec467b88826aba4537602d514425f3b0bdf467bbf302458337c45f6021e539, - 0x213b984777d9556bac89fd2aebbda0c4f420b98440cfdba7cc83ba09fde1ac8, - 0x5ce3fa16c35cb4da537753675ca3276ead24059dddea2ca47c36587e5a538d1, - 0x231c05e93ca34c35ac88ac98a35cd89152dbfa622215d35b83c9a781a5ac730, - 0x00b54759e8c46e1258dc80f091e6f3be387888015452ce5f0ca09ce9e571f52, - 0x7f4ab8a6173b92fda7237f0f6e190c41c78777feabad31a0f35f63161a8e0af, - 0x23c12f3909539339b83645c1b8de3e14ebfee15c2e8b3ad2867e3a47eba558c, - 0x5c3ed0c6f6ac6dd647c9ba3e4721c1eb14011ea3d174c52d7981c5b8145aa75, -] -``` - -* that is, if x pointed at the beginning of a coset, then we don't need to correct it (the first evaluation committed to contains x) -* but if x pointed at the first value, it actually points to an evaluation of -x, so we need to correct the -x we have by multiplying with -1 again so that we get x (or -1/x becomes 1/x, same thing) -* if x points to the 2 value, then - ## Protocol The FRI protocol is split into two phases: @@ -749,22 +690,22 @@ struct FriVerificationStateVariable { We give more detail to each function below. -**`fri_commit(channel, cfg)`**. +**`fri_commit(channel)`**. 1. Take a channel with a prologue (See the [Channel](#channel) section). A prologue contains any context relevant to this proof. -1. Produce the FRI commits according to the [Commit Phase](#commit-phase) section. -2. Produce the proof of work according to the [Proof of Work](#proof-of-work) section. -3. Generate `n_queries` queries in the `eval_domain_size` according to the [Generating Queries](#generating-the-first-queries) section. -4. Convert the queries to evaluation points following the [Converting A Query To An Evaluation Point](#converting-a-query-to-an-evaluation-point) section, producing `points`. -5. Evaluate the first layer at the queried `points` using the external dependency (see [External Dependencies](#external-dependencies) section), producing `values`. -6. Produce the fri_decommitment as `FriDecommitment { values, points }`. - -**`fri_verify_initial(queries, fri_commitment, decommitment)`**. - -* enforce that the number of queries matches the number of values to decommit -* enforce that last layer has the right number of coefficients (TODO: how?) -* compute the first layer of queries `gather_first_layer_queries` as `FriLayerQuery { index, y_value, x_inv_value: 3 / x_value }` for each `x_value` and `y_value` -* initialize and return the two state objects +2. Produce the FRI commits according to the [Commit Phase](#commit-phase) section. +3. Produce the proof of work according to the [Proof of Work](#proof-of-work) section. +4. Generate `n_queries` queries in the `eval_domain_size` according to the [Generating Queries](#generating-the-first-queries) section. +5. Convert the queries to evaluation points following the [Converting A Query To An Evaluation Point](#converting-a-query-to-an-evaluation-point) section, producing `points`. +6. Evaluate the first layer at the queried `points` using the external dependency (see [External Dependencies](#external-dependencies) section), producing `values`. +7. Produce the fri_decommitment as `FriDecommitment { values, points }`. + +**`fri_verify_initial(queries, fri_commitment, decommitment)`**. Takes the FRI queries, the FRI commitments (each layer's committed polynomial), as well as the evaluation points and their associated evaluations of the first layer (in `decommitment`). + +* Enforce that for each query there is a matching derived evaluation point and evaluation at that point on the first layer contained in the given `decommitment`. +* Enforce that last layer has the right number of coefficients as expected by the FRI configuration (see the [FRI Configuration](#fri-configuration) section). +* Compute the first layer of queries as `FriLayerQuery { index, y_value, x_inv_value: 3 / x_value }` for each `x_value` and `y_value` given in the `decommitment` +* Initialize and return the two state objects ```rust ( diff --git a/source/starknet/polynomial_commitment.md b/source/starknet/polynomial_commitment.md new file mode 100644 index 0000000..23a9d1b --- /dev/null +++ b/source/starknet/polynomial_commitment.md @@ -0,0 +1,66 @@ +--- +title: "Starknet Merkle Tree Polynomial Commitments" +abstract: "TKTK" +sotd: "none" +shortName: "starknet-commit" +editor: "David Wong" +tags: ["starknet", "PCS", "Merkle tree", "hash-based commitments"] +--- + +## Overview + +Commitments of polynomials are done using [Merkle trees](). The Merkle trees can be configured to hash some parameterized number of the lower layers using a circuit-friendly hash function (Poseidon). + +* TODO: why montgomery form? + +### Table commitments + +A table commitment in this context is a vector commitment where leaves are potentially hashes of several values (tables of multiple columns and a single row). + +### Vector commitments + +A vector commitment is simply a Merkle tree. + +TODO: diagram. + +![vector commit](/img/starknet/fri/vector_commit.png) + +### Vector membership proofs + +A vector decommitment/membership proof must provide a witness (the neighbor nodes missing to compute the root of the Merkle tree) ordered in a specific way. The following algorithm dictates in which order the nodes hash values provided in the proof are consumed: + +![vector decommit](/img/starknet/fri/vector_decommit.png) + +### Note on commitment multiple evaluations under the same leaf + +* the following array contains all the 16-th roots of unity, handily ordered +* that is, the first represents the subgroup of order 1, the two first values represent the subgroup of order 2, the four first values represent the subgroup of order 4, and so on +* furthermore, these values are chosen in relation to how evaluations are ordered in a leaf of a commitment +* each value tells you exactly what to multiply to 1/(something*x) to obtain 1/(x) +* TODO: but wait, how is inv_x obtained... that doesn't make sense no? +* it seems like the following values are used to "correct" the x value depending on where x pointed at + +``` +array![ + 0x1, + 0x800000000000011000000000000000000000000000000000000000000000000, + 0x625023929a2995b533120664329f8c7c5268e56ac8320da2a616626f41337e3, + 0x1dafdc6d65d66b5accedf99bcd607383ad971a9537cdf25d59e99d90becc81e, + 0x63365fe0de874d9c90adb1e2f9c676e98c62155e4412e873ada5e1dee6feebb, + 0x1cc9a01f2178b3736f524e1d06398916739deaa1bbed178c525a1e211901146, + 0x3b912c31d6a226e4a15988c6b7ec1915474043aac68553537192090b43635cd, + 0x446ed3ce295dda2b5ea677394813e6eab8bfbc55397aacac8e6df6f4bc9ca34, + 0x5ec467b88826aba4537602d514425f3b0bdf467bbf302458337c45f6021e539, + 0x213b984777d9556bac89fd2aebbda0c4f420b98440cfdba7cc83ba09fde1ac8, + 0x5ce3fa16c35cb4da537753675ca3276ead24059dddea2ca47c36587e5a538d1, + 0x231c05e93ca34c35ac88ac98a35cd89152dbfa622215d35b83c9a781a5ac730, + 0x00b54759e8c46e1258dc80f091e6f3be387888015452ce5f0ca09ce9e571f52, + 0x7f4ab8a6173b92fda7237f0f6e190c41c78777feabad31a0f35f63161a8e0af, + 0x23c12f3909539339b83645c1b8de3e14ebfee15c2e8b3ad2867e3a47eba558c, + 0x5c3ed0c6f6ac6dd647c9ba3e4721c1eb14011ea3d174c52d7981c5b8145aa75, +] +``` + +* that is, if x pointed at the beginning of a coset, then we don't need to correct it (the first evaluation committed to contains x) +* but if x pointed at the first value, it actually points to an evaluation of -x, so we need to correct the -x we have by multiplying with -1 again so that we get x (or -1/x becomes 1/x, same thing) +* if x points to the 2 value, then \ No newline at end of file diff --git a/source/starknet/stark.md b/source/starknet/stark.md index 1c90cca..b957e9b 100644 --- a/source/starknet/stark.md +++ b/source/starknet/stark.md @@ -1,9 +1,10 @@ --- title: "Starknet STARK Verifier" abstract: "In this document we specify the STARK verifier used in Starknet." -sotd: "none" +sotd: "draft" shortName: "starknet-stark" editor: "David Wong" +tags: ["starknet", "stark", "ethSTARK"] --- ## Overview @@ -26,7 +27,7 @@ This protocol is instantiated in several places to our knowledge: TKTK -### Interactive Arithemtization +### Interactive Arithmetization TKTK @@ -109,8 +110,6 @@ To validate: } ``` - - ## Main STARK functions / Buiding blocks ```rust @@ -139,6 +138,8 @@ TODO: StarkDomainsImpl::new() ### STARK commit +The goal of the STARK commit is to process all of the commitments produced by the prover during the protocol (including the FRI commitments), as well as produce the verifier challenges: + 1. Absorb the original table with the channel. 2. Sample the interaction challenges (e.g. z and alpha for the memory check argument (different alpha called memory_alpha to distinguish it from the alpha used to aggregate the different constraints into the composition polynomial)). 3. Absorb the interaction table with the channel. @@ -152,32 +153,18 @@ TODO: StarkDomainsImpl::new() ### STARK verify (TODO: consolidate with above) -in `src/stark/stark_verify.cairo`: - -stark_verify takes these inputs: +The goal of STARK verify is to verify evaluation queries (by checking that evaluations exist in the committed polynomials) and the FRI queries (by running the FRI verification). -* queries (array of FE) -* commitment -* witness -* stark_domains +To do this, we simply call the `fri_verify_initial` function contained in the FRI specification, and giving it the following oracle: -algorithm: +The oracle should provide the evaluations, under the same set of FRI queries (and specifically the point they are requesting the evaluations at) of the following polynomials: -1. traces_decommit() -2. table_decommit() (different depending on layout) -3. points = queries_to_points(queries, stark_domains) -4. eval_oods_boundary_poly_at_points() -5. fri_verify() +* the traces polynomials, which include both the original trace polynomial and the interaction trace polynomial) +* the composition column polynomials -actually, this is wrapped into StarKProofImpl::verify: +In addition the oracle should verify decommitment proofs (Merkle membership proofs) for each of these evaluations. We refer to the [Merkle Tree Polynomial Commitments specification](polynomial_commitment.html) on how to verify evaluation proofs. -1. cfg.validate(security_bits) -2. cfg.public_input.validate(stark_domains) -3. digest = get_public_input_hash(public_input) <-- what is the public input exactly? (should be program + inputs (+outputs?)) -4. channel = ChannelImpl::new(digest) <-- statement is a digest of the public_input -5. stark_commitment = stark_commit() -6. queries = generate_queries() -7. stark_verify() + ## Full Protocol @@ -206,6 +193,5 @@ The verify initial function is defined as: 1. Validate the public input (TODO: specify an external function for that?). 1. Compute the initial digest as `get_public_input_hash(public_input, cfg.n_verifier_friendly_commitment_layers, settings)` (TODO: define external function for that). 1. Initialize the channel using the digest as defined in the [Channel](#channel) section. -1. Call stark commit as defined in the [STARK commit](#stark-commit) section. -1. Call fri_commit as defined in the [FRI](#fri) section. +1. Call STARK commit as defined in the [STARK commit](#stark-commit) section. 1. Call STARK verify as defined in the [STARK verify](#stark-verify) section.