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 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 vk: VerifierKey<Bn254>,
 46    pub 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};
 82    use ark_crypto_primitives::sponge::{poseidon::PoseidonSponge, CryptographicSponge};
 83    use ark_ec::{AffineRepr, CurveGroup};
 84    use ark_ff::{BigInteger, PrimeField};
 85    use ark_std::rand::{RngCore, SeedableRng};
 86    use ark_std::Zero;
 87    use ark_std::{test_rng, UniformRand};
 88    use askama::Template;
 89    use itertools::chain;
 90
 91    use folding_schemes::{
 92        commitment::{kzg::KZG, CommitmentScheme},
 93        transcript::{poseidon::poseidon_canonical_config, Transcript},
 94    };
 95
 96    use super::KZG10Verifier;
 97    use crate::verifiers::tests::{setup, DEFAULT_SETUP_LEN};
 98
 99    const FUNCTION_SELECTOR_KZG10_CHECK: [u8; 4] = [0x9e, 0x78, 0xcc, 0xf7];
100
101    #[test]
102    fn kzg_vk_serde_roundtrip() {
103        let (_, pk, vk, _, _, _) = setup(DEFAULT_SETUP_LEN);
104
105        let kzg_vk = KZG10VerifierKey::from((vk, pk.powers_of_g[0..3].to_vec()));
106        let mut bytes = vec![];
107        kzg_vk.serialize_protocol_verifier_key(&mut bytes).unwrap();
108        let obtained_kzg_vk =
109            KZG10VerifierKey::deserialize_protocol_verifier_key(bytes.as_slice()).unwrap();
110
111        assert_eq!(kzg_vk, obtained_kzg_vk)
112    }
113
114    #[test]
115    fn kzg_verifier_compiles() {
116        let (_, kzg_pk, kzg_vk, _, _, _) = setup(DEFAULT_SETUP_LEN);
117        let kzg_vk = KZG10VerifierKey::from((kzg_vk.clone(), kzg_pk.powers_of_g[0..3].to_vec()));
118
119        let res = HeaderInclusion::<KZG10Verifier>::builder()
120            .template(kzg_vk)
121            .build()
122            .render()
123            .unwrap();
124
125        let kzg_verifier_bytecode = compile_solidity(res, "KZG10");
126        let mut evm = Evm::default();
127        _ = evm.create(kzg_verifier_bytecode);
128    }
129
130    #[test]
131    fn kzg_verifier_accepts_and_rejects_proofs() {
132        let mut rng = ark_std::rand::rngs::StdRng::seed_from_u64(test_rng().next_u64());
133        let poseidon_config = poseidon_canonical_config::<Fr>();
134        let transcript_p = &mut PoseidonSponge::<Fr>::new(&poseidon_config);
135        let transcript_v = &mut PoseidonSponge::<Fr>::new(&poseidon_config);
136
137        let (_, kzg_pk, kzg_vk, _, _, _) = setup(DEFAULT_SETUP_LEN);
138        let kzg_vk = KZG10VerifierKey::from((kzg_vk.clone(), kzg_pk.powers_of_g[0..3].to_vec()));
139
140        let v: Vec<Fr> = std::iter::repeat_with(|| Fr::rand(&mut rng))
141            .take(DEFAULT_SETUP_LEN)
142            .collect();
143        let cm = KZG::<Bn254>::commit(&kzg_pk, &v, &Fr::zero()).unwrap();
144        let proof = KZG::<Bn254>::prove(&kzg_pk, transcript_p, &cm, &v, &Fr::zero(), None).unwrap();
145        let template = HeaderInclusion::<KZG10Verifier>::builder()
146            .template(kzg_vk)
147            .build()
148            .render()
149            .unwrap();
150
151        let kzg_verifier_bytecode = compile_solidity(template, "KZG10");
152        let mut evm = Evm::default();
153        let verifier_address = evm.create(kzg_verifier_bytecode);
154
155        let (cm_affine, proof_affine) = (cm.into_affine(), proof.proof.into_affine());
156        let (x_comm, y_comm) = cm_affine.xy().unwrap();
157        let (x_proof, y_proof) = proof_affine.xy().unwrap();
158        let y = proof.eval.into_bigint().to_bytes_be();
159
160        transcript_v.absorb_nonnative(&cm);
161        let x = transcript_v.get_challenge();
162
163        let x = x.into_bigint().to_bytes_be();
164        let mut calldata: Vec<u8> = chain![
165            FUNCTION_SELECTOR_KZG10_CHECK,
166            x_comm.into_bigint().to_bytes_be(),
167            y_comm.into_bigint().to_bytes_be(),
168            x_proof.into_bigint().to_bytes_be(),
169            y_proof.into_bigint().to_bytes_be(),
170            x.clone(),
171            y,
172        ]
173        .collect();
174
175        let (_, output) = evm.call(verifier_address, calldata.clone());
176        assert_eq!(*output.last().unwrap(), 1);
177
178        // change calldata to make it invalid
179        let last_calldata_element = calldata.last_mut().unwrap();
180        *last_calldata_element = 0;
181        let (_, output) = evm.call(verifier_address, calldata);
182        assert_eq!(*output.last().unwrap(), 0);
183    }
184}