एक quadratic arithmetic program एक arithmetic circuit है, विशेष रूप से एक Rank 1 Constraint System (R1CS) जिसे polynomials के एक सेट के रूप में दर्शाया गया है। इसे Rank 1 Constraint System पर Lagrange interpolation का उपयोग करके प्राप्त किया जाता है। R1CS के विपरीत, एक Quadratic Arithmetic Program (QAP) को Schwartz-Zippel Lemma के माध्यम से समय में समानता (equality) के लिए टेस्ट किया जा सकता है।
मुख्य विचार (Key ideas)
Schwartz-Zippel Lemma के अध्याय में, हमने देखा कि हम दो vectors को polynomials में बदलकर और फिर उन polynomials पर Schwartz-Zippel Lemma टेस्ट चलाकर, समय में यह टेस्ट कर सकते हैं कि क्या वे बराबर हैं। (स्पष्ट करने के लिए, टेस्ट समय लेता है, vectors को polynomials में बदलने से overhead उत्पन्न होता है)।
चूँकि Rank 1 Constraint System पूरी तरह से vector ऑपरेशन्स से बना होता है, हमारा लक्ष्य यह टेस्ट करना है कि क्या
समय के बजाय समय में सही साबित होता है (जहाँ , , , और में पंक्तियों की संख्या है)।
लेकिन ऐसा करने से पहले, हमें vectors और उन्हें दर्शाने वाले polynomials के बीच के संबंध के कुछ प्रमुख गुणों को समझने की आवश्यकता है।
यहाँ सभी गणितीय गणनाओं के लिए, हम मान लेते हैं कि हम एक finite field में काम कर रहे हैं, लेकिन संक्षिप्तता के लिए हम नोटेशन को छोड़ देते हैं।
Vector addition और polynomial addition के बीच Homomorphisms
Vector addition, polynomial addition के homomorphic है
यदि हम दो vectors लेते हैं, उन्हें polynomials के साथ interpolate करते हैं, और फिर polynomials को एक साथ जोड़ते हैं, तो हमें वही polynomial प्राप्त होता है जो हमें तब मिलता जब हम vectors को एक साथ जोड़ते और फिर उनके sum vector को interpolate करते।
अधिक गणितीय रूप में कहें तो, मान लीजिए वह polynomial है जो vector पर Lagrange interpolation से प्राप्त होता है, जिसमें वैल्यू के रूप में का उपयोग किया गया है, जहाँ , की लंबाई है। निम्नलिखित सत्य है:
दूसरे शब्दों में, vectors और को अलग-अलग interpolate करके उनके polynomials को जोड़ने पर वही परिणाम मिलता है जो vectors को interpolate करने पर मिलता है।
हल किया गया उदाहरण
मान लीजिए और है। , या vector को interpolate करता है और , को interpolate करता है।
इन vectors का योग है और यह स्पष्ट है कि इसे interpolate करता है। मान लीजिए ।
Python में गणित को टेस्ट करना
किसी प्रस्तावित गणितीय identity की unit testing करने से वह सत्य नहीं हो जाती, लेकिन यह यह ज़रूर दर्शाती है कि क्या हो रहा है। पाठकों को प्रोत्साहित किया जाता है कि वे कुछ अलग-अलग vectors आज़माकर देखें कि यह identity सही साबित होती है या नहीं।
import galois
import numpy as np
p = 17
GF = galois.GF(p)
xs = GF(np.array([1,2,3]))
# two arbitrary vectors
v1 = GF(np.array([4,8,2]))
v2 = GF(np.array([1,6,12]))
def L(v):
return galois.lagrange_poly(xs, v)
assert L(v1 + v2) == L(v1) + L(v2)
Scalar multiplication
मान लीजिए एक scalar है (विशेष रूप से, finite field में एक field element)। तब
हल किया गया उदाहरण
मान लीजिए हमारे 3 points हैं। वह polynomial जो इसे interpolate करता है, वह है। यदि हम इस vector को 3 से गुणा करते हैं, तो हमें मिलता है। जो polynomial इसे interpolate करता है वह है
from scipy.interpolate import lagrange
x_values = [1, 2, 3]
y_values = [9, 18, 33]
print(lagrange(x_values, y_values))
# 2
# 3 x + 6
, जो के बराबर है।
कोड में हल किया गया उदाहरण
import galois
import numpy as np
p = 17
GF = galois.GF(p)
xs = GF(np.array([1,2,3]))
# arbitrary vector
v = GF(np.array([4,8,2]))
# arbitrary constant
lambda_ = GF(15)
def L(v):
return galois.lagrange_poly(xs, v)
assert L(lambda_ * v) == lambda_ * L(v)
Scalar multiplication वास्तव में vector addition है
जब हम कहते हैं कि “एक vector को 3 से गुणा करें”, तो हम वास्तव में यह कह रहे होते हैं कि “vector को उसी में तीन बार जोड़ें”। चूँकि हम केवल finite fields में काम कर रहे हैं, हमें “0.5” जैसे scalars की व्याख्या से कोई सरोकार नहीं है।
हम element-wise addition (एक finite field में) के अंतर्गत vectors और addition के अंतर्गत polynomials (यह भी finite field में) दोनों को groups के रूप में मान सकते हैं।
इस अध्याय से सबसे महत्वपूर्ण निष्कर्ष यह है:
एक finite field में addition के अंतर्गत vectors का group, एक finite field में addition के अंतर्गत polynomials के group के homomorphic होता है।
यह बहुत महत्वपूर्ण है क्योंकि vector समानता (equality) की टेस्टिंग में समय लगता है, लेकिन polynomial समानता की टेस्टिंग में समय लगता है।
इसलिए, जहाँ R1CS समानता को टेस्ट करने में समय लगता था, हम इस homomorphism का लाभ उठाकर R1CSs की समानता को समय में टेस्ट कर सकते हैं।
यही Quadratic Arithmetic Program होता है।
Polynomials में Rank 1 Constraint System
ध्यान दें कि एक rectangular matrix और एक vector के बीच matrix multiplication को vector addition और scalar multiplication के रूप में लिखा जा सकता है।
उदाहरण के लिए, यदि हमारे पास matrix और एक 4 डायमेंशनल vector है, तो हम इस matrix multiplication को इस प्रकार लिख सकते हैं:
हम आमतौर पर सोचते हैं कि vector “फ़्लिप” होकर प्रत्येक पंक्ति के साथ एक inner product (सामान्यीकृत dot product) करता है, अर्थात
हालाँकि, इसके बजाय हम matrix को कई vectors के समूह में विभाजित करने के बारे में सोच सकते हैं, कुछ इस प्रकार:
और प्रत्येक vector को vector के एक scalar से गुणा करके:
हमने और के बीच matrix multiplication को पूरी तरह से vector addition और scalar multiplication के रूप में व्यक्त किया है।
चूँकि हमने पहले यह स्थापित किया था कि एक finite field में addition के अंतर्गत vectors का group, finite field में addition के अंतर्गत polynomials के group के homomorphic होता है, इसलिए हम उपरोक्त गणना को vectors को दर्शाने वाले polynomials के रूप में व्यक्त कर सकते हैं।
संक्षेप में यह टेस्ट करना कि
मान लीजिए कि हमारे पास matrix और हैं, जैसे कि
और vectors तथा हैं
हम यह टेस्ट करना चाहते हैं कि क्या
सत्य है।
जाहिर है कि हम matrix arithmetic को हल कर सकते हैं, लेकिन अंतिम जाँच में तुलनाओं (comparisons) की आवश्यकता होगी, जहाँ , और में पंक्तियों की संख्या है। हम इसे समय में करना चाहते हैं।
सबसे पहले, हम matrix multiplication और को addition के अंतर्गत vectors के group में बदलते हैं:
अब हम polynomial group में
का homomorphic समतुल्य (equivalent) खोजना चाहते हैं।
आइए इनमें से प्रत्येक vector को वैल्यू पर polynomials में बदलें:
Langrage interpolation की गणना करने के लिए हम कुछ Python कोड का उपयोग करेंगे:
import galois
import numpy as np
p = 17
GF = galois.GF(p)
x_values = GF(np.array([1, 2]))
def L(v):
return galois.lagrange_poly(x_values, v)
p1 = L(GF(np.array([6, 4])))
p2 = L(GF(np.array([3, 7])))
q1 = L(GF(np.array([3, 12])))
q2 = L(GF(np.array([9, 6])))
print(p1)
# 15x + 8 (mod 17)
print(p2)
# 4x + 16 (mod 17)
print(q1)
# 9x + 11 (mod 17)
print(q2)
# 14x + 12 (mod 17)
अंत में, हम Schwartz-Zippel Lemma का उपयोग करके यह जाँच कर सकते हैं कि क्या
सत्य है:
import random
u = random.randint(0, p)
tau = GF(u) # a random point
left_hand_side = p1(tau) * GF(2) + p2(tau) * GF(4)
right_hand_side = q1(tau) * GF(2) + q2(tau) * GF(2)
assert left_hand_side == right_hand_side
अंतिम assert स्टेटमेंट की बजाय केवल एक तुलना (comparison) करके यह टेस्ट करने में सक्षम है कि क्या है।
R1CS से QAP: संक्षेप में यह टेस्ट करना कि
चूँकि हम जानते हैं कि का संक्षेप में टेस्ट कैसे किया जाता है, क्या हम यह भी संक्षेप में टेस्ट कर सकते हैं कि है?
Matrices में कॉलम होते हैं, इसलिए आइए प्रत्येक matrices को कॉलम vectors में विभाजित करें और प्रत्येक के लिए polynomials उत्पन्न करने के लिए उन्हें पर interpolate करें।
मान लीजिए वे polynomials हैं जो के कॉलम vectors को interpolate करते हैं।
मान लीजिए वे polynomials हैं जो के कॉलम vectors को interpolate करते हैं।
मान लीजिए वे polynomials हैं जो के कॉलम vectors को interpolate करते हैं।
व्यापकता खोए बिना (Without loss of generality), मान लीजिए कि हमारे पास 4 कॉलम () और तीन पंक्तियाँ () हैं।
विज़ुअल रूप से, इसे इस प्रकार दर्शाया जा सकता है:
चूँकि किसी कॉलम vector को एक scalar से गुणा करना किसी polynomial को scalar से गुणा करने के homomorphic होता है, इसलिए प्रत्येक polynomials को witness के संबंधित एलिमेंट से गुणा किया जा सकता है।
उदाहरण के लिए,
बन जाता है
ध्यान दें कि अंतिम परिणाम अधिकतम डिग्री वाला एक एकल (single) polynomial है, क्योंकि में से प्रत्येक की डिग्री अधिकतम है।
यह इस बात से स्पष्ट होता है कि हमने उन्हें कैसे बनाया: के प्रत्येक कॉलम में एंट्रीज़ होती हैं, और Lagrange interpolation के माध्यम से पॉइंट्स को interpolate करने पर अधिकतम डिग्री का polynomial उत्पन्न होता है।
सामान्य मामले में, को प्रत्येक कॉलम को polynomials में बदलने के बाद
के रूप में लिखा जा सकता है।
ऊपर दिए गए समान चरणों का उपयोग करके, R1CS में प्रत्येक matrix-witness गुणनफल (product) को इस प्रकार बदला जा सकता है:
चूँकि प्रत्येक योग (sum) पद एक एकल (single) polynomial उत्पन्न करता है, हम उन्हें इस प्रकार लिख सकते हैं:
सभी कॉलम को interpolate क्यों करें?
Homomorphisms और के कारण, यदि हम की गणना के रूप में करते हैं, तो हमें वही परिणाम मिलता है जो के कॉलम पर Lagrange interpolation लागू करने और फिर प्रत्येक polynomials को में मौजूद संबंधित एलिमेंट से गुणा करके परिणाम जोड़ने पर मिलता है।
दूसरे शब्दों में कहें तो,
तो फिर के बजाय केवल एक ही Lagrange interpolation की गणना क्यों न की जाए?
हमें इस बात में अंतर करना होगा कि QAP का उपयोग कौन कर रहा है। Verifier (और trusted setup जिसे हम बाद में कवर करेंगे) witness को नहीं जानता है और इसलिए की गणना नहीं कर सकता है। यह एक ऑप्टिमाइज़ेशन है जो prover कर सकता है, लेकिन ZK प्रोटोकॉल में अन्य पक्ष इस ऑप्टिमाइज़ेशन का उपयोग नहीं कर सकते।
इसमें शामिल सभी पक्षों को QAP पर एक साझा सहमति होनी चाहिए – किसी भी proof और वेरिफिकेशन से पहले matrices के polynomial interpolations पर।
Polynomial डिग्री का असंतुलन (Polynomial degree imbalance)
हालाँकि, हम अंतिम परिणाम को सरलता से इस प्रकार व्यक्त नहीं कर सकते:
क्योंकि डिग्रियाँ मेल नहीं खाएँगी।
दो polynomials को एक साथ गुणा करने पर एक गुणनफल polynomial (product polynomial) प्राप्त होता है जिसकी डिग्री उन दो polynomials की डिग्री का योग होती है जिन्हें एक साथ गुणा किया जा रहा है।
चूँकि , , और में से प्रत्येक की डिग्री होगी, की डिग्री सामान्यतः होगी और की डिग्री होगी, इसलिए वे बराबर नहीं होंगे, भले ही जिन अंतर्निहित (underlying) vectors को उन्होंने गुणा किया है, वे बराबर हों।
ऐसा इसलिए है क्योंकि जो homomorphisms हमने पहले स्थापित किए थे, वे केवल vector addition के बारे में दावा करते हैं, Hadamard product के बारे में नहीं।
हालाँकि, वह vector जिसे interpolate करता है, अर्थात
वही vector है जिसे interpolate करता है, अर्थात
दूसरे शब्दों में
यद्यपि “अंतर्निहित (underlying)” vectors बराबर हैं, उन्हें interpolate करने वाले polynomials बराबर नहीं हैं।
Underlying equality का उदाहरण
मान लीजिए कि वह polynomial है जो
को interpolate करता है, और वह polynomial है जो
को interpolate करता है।
यदि हम को vector को interpolate करने वाला और को vector को interpolate करने वाला मानते हैं, तो हम देख सकते हैं कि उनका product polynomial दोनों vectors के Hadamard product को interpolate करता है। और का Hadamard product है।
यदि हम और को एक साथ गुणा करते हैं, तो हमें प्राप्त होता है।
हम नीचे दिए गए प्लॉट में देख सकते हैं कि product polynomial दोनों vectors के Hadamard product को interpolate करता है।

