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