-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
7ff1a05
commit 1f8aa7b
Showing
1 changed file
with
2 additions
and
148 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,149 +1,3 @@ | ||
# Cyclic Hash Computation with Plonky2 | ||
# Recursive hash chain with Keccak support | ||
|
||
Have you ever been sitting behind your desk one evening and thought to yourself, "Gee whiz, I sure wish I could cryptographically prove in quantum-resistant zero knowledge that I computed a gigantic chain of hashes correctly"? Well _good news_ because this repo will fill that burning hole in your heart with a plonky2-based implementation of a prover and verifier pair for a recursive computation chain that argues the computational integrity of a series of hashes a la IVC style and outputs a compressed proof of constant size. The recursive nature of this circuit allows it to scale to potentially unlimited computation size. | ||
|
||
## Quick start: | ||
|
||
You can download the repo and run the main branch with: | ||
```bash | ||
cargo test | ||
``` | ||
|
||
Which is run in release mode by default. This repo requires the nightly toolchain. If you are seeing errors related to: | ||
|
||
```bash | ||
6 | #![feature(specialization)] | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
|
||
error[E0554]: `#![feature]` may not be used on the stable release channel | ||
| | ||
7 | #![cfg_attr(target_arch = "x86_64", feature(stdarch_x86_avx512))] | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
|
||
error[E0554]: `#![feature]` may not be used on the stable release channel | ||
| | ||
7 | #![cfg_attr(target_arch = "x86_64", feature(stdarch_x86_avx512))] | ||
| ^^^^^^^^^^^^^^^^^^ | ||
``` | ||
|
||
Then please double check your toolchain. Otherwise, this repo should work out of the box. | ||
|
||
## Supported Hashes: | ||
|
||
The following hashes are supported in the recursive chain: | ||
|
||
| Hasher | Validation | | ||
|----------|----------| | ||
| Poseidon Hash | [![Tests](https://github.com/drcapybara/hash-chain/actions/workflows/test_hash_chain.yml/badge.svg)](https://github.com/drcapybara/hash-chain/actions/workflows/test_hash_chain.yml) | | ||
| Keccak | [![Rust Nightly Tests](https://github.com/drcapybara/hash-chain/actions/workflows/test_hash_chain.yml/badge.svg)](https://github.com/drcapybara/hash-chain/actions/workflows/test_hash_chain.yml) | | ||
|
||
# Strategy | ||
|
||
Our approach is to insert the following gates into the circuit with the requisite connections. It is not enough to create a circuit that simply connects each hash output the next input, the prover must argue the hash computation _and_ verify the preceeding hash in a single step, taking into account the recursive structure of the chain: | ||
|
||
```text | ||
+--------------------------------+ +-------------------------+ +------------------------------+ | ||
| 1. initialize_circuit_builder | | 2. setup_hashes | | 3. common_data_for_recursion | | ||
| Set up the circuit builder |──▶| Configure initial |──▶| Set up data for recursion | | ||
| and configuration. | | and current hash | | and verifier data inputs. | | ||
+--------------------------------+ | targets and register | +------------------------------+ | ||
| | them as public inputs. | | | ||
| +-------------------------+ | | ||
│ │ | ||
│ +--------------------+ │ | ||
└──────────▶| 4. setup_condition | │ | ||
| Set condition for | │ | ||
| recursion base. | │ | ||
+--------------------+ │ | ||
│ ▼ | ||
│ +--------------------------------------+ | ||
└──────────▶| 5. setup_recursive_layers | | ||
| Configure recursive layers | | ||
| and integrate proof. | | ||
+--------------------------------------+ | ||
│ ▲ | ||
│ │ | ||
│ │ | ||
▼ │ | ||
+-----------------------------+ │ | ||
| 6. process_recursive_layer |──┘ | ||
| Handle recursion, verify, | | ||
| and loop through steps. | | ||
+-----------------------------+ | ||
│ | ||
▼ | ||
+-------------------------+ | ||
| 7. compile_and_process | | ||
| Finalize circuit and | | ||
| handle processing. | | ||
+-------------------------+ | ||
``` | ||
|
||
### Initial Setup | ||
- **Counter Initialization**: A counter gate is initialized to track the depth of recursion. | ||
- **Hash Initialization**: A virtual hash target gate is inserted and registered as a public input, marking the starting point of the hash chain. | ||
- **Hash Gate**: An updateable hash gate is added to enable hash updates as the recursion progresses. | ||
|
||
### Recursive Hashing | ||
- **Verifier Data Setup**: Circuit common data is prepared, including configuration and partial witnesses required for recursion. | ||
- **Base Case Identification**: A condition is set to identify whether the current computation is the base case or a recursive case. | ||
- **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. | ||
|
||
### Recursive Proof Verification | ||
- **Circuit Building**: The circuit for the current step is built. | ||
- **Proof Generation**: A proof of the correctness of the current hash computation is generated using the circuit data. | ||
- **Proof Verification**: The generated proof is verified to ensure that the hash was computed correctly. | ||
|
||
### Final Verification | ||
- **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. | ||
|
||
## Usage: | ||
|
||
```rust | ||
use hash_chain::HashChain; | ||
use plonky2::{ | ||
field::goldilocks_field::GoldilocksField, | ||
plonk::{ | ||
circuit_builder::CircuitBuilder, | ||
circuit_data::CircuitConfig, | ||
config::{GenericConfig, PoseidonGoldilocksConfig}, | ||
}, | ||
}; | ||
|
||
const D: usize = 2; | ||
type C = PoseidonGoldilocksConfig; // A config with poseidon as the hasher for FRI | ||
type F = <C as GenericConfig<D>>::F; | ||
|
||
// a non-ZK config, commitments and proof may reveal input data | ||
let config = CircuitConfig::standard_recursion_config(); | ||
let mut circuit = CircuitBuilder::<F, D>::new(config.clone()); | ||
|
||
// Prove | ||
let (proof, circuit_data) = | ||
<CircuitBuilder<GoldilocksField, D> as HashChain<GoldilocksField, D, C>>::build_hash_chain_circuit( | ||
&mut circuit, | ||
2, // number of steps in the hash chain | ||
) | ||
.unwrap(); | ||
|
||
// Verify | ||
let verification_result = | ||
<CircuitBuilder<GoldilocksField, D> as HashChain<GoldilocksField, D, C>>::verify(proof, circuit_data); | ||
assert!(verification_result.is_ok()); | ||
``` | ||
|
||
We observe a total uncompressed proof size of 133440 bytes, regardless of number of steps in the chain. This is, in my humble opinion, totally awesome and cool, 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-succint blockchains, in which light clients can verify the entire state of the chain trustlessly by verifying a small and simple proof. | ||
|
||
## Acknowledgments | ||
|
||
This project makes use of the following open-source libraries: | ||
|
||
- **[plonky2](https://github.com/drcapybara/plonky2)** by Polygon Labs - Although poorly documented and cumbersome to get up and running, Polygon keeps the hits coming with this library by presenting a very compelling framework for blending the expresivity of PLONK with the killer performance of ZK-STARKS. | ||
|
||
- **[plonky2_crypto](https://github.com/JumpCrypto/plonky2-crypto)** by Jump Crypto - This component extends the capabilities of plonky2 with additional cryptographic functionalities, sourced from the `patch-plonky2` branch. This crate contains keccak and sha256 hasher gadgets that we use in our recursive circuit. | ||
|
||
TODO | ||
- [ ] Compress the proof at the end | ||
- [ ] support keccak | ||
- [ ] add benches | ||
- [x] better error handling with thiserr | ||
This circuit is failing to build at current, see [this branch](https://github.com/drcapybara/hash-chain) for a working example with the poseidon hasher |