मुख्य सामग्री पर जाएं

येलो पेपर के EVM विनिर्देशों को समझना

evm
मध्यवर्ती
qbzzt
15 मई 2022
22 मिनट पढ़ें

येलो पेपर (एक नए टैब में खुलता है) इथेरियम के लिए औपचारिक विनिर्देश है। जहां EIP प्रक्रिया द्वारा संशोधन किया गया है उसे छोड़कर, इसमें हर चीज़ कैसे काम करती है इसका सटीक विवरण शामिल है। इसे एक गणितीय पेपर के रूप में लिखा गया है, जिसमें ऐसी शब्दावली शामिल है जिससे प्रोग्रामर शायद परिचित न हों। इस पेपर में आप सीखेंगे कि इसे कैसे पढ़ा जाए, और इसके विस्तार से अन्य संबंधित गणितीय पेपरों को भी।

कौन सा येलो पेपर?

इथेरियम में लगभग हर दूसरी चीज़ की तरह, येलो पेपर भी समय के साथ विकसित होता है। किसी विशिष्ट संस्करण का संदर्भ देने में सक्षम होने के लिए, मैंने लिखते समय वर्तमान संस्करण (एक नए टैब में खुलता है) अपलोड किया है। मेरे द्वारा उपयोग किए जाने वाले अनुभाग, पृष्ठ और समीकरण संख्याएँ उसी संस्करण को संदर्भित करेंगी। इस दस्तावेज़ को पढ़ते समय इसे एक अलग विंडो में खुला रखना एक अच्छा विचार है।

EVM क्यों?

मूल येलो पेपर इथेरियम के विकास की शुरुआत में ही लिखा गया था। यह मूल प्रूफ-ऑफ-वर्क (PoW) आधारित सर्वसम्मति तंत्र का वर्णन करता है जिसका उपयोग मूल रूप से नेटवर्क को सुरक्षित करने के लिए किया गया था। हालाँकि, इथेरियम ने प्रूफ-ऑफ-वर्क को बंद कर दिया और सितंबर 2022 में प्रूफ-ऑफ़-स्टेक (PoS) आधारित सर्वसम्मति का उपयोग करना शुरू कर दिया। यह ट्यूटोरियल येलो पेपर के उन हिस्सों पर ध्यान केंद्रित करेगा जो इथेरियम वर्चुअल मशीन (EVM) को परिभाषित करते हैं। प्रूफ-ऑफ़-स्टेक में संक्रमण से EVM अपरिवर्तित रहा (DIFFICULTY ऑपकोड के रिटर्न मान को छोड़कर)।

9 निष्पादन मॉडल (Execution model)

इस अनुभाग (पृष्ठ 14-16) में EVM की अधिकांश परिभाषा शामिल है。

सिस्टम स्थिति (system state) शब्द में वह सब कुछ शामिल है जो आपको सिस्टम को चलाने के लिए इसके बारे में जानने की आवश्यकता है। एक सामान्य कंप्यूटर में, इसका अर्थ मेमोरी, रजिस्टरों की सामग्री आदि है।

एक ट्यूरिंग मशीन (Turing machine) (एक नए टैब में खुलता है) एक कम्प्यूटेशनल मॉडल है। अनिवार्य रूप से, यह एक कंप्यूटर का सरलीकृत संस्करण है, जो यह साबित करता है कि इसमें गणना चलाने की वही क्षमता है जो एक सामान्य कंप्यूटर कर सकता है (वह सब कुछ जो एक कंप्यूटर गणना कर सकता है, एक ट्यूरिंग मशीन गणना कर सकती है और इसके विपरीत)। यह मॉडल इस बारे में विभिन्न प्रमेयों को साबित करना आसान बनाता है कि क्या गणना योग्य है और क्या नहीं।

ट्यूरिंग-पूर्ण (Turing-complete) (एक नए टैब में खुलता है) शब्द का अर्थ एक ऐसा कंप्यूटर है जो ट्यूरिंग मशीन के समान गणना चला सकता है। ट्यूरिंग मशीनें अनंत लूप (infinite loops) में जा सकती हैं, और EVM ऐसा नहीं कर सकता क्योंकि इसकी गैस खत्म हो जाएगी, इसलिए यह केवल अर्ध-ट्यूरिंग-पूर्ण (quasi-Turing-complete) है।

9.1 मूल बातें

यह अनुभाग EVM की मूल बातें देता है और यह अन्य कम्प्यूटेशनल मॉडलों के साथ कैसे तुलना करता है।

