इस पृष्ठ का उपयोग किसी भी ऐसी चीज़ को बनाने या ऑडिट करने के लिए करें जो पूल को पढ़ती है: ऐसा वॉलेट जो अपने नोट्स के लिए स्कैन करता है, ऐसा इंडेक्सर जो कमिटमेंट और न्यूलिफ़ायर का अनुसरण करता है, या ऐसा टूल जो जाँचता है कि कोई ट्रांज़ैक्शन क्या प्रकाशित करता है। इस चेन पर मूल्य नोट्स का एक समुच्चय है; चेन उनके कमिटमेंट रखती है, उनकी सामग्री कभी नहीं।
एक नोट
एक नोट { pk, from, amount, asset, time, r } है: 32 बिट के 28 वर्ड, 112 बाइट, जिनका क्रम pk(8) from(8) amount_lo amount_hi asset time r(8) है। pk स्वामी का नोट सार्वजनिक मान है (व्यूइंग कुंजी से व्युत्पन्न), from प्रेषक का, amount इकाइयों में एक u64 (1 RAND = 10⁹ इकाइयाँ), asset एक u32 (RAND के लिए 0, अन्यथा किसी RPL टोकन के लिए, चाहे ब्रिज्ड हो या नेटिव, टोकन रजिस्ट्री का सघन सूचकांक; देखें RPL टोकन), time वह ब्लॉक ऊँचाई जिसे प्रेषक ने लक्षित किया, और r ब्लाइंडिंग के आठ यादृच्छिक वर्ड।
प्लेनटेक्स्ट कभी चेन पर प्रकट नहीं होता। जो प्रकट होता है, वह है:
- इसका कमिटमेंट
cm = H(CM, words), डोमेन टैग 4 के अंतर्गत 28 वर्डों का Poseidon2 हैश, जो ट्री में एक लीफ़ के रूप में जोड़ा जाता है; - इसका एनवेलप, स्वामी के पते पर सील किया गया प्लेनटेक्स्ट, ताकि केवल स्वामी, या अपनी आउटगोइंग व्यूइंग कुंजी के माध्यम से प्रेषक, उसे पढ़ सके। चेन 18 से (चेन 20 सहित) एनवेलप में एक एन्क्रिप्टेड मेमो भी होता है। कुछ नोट्स, जिनकी गणना चेन सार्वजनिक फ़ील्ड से करती है, कोई एनवेलप नहीं रखते (नीचे)।
नोट को खर्च करने पर उसका न्यूलिफ़ायर H(NF, nk, cm) प्रकाशित होता है, जो स्वामी की व्यूइंग कुंजी और कमिटमेंट का डोमेन टैग 3 के अंतर्गत Poseidon2 हैश है। nk के बिना किसी न्यूलिफ़ायर को उसके कमिटमेंट से नहीं जोड़ा जा सकता। न्यूलिफ़ायर समुच्चय ही दोहरे व्यय को रोकता है।
एनवेलप
Envelope { kem_ct, to_receiver, to_sender, body }
| भाग | बाइट | विवरण |
|---|---|---|
kem_ct | 1,088 | प्राप्तकर्ता के पते पर एक ML-KEM-768 एनकैप्सुलेशन |
to_receiver | 60 | प्रति-ट्रांज़ैक्शन कुंजी TxKey, एनकैप्सुलेट किए गए सीक्रेट के अंतर्गत रैप की गई |
to_sender | 60 | वही TxKey, प्रेषक की आउटगोइंग व्यूइंग कुंजी ovk के अंतर्गत रैप की गई |
body | 652 | 112-बाइट नोट और 512-बाइट मेमो फ़ील्ड, TxKey के अंतर्गत (चेन 17 तक 140 बाइट, केवल नोट) |
हर भाग ChaCha20-Poly1305 है, जिसके आगे एक यादृच्छिक 12-बाइट नॉन्स जुड़ा होता है और एक 16-बाइट टैग होता है। संबद्ध डेटा एक टैग (rand-envelope-receiver, rand-envelope-sender, rand-envelope-body) है जिसके बाद नोट का कमिटमेंट आता है, ताकि कोई कुंजी ऐसा एनवेलप न खोल सके जिसे उसने सील नहीं किया, और खोला गया नोट उसी लीफ़ से बँधा रहे जिसके अंतर्गत वह स्थित है। यह 1,860 बाइट सिफ़रटेक्स्ट है; bincode के लंबाई-प्रीफ़िक्स इसे वायर पर 1,892 बाइट बना देते हैं। चेन 20 का जेनेसिस envelope_bytes: 1860 सेट करता है, और उसका लेजर किसी भी अन्य लंबाई के नोट एनवेलप को अस्वीकार करता है (envelope is 1348 bytes, this chain requires exactly 1860); वह इसके बारे में और कुछ नहीं जाँचता। चेन 17 तक एनवेलप में कोई मेमो फ़ील्ड नहीं था और वह 1,348 बाइट (वायर पर 1,380) का था, और लेजर केवल उसकी अधिकतम सीमा 2,048 बाइट तय करता था। जिस चेन के जेनेसिस में envelope_bytes नहीं है, उस पर अब भी यही नियम लागू है।
मेमो फ़ील्ड len (u16 LE) ‖ UTF-8 text ‖ zero padding है, 512 बाइट, अतः अधिकतम 510 बाइट टेक्स्ट। चेन 20 के हर नोट एनवेलप में यह होता है, चाहे मेमो हो या न हो: चेंज आउटपुट, डमी आउटपुट और बिना मेमो का भुगतान एक ही तरह से पैड किए जाते हैं, और चेन पर कुछ भी न मेमो को, न उसकी लंबाई को, न उसकी अनुपस्थिति को अलग से पहचानने देता है। मेमो न नोट में है, न कमिटमेंट में, न किसी प्रूफ़ में। इसे ठीक वही पढ़ सकता है जो पहले से नोट पढ़ सकता है: स्वामी, ovk के माध्यम से प्रेषक, या कोई भी जिसे उस आउटपुट की TxKey सौंपी गई हो। विकृत मेमो फ़ील्ड (गलत लंबाई, अमान्य UTF-8, गैर-शून्य पैडिंग) “कोई मेमो नहीं” के रूप में खुलता है, और इससे स्वामी का नोट कभी नहीं खोता। मेमो का टेक्स्ट कोई भी लिख सकता है, क्योंकि कोई भी किसी सार्वजनिक पते पर डस्ट नोट भेज सकता है: इसे अविश्वसनीय मानकर दिखाएँ, और कंट्रोल तथा Unicode फ़ॉर्मैट वर्णों को बदल दें, जैसा rand वॉलेट करता है। rand send --memo भुगतान आउटपुट में एक मेमो सील करता है; rand notes --memo और rand history --memo उसे दिखाते हैं।
ट्री, एंकर और विंडो
कमिटमेंट एक 32-गहराई वाले Poseidon2 ट्री में सबसे पुराने से शुरू करके क्रम से जोड़े जाते हैं, और कभी हटाए नहीं जाते। लीफ़ i वह i-वाँ नोट है जो चेन ने कभी बनाया; जेनेसिस डिपॉज़िट नोट्स पहले लीफ़ हैं। एक बंडल चाहे जो भी स्थानांतरित करे, वह चार लीफ़ और चार न्यूलिफ़ायर जोड़ता है, डमी सहित। खाली लीफ़ पूरी तरह शून्य होता है और एक नोड H(NODE, left, right) होता है (डोमेन टैग 7)। एक नोड केवल फ्रंटियर रखता है, इसलिए सर्वसम्मति अवस्था में लीफ़ कभी नहीं रहते; rand_getWitness माँग पर संग्रहीत लीफ़ों से पूरा ट्री फिर से बनाता है, इसीलिए यह किसी नोड द्वारा दिया जाने वाला सबसे महँगा रीड है।
एक बंडल अपने इनपुट की सदस्यता एक एंकर, यानी एक ट्री रूट, के विरुद्ध सिद्ध करता है। दो नियम एंकर की प्रामाणिकता सुनिश्चित करते हैं:
| स्थिरांक | मान | नियम |
|---|---|---|
ANCHOR_WINDOW | 256 ब्लॉक; चेन 20 पर 1,024 | एंकर अंतिम window ब्लॉक-अंत रूट में से एक होना चाहिए; ब्लॉक के बीच में ट्री जिस रूट से गुज़रता है, वह कभी एंकर नहीं होता |
TIME_WINDOW | 256 ब्लॉक; चेन 20 पर 1,024 | बंडल का time [height − window, height] के भीतर होना चाहिए |
दोनों विंडो 256 ब्लॉक की होती हैं, जब तक जेनेसिस proof_window_blocks (v0.6.8, 256 से 4,096) सेट न करे, जो दोनों को एक साथ प्रतिस्थापित करता है। चेन 20 इसे 1,024 पर सेट करती है; चेन 14 से 19 में यह फ़ील्ड नहीं था।
विंडो इसलिए हैं क्योंकि प्रूविंग में वास्तविक समय लगता है: लैपटॉप पर एक टियर-14 बंडल प्रूफ़ में लगभग 100 सेकंड मापे गए हैं (और चेन 17 से वॉलेट एक दूसरा, टियर-10 ऑथ प्रूफ़ भी बनाता है, लगभग 7 सेकंड में)। चेन 18 के 1.17 s ब्लॉकों पर 256 ब्लॉक लगभग पाँच मिनट के बराबर थे, और एक धीमे प्रूवर पर डेलिगेटेड प्रूफ़ 294 s पर अस्वीकार हो गया था; वहाँ एक्सप्लोरर द्वारा बताए गए 1.34 s पर चेन 20 के 1,024 ब्लॉक लगभग 23 मिनट हैं। जो वॉलेट यह दौड़ हार जाता है, उसे anchor is not one of the last 1024 roots संदेश मिलता है और वह फिर से प्रूव करता है। rand_getAnchor बिना पैरामीटर के हेड का ब्लॉक-अंत रूट लौटाता है; यही एकमात्र एंकर है जिसके विरुद्ध प्रूवर को प्रूफ़ बनाना चाहिए।
बंडल
मूल्य स्थानांतरित करने वाले हर ट्रांज़ैक्शन में ठीक एक निश्चित 4-इन-4-आउट हिडन-एसेट बंडल होता है (चेन 14 से; चेन 13 तक यह 2-इन-2-आउट था)। इसे हिडन-एसेट zkVM गेस्ट सिद्ध करता है, जिसका डाइजेस्ट hc_bundle जेनेसिस फ़ाइल में पिन किया गया है (60af094acfe65d85fdb18fb3d06cf9085dcf28c96e59e87f1ee527226e6e3fce, बंडल गेस्ट v3, चेन 17 से 20 पर; चेन 14 और 15 पर यह 83d3a3704a1fcdb9bae7136c0a947ffa34bd53f055388395ed705fe8cacd0ef8 था, गेस्ट v1):
Bundle { anchor, nullifiers[4], commitments[4], fee, burn_a, burn_r, burn_asset, time, envelopes[4], proof,
auth_commit, auth_proof } // the last two since chain 17
स्लॉट 0–1, इनपुट और आउटपुट दोनों में, एक निजी एसेट A रखते हैं; स्लॉट 2–3 हमेशा RAND रखते हैं। केवल-RAND भुगतान में स्लॉट 0–1 डमी होते हैं, और मूल्य तथा शुल्क स्लॉट 2–3 से होकर जाते हैं। टोकन ट्रांसफ़र में टोकन स्लॉट 0–1 से होकर जाता है और RAND शुल्क उसी प्रूफ़ के स्लॉट 2–3 से चुकाया जाता है। A प्रूफ़ का एक विटनेस वर्ड है और किसी सार्वजनिक फ़ील्ड में नहीं होता, इसलिए किसी भी RPL टोकन का ट्रांसफ़र burn_a = burn_r = burn_asset = 0 के साथ Action::None होता है, और फ़ील्ड-दर-फ़ील्ड उसका आकार RAND भुगतान जैसा ही होता है।
प्रूफ़ यह स्थापित करता है कि हर वास्तविक इनपुट anchor के अंतर्गत एक लीफ़ है और अपने स्लॉट का एसेट रखता है, कि चारों न्यूलिफ़ायर वही हैं जो प्रकाशित किए गए हैं, कि हर समूह संतुलित है (निजी एसेट में in0 + in1 = out0 + out1 + burn_a, RAND में in2 + in3 = out2 + out3 + fee + burn_r), और कि खर्च करने वाले के पास कुंजियाँ हैं — यह प्रकट किए बिना कि कौन-से लीफ़, कौन-सी राशियाँ, कौन-सा एसेट, या कौन। तीनों बर्न फ़ील्ड पूल से बाहर जाने वाले मूल्य के बारे में बंडल का एकमात्र सार्वजनिक कथन हैं: burn_a और burn_asset केवल TokenBurn या BridgeBurn में गैर-शून्य होते हैं, जहाँ वे एक्शन की राशि और एसेट के बराबर होते हैं; burn_r बर्न किया गया RAND है, जो केवल Bond (स्टेक) और RegisterAggregator (बॉन्ड) में गैर-शून्य होता है। शुल्क हमेशा RAND में होता है।
चेन 17 से खर्च करने का अधिकार दो प्रूफ़ में विभाजित है (विभाजित प्राधिकरण)। पहले के गेस्ट स्पेंड कुंजी लेते थे; बंडल गेस्ट v3 उसकी जगह व्यूइंग कुंजी nk और एक सॉल्ट लेता है: यह pk_self = H(PK, nk) व्युत्पन्न करता है, यह अनिवार्य करता है कि हर इनपुट का स्वामी यही हो, और c = H(AUTH, nk ‖ salt) को उस डाइजेस्ट में शामिल करता है जिसे वह प्रकाशित करता है। एक दूसरा गेस्ट, ऑथ गेस्ट (जेनेसिस hc_auth, 1e4e347f44cf86750b30a9a4bdf9ec9256efe353d4ff8017451eca7d195639c1), स्पेंड कुंजी sk और वही सॉल्ट लेता है, nk = H(NK, sk) व्युत्पन्न करता है और वही c प्रकाशित करता है। बंडल c को auth_commit के रूप में और ऑथ गेस्ट के टियर-10 प्रूफ़ को auth_proof के रूप में रखता है। लेजर यह अनिवार्य करता है कि दोनों प्रूफ़ एक ही ट्रांज़ैक्शन बाइंडिंग के विरुद्ध सत्यापित हों और c के दोनों मान मेल खाएँ। इसलिए nk और सॉल्ट रखने वाला प्रूवर बंडल प्रूफ़ बना सकता है, पर ऑथ प्रूफ़ नहीं, और डेलिगेटेड प्रूविंग इसी पर आधारित है। सॉल्ट हर बंडल के लिए 256 नए यादृच्छिक बिट होता है, इसलिए auth_commit सार्वजनिक होते हुए भी किसी चीज़ को किसी दूसरी चीज़ से नहीं जोड़ता। जो वॉलेट स्वयं प्रूव करता है, वह भी दोनों प्रूफ़ बनाता है, इसलिए स्वयं प्रूव किया गया और डेलिगेटेड ट्रांज़ैक्शन चेन पर एक जैसे दिखते हैं।
आकार स्थिर है, इसलिए स्लॉट प्रायः डमी होते हैं: डमी इनपुट खर्च करने वाले के स्वामित्व वाला शून्य-मूल्य नोट होता है (उसका न्यूलिफ़ायर फिर भी प्रकाशित होता है), डमी आउटपुट शून्य-राशि का नोट होता है, और चेंज आउटपुट तब भी मौजूद रहता है जब चेंज शून्य हो। जो ट्रांज़ैक्शन चेंज न होने पर अलग दिखता, वह यह उजागर कर देता कि चेंज नहीं था। वॉलेट के लिए इसका परिणाम: किसी बंडल के दोनों समूहों में से प्रत्येक अधिकतम दो नोट खर्च करता है। RAND भुगतान, बॉन्ड, डिप्लॉय या कॉल अधिकतम दो RAND नोट खर्च करता है; टोकन ट्रांसफ़र या बर्न टोकन के अधिकतम दो नोट और शुल्क के लिए अधिकतम दो RAND नोट खर्च करता है। एक समूह में तीन या अधिक नोटों में बँटे मूल्य को पहले समेकित करना होता है, अपने ही पते पर भेजकर।
चेन 14 से प्रूफ़ अपने ट्रांज़ैक्शन से भी बंधा है: वह प्रूफ़ों को रिक्त करके पूरे ट्रांज़ैक्शन के हैश पर बनाया और उसी के विरुद्ध सत्यापित किया जाता है, इसलिए उसे किसी अन्य ऐक्शन, अन्य एनवेलपों या अन्य चेन पर कॉपी नहीं किया जा सकता; चेन 20 पर हैश में जेनेसिस हैश भी शामिल है, इसलिए उसे ऐसी चेन पर भी कॉपी नहीं किया जा सकता जिसकी चेन आईडी समान हो (ट्रांज़ैक्शन)।
क्या सार्वजनिक है और क्या छिपा है
| चेन पर सार्वजनिक | छिपा हुआ | |
|---|---|---|
| RAND का या किसी भी RPL टोकन का ट्रांसफ़र | एंकर, चारों न्यूलिफ़ायर, चारों कमिटमेंट, शुल्क, burn_a = burn_r = burn_asset = 0, time, चार एनवेलप सिफ़रटेक्स्ट, प्रूफ़, auth_commit और ऑथ प्रूफ़ | किसने भेजा, किसे भुगतान हुआ, राशि, मेमो, कौन-सा एसेट स्थानांतरित हुआ, चेंज, कौन-सी लीफ़ खर्च हुईं, कौन-से स्लॉट डमी थे |
| टोकन बर्न या ब्रिज बर्न | वह सब जो ट्रांसफ़र प्रकाशित करता है, साथ में burn_asset और burn_a ऐक्शन के एसेट और राशि के बराबर (और, ब्रिज बर्न के लिए, रिलेयर शुल्क, बैकिंग टोकन और गंतव्य) | कौन-से नोट बर्न हुए, और उन्हें किसने बर्न किया |
| फ़ॉसेट मिंट | कमिटमेंट, एनवेलप, राशि, मिंट करने वाला वैलिडेटर, और चेन 14 से नोट का ओपनिंग (pk, time, r), जिससे एडमिशन कमिटमेंट की पुनर्गणना करता है | नोट का हर बाद का खर्च |
| जेनेसिस डिपॉज़िट | जेनेसिस फ़ाइल में { cm, envelope, amount, opening: { pk, time, r } }, सूचीबद्ध टोकन के नोट के लिए ओपनिंग में asset के साथ (चेन 20 के जेनेसिस में दो zUSD नोट हैं): स्वामी का pk, राशि और एसेट डिज़ाइन के अनुसार सार्वजनिक हैं | वह बाद में कब और किसमें खर्च होता है |
| विदड्रॉ, ब्रिज डिपॉज़िट, टोकन मिंट या रजिस्ट्रेशन का प्रारंभिक मिंट | राशि, प्राप्तकर्ता, नोट का time और ब्लाइंडिंग r (चेन कमिटमेंट की गणना स्वयं करती है) | नोट का हर बाद का खर्च |
| इनवोक का पेआउट या प्रोग्राम मिंट (चेन 20) | राशि, एसेट, प्राप्तकर्ता और r; नोट का time बंडल का होता है | नोट का हर बाद का खर्च |
| ब्रिज शुल्क नोट (चेन 20) | राशि, एसेट और time, एक व्युत्पन्न ब्लाइंडिंग, स्वामी के रूप में जेनेसिस ट्रेज़री, और कोई एनवेलप नहीं | नोट का हर बाद का खर्च |
मूल्य पूल में सार्वजनिक राशि के साथ प्रवेश करता है — फ़ॉसेट मिंट, जेनेसिस डिपॉज़िट, वैलिडेटर का विदड्रॉ, ब्रिज अटेस्टेशन और उसका शुल्क नोट, टोकन मिंट, प्रोग्राम वॉल्ट का पेआउट — और सार्वजनिक शुल्क या बर्न के रूप में उससे बाहर निकलता है। बीच में सब कुछ नोट है।
यह तालिका वही दर्शाती है जो चेन 20 के प्रूफ़ छिपाते हैं, और यह हमेशा सच नहीं थी। चेन 14 और 15 पर बंडल प्रूफ़ स्वयं अधिक उजागर करता था (2026-09-27 की zkVM समीक्षा, INT-2 / GV-1): प्रत्येक तालिका का LogUp रनिंग टोटल बिना ब्लाइंडिंग के प्रकाशित होता था, और v1 गेस्ट डमी इनपुट के लिए मर्कल और एसेट जाँच छोड़ देता था और हर मर्कल पाथ बिट पर ब्रांच करता था, इसलिए कोई भी बंडल प्रूफ़ से पढ़ सकता था कि चार इनपुट स्लॉट में से कौन-से वास्तविक थे, और इस प्रकार यह भी कि उसने कोई टोकन स्थानांतरित किया या केवल RAND, तथा प्रत्येक खर्च की गई लीफ़ के इंडेक्स में 1 बिट की संख्या। दो परिवर्तनों ने इसे बंद किया। चेन 16 कंस्ट्रेंट सेट 7 पर गई, जो हर LogUp टर्मिनल को ब्लाइंड करता है और हर घोषित तालिका को न्यूनतम 2^7 पंक्तियों तक रखता है, और ब्रांच-रहित बंडल गेस्ट v2 पर गई, जिसमें हर स्लॉट, डमी हो या वास्तविक, समान निर्देशों के माध्यम से पूर्ण सदस्यता और एसेट जाँच चलाता है। गेस्ट v3, जिसे चेन 17 से 20 चलाती हैं, v2 का ही रिलेशन है जिसमें स्पेंड की के स्थान पर nk और सॉल्ट हैं, और वह भी ब्रांच-रहित है। चेन 14 और 15 पर कमिट हुए बंडलों ने जो उजागर किया, वह उजागर ही रहता है। चेन 20 पर प्रूफ़ अब भी जो दिखाता है, वह उसका हेडर है: बंडल के लिए वह एक स्थिर आकार है (टियर 14, हर बंडल पर 20,479 की घोषित गैस सीमा), और Call या Invoke के लिए वह टियर, घोषित गैस सीमा, और यह है कि कॉल ने keccak या sha256 प्रीकंपाइल का उपयोग किया या नहीं और लगभग कितनी बार (प्रूफ़)।
एनवेलप के बिना नोट
अधिकांश नोट अपना एनवेलप खोलकर पाए जाते हैं। कुछ की गणना चेन सार्वजनिक फ़ील्ड से करती है, और उनके लिए एनवेलप या तो अनुपस्थित होता है या भरोसे योग्य नहीं होता।
- ब्रिज शुल्क नोट (चेन 20)।
bridge.feesके अंतर्गत चेन हर डिपॉज़िट और हर बर्न पर जेनेसिस ट्रेज़री के लिए एक zUSD नोट जोड़ती है (RPL टोकन)। इसका कोई एनवेलप नहीं होता: स्टोरेज इसे एक रिक्त एनवेलप के साथ इंडेक्स करता है, जो किसी के लिए सील नहीं है, औरrand_getCompactBlocksतथाrand_getCommitmentsइसे इसी रूप में दिखाते हैं, डिपॉज़िट का शुल्क नोट डिपॉज़िट नोट के बाद और बर्न का शुल्क नोट बंडल के चार नोटों के बाद। नोट का हर शब्द सार्वजनिक है: राशि ट्रांज़ैक्शन और जेनेसिस दर से, एसेट औरtimeट्रांज़ैक्शन से,from = 0, ब्लाइंडिंग डिपॉज़िट के लिएblake3("rand-bridge-fee-r-1" ‖ mu)या बर्न के लिएblake3("rand-bridge-burn-fee-r-1" ‖ txid), और स्वामी जेनेसिसrecipient। - ऐसे नोट जिनका एनवेलप कुछ नहीं बाँधता। ब्रिज डिपॉज़िट, टोकन मिंट, रजिस्ट्रेशन का प्रारंभिक मिंट और, चेन 20 पर, इनवोक के पेआउट और प्रोग्राम मिंट ऐसा एनवेलप रखते हैं जिसे ट्रांज़ैक्शन सबमिट करने वाले ने सील किया है, परंतु चेन नोट की गणना ऐक्शन के सार्वजनिक फ़ील्ड से करती है और एनवेलप को उसके विरुद्ध कभी नहीं जाँचती। लापरवाह या शत्रुतापूर्ण सबमिटर कचरा सील कर सकता है, इसलिए प्राप्तकर्ता को उस पर निर्भर नहीं होना चाहिए।
इसलिए rand वॉलेट इन नोटों का पुनर्निर्माण स्वयं करता है (wallet::rebuilt_notes_with), ट्रायल डिक्रिप्शन के साथ-साथ एक सार्वजनिक पास में: अपने pk का नाम लेने वाले हर ऐसे ट्रांज़ैक्शन के लिए, और शुल्क नोटों के लिए जब उसका पता ट्रेज़री हो, वह नोट की गणना करता है और उसे उस लीफ़ पर दर्ज करता है जिसके कमिटमेंट से उसका हैश मेल खाता है। पुनर्निर्मित नोट केवल एक उम्मीदवार है: कोई नोड जो किसी ट्रांज़ैक्शन, शुल्क दर या हैश के बारे में झूठ बोलता है, किसी नोट को अप्राप्त बना देता है, किसी नोट को कभी क्रेडिट नहीं करता। v0.6.8 से rand_getBlocks द्वारा लौटाए गए हेडर public_notes में डिपॉज़िट, मिंट और रजिस्ट्रेशन ट्रांज़ैक्शन रखते हैं, और ब्रिज शुल्क वाली चेन पर बर्न भी, प्रूफ़ हटाकर, उनकी वास्तविक आईडी के अंतर्गत, इसलिए पास केवल हेडर पेज पढ़ता है। v0.6.8 में इनवोक public_notes में नहीं हैं, इसलिए v0.6.8 नोड के विरुद्ध वॉलेट इनवोक का पेआउट केवल उसके एनवेलप से पाता है, जिसे इनवोकर सील करता है और जिसे कुछ भी नहीं जाँचता। फ़ुलनोड main में d0bb73fb से इनवोक भी वहाँ हैं, प्रूफ़ हटाकर; यह केवल नोड का परिवर्तन है, अभी चेन 20 के फ़्लीट पर लागू नहीं हुआ है, और वॉलेट को इसके लिए किसी परिवर्तन की आवश्यकता नहीं है।
स्कैनिंग: वॉलेट अपने नोट कैसे पाता है
नोड उत्तर देता है “यह रहा पूरा ट्री”, कभी “यह रहा आपका बैलेंस” नहीं। वॉलेट:
rand_getCommitments(from_index, limit)(प्रति कॉल अधिकतम 1,000) या प्रति-ब्लॉक स्ट्रीमrand_getCompactBlocks(from_height, to_height)(प्रति कॉल अधिकतम 128 ब्लॉक) से लीफ़ को पेज-दर-पेज पढ़ता है; बंडल वाला हर ट्रांज़ैक्शन वहाँ चार नोट और चार न्यूलिफ़ायर सूचीबद्ध करता है, और कोई पाठक डमी स्लॉट को वास्तविक स्लॉट से अलग नहीं पहचान सकता;- हर एनवेलप को ट्रायल-डिक्रिप्ट करता है: प्राप्तकर्ता के रूप में अपनी ML-KEM डीकैप्सुलेशन की के माध्यम से, प्रेषक के रूप में
ovkके माध्यम से; उन नोटों को रखता है जिनकाpkउसका अपना है; और सार्वजनिक राशि वाले नोटों का उनके ट्रांज़ैक्शन से पुनर्निर्माण करता है (ऊपर); - हर रखे गए नोट के न्यूलिफ़ायर की गणना करता है और उन नोटों को चिह्नित करता है जिनके न्यूलिफ़ायर
rand_getNullifiers(from_height, limit)में दिखाई देते हैं; - शेष का योग करता है।
rand_getTreeInfo बताता है कि कितना स्कैन करना बाकी है: { "next_index", "root", "nullifiers" }। खर्च के लिए वॉलेट को हर वास्तविक इनपुट का 32-स्तरीय मर्कल पाथ चाहिए। rand वॉलेट कमिटमेंट ट्री की अपनी प्रति रखता है, जो स्कैन के दौरान उन्हीं rand_getCommitments पेजों से बनती है, और हर पाथ की गणना स्वयं करता है, इसलिए भेजते समय नोड से ट्री के बारे में पूछा जाने वाला एकमात्र प्रश्न rand_getAnchor है, जो किसी लीफ़ का नाम नहीं लेता। rand_getWitness(index) अन्य क्लाइंटों के लिए नोड पर बना रहता है। यह नोड को बताता है कि कॉलर कौन-सी लीफ़ खर्च करने वाला है, जो लोकल ट्री से पहले पूल का सबसे बड़ा लीक था: जिस क्लाइंट को इसका उपयोग करना ही पड़े, उसे अपना नोड चलाना चाहिए, या जिन विटनेस की उसे आवश्यकता है उनके साथ ऐसे विटनेस भी माँगने चाहिए जिनकी उसे आवश्यकता नहीं है।
rand sync # scanned 41 leaves and 37 blocks; 1 notes, 1 unspent
rand notes # index, asset, amount, height, spent, pending, memo
rand history # notes this wallet created for others, opened through ovk
rand send --no-wait और उसके बाद के उस sync के बीच, जो या तो उसका nullifier देखे या time + window के आगे के ब्लॉक देखे (chain 20 पर 1,024, जो rand_getLimits.proof_window_blocks से पढ़ा जाता है; इसके बिना 256), नोट pending रहता है। इसके बाद बंडल कभी स्वीकार नहीं किया जा सकता और नोट फिर से ख़र्च करने योग्य हो जाता है।