Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FRI Implementation: frontend + CPU Backend + GPU Backend #795

Open
wants to merge 135 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 128 commits
Commits
Show all changes
135 commits
Select commit Hold shift + click to select a range
b848b0e
add sumcheck frontend
mickeyasa Dec 11, 2024
92f3579
format
mickeyasa Dec 11, 2024
d6a9c59
strange compilation err
mickeyasa Dec 11, 2024
e6672ff
added test for kickoff
mickeyasa Dec 12, 2024
bb3b1d5
small fixes to sumcheck frontend compilation
yshekel Dec 15, 2024
46b4d72
fix rust warppers
yshekel Dec 15, 2024
563694d
enable sumcheck for all fields and curves
yshekel Dec 15, 2024
ee5b5de
removed Sumcheck test from field api
mickeyasa Dec 15, 2024
aa68bb5
dummy backend added
mickeyasa Dec 16, 2024
ffae6b4
compilation fix
yshekel Dec 16, 2024
f3331cc
test fix
mickeyasa Dec 19, 2024
6cdcee8
format
mickeyasa Dec 19, 2024
9e9ca5a
changinf sumcheck without hash compilatio to warning
mickeyasa Dec 19, 2024
766dbe9
removed sumcheck file duplication
mickeyasa Dec 22, 2024
588a84c
default hash on for cargo
mickeyasa Dec 22, 2024
1a83ec2
cmake fix
mickeyasa Dec 22, 2024
e7ed244
removed commented code
mickeyasa Dec 23, 2024
7248477
format
mickeyasa Dec 23, 2024
4a22355
review
mickeyasa Dec 23, 2024
a9b6256
added comment to the MLE polynomial
mickeyasa Dec 24, 2024
b989711
review fixes
mickeyasa Dec 24, 2024
6a71b95
format
mickeyasa Dec 24, 2024
44663c1
mle polynomials is a vector of pointers
mickeyasa Dec 25, 2024
85de44d
format
mickeyasa Dec 25, 2024
01b7137
cpu backend inplementation start
mickeyasa Dec 25, 2024
d61ca9e
nackend implementation
mickeyasa Dec 31, 2024
d8abe7a
backend implementation
mickeyasa Dec 31, 2024
6550860
Merge remote-tracking branch 'origin/main' into add-sumcheck-frontend
mickeyasa Jan 12, 2025
30fc2bb
compilation start
mickeyasa Jan 12, 2025
1628b52
compile, fail on verification test
mickeyasa Jan 12, 2025
3b1165e
verification failed on round 1
mickeyasa Jan 12, 2025
698fb7e
test pass
mickeyasa Jan 12, 2025
b2b5ff1
format
mickeyasa Jan 12, 2025
3928fd9
spell check
mickeyasa Jan 12, 2025
8cc6078
test fix
mickeyasa Jan 12, 2025
a00a1d1
format
mickeyasa Jan 12, 2025
17fb2d1
adjusting sumcheck test to all fields
mickeyasa Jan 13, 2025
d7673f6
format
mickeyasa Jan 13, 2025
3cb70fa
reduce alpha feet small and large fields
mickeyasa Jan 13, 2025
07c1e85
format
mickeyasa Jan 13, 2025
9e60bb9
documentation
mickeyasa Jan 13, 2025
53dd569
format
mickeyasa Jan 13, 2025
b7d5ddc
go comp issue
mickeyasa Jan 13, 2025
d94ebec
remove prints
mickeyasa Jan 13, 2025
7b06f73
return the std::
mickeyasa Jan 13, 2025
2840f91
name fix
mickeyasa Jan 13, 2025
c22d38e
include added for compilation
mickeyasa Jan 13, 2025
48f30df
review fixes
mickeyasa Jan 13, 2025
81d870f
format
mickeyasa Jan 13, 2025
5baee05
removed OR HASH
mickeyasa Jan 13, 2025
ae57939
review fixes
mickeyasa Jan 15, 2025
7956576
format
mickeyasa Jan 15, 2025
51d6e8d
spell
mickeyasa Jan 15, 2025
5bd4e56
added use_extension_field for Sumcheckconfig
mickeyasa Jan 15, 2025
6d20856
format
mickeyasa Jan 15, 2025
9ea4eea
enlarging the sumcheck test to 8k
mickeyasa Jan 15, 2025
a9da45d
fiat shamir moved to frontend
mickeyasa Jan 19, 2025
17a659e
format
mickeyasa Jan 19, 2025
12469fb
another format
mickeyasa Jan 19, 2025
bc5e639
Fix/release script (#721)
LeonHibnik Jan 13, 2025
8447e1a
Fix bug in CPU vec ops regarding nof workers (#731)
yshekel Jan 13, 2025
db78555
Support android and vulkan (#735)
yshekel Jan 14, 2025
28cab47
Parallelize-vecop-program-execution (#736)
mickeyasa Jan 14, 2025
31dbb47
Create docs for program & program execution (#722)
idanfr-ingo Jan 14, 2025
64767a6
Feat: Blake3 (#733)
aviadingo Jan 14, 2025
be8cd4c
Bump rust crates' version
Jan 14, 2025
7f98ad6
Bump docs version
Jan 14, 2025
8a02604
Update sidebars.ts (#729)
ShaniBabayoff Jan 14, 2025
752dc93
Update documentation for v3.4 (#738)
ShaniBabayoff Jan 14, 2025
87677d0
Deprecated icicle/api headers and updated examples/docs (#740)
yshekel Jan 15, 2025
31a5efb
avoid warning
mickeyasa Jan 20, 2025
430afc1
fri_cpu initial implementation
ShanieWinitz Feb 11, 2025
b478aa6
When creating FRI without a given MerkleTree vector, generate it in t…
ShanieWinitz Feb 11, 2025
9ee1b8d
basic test added, api fix
ShanieWinitz Feb 11, 2025
7e3dbd5
merkle_trees passed by value (only holds std::shared_ptr<MerkleTreeBa…
ShanieWinitz Feb 12, 2025
c35f823
merge main to fri_cpu branch
ShanieWinitz Feb 13, 2025
a334b0e
fri_transcript moved to frontend
ShanieWinitz Feb 13, 2025
1b1fc4e
verifier added
ShanieWinitz Feb 16, 2025
c4122f1
Change create_fri API to accept separate hash functions for Merkle tr…
ShanieWinitz Feb 24, 2025
c06a038
FIXMEs and TODOs fixed and removed
ShanieWinitz Feb 25, 2025
c2953a1
merge with main
ShanieWinitz Feb 25, 2025
2efd9ae
FRI: ext_field support added. F::from() function added for ext_field
ShanieWinitz Mar 2, 2025
40392af
format
ShanieWinitz Mar 2, 2025
1048dfb
Merge remote-tracking branch 'origin/main' into swinitz/fri_cpu
ShanieWinitz Mar 2, 2025
d11f03a
Fixed fri_transcript_config: using the same instance for both prover …
ShanieWinitz Mar 2, 2025
e503dd8
format
ShanieWinitz Mar 2, 2025
b4b2d1d
format
ShanieWinitz Mar 2, 2025
59b0e72
format
ShanieWinitz Mar 2, 2025
dc3f2bf
format
ShanieWinitz Mar 2, 2025
0b4dafe
format
ShanieWinitz Mar 2, 2025
cdbe020
format
ShanieWinitz Mar 2, 2025
0e8670a
debug function removed
ShanieWinitz Mar 2, 2025
13ef0f0
remove code in comment, fri test under ifdef
ShanieWinitz Mar 2, 2025
00a5ef3
format
ShanieWinitz Mar 2, 2025
518318d
Remove unnecessary files
ShanieWinitz Mar 3, 2025
a9bce88
asserts replaced with errors
ShanieWinitz Mar 3, 2025
77f2646
merkle_trees is now moved into CpuFriBackend when calling create_fri.…
ShanieWinitz Mar 3, 2025
907abbf
Replaced assertions with error logs, applied additional code review f…
ShanieWinitz Mar 4, 2025
627947b
rand_query_indicies function update
ShanieWinitz Mar 4, 2025
42fa634
Removed fri_c_api.cpp. It will be added back in the next PR
ShanieWinitz Mar 4, 2025
1569b2a
m_first_round removed
ShanieWinitz Mar 4, 2025
02a39f5
refactored verify method with smaller calls
ShanieWinitz Mar 4, 2025
7205dbe
Pass fri_transcript_config by reference, and test for non-default config
ShanieWinitz Mar 4, 2025
f5cefa1
FriProof init: Added description and error handling for invalid argum…
ShanieWinitz Mar 4, 2025
755b0f5
format
ShanieWinitz Mar 4, 2025
9b2a900
revert MerkleTree build method to use sizeof(T)
ShanieWinitz Mar 4, 2025
366f1b8
Removed for this PR: create_fri frontend for the case where merkle_tr…
ShanieWinitz Mar 5, 2025
f092a76
added test for cases where fri should fail. The basic test is now wit…
ShanieWinitz Mar 5, 2025
881f0cb
format
ShanieWinitz Mar 5, 2025
20585e6
minor
ShanieWinitz Mar 5, 2025
48da21b
minor
ShanieWinitz Mar 6, 2025
9ab1880
Merge branch 'main' into swinitz/fri_cpu
ShanieWinitz Mar 6, 2025
f4fc903
Merge remote-tracking branch 'origin/main' into swinitz/fri_cpu
ShanieWinitz Mar 6, 2025
4cefe5d
Merge branch 'swinitz/fri_cpu' of github.com:ingonyama-zk/icicle into…
ShanieWinitz Mar 6, 2025
bd238aa
FRI frontend and cpu changes (#803)
jeremyfelder Mar 9, 2025
6319dee
Formatting
jeremyfelder Mar 9, 2025
01893ed
added documentation, removed debug prints
ShanieWinitz Mar 9, 2025
5f49f36
api update - creat_fri() removed, now just calling get_proof or verify
ShanieWinitz Mar 11, 2025
14db388
format
ShanieWinitz Mar 11, 2025
2f16963
Changed FriShouldFailCases test to be deterministic. Removed redundan…
ShanieWinitz Mar 11, 2025
2d792dc
format
ShanieWinitz Mar 11, 2025
fafb40d
Uncommented CUDA tests
ShanieWinitz Mar 12, 2025
c1eb318
Added more cases to FriShouldFailCases test. + some more code review …
ShanieWinitz Mar 12, 2025
0746e1b
format
ShanieWinitz Mar 12, 2025
6f6435b
Merge remote-tracking branch 'origin/main' into swinitz/fri_cpu
ShanieWinitz Mar 12, 2025
19abf19
update documentation
ShanieWinitz Mar 12, 2025
c205291
copy MerkleTree instead of using a reference (The MerkleTree class on…
ShanieWinitz Mar 12, 2025
39ab65f
format
ShanieWinitz Mar 12, 2025
d69b33e
FRI struct replaced with fri_merkle_tree namespace. const added to Fr…
ShanieWinitz Mar 12, 2025
4da615c
"output_store_min_layer" removed from verify
ShanieWinitz Mar 12, 2025
56ed067
change names to get_fri_proof_merkle_tree, fri_merkle_tree::prove, ve…
ShanieWinitz Mar 12, 2025
d80d180
moved Fri class from fri.h to fri.cpp.
ShanieWinitz Mar 12, 2025
414b7dc
format
ShanieWinitz Mar 12, 2025
d3789cb
removed S from template
ShanieWinitz Mar 12, 2025
58a8cc7
format
ShanieWinitz Mar 12, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
251 changes: 251 additions & 0 deletions docs/versioned_docs/version-3.5.0/icicle/primitives/fri.md
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move out of versioned docs @ShanieWinitz, this only relates to v3.5 and we don't have fri in this version

Original file line number Diff line number Diff line change
@@ -0,0 +1,251 @@
# FRI API Documentation

## Overview
The Fast Reed-Solomon Interactive Oracle Proof of Proximity (FRI) protocol is used to efficiently verify that a given polynomial has a bounded degree.

The Prover asserts that they know a low-degree polynomial F(x) of degree d, and they provide oracle access to a Reed-Solomon (RS) codeword representing evaluations of this polynomial over a domain L:

$$
RS(F(x), L, n) = \{F(1), F(\alpha), F(\alpha^2), ..., F(\alpha^{n-1})\}
$$

where α is a primitive root of unity, and $n = 2^l$ (for $l ∈ Z$) is the domain size.

## How it works
The proof construction consists of three phases: the Commit and Fold Phase, the Proof of Work Phase (optional), and the Query Phase.
Using a Fiat-Shamir (FS) scheme, the proof is generated in a non-interactive manner, enabling the Prover to generate the entire proof and send it to the Verifier for validation.
The polynomial size must be a power of 2 and is passed to the protocol in evaluation form.

### Prover

#### Commit and Fold Phase
* The prover commits to the polynomial evaluations by constructing a Merkle tree.
* A folding step is performed iteratively to reduce the polynomial degree.
* In each step, the polynomial is rewritten using random coefficients derived from Fiat-Shamir hashing, and a new Merkle tree is built for the reduced polynomial.
* This process continues recursively until the polynomial reaches a minimal length.
* Currently, only a folding factor of 2 is supported.

#### Proof of Work Phase (Optional)
* If enabled, the prover is required to find a nonce such that, when hashed with the final Merkle tree root, the result meets a certain number of leading zero bits.

#### Query Phase
* Using the Fiat-Shamir transform, the prover determines the random query indices based on the previously committed Merkle roots.
* For each sampled index, the prover provides the corresponding Merkle proof, showing that the value is part of the committed Merkle tree.
* The prover returns all required data as the FriProof, which is then verified by the verifier.

### Verifier
* The verifier checks the Merkle proofs to ensure the sampled values were indeed committed to in the commit phase.
* The verifier reconstructs the Fiat-Shamir challenges from the prover's commitments and verifies that the prover followed the protocol honestly.
* The folding relation is checked for each sampled query.
* If all checks pass, the proof is accepted as valid.


## C++ API

### Configuration structs
There are two key configuration structs related to the Fri protocol.

#### FriConfig
The `FriConfig` struct is used to specify parameters for the FRI protocol. It contains the following fields:
- **`stream: icicleStreamHandle`**: The CUDA stream for asynchronous execution. If `nullptr`, the default stream is used.
- **`folding_factor: size_t`**: The factor by which the codeword is folded in each round.
- **`stopping_degree: size_t`**: The minimal polynomial degree at which folding stops.
- **`pow_bits: size_t`**: Number of leading zeros required for proof-of-work. If set, the optional proof-of-work phase is executed.
- **`nof_queries: size_t`**: Number of queries computed for each folded layer of FRI.
- **`are_inputs_on_device: bool`**: If true, the input polynomials are stored on the device (e.g., GPU); otherwise, they remain on the host (e.g., CPU).
- **`is_async: bool`**: If true, it runs the hash asynchronously.
Comment on lines +51 to +56
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What are the defaults?

- **`ext: ConfigExtension*`**: Backend-specific extensions.

The default values are:
```cpp
// icicle/fri/fri_config.h
struct FriConfig {
icicleStreamHandle stream = nullptr;
size_t folding_factor = 2;
size_t stopping_degree = 0;
size_t pow_bits = 16;
size_t nof_queries = 100;
bool are_inputs_on_device = false;
bool is_async = false;
ConfigExtension* ext = nullptr;
};
```
> **_NOTE:_** Currently, only a folding factor of 2 is supported.

#### FriTranscriptConfig
The `FriTranscriptConfig<TypeParam>` class is used to specify parameters for the Fiat-Shamir scheme used by the FRI protocol. It contains the following fields:
- **`hasher: Hash`**: The hash function used to generate randomness for Fiat-Shamir.
- **`domain_separator_label: std::vector<std::byte>`**
- **`round_challenge_label: std::vector<std::byte>`**
- **`commit_phase_label: std::vector<std::byte>`**
- **`nonce_label: std::vector<std::byte>`**
- **`public_state: std::vector<std::byte>`**
- **`seed_rng: TypeParam`**: The seed for initializing the RNG.

> **_NOTE:_** the encoding is little endian.

There are three constructors for `FriTranscriptConfig<TypeParam>`:

* **Default constructor**:
```cpp
// icicle/fri/fri_transcript_config.h
FriTranscriptConfig()
: m_hasher(create_keccak_256_hash()), m_domain_separator_label({}), m_commit_phase_label({}), m_nonce_label({}),
m_public({}), m_seed_rng(F::zero())
```

* **Constructor with byte vector for labels**:
```cpp
FriTranscriptConfig(
Hash hasher,
std::vector<std::byte>&& domain_separator_label,
std::vector<std::byte>&& round_challenge_label,
std::vector<std::byte>&& commit_phase_label,
std::vector<std::byte>&& nonce_label,
std::vector<std::byte>&& public_state,
F seed_rng)
: m_hasher(std::move(hasher)), m_domain_separator_label(std::move(domain_separator_label)),
m_round_challenge_label(std::move(round_challenge_label)),
m_commit_phase_label(std::move(commit_phase_label)), m_nonce_label(std::move(nonce_label)),
m_public(std::move(public_state)), m_seed_rng(seed_rng)
```

* **Constructor with `const char*` arguments for labels**:
```cpp
FriTranscriptConfig(
Hash hasher,
const char* domain_separator_label,
const char* round_challenge_label,
const char* commit_phase_label,
const char* nonce_label,
std::vector<std::byte>&& public_state,
F seed_rng)
: m_hasher(std::move(hasher)), m_domain_separator_label(cstr_to_bytes(domain_separator_label)),
m_round_challenge_label(cstr_to_bytes(round_challenge_label)),
m_commit_phase_label(cstr_to_bytes(commit_phase_label)), m_nonce_label(cstr_to_bytes(nonce_label)),
m_public(std::move(public_state)), m_seed_rng(seed_rng)
```

### Generating FRI Proofs
To generate a proof, first, an empty proof needs to be created. The FRI proof is represented by the `FriProof<TypeParam>` class:

```cpp
// icicle/fri/fri_proof.h
template <typename F>
class FriProof
```

The class has a default constructor `FriProof()` that takes no arguments.

To generate a FRI proof using the Merkle Tree commit scheme, use one of the following functions:
1. **Directly call `get_fri_proof_mt`:**
```cpp
template <typename S, typename F>
eIcicleError get_fri_proof_mt(
const FriConfig& fri_config,
const FriTranscriptConfig<F>& fri_transcript_config,
const F* input_data,
const size_t input_size,
Hash merkle_tree_leaves_hash,
Hash merkle_tree_compress_hash,
const uint64_t output_store_min_layer,
FriProof<F>& fri_proof /* OUT */);
```
2. **Use the `FRI` wrapper, which internally calls `get_fri_proof_mt`:**
```cpp
FRI::get_proof_mt<scalar_t, TypeParam>( ... );
```
This approach calls `get_fri_proof_mt` internally but provides a more structured way to access it.

- **`input_data: const F*`**: Evaluations of The input polynomial.
- **`fri_proof: FriProof<F>&`**: The output `FriProof` object containing the generated proof.
* `merkle_tree_leaves_hash`, `merkle_tree_compress_hash` and `output_store_min_layer` refer to the hashes used in the Merkle Trees built in each round of the folding. For further information about ICICLE's Merkle Trees, see [Merkle-Tree documentation](./merkle.md) and [Hash documentation](./merkle.md).

> **_NOTE:_** `folding_factor` must be divisible by `merkle_tree_compress_hash`.


> **_NOTE:_** An NTT domain is used for proof generation, so before generating a proof, an NTT domain of at least the input_data size must be initialized. For more information see [NTT documentation](./ntt.md).

```cpp
NTTInitDomainConfig init_domain_config = default_ntt_init_domain_config();
ntt_init_domain(scalar_t::omega(log_input_size), init_domain_config)
```
:::

#### Example: Generating a Proof

```cpp
// Initialize ntt domain
NTTInitDomainConfig init_domain_config = default_ntt_init_domain_config();
ntt_init_domain(scalar_t::omega(log_input_size), init_domain_config);

// Define hashers for merkle tree
uint64_t merkle_tree_arity = 2;
Hash hash = Keccak256::create(sizeof(TypeParam)); // hash element -> 32B
Hash compress = Keccak256::create(merkle_tree_arity * hash.output_size()); // hash every 64B to 32B

// set transcript config
const char* domain_separator_label = "domain_separator_label";
const char* round_challenge_label = "round_challenge_label";
const char* commit_phase_label = "commit_phase_label";
const char* nonce_label = "nonce_label";
std::vector<std::byte>&& public_state = {};
TypeParam seed_rng = TypeParam::one();

FriTranscriptConfig<TypeParam> transcript_config(
hash, domain_separator_label, round_challenge_label, commit_phase_label, nonce_label, std::move(public_state),
seed_rng);

// set fri config
FriConfig fri_config;
fri_config.nof_queries = 100;
fri_config.pow_bits = 16;
fri_config.folding_factor = 2;
fri_config.stopping_degree = 0;

FriProof<TypeParam> fri_proof;

// get fri proof
eIcicleError err = FRI::get_proof_mt<scalar_t, TypeParam>(
fri_config, transcript_config, scalars.get(), input_size, hash, compress, output_store_min_layer, fri_proof);
ICICLE_CHECK(err);

// Release ntt domain
ntt_release_domain<scalar_t>();
```

### Verifying Fri Proofs

To verify the FRI proof using the Merkle Tree commit scheme, use one of the following functions:

1. **Directly call `verify_fri_mt`**:
```cpp
// icicle/fri/fri.h
template <typename S, typename F>
eIcicleError verify_fri_mt(
const FriConfig& fri_config,
const FriTranscriptConfig<F>& fri_transcript_config,
FriProof<F>& fri_proof,
Hash merkle_tree_leaves_hash,
Hash merkle_tree_compress_hash,
const uint64_t output_store_min_layer,
bool& valid /* OUT */);
```

2. **Use the `FRI` wrapper, which internally calls `verify_fri_mt`:**
```cpp
FRI::verify_mt<scalar_t, TypeParam>( ... );
```

> **_NOTE:_** `FriConfig` and `FriTranscriptConfig` used for generating the proof must be identical to the one used for verification.

#### Example: Verifying a Proof
```cpp
bool valid = false;
eIcicleError err = FRI::verify_mt<scalar_t, TypeParam>(
fri_config, transcript_config, fri_proof, hash, compress, output_store_min_layer, valid);
ICICLE_CHECK(err);
ASSERT_EQ(true, valid); // Ensure proof verification succeeds
```

After calling `FRI::verify_mt`, the variable `valid` will be set to `true` if the proof is valid, and `false` otherwise.
1 change: 1 addition & 0 deletions icicle/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ option(HASH "Build hashes and tree builders" ON)
option(POSEIDON "Build poseidon hash" ON)
option(POSEIDON2 "Build poseidon2 hash" ON)
option(SUMCHECK "Build sumcheck" ON)
option(FRI "Build fri" ON)
option(SANITIZE "Enable memory address sanitizer" OFF)

# address sanitizer
Expand Down
3 changes: 3 additions & 0 deletions icicle/backend/cpu/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ if (FIELD)
if(SUMCHECK)
target_sources(icicle_field PRIVATE src/field/cpu_sumcheck.cpp)
endif()
if(FRI)
target_sources(icicle_field PRIVATE src/field/cpu_fri.cpp)
endif()
target_include_directories(icicle_field PRIVATE include)
endif() # FIELD

Expand Down
Loading
Loading