एक स्टैक मशीन (एक नए टैब में खुलता है) एक ऐसा कंप्यूटर है जो मध्यवर्ती डेटा को रजिस्टरों में नहीं, बल्कि एक स्टैक (एक नए टैब में खुलता है) में संग्रहीत करता है। यह वर्चुअल मशीनों के लिए पसंदीदा आर्किटेक्चर है क्योंकि इसे लागू करना आसान है जिसका अर्थ है कि बग और सुरक्षा कमजोरियों की संभावना बहुत कम है। स्टैक में मेमोरी को 256-बिट शब्दों (words) में विभाजित किया गया है। इसे इसलिए चुना गया था क्योंकि यह इथेरियम के मुख्य क्रिप्टोग्राफ़िक संचालन जैसे केकाक-256 हैशिंग और दीर्घवृत्तीय वक्र गणनाओं के लिए सुविधाजनक है। स्टैक का अधिकतम आकार 1024 आइटम (1024 x 256 बिट्स) है। जब ऑपकोड निष्पादित होते हैं तो वे आमतौर पर स्टैक से अपने पैरामीटर प्राप्त कर रहे होते हैं। स्टैक में तत्वों को पुनर्गठित करने के लिए विशेष रूप से ऑपकोड हैं जैसे POP (स्टैक के शीर्ष से आइटम हटाता है), DUP_N (स्टैक में Nवें आइटम की नकल करता है), आदि।

EVM में एक अस्थिर (volatile) स्थान भी होता है जिसे मेमोरी कहा जाता है जिसका उपयोग निष्पादन के दौरान डेटा संग्रहीत करने के लिए किया जाता है। यह मेमोरी 32-बाइट शब्दों में व्यवस्थित होती है। सभी मेमोरी स्थान शून्य पर प्रारंभ (initialized) किए जाते हैं। यदि आप मेमोरी में एक शब्द जोड़ने के लिए इस Yul (एक नए टैब में खुलता है) कोड को निष्पादित करते हैं, तो यह शब्द में खाली स्थान को शून्य से भरकर 32 बाइट्स मेमोरी भर देगा, यानी, यह एक शब्द बनाता है - स्थान 0-29 में शून्य के साथ, 30 में 0x60, और 31 में 0xA7।

mstore(0, 0x60A7)

mstore उन तीन ऑपकोड में से एक है जो EVM मेमोरी के साथ इंटरैक्ट करने के लिए प्रदान करता है - यह मेमोरी में एक शब्द लोड करता है। अन्य दो mstore8 हैं जो मेमोरी में एक बाइट लोड करता है, और mload जो मेमोरी से स्टैक में एक शब्द ले जाता है।

EVM में एक अलग गैर-अस्थिर (non-volatile) स्टोरेज मॉडल भी है जिसे सिस्टम स्थिति के हिस्से के रूप में बनाए रखा जाता है - यह मेमोरी शब्द सरणियों (word arrays) में व्यवस्थित होती है (स्टैक में शब्द-एड्रेसेबल बाइट सरणियों के विपरीत)। यह स्टोरेज वह जगह है जहां अनुबंध लगातार डेटा रखते हैं - एक अनुबंध केवल अपने स्वयं के स्टोरेज के साथ इंटरैक्ट कर सकता है। स्टोरेज को कुंजी-मूल्य (key-value) मैपिंग में व्यवस्थित किया जाता है।

हालांकि येलो पेपर के इस खंड में इसका उल्लेख नहीं किया गया है, यह जानना भी उपयोगी है कि चौथे प्रकार की मेमोरी भी होती है। कॉल डेटा बाइट-एड्रेसेबल रीड-ओनली मेमोरी है जिसका उपयोग लेन-देन के data पैरामीटर के साथ पारित मूल्य को संग्रहीत करने के लिए किया जाता है। EVM में calldata को प्रबंधित करने के लिए विशिष्ट ऑपकोड हैं। calldatasize डेटा का आकार लौटाता है। calldataload डेटा को स्टैक में लोड करता है। calldatacopy डेटा को मेमोरी में कॉपी करता है।

मानक वॉन न्यूमैन आर्किटेक्चर (एक नए टैब में खुलता है) कोड और डेटा को एक ही मेमोरी में संग्रहीत करता है। EVM सुरक्षा कारणों से इस मानक का पालन नहीं करता है - अस्थिर मेमोरी साझा करने से प्रोग्राम कोड को बदलना संभव हो जाता है। इसके बजाय, कोड को स्टोरेज में सहेजा जाता है।

केवल दो मामले हैं जिनमें कोड मेमोरी से निष्पादित किया जाता है:

  • जब एक अनुबंध दूसरा अनुबंध बनाता है (CREATE (एक नए टैब में खुलता है) या CREATE2 (एक नए टैब में खुलता है) का उपयोग करके), तो अनुबंध कंस्ट्रक्टर के लिए कोड मेमोरी से आता है।
  • किसी भी अनुबंध के निर्माण के दौरान, कंस्ट्रक्टर कोड चलता है और फिर वास्तविक अनुबंध के कोड के साथ वापस आता है, वह भी मेमोरी से।