तो हम को के बराबर कैसे “बना” सकते हैं यदि वे पर समान वैल्यू को interpolate करते हैं?
vector को interpolate करना
यदि है, तो होगा।
को Lagrange interpolation के साथ interpolate करने और प्राप्त करने के बजाय (याद रखें कि Lagrange interpolation सबसे कम डिग्री वाले interpolating polynomial को खोजता है), हम एक उच्च डिग्री वाले polynomial का उपयोग कर सकते हैं जो डिग्री के असंतुलन (mismatch) को संतुलित करेगा।
उदाहरण के लिए, नीचे दी गई छवि में काला polynomial (), को interpolate करता है:

अब, चूँकि , का एक मान्य (valid) interpolation है, हम अपने मूल समीकरण को इस प्रकार लिख सकते हैं:
और यह समीकरण संतुलित (balanced) हो जाएगा!
की गणना आसानी से के रूप में की गई थी (नीला polynomial माइनस लाल polynomial)।
हालाँकि, हम prover को कोई भी चुनने की अनुमति नहीं दे सकते, अन्यथा वे एक ऐसा चुन सकते हैं जो और को संतुलित कर दे, भले ही वे समान vector (हमारे उदाहरण में ) को interpolate न करते हों। को चुनने में prover के पास बहुत अधिक लचीलापन (flexibility) है। विशेष रूप से, हम यह आवश्यक करना चाहते हैं कि के roots पर हों – अर्थात्, vector को interpolate करें। इस तरह, का polynomial ट्रांसफॉर्मेशन अभी भी अंतर्निहित (underlying) vectors का सम्मान करता है।
के उनके चुनाव को सीमित करने के लिए, हम निम्नलिखित प्रमेय (theorem) का उपयोग कर सकते हैं:
Polynomial गुणनफल (product) के roots का union
Theorem: यदि है और के roots का सेट है तथा के roots का सेट है, तो के roots होंगे।
उदाहरण
मान लीजिए और है। तब के roots होंगे।
हम यह लागू करने (enforce) के लिए उपरोक्त theorem का उपयोग कर सकते हैं कि के roots पर हों।
को zero vector होने के लिए बाध्य करना
हम को में विघटित (decompose) करते हैं जहाँ यह polynomial है:
तब के साथ गुणा किया गया कोई भी polynomial भी zero vector होगा, क्योंकि इसके roots पर होने चाहिए।
इसलिए, हम अपने समीकरण में को से बदल देंगे।
इस प्रकार, हमारी समानता (equality) बन जाएगी:
हम बुनियादी बीजगणित (algebra) का उपयोग करके की गणना कर सकते हैं:
QAP एंड-टू-एंड
मान लीजिए कि हमारे पास matrices , , और तथा witness vector के साथ एक R1CS है।
Matrices में कॉलम और पंक्तियाँ हैं जहाँ और है।
अर्थात्, , , और इस प्रकार हैं:
और witness vector है:
हम प्रत्येक matrices को कॉलम vectors में विभाजित करते हैं और प्रत्येक के लिए polynomials उत्पन्न करने के लिए उन्हें पर interpolate करते हैं।
प्रत्येक matrix-vector गुणनफल (products) , , और निम्नलिखित polynomials के homomorphically समतुल्य (equivalent) हैं:
हमारे मामले में, होगा
और होगा
मूल R1CS के QAP प्रतिनिधित्व (representation) का अंतिम सूत्र (formula) है:
QAP के लिए अंतिम सूत्र (Final formula)
एक QAP निम्नलिखित सूत्र है:
जहाँ , , और वे polynomials हैं जो क्रमशः , , और के कॉलम को interpolate करते हैं, , है, जहाँ , , , और में पंक्तियों की संख्या है, तथा है:
Quadratic Arithmetic Programs के साथ Succinct Zero Knowledge Proofs
मान लीजिए हमारे पास एक ऐसा तरीका हो जिससे verifier, prover को एक रैंडम वैल्यू भेज सके और prover इसके जवाब में यह दे:
Verifier यह जाँच कर सकता है कि है और यह स्वीकार कर सकता है कि prover के पास एक मान्य (valid) witness है जो R1CS और QAP दोनों को संतुष्ट करता है।
हालाँकि, इसके लिए verifier को यह विश्वास करना होगा कि prover, polynomials का सही मूल्यांकन (evaluate) कर रहा है, और हमारे पास prover को ऐसा करने के लिए मजबूर करने का कोई तंत्र (mechanism) नहीं है।
अगले अध्याय में, हम इस अध्याय में हमारी चर्चा के आधार पर एक R1CS को QAP में बदलने के लिए Python कोड दिखाएंगे।
फिर हम यह समस्या हल करने के लिए trusted setups पर चर्चा करेंगे कि prover से ईमानदारी से polynomials का मूल्यांकन कैसे करवाया जाए।
मूल रूप से 23 अगस्त, 2023 को प्रकाशित