You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+37-25Lines changed: 37 additions & 25 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -9,7 +9,7 @@ You can download the repo and run the main branch with:
9
9
cargo test
10
10
```
11
11
12
-
Which is run in release mode by default. This repo requires the nightly toolchain. If you are seeing errors related to:
12
+
Which is run in release mode by default. This repo requires the nightly Rust toolchain. If you are seeing errors related to:
13
13
14
14
```bash
15
15
6 |#![feature(specialization)]
@@ -26,7 +26,7 @@ error[E0554]: `#![feature]` may not be used on the stable release channel
26
26
| ^^^^^^^^^^^^^^^^^^
27
27
```
28
28
29
-
Then please double check your toolchain. Otherwise, this repo should work out of the box.
29
+
Then please double check your toolchain. You may need to run `rustup update nightly` and ensure the `rustc` component is installed. Otherwise, this repo should work out of the box.
30
30
31
31
You can also run:
32
32
@@ -83,9 +83,9 @@ Our approach is to insert the following gates into the circuit with the requisit
83
83
│ │
84
84
▼ │
85
85
+-----------------------------+ │
86
-
| 6. process_recursive_layer |──┘
86
+
| 6. evaluate_recursive_circuit|──┘
87
87
| Handle recursion, verify, |
88
-
| and loop through steps. |
88
+
| and loop through steps. |
89
89
+-----------------------------+
90
90
│
91
91
▼
@@ -100,22 +100,22 @@ You can also view a rough sketch of a circuit diagram of the entire setup:
100
100
101
101
102
102
### Initial Setup
103
-
-**Counter Initialization**: A counter gate is initialized to track the depth of recursion.
104
-
-**Hash Initialization**: A virtual hash target gate is inserted and registered as a public input, marking the starting point of the hash chain.
105
-
-**Hash Gate**: An updateable hash gate is added to enable hash updates as the recursion progresses.
103
+
-**Counter Initialization**: A counter gate is initialized to track the depth of recursion. The counter starts at 1 after the base case performs the first hash iteration.
104
+
-**Hash Initialization**: A virtual hash target gate is inserted and registered as a public input, marking the starting point of the hash chain. The initial hash is set to the zero hash `[F::ZERO; 4]` (all zeros).
105
+
-**Hash Gate**: An updateable hash gate is added to enable hash updates as the recursion progresses. The circuit computes `current_hash_out = hash(current_hash_in)`, where `current_hash_in` is either the initial hash (base case) or the previous proof's output hash (recursive case).
106
106
107
107
### Recursive Hashing
108
-
-**Verifier Data Setup**: Circuit common data is prepared, including configuration and partial witnesses required for recursion.
109
-
-**Base Case Identification**: A condition is set to identify whether the current computation is the base case or a recursive case.
110
-
-**Hash Chain Connection**: The current hash is connected to the previous hash output or set as the initial hash based on whether it's a base or recursive step.
108
+
-**Verifier Data Setup**: Circuit common data is prepared, including configuration and partial witnesses required for recursion. This sets up the recursive proof structure using plonky2's cyclic recursion capabilities.
109
+
-**Base Case Identification**: A condition flag is set to identify whether the current computation is the base case (`condition=false`) or a recursive case (`condition=true`). In the base case, the hash chain starts with the zero hash. In recursive cases, each proof verifies the previous proof and extends the chain.
110
+
-**Hash Chain Connection**: The current hash input is connected to either the previous proof's output hash (when `condition=true`) or the initial hash (when `condition=false`). The circuit ensures proper chaining by verifying the inner cyclic proof and computing the next hash in the sequence.
111
111
112
112
### Recursive Proof Verification
113
-
-**Circuit Building**: The circuit for the current step is built.
114
-
-**Proof Generation**: A proof of the correctness of the current hash computation is generated using the circuit data.
115
-
-**Proof Verification**: The generated proof is verified to ensure that the hash was computed correctly.
113
+
-**Circuit Building**: The circuit for the current step is built with all necessary gates and constraints. The circuit structure remains constant regardless of the number of steps, enabling constant-size proofs.
114
+
-**Proof Generation**: A proof of the correctness of the current hash computation is generated using the circuit data. Each recursive step produces a new proof that verifies the previous proof and extends the hash chain by one iteration.
115
+
-**Proof Verification**: The generated proof is verified to ensure that the hash was computed correctly. The verification process checks both the proof's validity and that the hash chain was computed correctly by comparing against the expected hash value.
116
116
117
117
### Final Verification
118
-
-**Final Hash Check**: After all recursive steps, the final hash is compared against the expected result to confirm the integrity of the entire hash chain.
118
+
-**Final Hash Check**: After all recursive steps, the final hash is compared against the expected result to confirm the integrity of the entire hash chain. The `verify` function checks that `current_hash == hash^counter(initial_hash)` by iteratively hashing the initial hash `counter` times and comparing the result. This provides an additional validation beyond the proof verification itself.
We observe a total uncompressed proof size of 133440 bytes, regardless of number of steps in the chain. We find this is very nice because this number stays the same no matter how many hashes we compute. In theory, recursively verifiable proofs of this nature can compress extremely large computations into a very small space. Think fully-succinct blockchains, in which light clients can verify the entire state of the chain trustlessly by verifying a small and simple proof in trivial amounts of time.
156
156
157
+
### Public Inputs Structure
158
+
159
+
The proof's public inputs follow this structure:
160
+
-`[0..4]`: Initial hash (4 field elements) - remains constant throughout the chain, set to `[F::ZERO; 4]`
161
+
-`[4..8]`: Current hash (4 field elements) - the hash after `counter` iterations
162
+
-`[8]`: Counter (1 field element) - the number of hash iterations performed (starts at 1, increments by 1 each recursive step)
163
+
-`[9..]`: Verifier data (variable length) - plonky2's verifier circuit data
164
+
165
+
The verification function validates that `current_hash == hash^counter(initial_hash)`, ensuring the hash chain was computed correctly.
166
+
157
167
## Benches
158
168
159
169
This crate uses criterion for formal benchmarks. Bench prover and verifier performance with:
160
170
161
171
```bash
162
172
cargo bench
163
173
```
164
-
Here are some prelimnary performance metrics observed thus far:
165
-
166
-
| Circuit depth (steps) | Prover Runtime (s) | Verifier Runtime (ms)| System RAM Used (mb)|
**Key Observation**: Verifier runtime remains constant (~2.5ms) regardless of chain length, demonstrating the succinctness property of recursive proofs. Prover time scales roughly linearly with the number of steps.
0 commit comments