आर्किटेक्चर
श्वेतपत्र का इंजीनियरिंग साथी — संदर्भ नोड डिज़ाइन को कैसे साकार करता है, और उसके पीछे के निर्णय। व्याख्यात्मक, मानक नहीं।
प्रोटोकॉल है पैरामीटर फ़ाइलें और golden vectors, साथ में वे नामित नियम जहाँ भी वे परिभाषित हों; वायर विशिष्टि पीयर परत की अपेक्षाएँ ढोती है। यह पृष्ठ उस सतह की व्याख्या करता है और उसके पीछे के निर्णय दर्ज करता है। जहाँ यह मानक सतह से असहमत हो, वहाँ मानक सतह जीतती है और यह पाठ सुधारा जाता है। पूरा इंजीनियरिंग साथी docs/ARCHITECTURE.md है।
दो प्रिडिकेट, दो इंजन#
एक सर्टिफिकेट का जीवन, सिरे से सिरे तक:
wallet network every full node
+------------+ gossip +--------------+ +---------------------+
| build cert | ---------> | cert topic | ------------> | STATELESS PIPELINE |
| (reads, | | (TLS gossip) | | V1..V8, batch sigs, |
| writes, | +--------------+ | native re-exec |
| sigs, seq, | | -> mark VALID |
| deposit) | +----------+----------+
+------------+ | mempool
v
miner (any node) +---------------------+
+-------------------+ block | FOLD (sequential) |
| assemble ordered | --------> | F-rules per cert: |
| hash list + bodies| gossip | APPLY / SKIP / DROP |
| + RandomX solve | | -> new state |
+-------------------+ +---------------------+
वैधता स्टेटलेस और समानांतर है: वह प्रति नोड प्रति सर्टिफिकेट एक बार चलती है, ब्लॉकों से पहले और उनसे स्वतंत्र। प्रयोज्यता स्टेटफ़ुल और अनुक्रमिक है: वह fold के भीतर, सर्टिफिकेट की कमिट हुई स्थिति पर चलती है। माइनर कोई निष्पादन नहीं करता; वह उन हैशों का क्रम तय करता है जिन्हें वह पहले ही सत्यापित होते देख चुका है, और proof of work हल करता है। fold स्मृति में मौजूद कार्य-समुच्चय पर चलने वाला एक कसा हुआ लूप है — मिलाओ, जोड़ो, लिखो।
इंजीनियरिंग सिद्धांत#
| सिद्धांत | |
|---|---|
| P1 | fold पवित्र है। स्टेट-ट्रांज़िशन फ़ंक्शन एक ही शुद्ध पैकेज में रहता है, जिसमें न I/O है, न घड़ियाँ, न goroutine, न map पुनरावर्तन, न फ़्लोटिंग पॉइंट। यही एकमात्र ऐसा कोड है जिसके बग बाद में ठीक नहीं किए जा सकते। नोड में बाक़ी सब बदली जा सकने वाली नलसाज़ी है। |
| P2 | नियतत्व प्रदर्शन से ऊपर है। जो भी अनुकूलन अनियततत्व का जोखिम लाए वह consensus कोड में अस्वीकृत है। प्रदर्शन की जगह स्टेटलेस पाइपलाइन है, जहाँ वह सुरक्षित है। |
| P3 | न एडमिन कुंजियाँ, न विशेषाधिकार-प्राप्त RPC। ऐसा कोई कोड-पथ नहीं है जिससे कोई कुंजी रोक सके, अपग्रेड कर सके, नई मुद्रा गढ़ सके या पुनर्गठन कर सके। जो fold नियमों में नहीं है, वह है ही नहीं। |
| P4 | छोटी consensus सतह। core/ मानक लाइब्रेरी के बाहर कुछ भी import नहीं करता। नोड का बाक़ी हिस्सा पारिस्थितिकी की लाइब्रेरी इस्तेमाल कर सकता है; core नहीं कर सकता। |
| P5 | पहले विशिष्टि। golden vectors ही प्रोटोकॉल हैं। Go कोड एक संदर्भ कार्यान्वयन है; जो स्वतंत्र कार्यान्वयन उन vectors को पास कर ले वह एक पीयर है, fork नहीं। यही वह बात है जो अनुरक्षक को आख़िरकार कोई ख़ास व्यक्ति न होने देती है। |
| P6 | v0.1 से पुनरुत्पाद्य। पिन किया गया Go toolchain, -trimpath, पिन की गई निर्भरताएँ। भरोसा बाइनरी से हटकर कोड पर चला जाता है, और गुमनाम लेखक बस यही भरोसा दे सकता है। |
| P7 | एक ही बाइनरी, ऊँचाई से खुलती है। मशीन, bond संक्रियाएँ और sequencer पंजीकरण हर रिलीज़ में संकलित होते हैं और अपनी सक्रियण ऊँचाई से नीचे अस्वीकार किए जाते हैं — Validate के लिए h1_vm ≥ h1_bond ज़रूरी है और h1_vm का किसी epoch सीमा पर पड़ना ज़रूरी है। कोई Era इसलिए आता है कि चेन किसी संख्या तक पहुँच गई, इसलिए कभी नहीं कि संचालकों से अपग्रेड करने को कहा गया। |
P3 पर ही किसी संदेही पाठक को सबसे ज़ोर से दबाव डालना चाहिए, और दबाव डालने की जगह treasury है: genesis में कोई कुंजी है ही नहीं और कोई खर्च-पथ भी नहीं, इसलिए रखने, सौंपने या चुराने को कोई विशेषाधिकार है ही नहीं। Era 2 का 3-में-से-5 कोरम एक भविष्य के hard fork से पिन होता है — वही सामाजिक तंत्र जो किसी भी अन्य consensus बदलाव का है, वैसी ही अस्वीकृति के अधीन, और तब भी वह ठीक एक cell हिला सकता है। ऐसा कोरम जो तभी प्रकट होता है जब नेटवर्क उसे लिखने पर सहमत हो, और जो फिर एक cell थामता हो, वह एक खर्च-नियम है। एडमिन कुंजी वह होती है जो किसी की सहमति से पहले मौजूद होती है और हर चीज़ तक पहुँचती है।
क्रिप्टोग्राफ़िक प्रिमिटिव#
| भूमिका | चुनाव | क्यों |
|---|---|---|
| हस्ताक्षर | Ed25519 | बैच सत्यापन (GPU तक पहुँचने का रास्ता), कोई लचीलापन नहीं, बहुत छोटी कुंजियाँ। genesis पर तय कड़े नियम: सार्वजनिक कुंजी और R के लिए कैनोनिकल एन्कोडिंग अनिवार्य, सार्वजनिक कुंजी torsion-मुक्त और निम्न कोटि की नहीं, और सत्यापन cofactor-रहित। |
| हैशिंग | BLAKE3 | सर्टिफिकेट और ब्लॉक id, पते, state root। relay की गति पर हैश करने के लिए पर्याप्त तेज़; epoch state root के लिए समानांतर-अनुकूल। |
| Proof of work | RandomX | CPU के लिए अनुकूलित। पेड़ में इकलौता cgo, एक build tag के पीछे, और उसके बिना बने बिल्ड में अनुपस्थित। pow_engine consensus root में है, इसलिए ग़लत इंजन रखने वाली बाइनरी ग़लत प्रमाण स्वीकारने के बजाय शुरू होने से मना कर देती है। |
| डोमेन पृथक्करण | अनिवार्य | हर हैश blake3(tag ‖ payload) है। हस्ताक्षर chain id और consensus root दोनों पर होते हैं, जो नेटवर्कों के बीच और एक ही नेटवर्क के दो अवतारों के बीच, दोनों जगह replay ख़त्म कर देता है। |
torsion अस्वीकृति ही बैच पथ को सुरक्षित बनाती है। मिश्रित-कोटि की कुंजी निम्न-कोटि की नहीं होती, इसलिए कोई blocklist उस तक नहीं पहुँचती, और ठीक वहीं cofactor वाला बैच सत्यापक और cofactor-रहित एकल सत्यापक असहमत होते हैं। कुंजी और R के अभाज्य-कोटि उपसमूह में होने पर दोनों सिद्ध रूप से समतुल्य हैं — इसलिए बैच सत्यापक cofactor वाला हो सकता है, बशर्ते वह बैच बनाने से पहले वही एन्कोडिंग और torsion नियम लागू करे। यह बाध्यता ही इस चुनाव की क़ीमत है, और बैच सत्यापक अभी मौजूद नहीं है।
कैनोनिकल एन्कोडिंग और पहचानकर्ता#
सभी consensus वस्तुएँ SSZ कंटेनर हैं: एक अकेली कैनोनिकल बाइट एन्कोडिंग, कोई map क्रम नहीं, वैकल्पिक-फ़ील्ड की कोई अस्पष्टता नहीं, सस्ते आंशिक पार्सिंग के लिए नियत ऑफ़सेट, और देशी merkleization।
cert_id = blake3("zcd/certid/v1" || ssz(certificate with an empty signature list))
cert_exemplar = blake3("zcd/cert/v1" || ssz(certificate))
block_id = blake3("zcd/block/v1" || ssz(header))
पहले दो अलग-अलग प्रश्नों का उत्तर देने वाले अलग digest हैं, और जो कार्यान्वयन एक को वहाँ इस्तेमाल करता है जहाँ दूसरा चाहिए वह मौद्रिक रूप से टूटा हुआ है। id इसका उत्तर देती है कि क्या इस अधिकार का बिल बन चुका है; exemplar हैश इसका कि क्या ये बाइट उसे सिद्ध करते हैं। दोनों कभी एक कुंजी साझा नहीं करते।
हस्ताक्षर id के preimage से बाहर हैं क्योंकि हस्ताक्षर एक यादृच्छिक प्रदर्शन है: nonce हस्ताक्षरकर्ता चुनता है, हर nonce उसी बॉडी पर एक और valid और बिलकुल कैनोनिकल हस्ताक्षर देता है, और कोई सत्यापक जाँच नहीं सकता कि कौन-सा इस्तेमाल हुआ। अगर वे भीतर होते, तो एक अधिकार की असीम रूप से कई id होतीं, हर एक बिल-योग्य, और हर एक उसके ज़रूरी हस्ताक्षरकर्ताओं में से किसी एक द्वारा बाक़ी के अधिकार से बनाई जा सकने वाली।
id के बाहर की बोली ऐसी बोली होती जिसे रास्ते में कोई भी दोबारा लिख सकता — इतनी बढ़ा देता कि आधार शुल्क से हस्ताक्षरकर्ता का शेष जल जाए, या शून्य कर देता ताकि सर्टिफिकेट हर ब्लॉक से बाहर रहे। सर्टिफिकेट क्या चुकाता है यह उसी का हिस्सा है जिसे उसके हस्ताक्षरकर्ता ने अधिकृत किया, इसलिए वह हैश होता है और उस पर हस्ताक्षर होता है। बाद में हुआ ऐसा कोई एन्कोडिंग बदलाव जो "relay के लचीलेपन के लिए शुल्क को हस्ताक्षरित बॉडी से बाहर करे" अनुकूलन जैसा दिखेगा और चोरी का रास्ता होगा।
इससे निकलने वाला नियम: पार्स करो, दो बार वैधता मत जाँचो। डिकोडिंग कैनोनिकल रूप को लागू करती है, इसलिए डिकोड की गई वस्तु रचना से ही संरचनात्मक रूप से valid होती है और नियम-इंजन आकार दोबारा कभी नहीं जाँचते।
cell मॉडल#
एक cell किसी slot पर मौजूद मान है। cell के मान 32 बाइट में big-endian संग्रहीत अचिह्नित 256-बिट पूर्णांक होते हैं। अनुपस्थित cell शून्य के रूप में पढ़े जाते हैं — शून्य ही अनुपस्थिति है, और यह कार्यान्वयन की सुविधा नहीं बल्कि एक consensus अपेक्षा है: इससे state root उस स्टेट का फलन बना रहता है, न कि उस इतिहास का जिसने उसे बनाया।
अलग से, प्रोटोकॉल एक spent-address registry रखता है: उन one-shot पतों का स्थायी consensus समुच्चय जिनका हस्ताक्षर अधिकार जला दिया गया है।
Addr = version || blake3("zcd/addr/v1" || version || payload)[:31]
| संस्करण | प्रकार | डेबिट अधिकार |
|---|---|---|
0x01 | one-shot उपयोगकर्ता | स्वामी का हस्ताक्षर; डेबिट करने वाले हर सर्टिफिकेट को एक स्पष्ट MARK_SPENT भी ढोना होगा। उसके लागू होने के बाद उस पते के तहत हर पठन और लेखन हमेशा के लिए विफल हो जाता है। |
0x02 | persistent उपयोगकर्ता | स्वामी का हस्ताक्षर; हमेशा दोबारा इस्तेमाल योग्य। कभी spent registry में नहीं जा सकता। |
0x03 | परिसंपत्ति | परिसंपत्ति के अपरिवर्तनीय अधिकार cell से संचालित। |
0x00 | प्रोटोकॉल | केवल fold: epoch beacon, आधार-शुल्क cell, coinbase maturity रिंग, treasury cell। |
0x04 | आरक्षित — छिपे-मान वाला cell (Era S) | Era 0 में अपहुँच। |
0x04 बाद में आवंटित करने के बजाय अभी आरक्षित है, क्योंकि छिपे मान को
साधारण मान से उसके पते से अलग पहचाना जा सकना चाहिए: एक Pedersen commitment और एक 256-बिट शेष,
दोनों 32 बाइट के हैं, इसलिए भूल या दुर्भावना से किसी commitment slot पर ताना गया guarded delta fold से एक
पूर्णांक को वक्र-बिंदु एन्कोडिंग में जुड़वा देता — ऐसा अंकगणित जो हर जाँच पास कर जाता है और एक ऐसा cell
छोड़ जाता है जिसे कोई कभी खर्च नहीं कर सकता। यह तालिका genesis पर जमा दी गई है, इसलिए यह बाइट यहीं दावा कर
ली गई है और अपहुँच छोड़ दी गई है।
registry की प्रविष्टि कभी संकुचित नहीं की जाती। spent पते के तहत cell के मान undo horizon के बाद छाँटे जा सकते हैं, पर जो प्रविष्टि पते को spent दर्ज करती है वही उसे पुनर्जीवित होने से रोकती है। यह केवल-जोड़ी जाने वाली consensus स्टेट है, प्रति पता लगभग 33 बाइट, हमेशा के लिए — प्रोटोकॉल की ईमानदार खुली समस्या, जो हर nullifier-set डिज़ाइन के साथ संरचनात्मक रूप से साझा है।
स्टेटलेस वैधता, और बिलिंग नियम#
V-नियम हर सर्टिफिकेट पर, समानांतर में, mempool में प्रवेश से पहले और ब्लॉक सत्यापन के दौरान चलते हैं, और उन्हें शून्य स्टेट चाहिए: कैनोनिकल रूप और chain id; हर हस्ताक्षर का signing root पर सत्यापित होना; अधिकार का केवल सर्टिफिकेट से व्युत्पन्न होना; घोषित reads का उसके बराबर होना जो प्रोग्राम निकालता है; और रिफ़ंड गंतव्य का उसके विरुद्ध जाँचा जाना जिसे सर्टिफिकेट ख़ुद जलाता है।
व्यवस्था का बिलिंग नियम एक वाक्य का है, और यही पकड़कर रखने लायक चीज़ है:
एक हस्ताक्षर, अधिकतम एक बिल, और कभी ऐसी स्थिति पर नहीं जिससे उसका हस्ताक्षरकर्ता बच न सकता हो।
यह विशिष्टि श्वेतपत्र की शब्दावली में एक शब्द जोड़ती है: drop, यानी बिना बिल वाली अघटना। जो सर्टिफिकेट अपनी जमा राशि पहले ही खप जाने के बाद प्रयोग तक पहुँचता है वह drop हो जाता है — न बिल, न seen चिह्न, और ताज़ा जमा के विरुद्ध दोबारा भेजने को स्वतंत्र — इसलिए ईमानदार उपयोगकर्ता अपने ही जमा cell पर हुई दौड़ में कुछ नहीं गँवाते।
रिपॉज़िटरी का ढाँचा#
zycord/
spec/ parameter sets, golden vectors, library images <- THE PROTOCOL
core/ consensus-critical; standard library only (P4)
types/ crypto/ ssz/ u256/ state/ validity/ fold/ params/ genesis/
cevm/ the certificate-adapted EVM; vendored interpreter, pure Go
stdlib/ the pre-deployed library, its addresses and code hashes
pow/randomx/ the mainnet engine: vendored C++, cgo, behind a build tag
node/ storage/ chain/ verify/ mempool/ miner/ p2p/ sync/ rpc/ stratum/
wallet/ key management, certificate builders (reference; not consensus)
contracts/ the reference contracts, in Solidity
sim/ simulator, fuzz harnesses, differential refold, chaos soak
cmd/ zycordd, zcd
desktop/ the wallet in a native window — a separate Go module
docs/ architecture, protocol, operating guide, whitepaper
निर्भरता के तीर केवल भीतर की ओर जाते हैं — node → core,
wallet → core, कभी उल्टा नहीं — और core/ के भीतर कुछ भी
core/ और मानक लाइब्रेरी के बाहर नहीं पहुँचता। एक अपवाद, नामित और प्रवर्तित:
core/pow/randomx पेड़ का इकलौता cgo है, और वह केवल उस build tag के तहत कंपाइल होता है,
इसलिए उस tag के बिना बना हर बिल्ड अब भी केवल मानक-लाइब्रेरी वाला है और उसे किसी C toolchain की ज़रूरत नहीं।
इसे प्रवर्तित करने वाली जाँच CI चलाता है, क्योंकि तीसरे-पक्ष वाली जाँच मॉड्यूल पथ खोजती है और cgo के पास
कोई पथ नहीं होता — जिससे यह नियम तब तक किसी से प्रवर्तित नहीं था जब तक वह जाँच जोड़ी नहीं गई।
इसका परीक्षण कैसे होता है#
- Golden vectors। हर fold, ब्लॉक और वैधता नियम के सकारात्मक और नकारात्मक मामले
(pre-state, block) → (post-state | invalid, outcomes, fees)के रूप में हैं। यह सुइट स्वतंत्र कार्यान्वयनों के लिए संगतता अनुबंध है। - griefing सुइट। लागू और skip हुए सर्टिफिकेट का दोबारा शामिल होना, समय-समाप्त शामिलीकरण, कम-बोली शामिलीकरण, proposer फेरबदल के तहत निर्भर शृंखलाएँ, जला-और-लौटा चक्र, तीसरे-पक्ष की क्रेडिट आँधियाँ, mint-सीमा पर सीमांत दौड़ें।
- गुण-आधारित। proposer-क्रम के क्रमचय के तहत fold की नियतता, delta की क्रम-निरपेक्षता, ABA सहनशीलता, और संरक्षण — जिसमें रास्ते में पड़ी जमा राशियाँ, maturity रिंग और treasury cell भी शामिल हैं, क्योंकि जो संरक्षण जाँच treasury को छोड़ देती है वह हर ब्लॉक को मूल्य गढ़ता हुआ बताती है।
- विभेदक। जानबूझकर भोला बनाया गया दूसरा fold कार्यान्वयन, जो गति के बजाय स्पष्टता के लिए लिखा गया है, असली वाले के विरुद्ध fuzz किया जाता है। दोनों में फ़र्क़ आना रिलीज़ रोक देता है।
- प्रतिकूल अनुकरण। skip की आँधियाँ, जमा-निचोड़ दौड़ें, drop भरने वाले माइनर, reorg यंत्रणा, टाइमस्टैम्प तोड़-मरोड़, हल्के eclipse relay परिदृश्य। परिदृश्य कॉन्फ़िग कमिट किए जाते हैं; रन seed से पुनरुत्पाद्य हैं।
- समवर्तिता, जानबूझकर। जिस भी घटक को एक से ज़्यादा goroutine छूती हैं उसका एक ऐसा परीक्षण है जो ख़ुद समवर्ती है, उसी आकार में जिसमें प्रक्रिया वास्तव में चलती है। एकल-goroutine सुइट पर
-raceकुछ नहीं मापता और सफलता बता देता है। - अफ़रा-तफ़री वाला soak। असली नोड प्रक्रियाएँ, असली सॉकेट पर, ऐसी प्रॉक्सी के पीछे जो विलंब, jitter, हानि और विभाजन डालती है, और नोड को बेतरतीब
SIGKILLसे मारा जाता है। यही वह सतह है जिसने उस डेटा race को पकड़ा जिसे पूरा-raceसुइट चूक गया था।
Genesis एक कलाकृति है, कोई समारोह नहीं#
zcd genesis genesis ब्लॉक निकालता है — ख़ाली स्टेट, आरंभीकृत beacon cell,
ख़ाली spent registry, किसी भी तरह का कोई आवंटन नहीं — और उसकी id। घोषित
लॉन्च हफ़्तों पहले कोड टैग, पैरामीटर हैश, genesis id और लॉन्च समय के प्रति प्रतिबद्ध होता है। कोई भी इन चारों
को स्रोत से, किसी भी मशीन पर, मिलीसेकंडों में दोबारा बना सकता है।
भरोसा करने को और कुछ है ही नहीं।