plonky2_monolith

Crates.ioplonky2_monolith
lib.rsplonky2_monolith
version0.1.0
sourcesrc
created_at2023-10-02 15:35:26.289091
updated_at2023-10-02 15:35:26.289091
descriptionUse Monolith hash to generate Plonky2 proofs and to write Plonky2 circuits
homepage
repositoryhttps://github.com/HorizenLabs/monolith
max_upload_size
id990074
size130,130
(DanieleDiBenedetto)

documentation

README

Monolith Plonky2

This crate provides an implementation of the Monolith hash function that can be employed in the Plonky2 proving system. 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:

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:

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)?)
}
Commit count: 10

cargo fmt