use crate::hashing::blake2b_224;
use crate::register::Register;
use blstrs::{G1Affine, G1Projective, Scalar};
use anyhow::{Context, Result, anyhow};
use ff::Field;
use hex;
use rand_core::OsRng;
pub fn fiat_shamir_heuristic(g_b: String, g_r_b: String, u_b: String, b: String) -> Result<String> {
let concatenated: String = format!("{g_b}{g_r_b}{u_b}{b}");
blake2b_224(&concatenated)
}
pub fn random_scalar() -> Scalar {
Scalar::random(&mut OsRng)
}
pub fn create_proof(
datum: Register,
sk: Scalar,
bound: String,
r: Scalar,
) -> Result<(String, String)> {
let g1: G1Affine = G1Affine::from_compressed(
&hex::decode(&datum.generator)
.context("Failed to decode generator hex")?
.try_into()
.map_err(|e| anyhow::anyhow!("{e:?}"))?,
)
.into_option()
.ok_or_else(|| anyhow!("Failed to decompress generator"))?;
let g_r: G1Projective = G1Projective::from(g1) * r;
let c_hex: String = fiat_shamir_heuristic(
datum.generator,
hex::encode(g_r.to_compressed()),
datum.public_value,
bound,
)
.context("Fair Shamir Heuristic Failure")?;
let c_bytes: Vec<u8> = hex::decode(&c_hex).context("Failed to decode Fiat-Shamir output")?;
let mut c_array: [u8; 32] = [0u8; 32];
c_array[(32 - c_bytes.len())..].copy_from_slice(&c_bytes);
let c: Scalar = Scalar::from_bytes_be(&c_array)
.into_option()
.ok_or_else(|| anyhow!("Failed to Convert To Scalar"))?;
let z: Scalar = r + c * sk;
Ok((
hex::encode(z.to_bytes_be()),
hex::encode(g_r.to_compressed()),
))
}
pub fn prove(
generator: &str,
public_value: &str,
z_b: &str,
g_r_b: &str,
bound: &str,
) -> Result<bool> {
let g1: G1Affine = G1Affine::from_compressed(
&hex::decode(generator)
.context("Failed to decode generator hex")?
.try_into()
.map_err(|e| anyhow::anyhow!("{e:?}"))?,
)
.into_option()
.ok_or_else(|| anyhow!("Failed to decompress generator"))?;
let u: G1Affine = G1Affine::from_compressed(
&hex::decode(public_value)
.context("Failed to decode public value hex")?
.try_into()
.map_err(|e| anyhow::anyhow!("{e:?}"))?,
)
.into_option()
.ok_or_else(|| anyhow!("Failed to decompress generator"))?;
let g_r: G1Affine = G1Affine::from_compressed(
&hex::decode(g_r_b)
.context("Failed to decode g_r_b hex")?
.try_into()
.map_err(|e| anyhow::anyhow!("{e:?}"))?,
)
.into_option()
.ok_or_else(|| anyhow!("Failed to decompress generator"))?;
let z_bytes: Vec<u8> = hex::decode(z_b).context("Failed to decode z_b hex")?;
let mut z_array: [u8; 32] = [0u8; 32];
z_array[(32 - z_bytes.len())..].copy_from_slice(&z_bytes);
let z: Scalar = Scalar::from_bytes_be(&z_array)
.into_option()
.ok_or_else(|| anyhow!("Failed to Convert To Scalar"))?;
let g_z: G1Projective = g1 * z;
let c_hex: String = fiat_shamir_heuristic(
generator.to_string(),
g_r_b.to_string(),
public_value.to_string(),
bound.to_string(),
)
.context("Fair Shamir Heuristic Failure")?;
let c_bytes: Vec<u8> = hex::decode(&c_hex).context("Failed to decode Fiat-Shamir output")?;
let mut c_array = [0u8; 32];
c_array[(32 - c_bytes.len())..].copy_from_slice(&c_bytes);
let c = Scalar::from_bytes_be(&c_array)
.into_option()
.ok_or_else(|| anyhow!("Failed to Convert To Scalar"))?;
let u_c: G1Projective = u * c;
Ok(g_z == (G1Projective::from(g_r) + u_c))
}