diff --git a/src/algebra/curves/alt_bn128/alt_bn128_pairing.cpp b/src/algebra/curves/alt_bn128/alt_bn128_pairing.cpp index 3eb5aa11..91ce0df0 100644 --- a/src/algebra/curves/alt_bn128/alt_bn128_pairing.cpp +++ b/src/algebra/curves/alt_bn128/alt_bn128_pairing.cpp @@ -418,18 +418,19 @@ alt_bn128_Fq12 alt_bn128_ate_miller_loop(const alt_bn128_ate_G1_precomp &prec_P, return f; } -alt_bn128_Fq12 alt_bn128_ate_double_miller_loop(const alt_bn128_ate_G1_precomp &prec_P1, - const alt_bn128_ate_G2_precomp &prec_Q1, - const alt_bn128_ate_G1_precomp &prec_P2, - const alt_bn128_ate_G2_precomp &prec_Q2) -{ - enter_block("Call to alt_bn128_ate_double_miller_loop"); - alt_bn128_Fq12 f = alt_bn128_Fq12::one(); +alt_bn128_Fq12 alt_bn128_ate_multiple_miller_loop( + const std::initializer_list >& v +) +{ + enter_block("Call to alt_bn128_ate_multiple_miller_loop"); + auto f = alt_bn128_Fq12::one(); bool found_one = false; size_t idx = 0; - const bigint &loop_count = alt_bn128_ate_loop_count; for (long i = loop_count.max_bits(); i >= 0; --i) { @@ -445,48 +446,62 @@ alt_bn128_Fq12 alt_bn128_ate_double_miller_loop(const alt_bn128_ate_G1_precomp & alt_bn128_param_p (skipping leading zeros) in MSB to LSB order */ - alt_bn128_ate_ell_coeffs c1 = prec_Q1.coeffs[idx]; - alt_bn128_ate_ell_coeffs c2 = prec_Q2.coeffs[idx]; - ++idx; - f = f.squared(); - - f = f.mul_by_024(c1.ell_0, prec_P1.PY * c1.ell_VW, prec_P1.PX * c1.ell_VV); - f = f.mul_by_024(c2.ell_0, prec_P2.PY * c2.ell_VW, prec_P2.PX * c2.ell_VV); + for(auto& p:v){ + auto c = p.second.coeffs[idx]; + f = f.mul_by_024(c.ell_0, p.first.PY * c.ell_VW, p.first.PX * c.ell_VV); + } + ++idx; if (bit) { - alt_bn128_ate_ell_coeffs c1 = prec_Q1.coeffs[idx]; - alt_bn128_ate_ell_coeffs c2 = prec_Q2.coeffs[idx]; + for(auto& p:v){ + auto c = p.second.coeffs[idx]; + f = f.mul_by_024(c.ell_0, p.first.PY * c.ell_VW, p.first.PX * c.ell_VV); + } ++idx; - f = f.mul_by_024(c1.ell_0, prec_P1.PY * c1.ell_VW, prec_P1.PX * c1.ell_VV); - f = f.mul_by_024(c2.ell_0, prec_P2.PY * c2.ell_VW, prec_P2.PX * c2.ell_VV); } } if (alt_bn128_ate_is_loop_count_neg) { - f = f.inverse(); + f = f.inverse(); } - alt_bn128_ate_ell_coeffs c1 = prec_Q1.coeffs[idx]; - alt_bn128_ate_ell_coeffs c2 = prec_Q2.coeffs[idx]; - ++idx; - f = f.mul_by_024(c1.ell_0, prec_P1.PY * c1.ell_VW, prec_P1.PX * c1.ell_VV); - f = f.mul_by_024(c2.ell_0, prec_P2.PY * c2.ell_VW, prec_P2.PX * c2.ell_VV); + for(auto& p:v){ + auto c = p.second.coeffs[idx]; + f = f.mul_by_024(c.ell_0, p.first.PY * c.ell_VW, p.first.PX * c.ell_VV); + } + ++idx; - c1 = prec_Q1.coeffs[idx]; - c2 = prec_Q2.coeffs[idx]; - ++idx; - f = f.mul_by_024(c1.ell_0, prec_P1.PY * c1.ell_VW, prec_P1.PX * c1.ell_VV); - f = f.mul_by_024(c2.ell_0, prec_P2.PY * c2.ell_VW, prec_P2.PX * c2.ell_VV); + for(auto& p:v){ + auto c = p.second.coeffs[idx]; + f = f.mul_by_024(c.ell_0, p.first.PY * c.ell_VW, p.first.PX * c.ell_VV); + } + ++idx; + leave_block("Call to alt_bn128_ate_multiple_miller_loop"); + return f; +} + +alt_bn128_Fq12 alt_bn128_ate_double_miller_loop(const alt_bn128_ate_G1_precomp &prec_P1, + const alt_bn128_ate_G2_precomp &prec_Q1, + const alt_bn128_ate_G1_precomp &prec_P2, + const alt_bn128_ate_G2_precomp &prec_Q2) +{ + enter_block("Call to alt_bn128_ate_double_miller_loop"); + + auto f = alt_bn128_ate_multiple_miller_loop({ + std::make_pair(prec_P1,prec_Q1), + std::make_pair(prec_P2,prec_Q2) + }); leave_block("Call to alt_bn128_ate_double_miller_loop"); return f; } + alt_bn128_Fq12 alt_bn128_ate_pairing(const alt_bn128_G1& P, const alt_bn128_G2 &Q) { enter_block("Call to alt_bn128_ate_pairing"); diff --git a/src/algebra/curves/alt_bn128/alt_bn128_pairing.hpp b/src/algebra/curves/alt_bn128/alt_bn128_pairing.hpp index 15d32548..8744faa7 100644 --- a/src/algebra/curves/alt_bn128/alt_bn128_pairing.hpp +++ b/src/algebra/curves/alt_bn128/alt_bn128_pairing.hpp @@ -56,6 +56,12 @@ alt_bn128_Fq12 alt_bn128_ate_double_miller_loop(const alt_bn128_ate_G1_precomp & const alt_bn128_ate_G2_precomp &prec_Q1, const alt_bn128_ate_G1_precomp &prec_P2, const alt_bn128_ate_G2_precomp &prec_Q2); +alt_bn128_Fq12 alt_bn128_ate_multiple_miller_loop( + const std::initializer_list >& v +); alt_bn128_Fq12 alt_bn128_ate_pairing(const alt_bn128_G1& P, const alt_bn128_G2 &Q); diff --git a/src/algebra/curves/alt_bn128/alt_bn128_pp.cpp b/src/algebra/curves/alt_bn128/alt_bn128_pp.cpp index 25ea924d..f23af110 100644 --- a/src/algebra/curves/alt_bn128/alt_bn128_pp.cpp +++ b/src/algebra/curves/alt_bn128/alt_bn128_pp.cpp @@ -43,6 +43,15 @@ alt_bn128_Fq12 alt_bn128_pp::double_miller_loop(const alt_bn128_G1_precomp &prec return alt_bn128_double_miller_loop(prec_P1, prec_Q1, prec_P2, prec_Q2); } +alt_bn128_Fq12 alt_bn128_pp::multiple_miller_loop( + const std::initializer_list >& v +) +{ + return alt_bn128_ate_multiple_miller_loop(v); +} alt_bn128_Fq12 alt_bn128_pp::pairing(const alt_bn128_G1 &P, const alt_bn128_G2 &Q) { diff --git a/src/algebra/curves/alt_bn128/alt_bn128_pp.hpp b/src/algebra/curves/alt_bn128/alt_bn128_pp.hpp index ec8059dc..32b8cc17 100644 --- a/src/algebra/curves/alt_bn128/alt_bn128_pp.hpp +++ b/src/algebra/curves/alt_bn128/alt_bn128_pp.hpp @@ -39,6 +39,12 @@ class alt_bn128_pp { const alt_bn128_G2_precomp &prec_Q1, const alt_bn128_G1_precomp &prec_P2, const alt_bn128_G2_precomp &prec_Q2); + static alt_bn128_Fq12 multiple_miller_loop( + const std::initializer_list >& v + ); static alt_bn128_Fq12 pairing(const alt_bn128_G1 &P, const alt_bn128_G2 &Q); static alt_bn128_Fq12 reduced_pairing(const alt_bn128_G1 &P, diff --git a/src/algebra/curves/bn128/bn128_pairing.cpp b/src/algebra/curves/bn128/bn128_pairing.cpp index ac4290ac..ae78e08d 100644 --- a/src/algebra/curves/bn128/bn128_pairing.cpp +++ b/src/algebra/curves/bn128/bn128_pairing.cpp @@ -201,6 +201,26 @@ bn128_Fq12 bn128_double_ate_miller_loop(const bn128_ate_G1_precomp &prec_P1, return f; } + +bn128_Fq12 bn128_ate_multiple_miller_loop( + const std::initializer_list >& v +) +{ + enter_block("Call to bn128_ate_multiple_miller_loop"); + bn128_Fq12 f = bn128_Fq12::one(); + for(auto& p:v) + { + bn128_Fq12 g; + bn::components::millerLoop(g.elem,p.second.coeffs,p.first.P); + f = f * g; + } + leave_block("Call to bn128_ate_multiple_miller_loop"); + return f; + +} bn128_GT bn128_final_exponentiation(const bn128_Fq12 &elt) { enter_block("Call to bn128_final_exponentiation"); diff --git a/src/algebra/curves/bn128/bn128_pairing.hpp b/src/algebra/curves/bn128/bn128_pairing.hpp index f639d0a0..3e22bf22 100644 --- a/src/algebra/curves/bn128/bn128_pairing.hpp +++ b/src/algebra/curves/bn128/bn128_pairing.hpp @@ -46,6 +46,13 @@ bn128_Fq12 bn128_double_ate_miller_loop(const bn128_ate_G1_precomp &prec_P1, bn128_Fq12 bn128_ate_miller_loop(const bn128_ate_G1_precomp &prec_P, const bn128_ate_G2_precomp &prec_Q); +//returns the product of Miller loops of all pairs in the list +bn128_Fq12 bn128_ate_multiple_miller_loop( + const std::initializer_list >& v +); bn128_GT bn128_final_exponentiation(const bn128_Fq12 &elt); } // libsnark diff --git a/src/algebra/curves/bn128/bn128_pp.cpp b/src/algebra/curves/bn128/bn128_pp.cpp index 6557f042..ec8d1480 100644 --- a/src/algebra/curves/bn128/bn128_pp.cpp +++ b/src/algebra/curves/bn128/bn128_pp.cpp @@ -50,6 +50,19 @@ bn128_Fq12 bn128_pp::double_miller_loop(const bn128_ate_G1_precomp &prec_P1, return result; } +//returns the product of Miller loops of all pairs in the list +bn128_Fq12 bn128_pp::multiple_miller_loop( + const std::initializer_list >& v +) +{ + enter_block("Call to multiple_miller_loop"); + bn128_Fq12 result = bn128_ate_multiple_miller_loop(v); + leave_block("Call to multiple_miller_loop"); + return result; +} bn128_Fq12 bn128_pp::pairing(const bn128_G1 &P, const bn128_G2 &Q) { diff --git a/src/algebra/curves/bn128/bn128_pp.hpp b/src/algebra/curves/bn128/bn128_pp.hpp index dfd1c6b4..ddce3b65 100644 --- a/src/algebra/curves/bn128/bn128_pp.hpp +++ b/src/algebra/curves/bn128/bn128_pp.hpp @@ -39,6 +39,13 @@ class bn128_pp { const bn128_ate_G2_precomp &prec_Q1, const bn128_ate_G1_precomp &prec_P2, const bn128_ate_G2_precomp &prec_Q2); + //returns the product of Miller loops of all pairs in the list + static bn128_Fq12 multiple_miller_loop( + const std::initializer_list >& v +); /* the following are used in test files */ static bn128_GT pairing(const bn128_G1 &P, diff --git a/src/algebra/curves/edwards/edwards_pairing.cpp b/src/algebra/curves/edwards/edwards_pairing.cpp index 22fab017..8d7a9ab6 100644 --- a/src/algebra/curves/edwards/edwards_pairing.cpp +++ b/src/algebra/curves/edwards/edwards_pairing.cpp @@ -772,4 +772,71 @@ edwards_GT edwards_reduced_pairing(const edwards_G1 &P, { return edwards_ate_reduced_pairing(P, Q); } + + +/***Ariel Code ** implementing multiple miller loop***/ +//computes the product of miller loops of all pairs in the list v +edwards_Fq6 edwards_ate_multiple_miller_loop( const std::initializer_list >& v +) +{ + enter_block("Call to edwards_multiple_miller_loop"); + const bigint &loop_count = edwards_ate_loop_count; + + edwards_Fq6 f = edwards_Fq6::one(); + bool found_one = false; + size_t idx = 0; + for (long i = loop_count.max_bits()-1; i >= 0; --i) + { + const bool bit = loop_count.test_bit(i); + if (!found_one) + { + /* this skips the MSB itself */ + found_one |= bit; + continue; + } + + /* code below gets executed for all bits (EXCEPT the MSB itself) of + edwards_param_p (skipping leading zeros) in MSB to LSB + order */ + f=f.squared(); + for(auto& p:v){ + auto cc = p.second[idx]; + auto g_RR_at_P = edwards_Fq6(p.first.P_XY * cc.c_XY + p.first.P_XZ * cc.c_XZ, + p.first.P_ZZplusYZ * cc.c_ZZ); + f=f*g_RR_at_P; + + } + ++idx; + + if (bit) + { + for(auto& p:v){ + auto cc = p.second[idx]; + auto g_RQ_at_P = edwards_Fq6(p.first.P_ZZplusYZ * cc.c_ZZ, + p.first.P_XY * cc.c_XY + p.first.P_XZ * cc.c_XZ); + f=f*g_RQ_at_P; + + } + ++idx; + } + } + leave_block("Call to edwards_multiple_miller_loop"); + + return f; +} + +edwards_Fq6 edwards_multiple_miller_loop( const std::initializer_list >& v +) +{ + return edwards_ate_multiple_miller_loop(v); +} + + + } // libsnark diff --git a/src/algebra/curves/edwards/edwards_pairing.hpp b/src/algebra/curves/edwards/edwards_pairing.hpp index f838ae39..fa0d1d23 100644 --- a/src/algebra/curves/edwards/edwards_pairing.hpp +++ b/src/algebra/curves/edwards/edwards_pairing.hpp @@ -118,5 +118,12 @@ edwards_Fq6 edwards_pairing(const edwards_G1& P, edwards_GT edwards_reduced_pairing(const edwards_G1 &P, const edwards_G2 &Q); +/**Ariel additions***/ +edwards_Fq6 edwards_multiple_miller_loop(const std::initializer_list >& v +); + } // libsnark #endif // EDWARDS_PAIRING_HPP_ diff --git a/src/algebra/curves/edwards/edwards_pp.cpp b/src/algebra/curves/edwards/edwards_pp.cpp index 5af40104..7845299e 100644 --- a/src/algebra/curves/edwards/edwards_pp.cpp +++ b/src/algebra/curves/edwards/edwards_pp.cpp @@ -42,6 +42,15 @@ edwards_Fq6 edwards_pp::double_miller_loop(const edwards_G1_precomp &prec_P1, { return edwards_double_miller_loop(prec_P1, prec_Q1, prec_P2, prec_Q2); } +edwards_Fq6 edwards_pp::multiple_miller_loop( + const std::initializer_list >& v +) +{ + return edwards_multiple_miller_loop(v); +} edwards_Fq6 edwards_pp::pairing(const edwards_G1 &P, const edwards_G2 &Q) diff --git a/src/algebra/curves/edwards/edwards_pp.hpp b/src/algebra/curves/edwards/edwards_pp.hpp index 32ca85dd..4803a123 100644 --- a/src/algebra/curves/edwards/edwards_pp.hpp +++ b/src/algebra/curves/edwards/edwards_pp.hpp @@ -39,6 +39,12 @@ class edwards_pp { const edwards_G2_precomp &prec_Q1, const edwards_G1_precomp &prec_P2, const edwards_G2_precomp &prec_Q2); + static edwards_Fq6 multiple_miller_loop( + const std::initializer_list >& v + ); /* the following are used in test files */ static edwards_Fq6 pairing(const edwards_G1 &P, const edwards_G2 &Q); diff --git a/src/algebra/curves/mnt/mnt4/mnt4_pairing.cpp b/src/algebra/curves/mnt/mnt4/mnt4_pairing.cpp index 6334283a..abaa0e3f 100644 --- a/src/algebra/curves/mnt/mnt4/mnt4_pairing.cpp +++ b/src/algebra/curves/mnt/mnt4/mnt4_pairing.cpp @@ -738,5 +738,89 @@ mnt4_GT mnt4_affine_reduced_pairing(const mnt4_G1 &P, const mnt4_GT result = mnt4_final_exponentiation(f); return result; } +//Ariel additions +mnt4_Fq4 mnt4_ate_multiple_miller_loop(const std::initializer_list >& v +) +{ + enter_block("Call to mnt4_ate_multiple_miller_loop"); + + + mnt4_Fq4 f = mnt4_Fq4::one(); + + bool found_one = false; + size_t dbl_idx = 0; + size_t add_idx = 0; + + const bigint &loop_count = mnt4_ate_loop_count; + for (long i = loop_count.max_bits() - 1; i >= 0; --i) + { + const bool bit = loop_count.test_bit(i); + + if (!found_one) + { + /* this skips the MSB itself */ + found_one |= bit; + continue; + } + + /* code below gets executed for all bits (EXCEPT the MSB itself) of + mnt4_param_p (skipping leading zeros) in MSB to LSB + order */ + + f=f.squared(); + for(auto& p:v) + { + mnt4_ate_dbl_coeffs dc = p.second.dbl_coeffs[dbl_idx]; + mnt4_Fq4 g_RR_at_P = mnt4_Fq4(- dc.c_4C - dc.c_J * p.first.PX_twist + dc.c_L, + dc.c_H * p.first.PY_twist); + f=f*g_RR_at_P; + + } + ++dbl_idx; + + if (bit) + { + for(auto& p:v) + { + auto L1_coeff = mnt4_Fq2(p.first.PX, mnt4_Fq::zero()) - p.second.QX_over_twist; + auto ac = p.second.add_coeffs[add_idx]; + mnt4_Fq4 g_RQ_at_P = mnt4_Fq4(ac.c_RZ * p.first.PY_twist, + -(p.second.QY_over_twist * ac.c_RZ + L1_coeff * ac.c_L1)); + f =f* g_RQ_at_P; + + } + ++add_idx; + } + + } + if (mnt4_ate_is_loop_count_neg) + { + for(auto& p:v) + { + auto L1_coeff = mnt4_Fq2(p.first.PX, mnt4_Fq::zero()) - p.second.QX_over_twist; + auto ac = p.second.add_coeffs[add_idx]; + mnt4_Fq4 g_RnegR_at_P = mnt4_Fq4(ac.c_RZ * p.first.PY_twist, + -(p.second.QY_over_twist * ac.c_RZ + L1_coeff * ac.c_L1)); + f =f* g_RnegR_at_P; + + } + f=f.inverse(); + ++add_idx; + } + leave_block("Call to mnt4_ate_multiple_miller_loop"); + return f; + +} +mnt4_Fq4 mnt4_multiple_miller_loop(const std::initializer_list >& v +) +{ + return mnt4_ate_multiple_miller_loop(v); +} } // libsnark diff --git a/src/algebra/curves/mnt/mnt4/mnt4_pairing.hpp b/src/algebra/curves/mnt/mnt4/mnt4_pairing.hpp index 00471151..a41f7e09 100644 --- a/src/algebra/curves/mnt/mnt4/mnt4_pairing.hpp +++ b/src/algebra/curves/mnt/mnt4/mnt4_pairing.hpp @@ -143,6 +143,18 @@ mnt4_GT mnt4_reduced_pairing(const mnt4_G1 &P, mnt4_GT mnt4_affine_reduced_pairing(const mnt4_G1 &P, const mnt4_G2 &Q); +//Ariel additions +mnt4_Fq4 mnt4_multiple_miller_loop(const std::initializer_list >& v +); +mnt4_Fq4 mnt4_ate_multiple_miller_loop(const std::initializer_list >& v +); + } // libsnark #endif // MNT4_PAIRING_HPP_ diff --git a/src/algebra/curves/mnt/mnt4/mnt4_pp.cpp b/src/algebra/curves/mnt/mnt4/mnt4_pp.cpp index 17eccab0..d1b727bd 100644 --- a/src/algebra/curves/mnt/mnt4/mnt4_pp.cpp +++ b/src/algebra/curves/mnt/mnt4/mnt4_pp.cpp @@ -83,7 +83,14 @@ mnt4_Fq4 mnt4_pp::double_miller_loop(const mnt4_G1_precomp &prec_P1, { return mnt4_double_miller_loop(prec_P1, prec_Q1, prec_P2, prec_Q2); } - +mnt4_Fq4 mnt4_pp::multiple_miller_loop(const std::initializer_list >& v +) +{ + return mnt4_multiple_miller_loop(v); +} mnt4_Fq4 mnt4_pp::pairing(const mnt4_G1 &P, const mnt4_G2 &Q) { diff --git a/src/algebra/curves/mnt/mnt4/mnt4_pp.hpp b/src/algebra/curves/mnt/mnt4/mnt4_pp.hpp index f93fc313..51bdf623 100644 --- a/src/algebra/curves/mnt/mnt4/mnt4_pp.hpp +++ b/src/algebra/curves/mnt/mnt4/mnt4_pp.hpp @@ -65,6 +65,11 @@ class mnt4_pp { const mnt4_G2_precomp &prec_Q1, const mnt4_G1_precomp &prec_P2, const mnt4_G2_precomp &prec_Q2); + static mnt4_Fq4 multiple_miller_loop(const std::initializer_list >& v +); /* the following are used in test files */ static mnt4_Fq4 pairing(const mnt4_G1 &P, diff --git a/src/algebra/curves/mnt/mnt6/mnt6_pairing.cpp b/src/algebra/curves/mnt/mnt6/mnt6_pairing.cpp index 41fc2f5d..64aecf81 100644 --- a/src/algebra/curves/mnt/mnt6/mnt6_pairing.cpp +++ b/src/algebra/curves/mnt/mnt6/mnt6_pairing.cpp @@ -749,5 +749,92 @@ mnt6_GT mnt6_affine_reduced_pairing(const mnt6_G1 &P, const mnt6_GT result = mnt6_final_exponentiation(f); return result; } +//Ariel additions +mnt6_Fq6 mnt6_ate_multiple_miller_loop(const std::initializer_list >& v +) +{ + enter_block("Call to mnt6_ate_multiple_miller_loop"); + + + mnt6_Fq6 f = mnt6_Fq6::one(); + + bool found_one = false; + size_t dbl_idx = 0; + size_t add_idx = 0; + + const bigint &loop_count = mnt6_ate_loop_count; + for (long i = loop_count.max_bits() - 1; i >= 0; --i) + { + const bool bit = loop_count.test_bit(i); + + if (!found_one) + { + /* this skips the MSB itself */ + found_one |= bit; + continue; + } + + /* code below gets executed for all bits (EXCEPT the MSB itself) of + mnt6_param_p (skipping leading zeros) in MSB to LSB + order */ + + f=f.squared(); + for(auto& p:v) + { + mnt6_ate_dbl_coeffs dc = p.second.dbl_coeffs[dbl_idx]; + mnt6_Fq6 g_RR_at_P = mnt6_Fq6(- dc.c_4C - dc.c_J * p.first.PX_twist + dc.c_L, + dc.c_H * p.first.PY_twist); + f=f*g_RR_at_P; + + } + ++dbl_idx; + + if (bit) + { + for(auto& p:v) + { + //mnt6_Fq3 L1_coeff1 = mnt6_Fq3(prec_P1.PX, mnt6_Fq::zero(), mnt6_Fq::zero()) - prec_Q1.QX_over_twist; + + mnt6_Fq3 L1_coeff = mnt6_Fq3(p.first.PX, mnt6_Fq::zero(),mnt6_Fq::zero()) - p.second.QX_over_twist; + auto ac = p.second.add_coeffs[add_idx]; + mnt6_Fq6 g_RQ_at_P = mnt6_Fq6(ac.c_RZ * p.first.PY_twist, + -(p.second.QY_over_twist * ac.c_RZ + L1_coeff * ac.c_L1)); + f =f* g_RQ_at_P; + + } + ++add_idx; + } + + } + + if (mnt6_ate_is_loop_count_neg) + { + for(auto& p:v) + { + auto L1_coeff = mnt6_Fq3(p.first.PX, mnt6_Fq::zero(),mnt6_Fq::zero()) - p.second.QX_over_twist; + auto ac = p.second.add_coeffs[add_idx]; + mnt6_Fq6 g_RnegR_at_P = mnt6_Fq6(ac.c_RZ * p.first.PY_twist, + -(p.second.QY_over_twist * ac.c_RZ + L1_coeff * ac.c_L1)); + f =f* g_RnegR_at_P; + + } + f=f.inverse(); + ++add_idx; + } + leave_block("Call to mnt6_ate_multiple_miller_loop"); + return f; + +} +mnt6_Fq6 mnt6_multiple_miller_loop(const std::initializer_list >& v +) +{ + return mnt6_ate_multiple_miller_loop(v); +} } // libsnark diff --git a/src/algebra/curves/mnt/mnt6/mnt6_pairing.hpp b/src/algebra/curves/mnt/mnt6/mnt6_pairing.hpp index f5c21177..7491cfa1 100644 --- a/src/algebra/curves/mnt/mnt6/mnt6_pairing.hpp +++ b/src/algebra/curves/mnt/mnt6/mnt6_pairing.hpp @@ -143,6 +143,19 @@ mnt6_GT mnt6_reduced_pairing(const mnt6_G1 &P, mnt6_GT mnt6_affine_reduced_pairing(const mnt6_G1 &P, const mnt6_G2 &Q); +//Ariel additions +mnt6_Fq6 mnt6_multiple_miller_loop(const std::initializer_list >& v +); +mnt6_Fq6 mnt6_ate_multiple_miller_loop(const std::initializer_list >& v +); + + } // libsnark #endif // MNT6_PAIRING_HPP_ diff --git a/src/algebra/curves/mnt/mnt6/mnt6_pp.cpp b/src/algebra/curves/mnt/mnt6/mnt6_pp.cpp index 9983d503..648eaf92 100644 --- a/src/algebra/curves/mnt/mnt6/mnt6_pp.cpp +++ b/src/algebra/curves/mnt/mnt6/mnt6_pp.cpp @@ -66,6 +66,14 @@ mnt6_Fq6 mnt6_pp::double_miller_loop(const mnt6_G1_precomp &prec_P1, return mnt6_double_miller_loop(prec_P1, prec_Q1, prec_P2, prec_Q2); } +mnt6_Fq6 mnt6_pp::multiple_miller_loop(const std::initializer_list >& v +) +{ + return mnt6_multiple_miller_loop(v); +} mnt6_Fq6 mnt6_pp::affine_ate_e_over_e_miller_loop(const mnt6_affine_ate_G1_precomputation &prec_P1, const mnt6_affine_ate_G2_precomputation &prec_Q1, const mnt6_affine_ate_G1_precomputation &prec_P2, diff --git a/src/algebra/curves/mnt/mnt6/mnt6_pp.hpp b/src/algebra/curves/mnt/mnt6/mnt6_pp.hpp index bbe05a4e..e674937a 100644 --- a/src/algebra/curves/mnt/mnt6/mnt6_pp.hpp +++ b/src/algebra/curves/mnt/mnt6/mnt6_pp.hpp @@ -61,6 +61,12 @@ class mnt6_pp { const mnt6_G1_precomp &prec_P2, const mnt6_G2_precomp &prec_Q2); + static mnt6_Fq6 multiple_miller_loop(const std::initializer_list >& v +); + /* the following are used in test files */ static mnt6_Fq6 pairing(const mnt6_G1 &P, const mnt6_G2 &Q); diff --git a/src/algebra/curves/tests/test_bilinearity.cpp b/src/algebra/curves/tests/test_bilinearity.cpp index 29574528..b98e4950 100644 --- a/src/algebra/curves/tests/test_bilinearity.cpp +++ b/src/algebra/curves/tests/test_bilinearity.cpp @@ -73,6 +73,57 @@ void double_miller_loop_test() assert(ans_1 * ans_2 == ans_12); } +//checking multiple_miller_loop really computes the product of corresponding miller loops +template +void multiple_miller_loop_test() +{ + const G1 P1 = (Fr::random_element()) * G1::one(); + const G1 P2 = (Fr::random_element()) * G1::one(); + const G1 P3 = (Fr::random_element()) * G1::one(); + const G1 P4 = (Fr::random_element()) * G1::one(); + const G1 P5 = (Fr::random_element()) * G1::one(); + + const G2 Q1 = (Fr::random_element()) * G2::one(); + const G2 Q2 = (Fr::random_element()) * G2::one(); + const G2 Q3 = (Fr::random_element()) * G2::one(); + const G2 Q4 = (Fr::random_element()) * G2::one(); + const G2 Q5 = (Fr::random_element()) * G2::one(); + + + const G1_precomp prec_P1 = ppT::precompute_G1(P1); + const G1_precomp prec_P2 = ppT::precompute_G1(P2); + const G1_precomp prec_P3 = ppT::precompute_G1(P3); + const G1_precomp prec_P4 = ppT::precompute_G1(P4); + const G1_precomp prec_P5 = ppT::precompute_G1(P5); + const G2_precomp prec_Q1 = ppT::precompute_G2(Q1); + const G2_precomp prec_Q2 = ppT::precompute_G2(Q2); + const G2_precomp prec_Q3 = ppT::precompute_G2(Q3); + const G2_precomp prec_Q4 = ppT::precompute_G2(Q4); + const G2_precomp prec_Q5 = ppT::precompute_G2(Q5); + const Fqk ans_1 = ppT::miller_loop(prec_P1, prec_Q1); + const Fqk ans_2 = ppT::miller_loop(prec_P2, prec_Q2); + const Fqk ans_3 = ppT::miller_loop(prec_P3, prec_Q3); + const Fqk ans_4 = ppT::miller_loop(prec_P4, prec_Q4); + const Fqk ans_5 = ppT::miller_loop(prec_P5, prec_Q5); + const Fqk ans_1234 = ppT::multiple_miller_loop({ + std::make_pair(prec_P1, prec_Q1), + std::make_pair(prec_P2, prec_Q2), + std::make_pair(prec_P3, prec_Q3), + std::make_pair(prec_P4, prec_Q4), + }); + const Fqk ans_12345 = ppT::multiple_miller_loop({ + std::make_pair(prec_P1, prec_Q1), + std::make_pair(prec_P2, prec_Q2), + std::make_pair(prec_P3, prec_Q3), + std::make_pair(prec_P4, prec_Q4), + std::make_pair(prec_P5, prec_Q5) + }); + assert(ans_1 * ans_2 * ans_3 * ans_4 * ans_5 == ans_12345); + assert(ans_1 * ans_2 * ans_3 * ans_4 == ans_1234); + + assert(!(ans_1*ans_3*ans_4==ans_12345)); +} + template void affine_pairing_test() { @@ -113,24 +164,28 @@ int main(void) edwards_pp::init_public_params(); pairing_test(); double_miller_loop_test(); - + multiple_miller_loop_test(); mnt6_pp::init_public_params(); pairing_test(); double_miller_loop_test(); affine_pairing_test(); - + multiple_miller_loop_test(); + mnt4_pp::init_public_params(); pairing_test(); double_miller_loop_test(); affine_pairing_test(); - + multiple_miller_loop_test(); + alt_bn128_pp::init_public_params(); pairing_test(); double_miller_loop_test(); - + multiple_miller_loop_test(); +#define CURVE_BN128 #ifdef CURVE_BN128 // BN128 has fancy dependencies so it may be disabled bn128_pp::init_public_params(); pairing_test(); double_miller_loop_test(); + multiple_miller_loop_test(); #endif } diff --git a/src/zk_proof_systems/batchverification.pdf b/src/zk_proof_systems/batchverification.pdf new file mode 100644 index 00000000..5aa6c346 Binary files /dev/null and b/src/zk_proof_systems/batchverification.pdf differ diff --git a/src/zk_proof_systems/ppzksnark/r1cs_ppzksnark/examples/run_r1cs_ppzksnark.tcc b/src/zk_proof_systems/ppzksnark/r1cs_ppzksnark/examples/run_r1cs_ppzksnark.tcc index 9bc87586..6cee048f 100644 --- a/src/zk_proof_systems/ppzksnark/r1cs_ppzksnark/examples/run_r1cs_ppzksnark.tcc +++ b/src/zk_proof_systems/ppzksnark/r1cs_ppzksnark/examples/run_r1cs_ppzksnark.tcc @@ -109,6 +109,47 @@ bool run_r1cs_ppzksnark(const r1cs_example > &example, return ans; } + + +///***Ariel version for testing batch verifier****// + + +/** + * The code below provides an example of all stages of running a R1CS ppzkSNARK. + * + * Of course, in a real-life scenario, we would have three distinct entities, + * mangled into one in the demonstration below. The three entities are as follows. + * (1) The "generator", which runs the ppzkSNARK generator on input a given + * constraint system CS to create a proving and a verification key for CS. + * (2) The "prover", which runs the ppzkSNARK prover on input the proving key, + * a primary input for CS, and an auxiliary input for CS. + * (3) The "verifier", which runs the ppzkSNARK verifier on input the verification key, + * a primary input for CS, and a proof. + */ +template +void add_proof_in_batch_verifier_test(batch_verification_accumulator &acc, + const r1cs_ppzksnark_proof &proof, + const r1cs_ppzksnark_verification_key &vk, + const r1cs_primary_input > &primary_input) +{ + enter_block("Call to add_proof_in_batch_verifier_test"); + + //r1cs_ppzksnark_keypair keypair = r1cs_ppzksnark_generator(example.constraint_system); + + + + print_header("R1CS ppzkSNARK Prover"); + //r1cs_ppzksnark_proof proof = r1cs_ppzksnark_prover(keypair.pk, example.primary_input, example.auxiliary_input); + + r1cs_ppzksnark_batcher(vk, acc, primary_input, proof); + + + leave_block("Call to add_proof_in_batch_verifier_test"); + + +} + + } // libsnark #endif // RUN_R1CS_PPZKSNARK_TCC_ diff --git a/src/zk_proof_systems/ppzksnark/r1cs_ppzksnark/r1cs_ppzksnark.hpp b/src/zk_proof_systems/ppzksnark/r1cs_ppzksnark/r1cs_ppzksnark.hpp index bbccf563..2760895b 100644 --- a/src/zk_proof_systems/ppzksnark/r1cs_ppzksnark/r1cs_ppzksnark.hpp +++ b/src/zk_proof_systems/ppzksnark/r1cs_ppzksnark/r1cs_ppzksnark.hpp @@ -462,6 +462,95 @@ bool r1cs_ppzksnark_affine_verifier_weak_IC(const r1cs_ppzksnark_verification_ke const r1cs_ppzksnark_primary_input &primary_input, const r1cs_ppzksnark_proof &proof); +/****Batch and probabilistic verification + * using randomness and the bilinearity of the pairing operation, the Pinocchio verifier can be made more efficient + * with the price of making the verification procedure probabilisitc, introducing a negligible chance of accepting a bad proofs + * in a similar way verifying a batch of proofs can be bundled into verifying a single pairing equation using randomness + * such that the verifier always accepts if all proofs in the batch are valid, and the verifier accepts with a negligible + * probability when one of the proofs in the batch is invalid. + * The methods below implemement these verifiers, + * and the logic behind them are described in https://github.com/arielgabizon/libsnark/blob/multimiller/src/zk_proof_systems/batchverification.pdf + * + */ +/** + * The purpose of this class is to enable one time precomputation of elements that are + * functions of the verification key + * and are used in each invocation of r1cs_ppzksnark_probabilistic_verifier + * and also r1cs_ppzksnark_batcher + * these elements are the G2 arguments of the pairings in + * https://github.com/arielgabizon/libsnark/blob/multimiller/src/zk_proof_systems/batchverification.pdf + */ + +//Better explanation of names, have this inherit from processed_verification_key +template +class r1cs_ppzksnark_processed_batch_verification_key : public r1cs_ppzksnark_processed_verification_key { +public: + //here pair_i is actually the G2 argument in the i'th pairing of the batch verifier equation + G2_precomp pair1; + G2_precomp pair2; + G2_precomp pair3; + G2_precomp pair4; + G2_precomp pair5; + G2_precomp pair6; + + // accumulation_vector > encoded_IC_query; + + // bool operator==(const r1cs_ppzksnark_processed_verification_key &other) const; + // friend std::ostream& operator<< (std::ostream &out, const r1cs_ppzksnark_processed_verification_key &pvk); + // friend std::istream& operator>> (std::istream &in, r1cs_ppzksnark_processed_verification_key &pvk); +}; + +//a data structure to store intermediate G1 argument results from various proofs before the final batch verification +// (except for the seventh member where we store the result of a product of Miller Loops. See Section 2 of https://github.com/arielgabizon/libsnark/blob/multimiller/src/zk_proof_systems/batchverification.pdf. +template +class batch_verification_accumulator{ +public: + //here pair_i is actually the G1 argument in the i'th pairing of the batch verifier equation + G1 pair1; + G1 pair2; + G1 pair3; + G1 pair4; + G1 pair5; + G1 pair6; + //as explained in the document, the 7th pairing contains elements of the proof in both arguments, so we need to store + //a product of Miller Loops rather than just the first argument + Fqk pair7; + +batch_verification_accumulator():pair1(G1::zero()),pair2(G1::zero()),pair3(G1::zero()),pair4(G1::zero()), +pair5(G1::zero()),pair6(G1::zero()),pair7(Fqk::one()) +{ + +}; +}; + + + + + +/* + * accumulate another proof inside acc for the final batch check + */ +template +void r1cs_ppzksnark_batcher(const r1cs_ppzksnark_verification_key &vk, + batch_verification_accumulator &acc, + const r1cs_ppzksnark_primary_input &primary_input, + const r1cs_ppzksnark_proof &proof); + +template +bool r1cs_ppzksnark_probabilistic_verifier(const r1cs_ppzksnark_verification_key &vk, + const r1cs_ppzksnark_primary_input &primary_input, + const r1cs_ppzksnark_proof &proof); +template +bool r1cs_ppzksnark_batch_verifier(const r1cs_ppzksnark_processed_batch_verification_key &pvk, + const batch_verification_accumulator &acc, + const r1cs_ppzksnark_primary_input &primary_input, + const r1cs_ppzksnark_proof &proof); +template +r1cs_ppzksnark_processed_batch_verification_key r1cs_ppzksnark_batch_verifier_process_vk( + const r1cs_ppzksnark_verification_key &vk, + const r1cs_ppzksnark_primary_input &primary_input, + const r1cs_ppzksnark_proof &proof); + } // libsnark diff --git a/src/zk_proof_systems/ppzksnark/r1cs_ppzksnark/r1cs_ppzksnark.tcc b/src/zk_proof_systems/ppzksnark/r1cs_ppzksnark/r1cs_ppzksnark.tcc index 88145da6..8ea80acc 100644 --- a/src/zk_proof_systems/ppzksnark/r1cs_ppzksnark/r1cs_ppzksnark.tcc +++ b/src/zk_proof_systems/ppzksnark/r1cs_ppzksnark/r1cs_ppzksnark.tcc @@ -25,7 +25,7 @@ See r1cs_ppzksnark.hpp . #include "algebra/scalar_multiplication/multiexp.hpp" #include "algebra/scalar_multiplication/kc_multiexp.hpp" #include "reductions/r1cs_to_qap/r1cs_to_qap.hpp" - +#include "algebra/curves/alt_bn128/alt_bn128_pp.hpp" namespace libsnark { template @@ -34,7 +34,7 @@ bool r1cs_ppzksnark_proving_key::operator==(const r1cs_ppzksnark_proving_ke return (this->A_query == other.A_query && this->B_query == other.B_query && this->C_query == other.C_query && - this->H_query == other.H_query && + this->H_query == other.H_query && this->K_query == other.K_query && this->constraint_system == other.constraint_system); } @@ -692,8 +692,9 @@ bool r1cs_ppzksnark_verifier_strong_IC(const r1cs_ppzksnark_verification_key &proof) { enter_block("Call to r1cs_ppzksnark_verifier_strong_IC"); - r1cs_ppzksnark_processed_verification_key pvk = r1cs_ppzksnark_verifier_process_vk(vk); - bool result = r1cs_ppzksnark_online_verifier_strong_IC(pvk, primary_input, proof); + //r1cs_ppzksnark_processed_verification_key pvk = r1cs_ppzksnark_verifier_process_vk(vk); + //bool result = r1cs_ppzksnark_online_verifier_strong_IC(pvk, primary_input, proof); + bool result = r1cs_ppzksnark_probabilistic_verifier(vk,primary_input,proof); leave_block("Call to r1cs_ppzksnark_verifier_strong_IC"); return result; } @@ -788,5 +789,241 @@ bool r1cs_ppzksnark_affine_verifier_weak_IC(const r1cs_ppzksnark_verification_ke return result; } + + + + +/*****Ariel stuff from here ****/ + +template +r1cs_ppzksnark_processed_batch_verification_key r1cs_ppzksnark_batch_verifier_process_vk(const r1cs_ppzksnark_verification_key &vk) +{ + enter_block("Call to r1cs_ppzksnark_batch_verifier_process_vk"); + r1cs_ppzksnark_processed_batch_verification_key pvk; + pvk.pair1 = ppT::precompute_G2(vk.alphaA_g2); + + //computing the second input for the second ML factor + // r1Pi'_a + R2Pi'_B+r3Pi'_C + r5Pi_C and -g2 + pvk.pair2 = alt_bn128_pp::precompute_G2(-G2::one()); + //computing the second input for the third ML factor + // r3Pi_c and vk_C + pvk.pair3 = alt_bn128_pp::precompute_G2(vk.alphaC_g2) ; + + //computing the second input for the fourth ML factor + // r4Pi_K and vk_gamma + pvk.pair4 = alt_bn128_pp::precompute_G2(vk.gamma_g2); + + //computing the second input for the fifth ML factor + //−r 4(vk x + πA + πC) and vk^2_betagamma + pvk.pair5 = alt_bn128_pp::precompute_G2(vk.gamma_beta_g2); + + //computing the second input for the six ML factor + //r5Pi_H and -vk_Z + pvk.pair6 = alt_bn128_pp::precompute_G2(-vk.rC_Z_g2); + + leave_block("Call to r1cs_ppzksnark_batch_verifier_process_vk"); + return pvk; +} + + + + +/* + * accumulate another proof inside acc for the final batch check + */ +template +void r1cs_ppzksnark_batcher(const r1cs_ppzksnark_verification_key &vk, + batch_verification_accumulator &acc, + const r1cs_ppzksnark_primary_input &primary_input, + const r1cs_ppzksnark_proof &proof) +{ + enter_block("Call to r1cs_ppzksnark_batcher"); + const accumulation_vector > accumulated_IC = vk.encoded_IC_query.template accumulate_chunk >(primary_input.begin(), primary_input.end(), 0); + const G1 &accu = accumulated_IC.first; + //computing the random coefficients that will be used + auto r_1 = Fr::random_element(); + auto r_2 = Fr::random_element(); + auto r_3 = Fr::random_element(); + auto r_4 = Fr::random_element(); + auto r_5 = Fr::random_element(); + + + //computing left input for the first ML factor + // r1Pi_a and vk_A + acc.pair1 = acc.pair1 + r_1*proof.g_A.g; + + //computing left input for the second ML factor + // r1Pi'_a + R2Pi'_B+r3Pi'_C + r5Pi_C and -g2 + acc.pair2 = acc.pair2 + r_1*proof.g_A.h+r_2*proof.g_B.h + r_3*proof.g_C.h + r_5*proof.g_C.g; + //computing left input for the third ML factor + // r3Pi_c and vk_C + acc.pair3 = acc.pair3 + r_3*proof.g_C.g; + + //computing left input for the fourth ML factor + // r4Pi_K and vk_gamma + acc.pair4 = acc.pair4 + r_4*proof.g_K; + //computing left input for the fifth ML factor + //−r 4(vk x + πA + πC) and vk^2_betagamma + acc.pair5 = acc.pair5 + -r_4*(accu + proof.g_A.g + proof.g_C.g); + + //computing left input for the six ML factor + //r5Pi_H and -vk_Z + acc.pair6 = acc.pair6 + r_5*proof.g_H; + + //computing left input for the seventh ML factor + //r_2 vk_B-r_4 vk^1_{\beta\gamma}+r_5(vk_x + \pi_A) and pi_B + auto left_7 = ppT::precompute_G1(r_2*vk.alphaB_g1-r_4*vk.gamma_beta_g1+r_5*(accu+proof.g_A.g)); + auto right_7 = ppT::precompute_G2(proof.g_B.g); + acc.pair7 = acc.pair7*ppT::miller_loop(left_7,right_7); + + leave_block("Call to r1cs_ppzksnark_batcher"); +} + + + + +/*A verifier that batches all pairing checks into zero using random coefficients + requires only zero FE (final expzerontiation). + Also requires only zero call to multiple_miller_loop, as only needs to compute zero product of + Miller loops (MLs). + Also uses rule e(a,c)*e(b,c)=e(a+b,c) to reduce number of factors in the ML product + If proof is wrong has at most 1/|F| probability of accepting it + Always accepts correct proofs +*/ +template<> +bool r1cs_ppzksnark_probabilistic_verifier(const r1cs_ppzksnark_verification_key &vk, + const r1cs_ppzksnark_primary_input &primary_input, + const r1cs_ppzksnark_proof &proof) +{ + enter_block("Call to r1cs_ppzksnark_probabilistic_verifier"); + const accumulation_vector > accumulated_IC = vk.encoded_IC_query.template accumulate_chunk >(primary_input.begin(), primary_input.end(), 0); + const G1 &acc = accumulated_IC.first; + //computing the random coefficients that will be used + auto r_1 = Fr::random_element(); + auto r_2 = Fr::random_element(); + auto r_3 = Fr::random_element(); + auto r_4 = Fr::random_element(); + auto r_5 = Fr::random_element(); + + enter_block("Preparing 7 ML factors"); + + //computing left input for the first ML factor + // r1Pi_a and vk_A + auto left_1 = alt_bn128_pp::precompute_G1(r_1*proof.g_A.g); + auto right_1 = alt_bn128_pp::precompute_G2(vk.alphaA_g2); + auto pair_1 = std::make_pair(left_1,right_1); + + //computing left input for the second ML factor + // r1Pi'_a + R2Pi'_B+r3Pi'_C + r5Pi_C and -g2 + auto left_2 = alt_bn128_pp::precompute_G1(r_1*proof.g_A.h+r_2*proof.g_B.h + r_3*proof.g_C.h + r_5*proof.g_C.g); + auto right_2 = alt_bn128_pp::precompute_G2(-G2::one()); + auto pair_2 = std::make_pair(left_2,right_2); + //computing left input for the third ML factor + // r3Pi_c and vk_C + auto left_3 = alt_bn128_pp::precompute_G1(r_3*proof.g_C.g); + auto right_3 = alt_bn128_pp::precompute_G2(vk.alphaC_g2) ; + auto pair_3 = std::make_pair(left_3,right_3); + + //computing left input for the fourth ML factor + // r4Pi_K and vk_gamma + auto left_4 = alt_bn128_pp::precompute_G1(r_4*proof.g_K); + auto right_4 = alt_bn128_pp::precompute_G2(vk.gamma_g2); + auto pair_4 = std::make_pair(left_4,right_4); + + //computing left input for the fifth ML factor + //−r 4(vk x + πA + πC) and vk^2_betagamma + auto left_5 = alt_bn128_pp::precompute_G1(-r_4*(acc + proof.g_A.g + proof.g_C.g)); + auto right_5 = alt_bn128_pp::precompute_G2(vk.gamma_beta_g2); + auto pair_5 = std::make_pair(left_5,right_5); + + //computing left input for the six ML factor + //r5Pi_H and -vk_Z + auto left_6 = alt_bn128_pp::precompute_G1(r_5*proof.g_H); + auto right_6 = alt_bn128_pp::precompute_G2(-vk.rC_Z_g2); + auto pair_6 = std::make_pair(left_6,right_6); + + //computing left input for the seventh ML factor + //r_2 vk_B-r_4 vk^1_{\beta\gamma}+r_5(vk_x + \pi_A) and pi_B + auto left_7 = alt_bn128_pp::precompute_G1(r_2*vk.alphaB_g1-r_4*vk.gamma_beta_g1+r_5*(acc+proof.g_A.g)); + auto right_7 = alt_bn128_pp::precompute_G2(proof.g_B.g); + auto pair_7 = std::make_pair(left_7,right_7); + leave_block("Preparing 7 ML factors"); + + /* auto ML1 = alt_bn128_pp::double_miller_loop(left_1,right_1,left_2,right_2); + auto ML2 = alt_bn128_pp::double_miller_loop(left_3,right_3,left_4,right_4); + auto ML3 = alt_bn128_pp::double_miller_loop(left_5,right_5,left_6,right_6); + auto ML4 = alt_bn128_pp::miller_loop(left_7,right_7);*/ + alt_bn128_Fq12 ML = alt_bn128_pp::multiple_miller_loop({ + pair_1,pair_2,pair_3,pair_4,pair_5,pair_6,pair_7 + }); + auto FE= alt_bn128_pp::final_exponentiation(ML); + leave_block("Call to r1cs_ppzksnark_probabilistic_verifier"); + return (FE==GT::one()); +} + +template +bool r1cs_ppzksnark_probabilistic_verifier(const r1cs_ppzksnark_verification_key &vk, + const r1cs_ppzksnark_primary_input &primary_input, + const r1cs_ppzksnark_proof &proof) +{ + r1cs_ppzksnark_processed_verification_key pvk = r1cs_ppzksnark_verifier_process_vk(vk); + bool result = r1cs_ppzksnark_online_verifier_strong_IC(pvk, primary_input, proof); + return result; +} + +template<> +bool r1cs_ppzksnark_batch_verifier(const r1cs_ppzksnark_processed_batch_verification_key &pvk, + const batch_verification_accumulator &acc, + const r1cs_ppzksnark_primary_input &primary_input, + const r1cs_ppzksnark_proof &proof) +{ + enter_block("Call to r1cs_ppzksnark_batch_verifier"); + + enter_block("Preparing 7 ML factors"); + + //computing left input for the first ML factor + // r3Pi_a and vk_A + auto pair_1 = std::make_pair(alt_bn128_pp::precompute_G1(acc.pair1),pvk.pair1); + + //computing left input for the second ML factor + // r3Pi'_a + R2Pi'_B+r3Pi'_C + r5Pi_C and -g2 + auto pair_2 = std::make_pair(alt_bn128_pp::precompute_G1(acc.pair2),pvk.pair2); + //computing left input for the third ML factor + // r3Pi_c and vk_C + auto pair_3 = std::make_pair(alt_bn128_pp::precompute_G1(acc.pair3),pvk.pair3); + + //computing left input for the fourth ML factor + // r4Pi_K and vk_gamma + auto pair_4 = std::make_pair(alt_bn128_pp::precompute_G1(acc.pair4),pvk.pair4); + + //computing left input for the fifth ML factor + //−r 4(vk x + πA + πC) and vk^2_betagamma + auto pair_5 = std::make_pair(alt_bn128_pp::precompute_G1(acc.pair5),pvk.pair5); + + //computing left input for the six ML factor + //r5Pi_H and -vk_Z + auto pair_6 = std::make_pair(alt_bn128_pp::precompute_G1(acc.pair6),pvk.pair6); + + //computing left input for the seventh ML factor + //r_2 vk_B-r_4 vk^3_{\beta\gamma}+r_5(vk_x + \pi_A) and pi_B + leave_block("Preparing 7 ML factors"); + + alt_bn128_Fq12 ML = alt_bn128_pp::multiple_miller_loop({ + pair_1,pair_2,pair_3,pair_4,pair_5,pair_6 + })*acc.pair7; + auto FE= alt_bn128_pp::final_exponentiation(ML); + leave_block("Call to r1cs_ppzksnark_batch_verifier"); + return (FE==GT::one()); +} + +template +bool r1cs_ppzksnark_batch_verifier(const r1cs_ppzksnark_processed_batch_verification_key &pvk, + const batch_verification_accumulator &acc, + const r1cs_ppzksnark_primary_input &primary_input, + const r1cs_ppzksnark_proof &proof) +{ + assert(false); + return false; +} } // libsnark #endif // R1CS_PPZKSNARK_TCC_ diff --git a/src/zk_proof_systems/ppzksnark/r1cs_ppzksnark/tests/test_r1cs_ppzksnark.cpp b/src/zk_proof_systems/ppzksnark/r1cs_ppzksnark/tests/test_r1cs_ppzksnark.cpp index 6f8b575f..fe5bf292 100644 --- a/src/zk_proof_systems/ppzksnark/r1cs_ppzksnark/tests/test_r1cs_ppzksnark.cpp +++ b/src/zk_proof_systems/ppzksnark/r1cs_ppzksnark/tests/test_r1cs_ppzksnark.cpp @@ -19,6 +19,42 @@ using namespace libsnark; +//****Ariel code-testing batch verifier****/// +template +void test_r1cs_ppzksnark_batch_verifier(size_t num_constraints, + size_t input_size) +{ + //silly test that takes the same proof/primary input multiple times + enter_block("Test R1CS ppzkSNARK batch verifier"); + r1cs_example > example = generate_r1cs_example_with_binary_input >(num_constraints, input_size); + r1cs_ppzksnark_keypair keypair = r1cs_ppzksnark_generator(example.constraint_system); + r1cs_ppzksnark_proof proof = r1cs_ppzksnark_prover(keypair.pk, example.primary_input, example.auxiliary_input); + + enter_block("In test_r1cs_ppzksnark_batch_verifier after generating example and proof"); + + r1cs_ppzksnark_processed_batch_verification_key pvk = r1cs_ppzksnark_batch_verifier_process_vk(keypair.vk); + + batch_verification_accumulator acc; + const bool test_serialization = true; + for(auto i=0; i<10;i++) + { + //r1cs_example > example = generate_r1cs_example_with_binary_input >(num_constraints, input_size); + add_proof_in_batch_verifier_test(acc,proof,keypair.vk,example.primary_input); + + + } + + const bool bit = r1cs_ppzksnark_batch_verifier(pvk, acc,example.primary_input,proof); + assert(bit); + leave_block("In test_r1cs_ppzksnark_batch_verifier after generating example and proof"); + + leave_block("Test R1CS ppzkSNARK batch verifier"); +} + + +///****End Ariel code ******////// + + template void test_r1cs_ppzksnark(size_t num_constraints, size_t input_size) @@ -38,5 +74,7 @@ int main() default_r1cs_ppzksnark_pp::init_public_params(); start_profiling(); - test_r1cs_ppzksnark(1000, 100); + //test_r1cs_ppzksnark(1000, 100); + //ariel change + test_r1cs_ppzksnark_batch_verifier(1000,100); }