Skip to content

Commit e900849

Browse files
Idan/sumcheck test (#761)
Co-authored-by: mickeyasa <[email protected]>
1 parent 617b01b commit e900849

File tree

6 files changed

+454
-10
lines changed

6 files changed

+454
-10
lines changed

docs/docs/icicle/primitives/overview.md

+1
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@ This section of the documentation is dedicated to the main APIs provided by ICIC
1010
- [Polynomials](../polynomials/overview.md)
1111
- [Hash](./hash.md)
1212
- [Merkle-tree commitment](./merkle.md)
13+
- [Sumcheck](./sumcheck.md)
+180
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
# Sumcheck API Documentation
2+
3+
## Overview
4+
Sumchek protocol is a protocol where a Prover proves to a Verifier that the sum of a multilinear polynomial, over the boolean hypercube, is a specific sum.
5+
6+
For a polynomial $P$, with $n$ dimension $n$ the Prover is trying to prove that:
7+
$$
8+
\sum_{X_1 \in \{0, 1\}}\sum_{X_2 \in \{0, 1\}}\cdot\cdot\cdot\sum_{X_n \in \{0, 1\}} P(X_1, X_2,..., X_n) = C,
9+
$$
10+
for some scalar $C$.
11+
12+
The proof is build in an interactive way, where the Prover and Verifier do a series of $n$ rounds. Each round is consists of a challenge (created by the Verifier), computation (made by the Prover) and verifying (done by the Verifier). Using a Fiat-Shamir (FS) scheme, the proof become non-interactive. This allow the Prover to generate the entire proof and send it to Verifier which then verify the whole proof.
13+
14+
### Sumcheck with Combine Function
15+
The Sumcheck protocol can be generalized to an arbitrary function of several multilinear polynomials. In this case, assuming there are $m$ polynomials of $n$ variables, and let $f$ be some arbitrary function that take $m$ polynomials and return a polynomial of higher (or equal) degree. Now the Prover tries to prove that:
16+
$$
17+
\sum_{X_1 \in \{0, 1\}}\sum_{X_2 \in \{0, 1\}}\cdot\cdot\cdot\sum_{X_n \in \{0, 1\}} f\left(P_1(X_1, ..., X_n), P_2(X_1, ..., X_n), ..., P_m(X_1, ..., X_n)\right) = C,
18+
$$
19+
for some scalar $C$.
20+
21+
## ICICLE's Sumecheck
22+
ICICLE implements a non-interactive Sumcheck protocol that supports a combine function. Sumcheck is supported by both CPU and CUDA backends of ICICLE. The polynomials are passed to the protocol as MLEs (evaluation representation).
23+
24+
### Implementation Limitations
25+
26+
There are some limitations / assumptions to the Sumcheck implementation.
27+
28+
- The maximum size of the polynomials (number of evaluations = $2^n$) depends on the number of polynomials and memory size of the device (e.g. CPU/GPU) used. For 4 polynomials one should expects that a GPU equipped with 24GB of memory can run Sumcheck with polynomials of size up to $2^{29}$.
29+
- The polynomial size must be of size which is a power of 2.
30+
31+
32+
## C++ API
33+
A sumcheck is created by the following function:
34+
```cpp
35+
Sumcheck<scalar_t> create_sumcheck()
36+
```
37+
38+
There are two configuration structs related to the Sumcheck protocol.
39+
40+
The `SumcheckConfig` struct is a configuration object used to specify parameters for Sumcheck. It contains the following fields:
41+
- **`stream: icicleStreamHandle`**: Specifies the CUDA stream for asynchronous execution. If `nullptr`, the default stream is used.
42+
- **`use_extension_field: bool`**: If true extension field is used for the Fiat-Shamir results. ***Currently not supported (should always be false)***
43+
- **`batch: int`**: Number of input chunks to hash in batch.
44+
- **`are_inputs_on_device: bool`**: If true expect the input polynomials to reside on the device (e.g. GPU), if false expect them to reside on the host (e.g. CPU).
45+
- **`is_async: bool`**: If true runs the hash asynchronously.
46+
- **`ext: ConfigExtension*`**: Backend-specific extensions.
47+
48+
The default values are:
49+
```cpp
50+
struct SumcheckConfig {
51+
icicleStreamHandle stream = nullptr;
52+
bool use_extension_field = false;
53+
uint64_t batch = 1;
54+
bool are_inputs_on_device =false;
55+
bool is_async = false;
56+
ConfigExtension* ext = nullptr;
57+
};
58+
```
59+
60+
The `SumcheckTranscriptConfig<F>` class is a configuration object used to specify parameters to the Fiat-Shamir scheme used by the Sumcheck. It contained the following fields:
61+
- **`hasher: Hash`**: Hash function used for randomness generation by Fiat-Shamir.
62+
- **`domain_label: char*`**: Label for the domain separator in the transcript.
63+
- **`poly_label: char*`**: Label for round polynomials in the transcript.
64+
- **`challenge_label: char*`**: Label for round challenges in the transcript.
65+
- **`seed: F`**: Seed for initializing the RNG.
66+
- **`little_endian: bool`**: Encoding endianness
67+
68+
There are three constructors for `SumcheckTranscriptConfig<F>`, each one with its own arguments and default value.
69+
70+
The default constructor:
71+
```cpp
72+
SumcheckTranscriptConfig()
73+
: m_little_endian(true), m_seed_rng(F::from(0)), m_hasher(std::move(create_keccak_256_hash()))
74+
```
75+
76+
A constructor with byte vector for labels:
77+
```cpp
78+
SumcheckTranscriptConfig(
79+
Hash hasher,
80+
std::vector<std::byte>&& domain_label,
81+
std::vector<std::byte>&& poly_label,
82+
std::vector<std::byte>&& challenge_label,
83+
F seed,
84+
bool little_endian = true)
85+
: m_hasher(std::move(hasher)), m_domain_separator_label(domain_label), m_round_poly_label(poly_label),
86+
m_round_challenge_label(challenge_label), m_little_endian(little_endian), m_seed_rng(seed)
87+
```
88+
A constructor with `const char*` arguments for labels
89+
```cpp
90+
SumcheckTranscriptConfig(
91+
Hash hasher,
92+
const char* domain_label,
93+
const char* poly_label,
94+
const char* challenge_label,
95+
F seed,
96+
bool little_endian = true)
97+
: m_hasher(std::move(hasher)), m_domain_separator_label(cstr_to_bytes(domain_label)),
98+
m_round_poly_label(cstr_to_bytes(poly_label)), m_round_challenge_label(cstr_to_bytes(challenge_label)),
99+
m_little_endian(little_endian), m_seed_rng(seed)
100+
```
101+
102+
### Generating Sumcheck Proofs
103+
To generate a Proof, first and empty proof needed to be created. Sumceck proof is represented by the class `SumcheckProof<S>`:
104+
105+
```cpp
106+
template <typename S>
107+
class SumcheckProof
108+
```
109+
110+
It has only the default constructor ` SumcheckProof()` which takes no arguments.
111+
112+
Then, the proof can be generate by the `get_proof` method of the `Sumcheck<F>` object:
113+
```cpp
114+
eIcicleError get_proof(
115+
const std::vector<F*>& mle_polynomials,
116+
const uint64_t mle_polynomial_size,
117+
const F& claimed_sum,
118+
const ReturningValueProgram<F>& combine_function,
119+
const SumcheckTranscriptConfig<F>&& transcript_config,
120+
const SumcheckConfig& sumcheck_config,
121+
SumcheckProof<F>& sumcheck_proof /*out*/) const
122+
```
123+
124+
The arguments for this method are:
125+
- **`mle_polynomials: std::vector<F*>&`**: A vector of pointer. Each pointer points to the evaluations of one of the input polynomials.
126+
- **`mle_polynomial_size: uint64_t`**: The length of the polynomials (number of evaluations). Should be a power of 2
127+
- **`claimed_sum: F&`**: The sum the claimed by the Prover to be the sum of the combine function over the evaluations of the polynomials.
128+
- **`combine_function: ReturningValueProgram<F>&`**: The combine function. Uses ICICLE's [program](program.md) API.
129+
- **`transcript_config: SumcheckTranscriptConfig<F>&&`**: The `SumcheckTranscriptConfig` object for the Fiat-Shamir scheme.
130+
- **`sumcheck_config: SumcheckConfig&`**: The `SumcheckConfig` object for the Sumcheck configuration.
131+
- **`sumcheck_proof: SumcheckProof<F>&`**: A `SumcheckProof` object which is the output of the `get_proof` method.
132+
133+
#### Example: Generating a Proof
134+
135+
Generating a Sumcheck proof:
136+
137+
```cpp
138+
auto prover_sumcheck = create_sumcheck<scalar_t>();
139+
SumcheckTranscriptConfig<scalar_t> transcript_config; // default configuration
140+
141+
ReturningValueProgram<scalar_t> combine_func(EQ_X_AB_MINUS_C);
142+
SumcheckConfig sumcheck_config;
143+
SumcheckProof<scalar_t> sumcheck_proof;
144+
ICICLE_CHECK(prover_sumcheck.get_proof(
145+
mle_polynomials, mle_poly_size, claimed_sum, combine_func, std::move(transcript_config), sumcheck_config,
146+
sumcheck_proof));
147+
```
148+
149+
### Verifying Sumcheck Proofs
150+
151+
To verify the proof, the Verifier should use the method `verify` of the `Sumcheck<F>` object:
152+
153+
```cpp
154+
eIcicleError verify(
155+
const SumcheckProof<F>& sumcheck_proof,
156+
const F& claimed_sum,
157+
const SumcheckTranscriptConfig<F>&& transcript_config,
158+
bool& valid /*out*/)
159+
```
160+
161+
The arguments for this method are:
162+
- **`sumcheck_proof: SumcheckProof<F>&`**: The proof the verifier wants to verify.
163+
- **`claimed_sum: F&`**: The sum, claimed by the Prover, the Verifier wants to check.
164+
- **`transcript_config: SumcheckTranscriptConfig<F>&&`**: The `SumcheckTranscriptConfig` object for the Fiat-Shamir scheme.
165+
- **`valid: bool`**: The output of the method. True if the proof was verified correctly, false otherwise.
166+
167+
> **_NOTE:_** The `SumcheckTranscriptConfig` used for generating the proof should be **identical** to the one used to verify it.
168+
169+
#### Example: Verifying a Proof
170+
171+
Verifying a Shumcheck proof:
172+
173+
```cpp
174+
auto verifier_sumcheck = create_sumcheck<scalar_t>();
175+
bool verification_pass = false;
176+
ICICLE_CHECK(
177+
verifier_sumcheck.verify(sumcheck_proof, claimed_sum, std::move(transcript_config), verification_pass));
178+
```
179+
180+
After `verifier_sumcheck.verify` the variable `verification_pass` is `true` if the proof is valid and `false` otherwise.

docs/sidebars.ts

+6-1
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,12 @@ const cppApi = [
8585
type: "doc",
8686
label: "Merkle-Tree",
8787
id: "icicle/primitives/merkle",
88-
}
88+
},
89+
{
90+
type: "doc",
91+
label: "Sumcheck",
92+
id: "icicle/primitives/sumcheck",
93+
},
8994
];
9095

9196
const golangBindingsApi = [

icicle/include/icicle/program/symbol.h

+3
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,9 @@ namespace icicle {
8888
return;
8989
}
9090
switch (m_opcode) {
91+
case OP_INPUT:
92+
m_poly_degree = 1;
93+
return;
9194
case OP_ADD:
9295
case OP_SUB:
9396
m_poly_degree = std::max(m_operand1->m_poly_degree, m_operand2->m_poly_degree);

icicle/include/icicle/sumcheck/sumcheck_config.h

-2
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,6 @@ namespace icicle {
2020
uint64_t batch = 1; /**< Number of input chunks to hash in batch. Default is 1. */
2121
bool are_inputs_on_device =
2222
false; /**< True if inputs reside on the device (e.g., GPU), false if on the host (CPU). Default is false. */
23-
bool are_outputs_on_device =
24-
false; /**< True if outputs reside on the device, false if on the host. Default is false. */
2523
bool is_async = false; /**< True to run the hash asynchronously, false to run synchronously. Default is false. */
2624
ConfigExtension* ext = nullptr; /**< Pointer to backend-specific configuration extensions. Default is nullptr. */
2725
};

0 commit comments

Comments
 (0)