असाधारण निष्पादन (exceptional execution) शब्द का अर्थ एक ऐसा अपवाद है जिसके कारण वर्तमान अनुबंध का निष्पादन रुक जाता है।

9.2 शुल्क अवलोकन

यह अनुभाग बताता है कि गैस शुल्क की गणना कैसे की जाती है। तीन लागतें हैं:

ऑपकोड लागत

विशिष्ट ऑपकोड की अंतर्निहित लागत। इस मान को प्राप्त करने के लिए, परिशिष्ट H (पृष्ठ 29, समीकरण (329) के तहत) में ऑपकोड का लागत समूह खोजें, और समीकरण (326) में लागत समूह खोजें। यह आपको एक लागत फ़ंक्शन देता है, जो अधिकांश मामलों में परिशिष्ट G (पृष्ठ 28) के मापदंडों का उपयोग करता है।

उदाहरण के लिए, ऑपकोड CALLDATACOPY (एक नए टैब में खुलता है) समूह Wcopy का सदस्य है। उस समूह के लिए ऑपकोड लागत Gverylow+Gcopy×⌈μs[2]÷32⌉ है। परिशिष्ट G को देखते हुए, हम देखते हैं कि दोनों स्थिरांक 3 हैं, जो हमें 3+3×⌈μs[2]÷32⌉ देता है।

हमें अभी भी व्यंजक ⌈μs[2]÷32⌉ को समझने की आवश्यकता है। सबसे बाहरी भाग, ⌈ <value> ⌉ सीलिंग फ़ंक्शन (ceiling function) है, एक ऐसा फ़ंक्शन जो किसी मान को दिए जाने पर सबसे छोटा पूर्णांक लौटाता है जो अभी भी मान से छोटा नहीं है। उदाहरण के लिए, ⌈2.5⌉ = ⌈3⌉ = 3। आंतरिक भाग μs[2]÷32 है। पृष्ठ 3 पर अनुभाग 3 (परंपराएं) को देखते हुए, μ मशीन स्थिति है। मशीन स्थिति को पृष्ठ 15 पर अनुभाग 9.4.1 में परिभाषित किया गया है। उस अनुभाग के अनुसार, मशीन स्थिति मापदंडों में से एक स्टैक के लिए s है। इन सबको एक साथ रखने पर, ऐसा लगता है कि μs[2] स्टैक में स्थान #2 है। ऑपकोड (एक नए टैब में खुलता है) को देखते हुए, स्टैक में स्थान #2 बाइट्स में डेटा का आकार है। समूह Wcopy में अन्य ऑपकोड, CODECOPY (एक नए टैब में खुलता है) और RETURNDATACOPY (एक नए टैब में खुलता है) को देखते हुए, उनके पास भी उसी स्थान पर डेटा का आकार है। इसलिए ⌈μs[2]÷32⌉ कॉपी किए जा रहे डेटा को संग्रहीत करने के लिए आवश्यक 32 बाइट शब्दों की संख्या है। सब कुछ एक साथ रखने पर, CALLDATACOPY (एक नए टैब में खुलता है) की अंतर्निहित लागत 3 गैस और कॉपी किए जा रहे डेटा के प्रति शब्द 3 है।

रनिंग लागत

हम जिस कोड को कॉल कर रहे हैं उसे चलाने की लागत।

मेमोरी विस्तार लागत

मेमोरी का विस्तार करने की लागत (यदि आवश्यक हो)।

समीकरण 326 में, यह मान Cmemi')-Cmemi) के रूप में लिखा गया है। अनुभाग 9.4.1 को फिर से देखते हुए, हम देखते हैं कि μi मेमोरी में शब्दों की संख्या है। इसलिए μi ऑपकोड से पहले मेमोरी में शब्दों की संख्या है और μi' ऑपकोड के बाद मेमोरी में शब्दों की संख्या है。

फ़ंक्शन Cmem को समीकरण 328 में परिभाषित किया गया है: Cmem(a) = Gmemory × a + ⌊a2 ÷ 512⌋⌊x⌋ फ़्लोर फ़ंक्शन (floor function) है, एक ऐसा फ़ंक्शन जो किसी मान को दिए जाने पर सबसे बड़ा पूर्णांक लौटाता है जो अभी भी मान से बड़ा नहीं है। उदाहरण के लिए, ⌊2.5⌋ = ⌊2⌋ = 2। जब a < √512, a2 < 512, और फ़्लोर फ़ंक्शन का परिणाम शून्य होता है। इसलिए पहले 22 शब्दों (704 बाइट्स) के लिए, लागत आवश्यक मेमोरी शब्दों की संख्या के साथ रैखिक रूप से (linearly) बढ़ती है। उस बिंदु के बाद ⌊a2 ÷ 512⌋ सकारात्मक है। जब आवश्यक मेमोरी पर्याप्त रूप से अधिक होती है तो गैस लागत मेमोरी की मात्रा के वर्ग (square) के समानुपाती होती है।

