scipr-lab / libsnark

C++ library for zkSNARKs
Other
1.8k stars 570 forks source link

Operators >> and << for verification keys not storing encoded IC q properly (or at least unclear documentation) #181

Open ThomasRossi opened 3 years ago

ThomasRossi commented 3 years ago

After a generator creates the keypair, I used >> to write the verification key to file. Then use << to load the verification key, but the loaded key does not verify the proof, moreover if you create a processed verification key from the original vk and then a processed vk from the loaded key, the two processed verification keys are not ==. In particular the encoded IC query is different, the >> << operators don't store it/retrieve it properly. Or at least, that's what I'd expect >> and << to do, if it was not the case, then some comment would have been really useful there. This makes the proving cycle a bit awkward when using files: because the verifier will have a vk file and a pvk file which describe the same key up to the encoded IC q, so they are not "exactly" the same.

This is an extract form my test classes, if it's useful I can create a small repo with just the minimal code to see the writing and loading of the verification keys and the comparison of their respective processed keys.

I may have misunderstood the use case for >> and <<, is it a practice to create ad hoc "write and load" operations for the keys and not using the operators? Thanks, eventually please let me know how/if I can help.

T.

    r1cs_ppzksnark_keypair<default_r1cs_ppzksnark_pp> keypair = generator(......); //some generator
    r1cs_ppzksnark_verification_key<default_r1cs_ppzksnark_pp> vk = keypair.vk;

    //write keys to file with <<
    std::filebuf fb;
    fb.open (pathToFile,std::ios::out);
    std::ostream os(&fb);
    os<<vk;
    fb.close();

    //load key from file with >>
    r1cs_ppzksnark_verification_key<default_r1cs_ppzksnark_pp> vk2;
    std::filebuf fb;
    if (fb.open (pathToFile,std::ios::in))
    {
          std::istream is(&fb);
          is>>vk2;
          fb.close();
    }
    else cout << "Unable to open file"; 

    EXPECT_TRUE(vk==vk2); //!!!!!!!! also this should not be true, let's see why ->

    //prepare the processed verification key
    r1cs_ppzksnark_processed_verification_key<default_r1cs_ppzksnark_pp> pvk = r1cs_ppzksnark_verifier_process_vk<default_r1cs_ppzksnark_pp>(vk);

    //prepare the processed verification key from the loaded vk 
    r1cs_ppzksnark_processed_verification_key<default_r1cs_ppzksnark_pp> pvk_star = r1cs_ppzksnark_verifier_process_vk<default_r1cs_ppzksnark_pp>(vk2);

    //pvk needs a special comparison since vk>>file doesn't port the IC query properly
    //i.e. pvk created by a vk reconstructed via file DOES NOT equals pvk created with the original vk 
    EXPECT_FALSE(pvk_star==pvk);
    EXPECT_TRUE(pvk_star.vk_alphaA_g2_precomp == pvk.vk_alphaA_g2_precomp);
    EXPECT_TRUE(pvk_star.vk_alphaB_g1_precomp == pvk.vk_alphaB_g1_precomp);
    EXPECT_TRUE(pvk_star.vk_alphaC_g2_precomp == pvk.vk_alphaC_g2_precomp);
    EXPECT_TRUE(pvk_star.vk_gamma_g2_precomp == pvk.vk_gamma_g2_precomp);
    EXPECT_TRUE(pvk_star.vk_gamma_beta_g1_precomp == pvk.vk_gamma_beta_g1_precomp);
    EXPECT_TRUE(pvk_star.vk_gamma_beta_g2_precomp == pvk.vk_gamma_beta_g2_precomp);
    EXPECT_TRUE(pvk_star.vk_rC_Z_g2_precomp == pvk.vk_rC_Z_g2_precomp);
    EXPECT_FALSE(pvk_star.encoded_IC_query == pvk.encoded_IC_query);//!!!!!! <-------