/* This file is part of DarkFi (https://dark.fi) * * Copyright (C) 2020-2023 Dyne.org foundation * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ use std::{io, io::Cursor}; use darkfi_serial::{SerialDecodable, SerialEncodable}; use halo2_proofs::{ pasta::{pallas, vesta}, plonk, plonk::{Circuit, SingleVerifier}, poly::commitment::Params, transcript::{Blake2bRead, Blake2bWrite}, }; use rand::RngCore; #[derive(Clone, Debug)] pub struct VerifyingKey { pub params: Params, pub vk: plonk::VerifyingKey, } impl VerifyingKey { pub fn build(k: u32, c: &impl Circuit) -> Self { let params = Params::new(k); let vk = plonk::keygen_vk(¶ms, c).unwrap(); VerifyingKey { params, vk } } pub fn write(&self, writer: &mut W) -> io::Result<()> { // FIXME: This can be optimized. let mut params = vec![]; self.params.write(&mut params)?; let mut vk = vec![]; self.vk.write(&mut vk)?; let _ = writer.write(&(params.len() as u32).to_le_bytes())?; let _ = writer.write(¶ms)?; let _ = writer.write(&(vk.len() as u32).to_le_bytes())?; let _ = writer.write(&vk)?; Ok(()) } pub fn read>( reader: &mut R, ) -> io::Result { // FIXME: This can be optimized // FIXME: Don't assert // FIXME: Make sure that the size is legitimate. // The format chosen in write(): // [params.len(), params..., vk.len(), vk...] let mut params_len = [0u8; 4]; reader.read_exact(&mut params_len)?; let params_len = u32::from_le_bytes(params_len) as usize; let mut params_buf = vec![0u8; params_len]; reader.read_exact(&mut params_buf)?; assert!(params_buf.len() == params_len); let mut vk_len = [0u8; 4]; reader.read_exact(&mut vk_len)?; let vk_len = u32::from_le_bytes(vk_len) as usize; let mut vk_buf = vec![0u8; vk_len]; reader.read_exact(&mut vk_buf)?; assert!(vk_buf.len() == vk_len); let mut params_c = Cursor::new(params_buf); let params: Params = Params::read(&mut params_c)?; let mut vk_c = Cursor::new(vk_buf); let vk: plonk::VerifyingKey = plonk::VerifyingKey::read::>, ConcreteCircuit>(&mut vk_c, ¶ms)?; Ok(Self { params, vk }) } } #[derive(Clone, Debug)] pub struct ProvingKey { pub params: Params, pub pk: plonk::ProvingKey, } impl ProvingKey { pub fn build(k: u32, c: &impl Circuit) -> Self { let params = Params::new(k); let vk = plonk::keygen_vk(¶ms, c).unwrap(); let pk = plonk::keygen_pk(¶ms, vk, c).unwrap(); ProvingKey { params, pk } } } #[derive(Clone, Default, PartialEq, Eq, SerialEncodable, SerialDecodable)] pub struct Proof(Vec); impl AsRef<[u8]> for Proof { fn as_ref(&self) -> &[u8] { &self.0 } } impl core::fmt::Debug for Proof { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { write!(f, "Proof({:?})", self.0) } } impl Proof { pub fn create( pk: &ProvingKey, circuits: &[impl Circuit], instances: &[pallas::Base], mut rng: impl RngCore, ) -> std::result::Result { let mut transcript = Blake2bWrite::<_, vesta::Affine, _>::init(vec![]); plonk::create_proof( &pk.params, &pk.pk, circuits, &[&[instances]], &mut rng, &mut transcript, )?; Ok(Proof(transcript.finalize())) } pub fn verify( &self, vk: &VerifyingKey, instances: &[pallas::Base], ) -> std::result::Result<(), plonk::Error> { let strategy = SingleVerifier::new(&vk.params); let mut transcript = Blake2bRead::init(&self.0[..]); plonk::verify_proof(&vk.params, &vk.vk, strategy, &[&[instances]], &mut transcript) } pub fn new(bytes: Vec) -> Self { Proof(bytes) } }