ध्यान दें कि ये कारक केवल अंतर्निहित गैस लागत को प्रभावित करते हैं - यह शुल्क बाजार या वैलिडेटर्स को दिए जाने वाले सुझावों (tips) को ध्यान में नहीं रखता है जो यह निर्धारित करते हैं कि अंतिम उपयोगकर्ता को कितना भुगतान करना आवश्यक है - यह EVM पर किसी विशेष ऑपरेशन को चलाने की केवल कच्ची लागत है।

गैस के बारे में और पढ़ें

9.3 निष्पादन वातावरण

निष्पादन वातावरण एक टुपल (tuple), I है, जिसमें ऐसी जानकारी शामिल है जो ब्लॉकचेन स्थिति या EVM का हिस्सा नहीं है।

पैरामीटरडेटा तक पहुंचने के लिए ऑपकोडडेटा तक पहुंचने के लिए Solidity कोड
IaADDRESS (एक नए टैब में खुलता है)address(this)
IoORIGIN (एक नए टैब में खुलता है)tx.origin
IpGASPRICE (एक नए टैब में खुलता है)tx.gasprice
IdCALLDATALOAD (एक नए टैब में खुलता है), आदि।msg.data
IsCALLER (एक नए टैब में खुलता है)msg.sender
IvCALLVALUE (एक नए टैब में खुलता है)msg.value
IbCODECOPY (एक नए टैब में खुलता है)address(this).code
IHब्लॉक हेडर फ़ील्ड, जैसे NUMBER (एक नए टैब में खुलता है) और DIFFICULTY (एक नए टैब में खुलता है)block.number, block.difficulty, आदि।
Ieअनुबंधों के बीच कॉल के लिए कॉल स्टैक की गहराई (अनुबंध निर्माण सहित)
Iwक्या EVM को स्थिति बदलने की अनुमति है, या यह स्थिर रूप से (statically) चल रहा है

अनुभाग 9 के शेष भाग को समझने के लिए कुछ अन्य पैरामीटर आवश्यक हैं:

पैरामीटरअनुभाग में परिभाषितअर्थ
σ2 (पृष्ठ 2, समीकरण 1)ब्लॉकचेन की स्थिति
g9.3 (पृष्ठ 14)शेष गैस
A6.1 (पृष्ठ 9)उपार्जित उप-स्थिति (accrued substate) (लेन-देन समाप्त होने पर निर्धारित परिवर्तन)
o9.3 (पृष्ठ 14)आउटपुट - आंतरिक लेन-देन के मामले में लौटाया गया परिणाम (जब एक अनुबंध दूसरे को कॉल करता है) और व्यू फ़ंक्शंस (view functions) को कॉल करता है (जब आप केवल जानकारी मांग रहे होते हैं, इसलिए लेन-देन की प्रतीक्षा करने की कोई आवश्यकता नहीं होती है)

9.4 निष्पादन अवलोकन

अब जब हमारे पास सभी प्रारंभिक बातें हैं, तो हम अंततः इस पर काम करना शुरू कर सकते हैं कि EVM कैसे काम करता है।

समीकरण 146-151 हमें EVM चलाने के लिए प्रारंभिक शर्तें देते हैं:

प्रतीकप्रारंभिक मानअर्थ
μggशेष गैस
μpc0प्रोग्राम काउंटर, निष्पादित करने के लिए अगले निर्देश का पता
μm(0, 0, ...)मेमोरी, सभी शून्यों पर प्रारंभ (initialized) की गई
μi0उपयोग किया गया उच्चतम मेमोरी स्थान
μs()स्टैक, प्रारंभ में खाली
μoआउटपुट, खाली सेट जब तक कि हम रिटर्न डेटा (RETURN (एक नए टैब में खुलता है) या REVERT (एक नए टैब में खुलता है)) के साथ या इसके बिना (STOP (एक नए टैब में खुलता है) या SELFDESTRUCT (एक नए टैब में खुलता है)) नहीं रुकते।

