|
| 1 | +use crate::bellman_ce::pairing::{bls12_381::Bls12, bn256::Bn256}; |
| 2 | +use algebraic::{errors::Result, utils::repr_to_big, PrimeField}; |
| 3 | +use franklin_crypto::bellman::{ |
| 4 | + bls12_381::{ |
| 5 | + Fq2 as Fq2_bls12381, G1Affine as G1Affine_bls12381, G2Affine as G2Affine_bls12381, |
| 6 | + }, |
| 7 | + bn256::{Fq2, G1Affine, G2Affine}, |
| 8 | + groth16::{Proof, VerifyingKey}, |
| 9 | + CurveAffine, |
| 10 | +}; |
| 11 | +use num_bigint::BigUint; |
| 12 | +use num_traits::Num; |
| 13 | +use serde::{Deserialize, Serialize}; |
| 14 | +use serde_json::to_string; |
| 15 | +#[derive(Debug, Serialize, Deserialize)] |
| 16 | +pub struct G1 { |
| 17 | + pub x: String, |
| 18 | + pub y: String, |
| 19 | +} |
| 20 | + |
| 21 | +#[derive(Debug, Serialize, Deserialize)] |
| 22 | +pub struct G2 { |
| 23 | + pub x: [String; 2], |
| 24 | + pub y: [String; 2], |
| 25 | +} |
| 26 | + |
| 27 | +#[derive(Debug, Serialize, Deserialize)] |
| 28 | +pub struct VerifyingKeyFile { |
| 29 | + #[serde(rename = "protocol")] |
| 30 | + pub protocol: String, |
| 31 | + #[serde(rename = "curve")] |
| 32 | + pub curve: String, |
| 33 | + #[serde(rename = "vk_alpha_1")] |
| 34 | + pub alpha_g1: G1, |
| 35 | + #[serde(rename = "vk_beta_1")] |
| 36 | + pub beta_g1: G1, |
| 37 | + #[serde(rename = "vk_beta_2")] |
| 38 | + pub beta_g2: G2, |
| 39 | + #[serde(rename = "vk_gamma_2")] |
| 40 | + pub gamma_g2: G2, |
| 41 | + #[serde(rename = "vk_delta_1")] |
| 42 | + pub delta_g1: G1, |
| 43 | + #[serde(rename = "vk_delta_2")] |
| 44 | + pub delta_g2: G2, |
| 45 | + #[serde(rename = "IC")] |
| 46 | + pub ic: Vec<G1>, |
| 47 | +} |
| 48 | + |
| 49 | +#[derive(Debug, Serialize, Deserialize)] |
| 50 | +pub struct ProofFile { |
| 51 | + #[serde(rename = "pi_a")] |
| 52 | + pub a: G1, |
| 53 | + #[serde(rename = "pi_b")] |
| 54 | + pub b: G2, |
| 55 | + #[serde(rename = "pi_c")] |
| 56 | + pub c: G1, |
| 57 | + #[serde(rename = "protocol")] |
| 58 | + pub protocol: String, |
| 59 | + #[serde(rename = "curve")] |
| 60 | + pub curve: String, |
| 61 | +} |
| 62 | + |
| 63 | +pub trait Parser: franklin_crypto::bellman::pairing::Engine { |
| 64 | + fn parse_g1(e: &Self::G1Affine, to_hex: bool) -> (String, String); |
| 65 | + fn parse_g2(e: &Self::G2Affine, to_hex: bool) -> (String, String, String, String); |
| 66 | + fn parse_g1_json(e: &Self::G1Affine, to_hex: bool) -> G1 { |
| 67 | + let parsed = Self::parse_g1(e, to_hex); |
| 68 | + G1 { |
| 69 | + x: parsed.0, |
| 70 | + y: parsed.1, |
| 71 | + } |
| 72 | + } |
| 73 | + fn parse_g2_json(e: &Self::G2Affine, to_hex: bool) -> G2 { |
| 74 | + let parsed = Self::parse_g2(e, to_hex); |
| 75 | + G2 { |
| 76 | + x: (parsed.0, parsed.1).into(), |
| 77 | + y: (parsed.2, parsed.3).into(), |
| 78 | + } |
| 79 | + } |
| 80 | + fn to_g1(x: &str, y: &str) -> Self::G1Affine; |
| 81 | + fn to_g2(x0: &str, x1: &str, y0: &str, y1: &str) -> Self::G2Affine; |
| 82 | +} |
| 83 | + |
| 84 | +pub fn render_scalar_to_str<F: PrimeField>(el: &F, to_hex: bool) -> String { |
| 85 | + let repr = el.into_repr(); |
| 86 | + if to_hex { |
| 87 | + repr.to_string() |
| 88 | + } else { |
| 89 | + repr_to_big(repr) |
| 90 | + } |
| 91 | +} |
| 92 | + |
| 93 | +pub fn render_str_to_scalar<F: PrimeField>(value: &str) -> F { |
| 94 | + let value = match value.starts_with("0x") { |
| 95 | + true => BigUint::from_str_radix(&value[2..], 16) |
| 96 | + .unwrap() |
| 97 | + .to_str_radix(10), |
| 98 | + _ => value.to_string(), |
| 99 | + }; |
| 100 | + F::from_str(&value).unwrap() |
| 101 | +} |
| 102 | + |
| 103 | +pub fn to_public_input<T: PrimeField>(s: &str) -> Vec<T> { |
| 104 | + let input: Vec<String> = serde_json::from_str(s).unwrap(); |
| 105 | + input |
| 106 | + .iter() |
| 107 | + .map(|hex_str| render_str_to_scalar::<T>(hex_str)) |
| 108 | + .collect() |
| 109 | +} |
| 110 | + |
| 111 | +impl Parser for Bn256 { |
| 112 | + fn parse_g1(e: &Self::G1Affine, to_hex: bool) -> (String, String) { |
| 113 | + let (x, y) = e.into_xy_unchecked(); |
| 114 | + ( |
| 115 | + render_scalar_to_str(&x, to_hex), |
| 116 | + render_scalar_to_str(&y, to_hex), |
| 117 | + ) |
| 118 | + } |
| 119 | + |
| 120 | + fn parse_g2(e: &Self::G2Affine, to_hex: bool) -> (String, String, String, String) { |
| 121 | + let (x, y) = e.into_xy_unchecked(); |
| 122 | + ( |
| 123 | + render_scalar_to_str(&x.c0, to_hex), |
| 124 | + render_scalar_to_str(&x.c1, to_hex), |
| 125 | + render_scalar_to_str(&y.c0, to_hex), |
| 126 | + render_scalar_to_str(&y.c1, to_hex), |
| 127 | + ) |
| 128 | + } |
| 129 | + |
| 130 | + fn to_g1(x: &str, y: &str) -> Self::G1Affine { |
| 131 | + G1Affine::from_xy_unchecked(render_str_to_scalar(x), render_str_to_scalar(y)) |
| 132 | + } |
| 133 | + |
| 134 | + fn to_g2(x0: &str, x1: &str, y0: &str, y1: &str) -> Self::G2Affine { |
| 135 | + let x = Fq2 { |
| 136 | + c0: render_str_to_scalar(x0), |
| 137 | + c1: render_str_to_scalar(x1), |
| 138 | + }; |
| 139 | + let y = Fq2 { |
| 140 | + c0: render_str_to_scalar(y0), |
| 141 | + c1: render_str_to_scalar(y1), |
| 142 | + }; |
| 143 | + G2Affine::from_xy_unchecked(x, y) |
| 144 | + } |
| 145 | +} |
| 146 | + |
| 147 | +impl Parser for Bls12 { |
| 148 | + fn parse_g1(e: &Self::G1Affine, to_hex: bool) -> (String, String) { |
| 149 | + let (x, y) = e.into_xy_unchecked(); |
| 150 | + ( |
| 151 | + render_scalar_to_str(&x, to_hex), |
| 152 | + render_scalar_to_str(&y, to_hex), |
| 153 | + ) |
| 154 | + } |
| 155 | + |
| 156 | + fn parse_g2(e: &Self::G2Affine, to_hex: bool) -> (String, String, String, String) { |
| 157 | + let (x, y) = e.into_xy_unchecked(); |
| 158 | + ( |
| 159 | + render_scalar_to_str(&x.c0, to_hex), |
| 160 | + render_scalar_to_str(&x.c1, to_hex), |
| 161 | + render_scalar_to_str(&y.c0, to_hex), |
| 162 | + render_scalar_to_str(&y.c1, to_hex), |
| 163 | + ) |
| 164 | + } |
| 165 | + |
| 166 | + fn to_g1(x: &str, y: &str) -> Self::G1Affine { |
| 167 | + G1Affine_bls12381::from_xy_unchecked(render_str_to_scalar(x), render_str_to_scalar(y)) |
| 168 | + } |
| 169 | + |
| 170 | + fn to_g2(x0: &str, x1: &str, y0: &str, y1: &str) -> Self::G2Affine { |
| 171 | + let x = Fq2_bls12381 { |
| 172 | + c0: render_str_to_scalar(x0), |
| 173 | + c1: render_str_to_scalar(x1), |
| 174 | + }; |
| 175 | + let y = Fq2_bls12381 { |
| 176 | + c0: render_str_to_scalar(y0), |
| 177 | + c1: render_str_to_scalar(y1), |
| 178 | + }; |
| 179 | + G2Affine_bls12381::from_xy_unchecked(x, y) |
| 180 | + } |
| 181 | +} |
| 182 | + |
| 183 | +pub fn serialize_vk<P: Parser>( |
| 184 | + vk: &VerifyingKey<P>, |
| 185 | + curve_type: &str, |
| 186 | + to_hex: bool, |
| 187 | +) -> Result<String> { |
| 188 | + let verifying_key_file = VerifyingKeyFile { |
| 189 | + protocol: "groth16".to_string(), |
| 190 | + curve: curve_type.to_string(), |
| 191 | + alpha_g1: P::parse_g1_json(&vk.alpha_g1, to_hex), |
| 192 | + beta_g1: P::parse_g1_json(&vk.beta_g1, to_hex), |
| 193 | + beta_g2: P::parse_g2_json(&vk.beta_g2, to_hex), |
| 194 | + gamma_g2: P::parse_g2_json(&vk.gamma_g2, to_hex), |
| 195 | + delta_g1: P::parse_g1_json(&vk.delta_g1, to_hex), |
| 196 | + delta_g2: P::parse_g2_json(&vk.delta_g2, to_hex), |
| 197 | + ic: vk |
| 198 | + .ic |
| 199 | + .iter() |
| 200 | + .map(|e| P::parse_g1_json(e, to_hex)) |
| 201 | + .collect::<Vec<_>>(), |
| 202 | + }; |
| 203 | + |
| 204 | + Ok(to_string(&verifying_key_file)?) |
| 205 | +} |
| 206 | + |
| 207 | +pub fn serialize_proof<P: Parser>(p: &Proof<P>, curve_type: &str, to_hex: bool) -> Result<String> { |
| 208 | + let proof_file = ProofFile { |
| 209 | + a: P::parse_g1_json(&p.a, to_hex), |
| 210 | + b: P::parse_g2_json(&p.b, to_hex), |
| 211 | + c: P::parse_g1_json(&p.c, to_hex), |
| 212 | + protocol: "groth16".to_string(), |
| 213 | + curve: curve_type.to_string(), |
| 214 | + }; |
| 215 | + |
| 216 | + Ok(to_string(&proof_file)?) |
| 217 | +} |
| 218 | + |
| 219 | +pub fn to_verification_key<P: Parser>(s: &str) -> VerifyingKey<P> { |
| 220 | + let vk_file: VerifyingKeyFile = |
| 221 | + serde_json::from_str(s).expect("Error during deserialization of the JSON data"); |
| 222 | + |
| 223 | + let convert_g1 = |point: &G1| P::to_g1(&point.x, &point.y); |
| 224 | + let convert_g2 = |point: &G2| P::to_g2(&point.x[0], &point.x[1], &point.y[0], &point.y[1]); |
| 225 | + |
| 226 | + VerifyingKey { |
| 227 | + alpha_g1: convert_g1(&vk_file.alpha_g1), |
| 228 | + beta_g1: convert_g1(&vk_file.beta_g1), |
| 229 | + beta_g2: convert_g2(&vk_file.beta_g2), |
| 230 | + gamma_g2: convert_g2(&vk_file.gamma_g2), |
| 231 | + delta_g1: convert_g1(&vk_file.delta_g1), |
| 232 | + delta_g2: convert_g2(&vk_file.delta_g2), |
| 233 | + ic: vk_file.ic.iter().map(convert_g1).collect(), |
| 234 | + } |
| 235 | +} |
| 236 | + |
| 237 | +pub fn to_proof<P: Parser>(s: &str) -> Proof<P> { |
| 238 | + let proof: ProofFile = |
| 239 | + serde_json::from_str(s).expect("Error during deserialization of the JSON data"); |
| 240 | + |
| 241 | + let convert_g1 = |point: &G1| P::to_g1(&point.x, &point.y); |
| 242 | + let convert_g2 = |point: &G2| P::to_g2(&point.x[0], &point.x[1], &point.y[0], &point.y[1]); |
| 243 | + |
| 244 | + Proof { |
| 245 | + a: convert_g1(&proof.a), |
| 246 | + b: convert_g2(&proof.b), |
| 247 | + c: convert_g1(&proof.c), |
| 248 | + } |
| 249 | +} |
| 250 | + |
| 251 | +#[cfg(test)] |
| 252 | +mod tests { |
| 253 | + use super::*; |
| 254 | + use crate::bellman_ce::groth16::{Proof, VerifyingKey}; |
| 255 | + use crate::bellman_ce::pairing::{bls12_381::Bls12, bn256::Bn256}; |
| 256 | + |
| 257 | + #[test] |
| 258 | + fn test_serialize_vk() { |
| 259 | + let mut reader = std::io::BufReader::with_capacity( |
| 260 | + 1 << 24, |
| 261 | + std::fs::File::open("./test-vectors/verification_key.bin").unwrap(), |
| 262 | + ); |
| 263 | + let vk_from_bin = VerifyingKey::<Bn256>::read(&mut reader).unwrap(); |
| 264 | + let result = serialize_vk(&vk_from_bin, "bn128", false).unwrap(); |
| 265 | + std::fs::write("./test-vectors/verification_key.json", result) |
| 266 | + .expect("Unable to write data to file"); |
| 267 | + |
| 268 | + let json_data = std::fs::read_to_string("./test-vectors/verification_key.json") |
| 269 | + .expect("Unable to read the JSON file"); |
| 270 | + let verifying_key_from_json = to_verification_key::<Bn256>(&json_data); |
| 271 | + assert_eq!( |
| 272 | + vk_from_bin.alpha_g1, verifying_key_from_json.alpha_g1, |
| 273 | + "VerificationKey are not equal" |
| 274 | + ); |
| 275 | + } |
| 276 | + |
| 277 | + #[test] |
| 278 | + fn test_serialize_vk_bls12381() { |
| 279 | + let mut reader = std::io::BufReader::with_capacity( |
| 280 | + 1 << 24, |
| 281 | + std::fs::File::open("./test-vectors/verification_key_bls12381.bin").unwrap(), |
| 282 | + ); |
| 283 | + let vk_from_bin = VerifyingKey::<Bls12>::read(&mut reader).unwrap(); |
| 284 | + let result = serialize_vk(&vk_from_bin, "bls12381", false).unwrap(); |
| 285 | + std::fs::write("./test-vectors/verification_key_bls12381.json", result) |
| 286 | + .expect("Unable to write data to file"); |
| 287 | + let json_data = std::fs::read_to_string("./test-vectors/verification_key_bls12381.json") |
| 288 | + .expect("Unable to read the JSON file"); |
| 289 | + let verifying_key_from_json = to_verification_key::<Bls12>(&json_data); |
| 290 | + assert_eq!( |
| 291 | + vk_from_bin.alpha_g1, verifying_key_from_json.alpha_g1, |
| 292 | + "VerificationKey are not equal" |
| 293 | + ); |
| 294 | + } |
| 295 | + |
| 296 | + #[test] |
| 297 | + fn test_serialize_proof() { |
| 298 | + let mut reader = std::io::BufReader::with_capacity( |
| 299 | + 1 << 24, |
| 300 | + std::fs::File::open("./test-vectors/proof.bin").unwrap(), |
| 301 | + ); |
| 302 | + let proof_from_bin = Proof::<Bn256>::read(&mut reader).unwrap(); |
| 303 | + let result = serialize_proof(&proof_from_bin, "bn128", false).unwrap(); |
| 304 | + std::fs::write("./test-vectors/proof.json", result).expect("Unable to write data to file"); |
| 305 | + |
| 306 | + let json_data = std::fs::read_to_string("./test-vectors/proof.json") |
| 307 | + .expect("Unable to read the JSON file"); |
| 308 | + let proof_from_json = to_proof::<Bn256>(&json_data); |
| 309 | + assert_eq!(proof_from_bin.a, proof_from_json.a, "Proofs are not equal"); |
| 310 | + } |
| 311 | +} |
0 commit comments