revm_precompile/kzg_point_evaluation/
arkworks.rs1use crate::{
3 bls12_381::arkworks::pairing_check, bls12_381_const::TRUSTED_SETUP_TAU_G2_BYTES,
4 PrecompileError,
5};
6use ark_bls12_381::{Fr, G1Affine, G2Affine};
7use ark_ec::{AffineRepr, CurveGroup};
8use ark_ff::{BigInteger, PrimeField};
9use ark_serialize::CanonicalDeserialize;
10use core::ops::Neg;
11
12#[inline]
17pub fn verify_kzg_proof(
18 commitment: &[u8; 48],
19 z: &[u8; 32],
20 y: &[u8; 32],
21 proof: &[u8; 48],
22) -> bool {
23 let Ok(commitment_point) = parse_g1_compressed(commitment) else {
25 return false;
26 };
27
28 let Ok(proof_point) = parse_g1_compressed(proof) else {
30 return false;
31 };
32
33 let Ok(z_fr) = read_scalar_canonical(z) else {
36 return false;
37 };
38 let Ok(y_fr) = read_scalar_canonical(y) else {
39 return false;
40 };
41
42 let tau_g2 = get_trusted_setup_g2();
44
45 let g1 = get_g1_generator();
47 let g2 = get_g2_generator();
48
49 let y_g1 = p1_scalar_mul(&g1, &y_fr);
51 let p_minus_y = p1_sub_affine(&commitment_point, &y_g1);
52
53 let z_g2 = p2_scalar_mul(&g2, &z_fr);
55 let x_minus_z = p2_sub_affine(&tau_g2, &z_g2);
56
57 let neg_g2 = p2_neg(&g2);
60
61 pairing_check(&[(p_minus_y, neg_g2), (proof_point, x_minus_z)])
62}
63
64fn get_trusted_setup_g2() -> G2Affine {
67 G2Affine::deserialize_compressed_unchecked(&TRUSTED_SETUP_TAU_G2_BYTES[..])
70 .expect("Failed to parse trusted setup G2 point")
71}
72
73fn parse_g1_compressed(bytes: &[u8; 48]) -> Result<G1Affine, PrecompileError> {
75 G1Affine::deserialize_compressed(&bytes[..]).map_err(|_| PrecompileError::KzgInvalidG1Point)
76}
77
78fn read_scalar_canonical(bytes: &[u8; 32]) -> Result<Fr, PrecompileError> {
80 let fr = Fr::from_be_bytes_mod_order(bytes);
81
82 let bytes_roundtrip = fr.into_bigint().to_bytes_be();
84
85 if bytes_roundtrip.as_slice() != bytes {
86 return Err(PrecompileError::NonCanonicalFp);
87 }
88
89 Ok(fr)
90}
91
92#[inline]
94fn get_g1_generator() -> G1Affine {
95 G1Affine::generator()
96}
97
98#[inline]
100fn get_g2_generator() -> G2Affine {
101 G2Affine::generator()
102}
103
104#[inline]
106fn p1_scalar_mul(point: &G1Affine, scalar: &Fr) -> G1Affine {
107 point.mul_bigint(scalar.into_bigint()).into_affine()
108}
109
110#[inline]
112fn p2_scalar_mul(point: &G2Affine, scalar: &Fr) -> G2Affine {
113 point.mul_bigint(scalar.into_bigint()).into_affine()
114}
115
116#[inline]
118fn p1_sub_affine(a: &G1Affine, b: &G1Affine) -> G1Affine {
119 (a.into_group() - b.into_group()).into_affine()
120}
121
122#[inline]
124fn p2_sub_affine(a: &G2Affine, b: &G2Affine) -> G2Affine {
125 (a.into_group() - b.into_group()).into_affine()
126}
127
128#[inline]
130fn p2_neg(p: &G2Affine) -> G2Affine {
131 p.neg()
132}