समीकरण 152 हमें बताता है कि निष्पादन के दौरान प्रत्येक समय बिंदु पर चार संभावित स्थितियां होती हैं, और उनके साथ क्या करना है:

  1. Z(σ,μ,A,I)। Z एक ऐसे फ़ंक्शन का प्रतिनिधित्व करता है जो परीक्षण करता है कि क्या कोई ऑपरेशन अमान्य स्थिति संक्रमण (invalid state transition) बनाता है (असाधारण हॉल्टिंग (exceptional halting) देखें)। यदि यह सत्य (True) का मूल्यांकन करता है, तो नई स्थिति पुरानी स्थिति के समान होती है (सिवाय इसके कि गैस जल जाती है) क्योंकि परिवर्तनों को लागू नहीं किया गया है।
  2. यदि निष्पादित किया जा रहा ऑपकोड REVERT (एक नए टैब में खुलता है) है, तो नई स्थिति पुरानी स्थिति के समान है, कुछ गैस खो जाती है।
  3. यदि ऑपरेशनों का क्रम समाप्त हो गया है, जैसा कि RETURN (एक नए टैब में खुलता है) द्वारा दर्शाया गया है, तो स्थिति को नई स्थिति में अपडेट किया जाता है।
  4. यदि हम अंत स्थितियों 1-3 में से किसी एक पर नहीं हैं, तो चलना जारी रखें।

9.4.1 मशीन स्थिति

यह अनुभाग मशीन की स्थिति को अधिक विस्तार से समझाता है। यह निर्दिष्ट करता है कि w वर्तमान ऑपकोड है। यदि μpc कोड की लंबाई ||Ib|| से कम है, तो वह बाइट (Ibpc]) ऑपकोड है। अन्यथा, ऑपकोड को STOP (एक नए टैब में खुलता है) के रूप में परिभाषित किया गया है।

चूंकि यह एक स्टैक मशीन (एक नए टैब में खुलता है) है, इसलिए हमें प्रत्येक ऑपकोड द्वारा बाहर निकाले गए (popped out) (δ) और अंदर धकेले गए (pushed in) (α) आइटमों की संख्या पर नज़र रखने की आवश्यकता है।

9.4.2 असाधारण हॉल्टिंग (Exceptional Halting)

यह अनुभाग Z फ़ंक्शन को परिभाषित करता है, जो यह निर्दिष्ट करता है कि हमारे पास असामान्य समाप्ति (abnormal termination) कब होती है। यह एक बूलियन (Boolean) (एक नए टैब में खुलता है) फ़ंक्शन है, इसलिए यह तार्किक OR (logical or) के लिए  (एक नए टैब में खुलता है) और तार्किक AND (logical and) के लिए  (एक नए टैब में खुलता है) का उपयोग करता है।

