arnaucube
arnaucube/sonobePublic Self-hosted repository
sonobe/solidity-verifiers/src/verifiers/kzg.rs
solidity-verifiers/src/verifiers/kzg.rsRaw
  1use crate::utils::encoding::{g1_to_fq_repr, g2_to_fq_repr};
  2use crate::utils::encoding::{G1Repr, G2Repr};
  3use crate::utils::HeaderInclusion;
  4use crate::{ProtocolVerifierKey, MIT_SDPX_IDENTIFIER};
  5use ark_bn254::{Bn254, G1Affine};
  6use ark_poly_commit::kzg10::VerifierKey;
  7use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
  8use askama::Template;
  9
 10use super::PRAGMA_KZG10_VERIFIER;
 11
 12#[derive(Template, Default)]
 13#[template(path = "kzg10_verifier.askama.sol", ext = "sol")]
 14pub(crate) struct KZG10Verifier {
 15    /// The generator of `G1`.
 16    pub(crate) g1: G1Repr,
 17    /// The generator of `G2`.
 18    pub(crate) g2: G2Repr,
 19    /// The verification key
 20    pub(crate) vk: G2Repr,
 21    /// Length of the trusted setup vector.
 22    pub(crate) g1_crs_len: usize,
 23    /// The trusted setup vector.
 24    pub(crate) g1_crs: Vec<G1Repr>,
 25}
 26
 27impl From<KZG10VerifierKey> for KZG10Verifier {
 28    fn from(data: KZG10VerifierKey) -> Self {
 29        Self {
 30            g1: g1_to_fq_repr(data.vk.g),
 31            g2: g2_to_fq_repr(data.vk.h),
 32            vk: g2_to_fq_repr(data.vk.beta_h),
 33            g1_crs_len: data.g1_crs_batch_points.len(),
 34            g1_crs: data
 35                .g1_crs_batch_points
 36                .iter()
 37                .map(|g1| g1_to_fq_repr(*g1))
 38                .collect(),
 39        }
 40    }
 41}
 42
 43#[derive(CanonicalDeserialize, CanonicalSerialize, Clone, PartialEq, Debug)]
 44pub struct KZG10VerifierKey {
 45    pub(crate) vk: VerifierKey<Bn254>,
 46    pub(crate) g1_crs_batch_points: Vec<G1Affine>,
 47}
 48
 49impl From<(VerifierKey<Bn254>, Vec<G1Affine>)> for KZG10VerifierKey {
 50    fn from(value: (VerifierKey<Bn254>, Vec<G1Affine>)) -> Self {
 51        Self {
 52            vk: value.0,
 53            g1_crs_batch_points: value.1,
 54        }
 55    }
 56}
 57
 58impl ProtocolVerifierKey for KZG10VerifierKey {
 59    const PROTOCOL_NAME: &'static str = "KZG";
 60
 61    fn render_as_template(self, pragma: Option<String>) -> Vec<u8> {
 62        HeaderInclusion::<KZG10Verifier>::builder()
 63            .sdpx(MIT_SDPX_IDENTIFIER.to_string())
 64            .pragma_version(pragma.unwrap_or(PRAGMA_KZG10_VERIFIER.to_string()))
 65            .template(self)
 66            .build()
 67            .render()
 68            .unwrap()
 69            .into_bytes()
 70    }
 71}
 72
 73#[cfg(test)]
 74mod tests {
 75    use super::KZG10VerifierKey;
 76    use crate::{
 77        evm::{compile_solidity, Evm},
 78        utils::HeaderInclusion,
 79        ProtocolVerifierKey,
 80    };
 81    use ark_bn254::{Bn254, Fr, G1Projective as G1};
 82    use ark_ec::{AffineRepr, CurveGroup};
 83    use ark_ff::{BigInteger, PrimeField};
 84    use ark_std::rand::{RngCore, SeedableRng};
 85    use ark_std::Zero;
 86    use ark_std::{test_rng, UniformRand};
 87    use askama::Template;
 88    use itertools::chain;
 89
 90    use folding_schemes::{
 91        commitment::{kzg::KZG, CommitmentScheme},
 92        transcript::{
 93            poseidon::{poseidon_test_config, PoseidonTranscript},
 94            Transcript,
 95        },
 96    };
 97
 98    use super::KZG10Verifier;
 99    use crate::verifiers::tests::{setup, DEFAULT_SETUP_LEN};
100
101    const FUNCTION_SELECTOR_KZG10_CHECK: [u8; 4] = [0x9e, 0x78, 0xcc, 0xf7];
102
103    #[test]
104    fn kzg_vk_serde_roundtrip() {
105        let (pk, vk, _, _, _) = setup(DEFAULT_SETUP_LEN);
106
107        let kzg_vk = KZG10VerifierKey::from((vk, pk.powers_of_g[0..3].to_vec()));
108        let mut bytes = vec![];
109        kzg_vk.serialize_protocol_verifier_key(&mut bytes).unwrap();
110        let obtained_kzg_vk =
111            KZG10VerifierKey::deserialize_protocol_verifier_key(bytes.as_slice()).unwrap();
112
113        assert_eq!(kzg_vk, obtained_kzg_vk)
114    }
115
116    #[test]
117    fn kzg_verifier_compiles() {
118        let (kzg_pk, kzg_vk, _, _, _) = setup(DEFAULT_SETUP_LEN);
119        let kzg_vk = KZG10VerifierKey::from((kzg_vk.clone(), kzg_pk.powers_of_g[0..3].to_vec()));
120
121        let res = HeaderInclusion::<KZG10Verifier>::builder()
122            .template(kzg_vk)
123            .build()
124            .render()
125            .unwrap();
126
127        let kzg_verifier_bytecode = compile_solidity(res, "KZG10");
128        let mut evm = Evm::default();
129        _ = evm.create(kzg_verifier_bytecode);
130    }
131
132    #[test]
133    fn kzg_verifier_accepts_and_rejects_proofs() {
134        let mut rng = ark_std::rand::rngs::StdRng::seed_from_u64(test_rng().next_u64());
135        let poseidon_config = poseidon_test_config::<Fr>();
136        let transcript_p = &mut PoseidonTranscript::<G1>::new(&poseidon_config);
137        let transcript_v = &mut PoseidonTranscript::<G1>::new(&poseidon_config);
138
139        let (kzg_pk, kzg_vk, _, _, _) = setup(DEFAULT_SETUP_LEN);
140        let kzg_vk = KZG10VerifierKey::from((kzg_vk.clone(), kzg_pk.powers_of_g[0..3].to_vec()));
141
142        let v: Vec<Fr> = std::iter::repeat_with(|| Fr::rand(&mut rng))
143            .take(DEFAULT_SETUP_LEN)
144            .collect();
145        let cm = KZG::<Bn254>::commit(&kzg_pk, &v, &Fr::zero()).unwrap();
146        let proof = KZG::<Bn254>::prove(&kzg_pk, transcript_p, &cm, &v, &Fr::zero(), None).unwrap();
147        let template = HeaderInclusion::<KZG10Verifier>::builder()
148            .template(kzg_vk)
149            .build()
150            .render()
151            .unwrap();
152
153        let kzg_verifier_bytecode = compile_solidity(template, "KZG10");
154        let mut evm = Evm::default();
155        let verifier_address = evm.create(kzg_verifier_bytecode);
156
157        let (cm_affine, proof_affine) = (cm.into_affine(), proof.proof.into_affine());
158        let (x_comm, y_comm) = cm_affine.xy().unwrap();
159        let (x_proof, y_proof) = proof_affine.xy().unwrap();
160        let y = proof.eval.into_bigint().to_bytes_be();
161
162        transcript_v.absorb_point(&cm).unwrap();
163        let x = transcript_v.get_challenge();
164
165        let x = x.into_bigint().to_bytes_be();
166        let mut calldata: Vec<u8> = chain![
167            FUNCTION_SELECTOR_KZG10_CHECK,
168            x_comm.into_bigint().to_bytes_be(),
169            y_comm.into_bigint().to_bytes_be(),
170            x_proof.into_bigint().to_bytes_be(),
171            y_proof.into_bigint().to_bytes_be(),
172            x.clone(),
173            y,
174        ]
175        .collect();
176
177        let (_, output) = evm.call(verifier_address, calldata.clone());
178        assert_eq!(*output.last().unwrap(), 1);
179
180        // change calldata to make it invalid
181        let last_calldata_element = calldata.last_mut().unwrap();
182        *last_calldata_element = 0;
183        let (_, output) = evm.call(verifier_address, calldata);
184        assert_eq!(*output.last().unwrap(), 0);
185    }
186}