सुरक्षित, off-chain मतदान प्रक्रियाओं पर Vocdoni का ताज़ा शोध।
F
Ferran
· पढ़ने में 12 मिनट
यह लेख एक ऐसा proof-of-concept (अवधारणा-प्रमाण) सामने रखता है जो गवर्नेंस की अगली मंज़िल तक पहुँचने के लिए zk-SNARKs का इस्तेमाल करता है: बिना gas वाली,सत्यापित और बाध्यकारी on-chain गवर्नेंस।
इस प्रस्ताव की तकनीकी सामग्री सामुदायिक चर्चा के लिएEthresear.chफ़ोरम पर यहाँ भी प्रकाशित की गई है।
पृष्ठभूमि
डिजिटल गवर्नेंस के एक अग्रणी प्रोजेक्ट के तौर पर Vocdoni गवर्नेंस मॉडलों पर शोध और नवाचार में खासा निवेश करता है। हमने layer-2 गवर्नेंस के कई ऐसे समाधान पहचाने हैं जिनमें संभावनाएँ तो हैं, पर जो कई तकनीकी सवाल भी खुले छोड़ देते हैं। हमने अपने विशेष वोटिंग blockchain Vochain पर बिना gas वाली मतदान प्रक्रियाएँ चलाकर दिखाई हैं, और Ethereum Storage Proofs की मदद से ERC20 token पर आधारित मतदाता सूचियों को Ethereum से Vochain तक लाने का तरीका डिज़ाइन करके लागू भी किया है। लेकिन अब तक परिणामों को वापस Ethereum तक पहुँचाना एक खुला शोध-सवाल बना हुआ था।
इसी मकसद से Vocdoni एक नए डिज़ाइन पर प्रयोग कर रहा है, जिससे off-chain चलने वाली मतदान प्रक्रिया के परिणाम Ethereum तक पहुँचाए जा सकें, वह भी बिना किसी व्यक्तिपरक oracle या भरोसे पर टिके किसी और घटक के।
इस प्रस्ताव के पीछे की मूल नवीनता साफ़ है: हमारी जानकारी में ऐसी कोई प्रणाली नहीं है जो मतदान प्रक्रिया off-chain चला सके और उसके परिणामों के आधार पर Ethereum पर बिना किसी भरोसे की शर्त के कार्रवाई कर सके। इस प्रस्ताव के संभावित इस्तेमाल में गवर्नेंस की हर वह प्रक्रिया आती है जो परिणामों के आधार पर बाध्यकारी कार्रवाई करती है, जैसे परिसंपत्ति आवंटन या स्मार्ट कॉन्ट्रैक्ट में बदलाव पर DAO का मतदान, और यह सूची यहीं खत्म नहीं होती। फ़िलहाल ये गवर्नेंस प्रक्रियाएँ Ethereum mainnet पर ही चलानी पड़ती हैं, जिसमें हर मतदाता को भारी gas शुल्क चुकाना पड़ता है। दूसरा रास्ता यह है कि मतदान off-chain हो, पर परिणामों को सही-सही और ईमानदारी से Ethereum तक लौटाने के लिए किसी बाहरी घटक पर भरोसा करना पड़े।
हमारा प्रस्ताव पूरी तरह off-chain चलने वाली मतदान प्रक्रियाओं को इस लायक बना देगा कि वे Ethereum पर परिणाम लागू कर सकें, उसी विश्वसनीयता के साथ जो on-chain गवर्नेंस में होती है और लागत के एक छोटे से हिस्से में।
मतदान प्रोटोकॉल के proof-of-concept की आवश्यकताएँ
कोई तकनीकी समाधान गढ़ने से पहले हमने अपने शोध-प्रस्ताव के मापदंड तय किए:
आवश्यकताएँ ये थीं कि मतदान प्रोटोकॉल:
अनुमति-मुक्त (permissionless) हो।
सेंसरशिप-रोधी हो।
Ethereum पर परिणामों को बाध्यकारी बना सके।
मतदाताओं के लिए बिना gas वाला हो।
token को ब्रिज किए बिना काम करे।
जितना हो सके उतना सरल हो (कोई sidechain नहीं)।
मतदान के लिए ERC20 / ERC777 और NFT के साथ इस्तेमाल हो सके।
proof-of-concept डिज़ाइन होने के नाते हमने प्रस्ताव पर ये सीमाएँ मंज़ूर कीं:
मतदाता की कोई गुमनामी नहीं: वोट को किसी Ethereum पते से जोड़ा जा सकता है।
रसीद-रहित (receipt-free) नहीं: वोट खरीदना मुमकिन हो सकता है।
राष्ट्रीय स्तर के चुनावों के लिए नहीं बनाया गया: सिर्फ़ DAO या ERC20 / NFT धारकों के लिए। इसलिए मतदाता सूची का एक अधिकतम आकार तय करना चाहिए (प्रदर्शन और लागत के हिसाब से)।
relayers के लिए कोई तय प्रोत्साहन मॉडल नहीं।
आदर्श प्रस्ताव
इस प्रस्ताव के डिज़ाइन में, नई मतदान प्रक्रिया बनाते समय आयोजक Ethereum पर एक ट्रांज़ैक्शन भेजते हैं, जिसमें वे उस ERC20 token का कॉन्ट्रैक्ट पता बताते हैं जिसे मतदाता सूची की तरह इस्तेमाल करना है। किसी तय ब्लॉक ऊँचाई (block height) पर इस पते का Storage Root Hash ही इस प्रक्रिया की census root बन जाता है। जिसके पास वह token है, वह token में अपने बैलेंस का Merkle Proof (EIP1186 के ज़रिए) देकर अपनी पात्रता साबित कर सकता है। इसके बाद वह यह प्रमाण (siblings) और एक हस्ताक्षर किसी zk-SNARK rollup relayer को भेजकर वोट डाल सकता है, जो अंतिम परिणामों का प्रमाण तैयार करेगा।
एक संभावित समस्या यह है कि परिणामों का zk-SNARK प्रमाण बनाने वाला पक्ष (समन्वयक) सैद्धांतिक तौर पर कुछ वोट छोड़ने का फ़ैसला करके परिणाम को सेंसर कर सकता है। इस समस्या का हल हमने यह निकाला कि नए वोट जमा करने का हक सिर्फ़ समन्वयक तक सीमित नहीं है, यह कोई भी कर सकता है: अगर किसी उपयोगकर्ता को लगे कि समन्वयक ने उसका वोट शामिल नहीं किया, तो वह खुद अपना वोट रखने वाला rollup बनाकर भेज सकता है।
हमारा प्रस्ताव zk-SNARKs का इस्तेमाल इन कामों के लिए करता है:
Merkle tree accumulator के ज़रिए यह जाँचने के लिए कि किसी पते से पहले वोट नहीं पड़ा है।
Storage Proofs के ज़रिए यह जाँचने के लिए कि उपयोगकर्ता के पास tokens हैं।
वोटों के एक बैच पर आंशिक परिणाम निकालने के लिए।
वोट के हस्ताक्षर की जाँच करने के लिए।
zkSNARKs के साथ Ethereum पर बाध्यकारी निष्पादन - आदर्श प्रस्ताव।
ऊपर दिए गए ढाँचे में हमें 2 मुख्य समस्याएँ दिखती हैं:
समस्या 1: ERC20 Storage Proof की जाँच SNARK के अनुकूल नहीं है¶
किसी SNARK के भीतर ERC20 Storage Proofs की जाँच करना बहुत जटिल है। इसकी एक वजह यह है कि इनमें Recursive Length Prefix (RLP) पार्सिंग और कई Keccak-256 hash जाँचें लगती हैं, और मौजूदा सबसे उन्नत SNARK rollup तकनीक में इन दोनों की गणना बेहद खर्चीली पड़ती है। इस समस्या का जुगाड़ निकालना मुश्किल है, इसलिए फ़िलहाल हम इसे ऑप्टिमिस्टिक जाँच (optimistic validation) से हल करते हैं।
समस्या 2: ECDSA / Secp256k1 हस्ताक्षर की जाँच SNARK के अनुकूल नहीं है¶
उपयोगकर्ता के हस्ताक्षर जाँचने के लिए आज एक क्रिप्टोग्राफ़िक मानक हमारे पास है: ECDSA, जिसमें Ethereum हस्ताक्षर से निकाली गई BabyJubJub कुंजी इस्तेमाल होती है और हस्ताक्षर को ही कच्ची निजी कुंजी की तरह लिया जाता है, जिससे उपयोगकर्ता अपना पता वापस पा सकता है। चूँकि यह तरीका उपयोगकर्ता के हस्ताक्षर पर टिका है, इसलिए इसमें यह खतरा रहता है कि कोई बदनीयत पक्ष उपयोगकर्ता को बहलाकर उसके Web3 वॉलेट में धोखाधड़ी वाले ट्रांज़ैक्शन पर हस्ताक्षर करा ले। यह कमज़ोरी हर उस जगह मौजूद है जहाँ ट्रांज़ैक्शन पर हस्ताक्षर के लिए ब्राउज़र वॉलेट इस्तेमाल होता है। इसका एक संभावित हल यह हो सकता है कि वेब पते को derivation path बनाकर निजी कुंजी निकाली जाए।
एक और चुनौती यह साबित करने की है कि हर token धारक का Ethereum पता, मतदान प्रक्रिया बनने की ब्लॉक ऊँचाई पर, मतदान के लिए BabyJubJub कुंजी को मंज़ूरी देता है। इसे हम एक 'singleton' स्मार्ट कॉन्ट्रैक्ट से हासिल करते हैं, जो Ethereum पतों को BabyJubJub सार्वजनिक कुंजियों से जोड़ता है और जिसमें उपयोगकर्ता को एक सामान्य ट्रांज़ैक्शन के ज़रिए अपनी कुंजी जोड़नी होती है। पते और कुंजी के इस जोड़ को storage के ऑप्टिमिस्टिक धोखाधड़ी-प्रमाण (fraud proof) से चुनौती दी जा सकती है, क्योंकि Storage Proofs की ऑप्टिमिस्टिक जाँच का दरवाज़ा तो हम पहले ही खोल चुके हैं। यह हल डेटा उपलब्धता की समस्या को भी एक दोबारा इस्तेमाल होने लायक डिज़ाइन से सुलझा देता है, क्योंकि उम्मीद है कि ये मंज़ूरशुदा कुंजियाँ अलग-अलग मतदान प्रक्रियाओं में कई बार काम आएँगी।
कुल मिलाकर, ज़्यादातर जाँचें हम SNARK के भीतर कर सकते हैं, पर सब नहीं:
यह जाँच कि किसी पते से पहले वोट नहीं पड़ा है, Merkle tree accumulator के ज़रिए → SNARK
यह जाँच कि उपयोगकर्ता के पास tokens हैं, Storage Proofs के ज़रिए → Optimistic
मतदान के आंशिक परिणामों की गणना → SNARK
वोट के हस्ताक्षर की जाँच → SNARK
प्रस्ताव
zkSNARKs के साथ Ethereum पर बाध्यकारी निष्पादन - प्रस्ताव
मतदान प्रक्रिया दर्ज करता है, जिसमें ये शामिल हैं: ERC20 स्मार्ट कॉन्ट्रैक्ट का पता, ERC20 के पता→बैलेंस मैपिंग का slot इंडेक्स, मतदान प्रक्रिया के शुरुआती ब्लॉक का state root hash, और वोटों की गिनती के लिए प्रक्रिया के पैरामीटर (देखें Vocdoni का Ballot Protocol)।
zk-Rollup के ज़रिए नए वोटों के दर्ज होने पर नज़र रखता है, यानी एक ऐसा SNARK जो साबित करता है:
परिणाम की गणना।
वोट पर हस्ताक्षर किसी BabyJubJub कुंजी से हुआ है।
मतदान के accumulators को अपडेट रखता है।
मतदाताओं की सूची अपडेट रखता है।
किसी को भी धोखाधड़ी-प्रमाण के ज़रिए पिछले वोट पंजीकरण को चुनौती देने देता है। चुनौती में इनमें से कोई एक देना ज़रूरी है:
ऐसा Storage Proof जो साबित करे कि किसी मतदाता के Ethereum पते पर tokens नहीं हैं।
ऐसा Storage Proof जो साबित करे कि किसी मतदाता का Ethereum पता किसी BabyJubJub कुंजी से जुड़ा नहीं है।
ऐसा प्रमाण जो साबित करे कि उस BabyJubJub कुंजी से वोट पड़ चुका है (कुंजी "पहले वोट डाल चुके" वाले tree में मौजूद है)।
चरण 0: चुनाव प्रक्रिया Ethereum पर बनाई जाती है और उपलब्ध relayers की सूची में से एक relayer चुना जाता है। चुनाव के आयोजक को उसकी लागत चुकानी होती है, जो समन्वयक को इनाम के तौर पर मिलती है। आयोजक वह EVM bytecode देता है जो चुनाव के बाद, परिणामों के हिसाब से, DAO के स्मार्ट कॉन्ट्रैक्ट या कॉन्ट्रैक्टों पर चलाया जाना है।
चरण 1: मतदान शुरू होता है। कोई भी चुने हुए समन्वयक को वोट पैकेज भेज सकता है (HTTPs या libp2p ट्रांसपोर्ट इस्तेमाल हो सकते हैं)। समन्वयक चुने हुए परिणामों को बैचों में rollup करता है, एक zk-SNARK प्रमाण बनाता है, यह प्रमाण और परिणाम Ethereum पर अपलोड करता है, उपयोगकर्ताओं के डाले हुए वोट इकट्ठा करके जाँचता है, और उन्हें बाकी relayers तक पहुँचा देता है।
चरण 2: जिन समन्वयकों को कोई ऐसा वोट दिखे जो जोड़ा नहीं गया, वे अपने वोट खुद rollup करके वोटिंग स्मार्ट कॉन्ट्रैक्ट को zk-SNARK वैधता-प्रमाण भेज सकते हैं। इसके अलावा, अगर उन्हें लगे कि कोई वोट गलत तरीके से जोड़ा गया है, तो वे धोखाधड़ी-प्रमाण भेजकर साबित कर सकते हैं कि पहले जोड़ा गया परिणाम अमान्य है, और जिस समन्वयक ने वह परिणाम बनाया था उस पर slashing लागू होगी।
चरण 3: जब मतदान की आखिरी तारीख आ जाती है:
अपलोड किए गए परिणामों का जोड़ (समन्वयक का और किसी भी तीसरे पक्ष का) मान्य माना जाता है, और इनाम समन्वयक के साथ-साथ उन पक्षों में भी बाँटा जाता है जिन्होंने ज़्यादा वोट शामिल किए (अगर कोई हो)।
कोई भी (आमतौर पर समन्वयक) अंतिम परिणामों को इनपुट बनाकर वह EVM bytecode चलवाता है।
एक zk-SNARK डाले गए वोटों की सूची को समेटेगा। zk-SNARK प्रमाण की वैधता वोटों की एक दी हुई सूची, एक census root, एक चुनाव पहचानकर्ता (electionId) और एक समेकित परिणाम पर टिकी होती है।
सर्किट और कॉन्ट्रैक्ट
zk-SNARK इनपुट
इनपुट का hash (सार्वजनिक) (यह SNARK जाँच की gas लागत घटाने के लिए किया जाता है)।
ElectionId (निजी)।
इस बैच के मतदान परिणामों की गणना (निजी)।
मौजूदा nullifiers root (निजी)।
अपडेट की गई nullifiers root (निजी)।
बैच में वोटों की संख्या (निजी)।
वोट के मान और उनके BabyJubJub हस्ताक्षर [1..BATCHSIZE] (निजी)।
समन्वयक के परिणाम अपलोड करने वाले स्मार्ट कॉन्ट्रैक्ट फ़ंक्शन कॉल के इनपुट ये हैं:
electionId।
इस बैच के मतदाताओं की सार्वजनिक कुंजियों की सूची।
अपडेट की गई nullifiers root।
इस बैच के मतदान परिणामों की गणना।
SNARK प्रमाण।
Proof of Concept को लागू करना
समाधान की लागत और व्यावहारिकता जाँचने के लिए हमने न्यूनतम काम-लायक स्मार्ट कॉन्ट्रैक्ट और सर्किट यहाँ लागू किए हैं। इस PoC में सिर्फ़ उपयोगकर्ता रजिस्ट्री, वोटों का समेकन और धोखाधड़ी-प्रमाण की जाँच शामिल है।
हमारी जाँच में gas की ये लागतें आईं:
user key registry
deployment 258,536
registration 68,956
voting
deployment 6,673,159
new voting 25,989
aggregate rollup 291,801
fraud proof-1 574,574 (babyjubjub key not registered)
fraud proof-2 908,822 (account ERC20 balance is zero)
कितने वोट एक साथ समेटना व्यावहारिक है, यह आँकने के लिए हमने 32GB RAM / 8 CPU वाले एक सामान्य सर्वर पर माप लिए और पाया कि 300 वोट तक समेटे जा सकते हैं (64-स्तरीय Merkle tree accumulator और ~38 लाख constraints के साथ), जिसमें प्रमाण बनाने में 450 सेकंड लगते हैं और 30GB RAM खर्च होती है। प्रमाणों के लिए हमने Circom के साथ Groth16, C++ में witness जनरेशन, और rapidSNARK इस्तेमाल किए।
अच्छी बात यह है कि धोखाधड़ी-प्रमाण बनाने के लिए जो प्रमाण तैयार करना पड़ता है वह इतना छोटा (50k) है कि ब्राउज़र में ही बन जाता है। इससे उपयोगकर्ता बिना कोई खास सॉफ़्टवेयर डाउनलोड किए वोटों के किसी बैच को चुनौती दे सकते हैं।
आगे का शोध
इस शोध पर आगे बढ़ते हुए हम इन विचारों को और गहराई से टटोलना चाहेंगे:
SNARKs के ज़रिए मानक Keccak / ECDSA / Sec256k1 हस्ताक्षरों की जाँच। हमें लगता है कि जल्द ही PLOOKUP इन योजनाओं की जाँच कर सकेगा, जिससे दो रास्ते खुलेंगे:
यह साबित करना कि BabyJubJub कुंजी किसी Secp256k1 कुंजी से निकाली गई है (यह सिर्फ़ एक बार करना पड़ता है)।
खुद वोट के हस्ताक्षर की जाँच करना।
SNARK के भीतर Storage Proofs की जाँच। हमें लगता है कि इस तरह का जटिल सर्किट zkVM के ज़रिए आसानी से जोड़ा जा सकता है, हालाँकि लागत काफ़ी बैठ सकती है। हमें चिंता है कि Ethereum क्लाइंट ज़्यादा gas limit को तरजीह देने के लिए archive nodes बंद कर सकते हैं, इसलिए शोध का एक और क्षेत्र यह है कि Storage Proofs के लिए EIP1186 के अलावा दूसरे तरीके आज़माए जाएँ।
गिनती निकालने के लिए zkVM के भीतर चलने वाले किसी तरह के opcodes जोड़ना, ताकि सामान्य प्रोग्राम-योग्य मतदान सर्किट बन सकें।
ब्राउज़र में मतदान प्रमाण बनाना, बैचिंग के ज़रिए मिक्स करना, और परिणामों को पुनरावर्ती तरीके से समेटना, कुछ वैसे ही जैसे zk.money प्रोटोकॉल में होता है। इससे मतदान प्रक्रिया की गोपनीयता बढ़ेगी।
SNARKs को ब्राउज़र के स्तर पर वितरित तरीके से गणना करने देना, भले ही वे गणना के लिहाज़ से महँगे हों। इससे बड़े, सबकी नज़र में रहने वाले सर्वरों पर निर्भरता खत्म होती है और पूरी तरह P2P होने के नाते सारी ताकत मतदाताओं के हाथ आ जाती है।
मतदान प्रोटोकॉल में नेटवर्क के स्तर पर ही गोपनीयता और मिक्सिंग जोड़ना।
ऐसा क्रिप्टो-इकोनॉमिक्स मॉडल खोजना जो तर्कसंगत हो और Ethereum 2.0 के साथ पूरी तरह इंटरऑपरेबल हो।
एक ऐसा अकेला प्रमाण बनाना जिसकी जाँच आसानी से हो सके। इससे यह संभावना खुलती है कि कोई भी प्रोग्राम-योग्य L1 और L2 (EVM हो या न हो) Ethereum के किसी भी मतदान परिणाम पर प्रतिक्रिया दे सके। लंबी दौड़ का लक्ष्य यह है कि किसी भी चेन पर वोट डाला जा सके और परिणामों की जाँच किसी भी दूसरी चेन पर हो सके। यह SNARKs के ज़रिए cross-rollup / चेन Storage Proof जाँच का एक तरह का स्वर्ण मानक बन सकता है।