यदि इनमें से कोई भी स्थिति सत्य है तो हमारे पास एक असाधारण हॉल्ट (exceptional halt) है:

  • μg < C(σ,μ,A,I) जैसा कि हमने अनुभाग 9.2 में देखा, C वह फ़ंक्शन है जो गैस लागत निर्दिष्ट करता है। अगले ऑपकोड को कवर करने के लिए पर्याप्त गैस नहीं बची है。

  • δw=∅ यदि किसी ऑपकोड के लिए बाहर निकाले गए (popped) आइटमों की संख्या अपरिभाषित है, तो ऑपकोड स्वयं अपरिभाषित है।

  • || μs || < δw स्टैक अंडरफ़्लो (Stack underflow), वर्तमान ऑपकोड के लिए स्टैक में पर्याप्त आइटम नहीं हैं।

  • w = JUMP ∧ μs[0]∉D(Ib) ऑपकोड JUMP (एक नए टैब में खुलता है) है और पता JUMPDEST (एक नए टैब में खुलता है) नहीं है। जंप (Jumps) केवल तभी मान्य होते हैं जब गंतव्य (destination) JUMPDEST (एक नए टैब में खुलता है) हो।

  • w = JUMPI ∧ μs[1]≠0 ∧ μs[0] ∉ D(Ib) ऑपकोड JUMPI (एक नए टैब में खुलता है) है, स्थिति सत्य (गैर शून्य) है इसलिए जंप होना चाहिए, और पता JUMPDEST (एक नए टैब में खुलता है) नहीं है। जंप केवल तभी मान्य होते हैं जब गंतव्य JUMPDEST (एक नए टैब में खुलता है) हो。

  • w = RETURNDATACOPY ∧ μs[1]+μs[2]>|| μo || ऑपकोड RETURNDATACOPY (एक नए टैब में खुलता है) है। इस ऑपकोड में स्टैक तत्व μs[1] रिटर्न डेटा बफ़र में पढ़ने के लिए ऑफ़सेट है, और स्टैक तत्व μs[2] डेटा की लंबाई है। यह स्थिति तब होती है जब आप रिटर्न डेटा बफ़र के अंत से आगे पढ़ने का प्रयास करते हैं। ध्यान दें कि कॉल डेटा या स्वयं कोड के लिए ऐसी कोई स्थिति नहीं है। जब आप उन बफ़र्स के अंत से आगे पढ़ने का प्रयास करते हैं तो आपको केवल शून्य मिलते हैं।

  • || μs || - δw + αw > 1024

    स्टैक ओवरफ़्लो (Stack overflow)। यदि ऑपकोड चलाने से 1024 से अधिक आइटम का स्टैक बन जाएगा, तो निरस्त (abort) करें।

  • ¬Iw ∧ W(w,μ) क्या हम स्थिर रूप से (statically) चल रहे हैं (¬ निषेध (negation) है (एक नए टैब में खुलता है) और Iw सत्य है जब हमें ब्लॉकचेन स्थिति बदलने की अनुमति होती है)? यदि ऐसा है, और हम स्थिति बदलने वाले ऑपरेशन का प्रयास कर रहे हैं, तो यह नहीं हो सकता।

    फ़ंक्शन W(w,μ) को बाद में समीकरण 159 में परिभाषित किया गया है। W(w,μ) सत्य है यदि इनमें से कोई एक स्थिति सत्य है:

    • w ∈ {CREATE, CREATE2, SSTORE, SELFDESTRUCT} ये ऑपकोड स्थिति को बदलते हैं, या तो एक नया अनुबंध बनाकर, एक मान संग्रहीत करके, या वर्तमान अनुबंध को नष्ट करके।

    • LOG0≤w ∧ w≤LOG4 यदि हमें स्थिर रूप से कॉल किया जाता है तो हम लॉग प्रविष्टियां (log entries) उत्सर्जित (emit) नहीं कर सकते हैं। लॉग ऑपकोड सभी LOG0 (A0) (एक नए टैब में खुलता है) और LOG4 (A4) (एक नए टैब में खुलता है) के बीच की सीमा में हैं। लॉग ऑपकोड के बाद की संख्या निर्दिष्ट करती है कि लॉग प्रविष्टि में कितने विषय (topics) शामिल हैं।

    • w=CALL ∧ μs[2]≠0 जब आप स्थिर (static) होते हैं तो आप किसी अन्य अनुबंध को कॉल कर सकते हैं, लेकिन यदि आप ऐसा करते हैं तो आप उसे ETH ट्रांसफर नहीं कर सकते।

  • w = SSTORE ∧ μg ≤ Gcallstipend आप SSTORE (एक नए टैब में खुलता है) नहीं चला सकते जब तक कि आपके पास Gcallstipend (परिशिष्ट G में 2300 के रूप में परिभाषित) से अधिक गैस न हो।

9.4.3 जंप डेस्टिनेशन की वैधता (Jump Destination Validity)

यहाँ हम औपचारिक रूप से परिभाषित करते हैं कि JUMPDEST (एक नए टैब में खुलता है) ऑपकोड क्या हैं। हम केवल बाइट मान 0x5B की तलाश नहीं कर सकते, क्योंकि यह PUSH के अंदर हो सकता है (और इसलिए यह डेटा होगा, ऑपकोड नहीं)।

समीकरण (162) में हम एक फ़ंक्शन, N(i,w) को परिभाषित करते हैं। पहला पैरामीटर, i, ऑपकोड का स्थान है। दूसरा, w, स्वयं ऑपकोड है। यदि w∈[PUSH1, PUSH32] है, तो इसका मतलब है कि ऑपकोड एक PUSH है (वर्गाकार कोष्ठक एक सीमा को परिभाषित करते हैं जिसमें अंतिम बिंदु शामिल होते हैं)। यदि ऐसा है तो अगला ऑपकोड i+2+(w−PUSH1) पर है। PUSH1 (एक नए टैब में खुलता है) के लिए हमें दो बाइट्स (स्वयं PUSH और एक बाइट मान) आगे बढ़ना होगा, PUSH2 (एक नए टैब में खुलता है) के लिए हमें तीन बाइट्स आगे बढ़ना होगा क्योंकि यह दो बाइट का मान है, आदि। अन्य सभी EVM ऑपकोड केवल एक बाइट लंबे होते हैं, इसलिए अन्य सभी मामलों में N(i,w)=i+1 होता है।

इस फ़ंक्शन का उपयोग समीकरण (161) में DJ(c,i) को परिभाषित करने के लिए किया जाता है, जो कोड c में सभी वैध जंप डेस्टिनेशन का सेट (एक नए टैब में खुलता है) है, जो ऑपकोड स्थान i से शुरू होता है। यह फ़ंक्शन पुनरावर्ती (recursively) रूप से परिभाषित किया गया है। यदि i≥||c|| है, तो इसका मतलब है कि हम कोड के अंत में या उसके बाद हैं। हमें कोई और जंप डेस्टिनेशन नहीं मिलने वाला है, इसलिए बस खाली सेट लौटाएं।

