proof.rs
1 /* This file is part of DarkFi (https://dark.fi) 2 * 3 * Copyright (C) 2020-2025 Dyne.org foundation 4 * 5 * This program is free software: you can redistribute it and/or modify 6 * it under the terms of the GNU Affero General Public License as 7 * published by the Free Software Foundation, either version 3 of the 8 * License, or (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU Affero General Public License for more details. 14 * 15 * You should have received a copy of the GNU Affero General Public License 16 * along with this program. If not, see <https://www.gnu.org/licenses/>. 17 */ 18 use std::{io, io::Cursor}; 19 20 #[cfg(feature = "async-serial")] 21 use darkfi_serial::async_trait; 22 23 use darkfi_sdk::pasta::{pallas, vesta}; 24 use darkfi_serial::{SerialDecodable, SerialEncodable}; 25 use halo2_proofs::{ 26 helpers::SerdeFormat, 27 plonk, 28 plonk::{Circuit, SingleVerifier}, 29 poly::commitment::Params, 30 transcript::{Blake2bRead, Blake2bWrite}, 31 }; 32 use rand::RngCore; 33 34 #[derive(Clone, Debug)] 35 pub struct VerifyingKey { 36 pub params: Params<vesta::Affine>, 37 pub vk: plonk::VerifyingKey<vesta::Affine>, 38 } 39 40 impl VerifyingKey { 41 pub fn build(k: u32, c: &impl Circuit<pallas::Base>) -> Self { 42 let params = Params::new(k); 43 let vk = plonk::keygen_vk(¶ms, c).unwrap(); 44 VerifyingKey { params, vk } 45 } 46 47 pub fn write<W: io::Write>(&self, writer: &mut W) -> io::Result<()> { 48 let mut params = vec![]; 49 self.params.write(&mut params)?; 50 51 let mut vk = vec![]; 52 self.vk.write(&mut vk, SerdeFormat::RawBytes)?; 53 54 let _ = writer.write(&(params.len() as u32).to_le_bytes())?; 55 let _ = writer.write(¶ms)?; 56 let _ = writer.write(&(vk.len() as u32).to_le_bytes())?; 57 let _ = writer.write(&vk)?; 58 59 Ok(()) 60 } 61 62 pub fn read<R: io::Read, ConcreteCircuit: Circuit<pallas::Base>>( 63 reader: &mut R, 64 circuit: ConcreteCircuit, 65 ) -> io::Result<Self> { 66 // The format chosen in write(): 67 // [params.len()<u32>, params..., vk.len()<u32>, vk...] 68 69 let mut params_len = [0u8; 4]; 70 reader.read_exact(&mut params_len)?; 71 let params_len = u32::from_le_bytes(params_len) as usize; 72 73 let mut params_buf = vec![0u8; params_len]; 74 reader.read_exact(&mut params_buf)?; 75 76 assert!(params_buf.len() == params_len); 77 78 let mut vk_len = [0u8; 4]; 79 reader.read_exact(&mut vk_len)?; 80 let vk_len = u32::from_le_bytes(vk_len) as usize; 81 82 let mut vk_buf = vec![0u8; vk_len]; 83 reader.read_exact(&mut vk_buf)?; 84 85 assert!(vk_buf.len() == vk_len); 86 87 let mut params_c = Cursor::new(params_buf); 88 let params: Params<vesta::Affine> = Params::read(&mut params_c)?; 89 90 let mut vk_c = Cursor::new(vk_buf); 91 let vk: plonk::VerifyingKey<vesta::Affine> = 92 plonk::VerifyingKey::read::<Cursor<Vec<u8>>, ConcreteCircuit>( 93 &mut vk_c, 94 SerdeFormat::RawBytes, 95 circuit.params(), 96 )?; 97 98 Ok(Self { params, vk }) 99 } 100 } 101 102 #[derive(Clone, Debug)] 103 pub struct ProvingKey { 104 pub params: Params<vesta::Affine>, 105 pub pk: plonk::ProvingKey<vesta::Affine>, 106 } 107 108 impl ProvingKey { 109 pub fn build(k: u32, c: &impl Circuit<pallas::Base>) -> Self { 110 let params = Params::new(k); 111 let vk = plonk::keygen_vk(¶ms, c).unwrap(); 112 let pk = plonk::keygen_pk(¶ms, vk, c).unwrap(); 113 ProvingKey { params, pk } 114 } 115 116 pub fn write<W: io::Write>(&self, writer: &mut W) -> io::Result<()> { 117 let mut params = vec![]; 118 self.params.write(&mut params)?; 119 120 let mut pk = vec![]; 121 self.pk.write(&mut pk, SerdeFormat::RawBytes)?; 122 123 let _ = writer.write(&(params.len() as u32).to_le_bytes())?; 124 let _ = writer.write(¶ms)?; 125 let _ = writer.write(&(pk.len() as u32).to_le_bytes())?; 126 let _ = writer.write(&pk)?; 127 128 Ok(()) 129 } 130 131 pub fn read<R: io::Read, ConcreteCircuit: Circuit<pallas::Base>>( 132 reader: &mut R, 133 circuit: ConcreteCircuit, 134 ) -> io::Result<Self> { 135 let mut params_len = [0u8; 4]; 136 reader.read_exact(&mut params_len)?; 137 let params_len = u32::from_le_bytes(params_len) as usize; 138 139 let mut params_buf = vec![0u8; params_len]; 140 reader.read_exact(&mut params_buf)?; 141 142 assert!(params_buf.len() == params_len); 143 144 let mut pk_len = [0u8; 4]; 145 reader.read_exact(&mut pk_len)?; 146 let pk_len = u32::from_le_bytes(pk_len) as usize; 147 148 let mut pk_buf = vec![0u8; pk_len]; 149 reader.read_exact(&mut pk_buf)?; 150 151 assert!(pk_buf.len() == pk_len); 152 153 let mut params_c = Cursor::new(params_buf); 154 let params: Params<vesta::Affine> = Params::read(&mut params_c)?; 155 156 let mut pk_c = Cursor::new(pk_buf); 157 let pk: plonk::ProvingKey<vesta::Affine> = 158 plonk::ProvingKey::read::<Cursor<Vec<u8>>, ConcreteCircuit>( 159 &mut pk_c, 160 SerdeFormat::RawBytes, 161 circuit.params(), 162 )?; 163 164 Ok(Self { params, pk }) 165 } 166 } 167 168 #[derive(Clone, Default, PartialEq, Eq, SerialEncodable, SerialDecodable)] 169 pub struct Proof(Vec<u8>); 170 171 impl AsRef<[u8]> for Proof { 172 fn as_ref(&self) -> &[u8] { 173 &self.0 174 } 175 } 176 177 impl core::fmt::Debug for Proof { 178 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 179 write!(f, "Proof({:?})", self.0) 180 } 181 } 182 183 impl Proof { 184 pub fn create( 185 pk: &ProvingKey, 186 circuits: &[impl Circuit<pallas::Base>], 187 instances: &[pallas::Base], 188 mut rng: impl RngCore, 189 ) -> std::result::Result<Self, plonk::Error> { 190 let mut transcript = Blake2bWrite::<_, vesta::Affine, _>::init(vec![]); 191 plonk::create_proof( 192 &pk.params, 193 &pk.pk, 194 circuits, 195 &[&[instances]], 196 &mut rng, 197 &mut transcript, 198 )?; 199 200 Ok(Proof(transcript.finalize())) 201 } 202 203 pub fn verify( 204 &self, 205 vk: &VerifyingKey, 206 instances: &[pallas::Base], 207 ) -> std::result::Result<(), plonk::Error> { 208 let strategy = SingleVerifier::new(&vk.params); 209 let mut transcript = Blake2bRead::init(&self.0[..]); 210 211 plonk::verify_proof(&vk.params, &vk.vk, strategy, &[&[instances]], &mut transcript) 212 } 213 214 pub fn new(bytes: Vec<u8>) -> Self { 215 Proof(bytes) 216 } 217 }