mirror of
https://github.com/logos-storage/proof-aggregation.git
synced 2026-01-03 22:33:08 +00:00
98 lines
4.0 KiB
Markdown
98 lines
4.0 KiB
Markdown
|
|
# Monolith Plonky2
|
||
|
|
This crate provides an implementation of the [Monolith hash function](https://eprint.iacr.org/2023/1025.pdf) that can be employed in the [Plonky2 proving system](https://github.com/mir-protocol/plonky2). Monolith hash function is a new zk-friendly hash function which is much faster than state-of-the-art zk-friendly hash functions, exhibiting performance similar to the Keccak hash function. In particular, according to our initial benchmarks, Monolith is from 2 to 3 times faster than Poseidon, the current hash function employed in the Plonky2 proving system.
|
||
|
|
|
||
|
|
This crate can be employed to:
|
||
|
|
|
||
|
|
- Generate Plonky2 proofs employing Monolith hash function
|
||
|
|
- Write Plonky2 circuits computing Monolith hashes, which is also useful to recursively verify Plonky2 proofs generated with Monolith. To this extent, this crate provides a Plonky2 gate for the Monolith permutation.
|
||
|
|
|
||
|
|
The crate also provides benchmarks that compare the Monolith implementation and the Monolith gate with the corresponding Poseidon components currently employed in Plonky2.
|
||
|
|
|
||
|
|
## Usage
|
||
|
|
Generate a proof employing Monolith hash function:
|
||
|
|
```rust
|
||
|
|
use plonky2::plonk::circuit_builder::CircuitBuilder;
|
||
|
|
use plonky2::iop::witness::PartialWitness;
|
||
|
|
use plonky2::field::goldilocks_field::GoldilocksField;
|
||
|
|
use plonky2::plonk::circuit_data::CircuitConfig;
|
||
|
|
use plonky2::field::types::Sample;
|
||
|
|
use plonky2::iop::witness::WitnessWrite;
|
||
|
|
use plonky2_monolith::monolith_hash::monolith_goldilocks::MonolithGoldilocksConfig;
|
||
|
|
use std::error::Error;
|
||
|
|
|
||
|
|
const D: usize = 2;
|
||
|
|
type F = GoldilocksField;
|
||
|
|
fn main() -> Result<(), Box<dyn Error>> {
|
||
|
|
let config = CircuitConfig::standard_recursion_config();
|
||
|
|
let mut builder = CircuitBuilder::<F, D>::new(config);
|
||
|
|
let init_t = builder.add_virtual_public_input();
|
||
|
|
let mut res_t = builder.add_virtual_target();
|
||
|
|
builder.connect(init_t, res_t);
|
||
|
|
for _ in 0..100 {
|
||
|
|
res_t = builder.mul(res_t, init_t);
|
||
|
|
}
|
||
|
|
builder.register_public_input(res_t);
|
||
|
|
let data = builder.build::<MonolithGoldilocksConfig>();
|
||
|
|
|
||
|
|
let mut pw = PartialWitness::<F>::new();
|
||
|
|
let input = F::rand();
|
||
|
|
pw.set_target(init_t, input);
|
||
|
|
|
||
|
|
|
||
|
|
let proof = data.prove(pw)?;
|
||
|
|
|
||
|
|
Ok(data.verify(proof)?)
|
||
|
|
}
|
||
|
|
```
|
||
|
|
Build a circuit employing Monolith gate:
|
||
|
|
```rust
|
||
|
|
use std::cmp;
|
||
|
|
use plonky2::plonk::circuit_builder::CircuitBuilder;
|
||
|
|
use plonky2::iop::witness::PartialWitness;
|
||
|
|
use plonky2::field::goldilocks_field::GoldilocksField;
|
||
|
|
use plonky2::plonk::circuit_data::CircuitConfig;
|
||
|
|
use plonky2::field::types::Sample;
|
||
|
|
use plonky2::iop::witness::WitnessWrite;
|
||
|
|
use plonky2::gates::gate::Gate;
|
||
|
|
use plonky2::hash::hash_types::NUM_HASH_OUT_ELTS;
|
||
|
|
use plonky2_monolith::monolith_hash::monolith_goldilocks::MonolithGoldilocksConfig;
|
||
|
|
use plonky2_monolith::gates::monolith::MonolithGate;
|
||
|
|
use plonky2_monolith::monolith_hash::MonolithHash;
|
||
|
|
use std::error::Error;
|
||
|
|
|
||
|
|
const D: usize = 2;
|
||
|
|
type F = GoldilocksField;
|
||
|
|
|
||
|
|
fn generate_config_for_monolith() -> CircuitConfig {
|
||
|
|
let needed_wires = cmp::max(MonolithGate::<F,D>::new().num_wires(), CircuitConfig::standard_recursion_config().num_wires);
|
||
|
|
CircuitConfig {
|
||
|
|
num_wires: needed_wires,
|
||
|
|
num_routed_wires: needed_wires,
|
||
|
|
..CircuitConfig::standard_recursion_config()
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
fn main() -> Result<(), Box<dyn Error>> {
|
||
|
|
let config = generate_config_for_monolith();
|
||
|
|
let mut builder = CircuitBuilder::<F, D>::new(config);
|
||
|
|
let inp_targets_array = builder.add_virtual_target_arr::<{NUM_HASH_OUT_ELTS}>();
|
||
|
|
let mut res_targets_array = inp_targets_array.clone();
|
||
|
|
for _ in 0..100 {
|
||
|
|
res_targets_array = builder.hash_or_noop::<MonolithHash>(res_targets_array.to_vec()).elements;
|
||
|
|
}
|
||
|
|
builder.register_public_inputs(&res_targets_array);
|
||
|
|
let data = builder.build::<MonolithGoldilocksConfig>();
|
||
|
|
|
||
|
|
|
||
|
|
let mut pw = PartialWitness::<F>::new();
|
||
|
|
inp_targets_array.into_iter().for_each(|t| {
|
||
|
|
let input = F::rand();
|
||
|
|
pw.set_target(t, input);
|
||
|
|
});
|
||
|
|
|
||
|
|
let proof = data.prove(pw)?;
|
||
|
|
|
||
|
|
Ok(data.verify(proof)?)
|
||
|
|
}
|
||
|
|
```
|