अन्य सभी मामलों में हम अगले ऑपकोड पर जाकर और उससे शुरू होने वाले सेट को प्राप्त करके बाकी कोड को देखते हैं। c[i] वर्तमान ऑपकोड है, इसलिए N(i,c[i]) अगले ऑपकोड का स्थान है। इसलिए DJ(c,N(i,c[i])) वैध जंप डेस्टिनेशन का सेट है जो अगले ऑपकोड से शुरू होता है। यदि वर्तमान ऑपकोड JUMPDEST नहीं है, तो बस उस सेट को लौटाएं। यदि यह JUMPDEST है, तो इसे परिणाम सेट में शामिल करें और उसे लौटाएं।

9.4.4 सामान्य हॉल्टिंग

हॉल्टिंग फ़ंक्शन H, तीन प्रकार के मान लौटा सकता है।

  • यदि हम हॉल्ट ऑपकोड में नहीं हैं, तो , खाली सेट लौटाएं। परंपरा के अनुसार, इस मान की व्याख्या बूलियन असत्य (false) के रूप में की जाती है।
  • यदि हमारे पास एक हॉल्ट ऑपकोड है जो आउटपुट उत्पन्न नहीं करता है (या तो STOP (एक नए टैब में खुलता है) या SELFDESTRUCT (एक नए टैब में खुलता है)), तो रिटर्न मान के रूप में शून्य बाइट्स आकार का अनुक्रम लौटाएं। ध्यान दें कि यह खाली सेट से बहुत अलग है। इस मान का अर्थ है कि EVM वास्तव में रुक गया था, बस पढ़ने के लिए कोई रिटर्न डेटा नहीं है।
  • यदि हमारे पास एक हॉल्ट ऑपकोड है जो आउटपुट उत्पन्न करता है (या तो RETURN (एक नए टैब में खुलता है) या REVERT (एक नए टैब में खुलता है)), तो उस ऑपकोड द्वारा निर्दिष्ट बाइट्स का अनुक्रम लौटाएं। यह अनुक्रम मेमोरी से लिया गया है, स्टैक के शीर्ष पर मान (μs[0]) पहला बाइट है, और इसके बाद का मान (μs[1]) लंबाई है।

H.2 निर्देश सेट (Instruction set)

EVM के अंतिम उपखंड, 9.5 पर जाने से पहले, आइए निर्देशों को ही देखें। उन्हें परिशिष्ट H.2 में परिभाषित किया गया है जो पृष्ठ 30 से शुरू होता है। जो कुछ भी उस विशिष्ट ऑपकोड के साथ बदलने के रूप में निर्दिष्ट नहीं है, उसके समान रहने की उम्मीद है। जो चर (variables) बदलते हैं उन्हें <something>′ के रूप में निर्दिष्ट किया जाता है।

उदाहरण के लिए, आइए ADD (एक नए टैब में खुलता है) ऑपकोड को देखें।

माननिमोनिकδαविवरण
0x01ADD21जोड़ संचालन।
μ′s[0] ≡ μs[0] + μs[1]

δ उन मानों की संख्या है जिन्हें हम स्टैक से बाहर निकालते (pop) हैं। इस मामले में दो, क्योंकि हम शीर्ष दो मानों को जोड़ रहे हैं।

α उन मानों की संख्या है जिन्हें हम वापस धकेलते (push) हैं। इस मामले में एक, जो कि योग है।

इसलिए नया स्टैक शीर्ष (μ′s[0]) पुराने स्टैक शीर्ष (μs[0]) और उसके नीचे के पुराने मान (μs[1]) का योग है।

एक उबाऊ सूची के साथ सभी ऑपकोड पर जाने के बजाय, यह लेख केवल उन ऑपकोड की व्याख्या करता है जो कुछ नया पेश करते हैं।

माननिमोनिकδαविवरण
0x20KECCAK25621केकाक-256 हैश की गणना करें।
μ′s[0] ≡ KEC(μms[0] . . . (μs[0] + μs[1] − 1)])
μ′i ≡ M(μis[0],μs[1])

यह पहला ऑपकोड है जो मेमोरी तक पहुंचता है (इस मामले में, केवल पढ़ने के लिए)। हालाँकि, यह मेमोरी की वर्तमान सीमाओं से आगे बढ़ सकता है, इसलिए हमें μi को अपडेट करने की आवश्यकता है। हम पृष्ठ 30 पर समीकरण 330 में परिभाषित M फ़ंक्शन का उपयोग करके ऐसा करते हैं।

माननिमोनिकδαविवरण
0x31BALANCE11दिए गए खाते का बैलेंस प्राप्त करें।
...

जिस पते का बैलेंस हमें खोजना है वह μs[0] mod 2160 है। स्टैक का शीर्ष पता है, लेकिन चूंकि पते केवल 160 बिट्स के होते हैं, इसलिए हम 2160 के मॉड्यूलो (modulo) (एक नए टैब में खुलता है) मान की गणना करते हैं。

यदि σ[μs[0] mod 2160] ≠ ∅ है, तो इसका मतलब है कि इस पते के बारे में जानकारी है। उस स्थिति में, σ[μs[0] mod 2160]b उस पते का बैलेंस है। यदि σ[μs[0] mod 2160] = ∅ है, तो इसका मतलब है कि यह पता अप्रारंभीकृत (uninitialized) है और बैलेंस शून्य है। आप पृष्ठ 4 पर अनुभाग 4.1 में खाता जानकारी फ़ील्ड की सूची देख सकते हैं।

दूसरा समीकरण, A'a ≡ Aa ∪ {μs[0] mod 2160}, वार्म स्टोरेज (वह स्टोरेज जिसे हाल ही में एक्सेस किया गया है और जिसके कैश होने की संभावना है) और कोल्ड स्टोरेज (वह स्टोरेज जिसे एक्सेस नहीं किया गया है और जिसके धीमे स्टोरेज में होने की संभावना है जिसे पुनर्प्राप्त करना अधिक महंगा है) तक पहुंच के बीच लागत में अंतर से संबंधित है। Aa लेन-देन द्वारा पहले एक्सेस किए गए पतों की सूची है, जिसे एक्सेस करना इसलिए सस्ता होना चाहिए, जैसा कि पृष्ठ 9 पर अनुभाग 6.1 में परिभाषित किया गया है। आप इस विषय के बारे में EIP-2929 (एक नए टैब में खुलता है) में अधिक पढ़ सकते हैं।

माननिमोनिकδαविवरण
0x8FDUP16161716वें स्टैक आइटम की नकल करें।
μ′s[0] ≡ μs[15]

ध्यान दें कि किसी भी स्टैक आइटम का उपयोग करने के लिए, हमें इसे बाहर निकालना (pop) होगा, जिसका अर्थ है कि हमें इसके ऊपर के सभी स्टैक आइटमों को भी बाहर निकालना होगा। DUP<n> (एक नए टैब में खुलता है) और SWAP<n> (एक नए टैब में खुलता है) के मामले में, इसका मतलब है कि सोलह मानों तक को बाहर निकालना और फिर वापस धकेलना (push) होगा।

9.5 निष्पादन चक्र (The execution cycle)

अब जब हमारे पास सभी भाग हैं, तो हम अंततः समझ सकते हैं कि EVM के निष्पादन चक्र का दस्तावेजीकरण कैसे किया जाता है।

समीकरण (164) कहता है कि दी गई स्थिति के अनुसार:

  • σ (वैश्विक ब्लॉकचेन स्थिति)
  • μ (EVM स्थिति)
  • A (उप-स्थिति, लेन-देन समाप्त होने पर होने वाले परिवर्तन)
  • I (निष्पादन वातावरण)

नई स्थिति (σ', μ', A', I') है।

समीकरण (165)-(167) स्टैक और ऑपकोड (μs) के कारण इसमें होने वाले परिवर्तन को परिभाषित करते हैं। समीकरण (168) गैस (μg) में परिवर्तन है। समीकरण (169) प्रोग्राम काउंटर (μpc) में परिवर्तन है। अंत में, समीकरण (170)-(173) निर्दिष्ट करते हैं कि अन्य पैरामीटर समान रहते हैं, जब तक कि ऑपकोड द्वारा स्पष्ट रूप से न बदला जाए।

इसके साथ ही EVM पूरी तरह से परिभाषित हो जाता है।

निष्कर्ष

गणितीय संकेतन सटीक है और इसने येलो पेपर को इथेरियम के हर विवरण को निर्दिष्ट करने की अनुमति दी है। हालाँकि, इसकी कुछ कमियाँ हैं:

शायद इन्हीं कारणों से, नए सर्वसम्मति परत विनिर्देश (एक नए टैब में खुलता है) Python में लिखे गए हैं। Python में निष्पादन परत विनिर्देश (एक नए टैब में खुलता है) हैं, लेकिन वे पूर्ण नहीं हैं। जब तक कि पूरा येलो पेपर भी Python या किसी समान भाषा में अनुवादित नहीं हो जाता, तब तक येलो पेपर सेवा में बना रहेगा, और इसे पढ़ने में सक्षम होना मददगार है।