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

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

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

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

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

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

EVM क्यों?

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

9 निष्पादन मॉडल

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

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

एक ट्यूरिंग मशीन (opens in a new tab) एक कम्प्यूटेशनल मॉडल है। अनिवार्य रूप से, यह एक कंप्यूटर का सरलीकृत संस्करण है, जो यह साबित करता है कि इसमें गणना चलाने की वही क्षमता है जो एक सामान्य कंप्यूटर में होती है (हर वह चीज़ जिसकी गणना एक कंप्यूटर कर सकता है, एक ट्यूरिंग मशीन भी कर सकती है और इसके विपरीत भी)। यह मॉडल इस बारे में विभिन्न प्रमेयों को साबित करना आसान बनाता है कि क्या गणना योग्य है और क्या नहीं।

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

9.1 मूल बातें

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

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

EVM में एक अस्थिर (volatile) स्थान भी होता है जिसे मेमोरी कहा जाता है जिसका उपयोग निष्पादन के दौरान डेटा संग्रहीत करने के लिए किया जाता है। यह मेमोरी 32-बाइट शब्दों में व्यवस्थित होती है। सभी मेमोरी स्थान शून्य पर प्रारंभ (initialized) किए जाते हैं। यदि आप मेमोरी में एक शब्द जोड़ने के लिए इस Yul (opens in a new tab) कोड को निष्पादित करते हैं, तो यह शब्द में खाली स्थान को शून्य से भरकर 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 डेटा को मेमोरी में कॉपी करता है।

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

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

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

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

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

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

ऑपकोड लागत

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

उदाहरण के लिए, ऑपकोड CALLDATACOPY (opens in a new tab) समूह 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 (परंपराएं) को देखते हुए, μ मशीन की स्थिति है। मशीन की स्थिति को पृष्ठ 13 पर अनुभाग 9.4.1 में परिभाषित किया गया है। उस अनुभाग के अनुसार, मशीन स्थिति मापदंडों में से एक स्टैक के लिए s है। इन सबको एक साथ रखने पर, ऐसा लगता है कि μs[2] स्टैक में स्थान #2 है। ऑपकोड (opens in a new tab) को देखते हुए, स्टैक में स्थान #2 बाइट्स में डेटा का आकार है। समूह Wcopy में अन्य ऑपकोड, CODECOPY (opens in a new tab) और RETURNDATACOPY (opens in a new tab) को देखते हुए, उनके पास भी उसी स्थान पर डेटा का आकार है। इसलिए ⌈μs[2]÷32⌉ कॉपी किए जा रहे डेटा को संग्रहीत करने के लिए आवश्यक 32 बाइट शब्दों की संख्या है। सब कुछ एक साथ रखने पर, CALLDATACOPY (opens in a new tab) की अंतर्निहित लागत 3 गैस प्लस कॉपी किए जा रहे डेटा के प्रति शब्द 3 है।

रनिंग लागत

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

9.4.1 मशीन स्थिति

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

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

9.4.2 असाधारण हॉल्टिंग

यह अनुभाग Z फ़ंक्शन को परिभाषित करता है, जो यह निर्दिष्ट करता है कि हमारे पास असामान्य समाप्ति कब होती है। यह एक बूलियन (opens in a new tab) फ़ंक्शन है, इसलिए यह तार्किक OR के लिए  (opens in a new tab) और तार्किक AND के लिए  (opens in a new tab) का उपयोग करता है।

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

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

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

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

  • w = JUMP ∧ μs[0]∉D(Ib) ऑपकोड JUMP (opens in a new tab) है और पता JUMPDEST (opens in a new tab) नहीं है। जंप केवल तभी मान्य होते हैं जब गंतव्य JUMPDEST (opens in a new tab) हो।

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

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

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

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

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

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

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

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

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

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

9.4.3 जंप गंतव्य वैधता

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

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

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

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

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

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

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

H.2 निर्देश सेट

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

उदाहरण के लिए, आइए ADD (opens in a new tab) ऑपकोड को देखें।

माननिमोनिकδαविवरण
0x01ADD21जोड़ (Addition) ऑपरेशन।
μ′s[0] ≡ μs[0] + μs[1]

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

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

इसलिए नया स्टैक शीर्ष (μ′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 को अपडेट करने की आवश्यकता है। हम पृष्ठ 29 पर समीकरण 328 में परिभाषित M फ़ंक्शन का उपयोग करके ऐसा करते हैं।

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

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

यदि σ[μ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 लेन-देन द्वारा पहले एक्सेस किए गए पतों की सूची है, जिसे इसलिए एक्सेस करना सस्ता होना चाहिए, जैसा कि पृष्ठ 8 पर अनुभाग 6.1 में परिभाषित किया गया है। आप इस विषय के बारे में EIP-2929 (opens in a new tab) में अधिक पढ़ सकते हैं।

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

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

9.5 निष्पादन चक्र

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

समीकरण (155) कहता है कि दी गई स्थिति:

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

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

समीकरण (156)-(158) स्टैक और ऑपकोड (μs) के कारण इसमें होने वाले परिवर्तन को परिभाषित करते हैं। समीकरण (159) गैस (μg) में परिवर्तन है। समीकरण (160) प्रोग्राम काउंटर (μpc) में परिवर्तन है। अंत में, समीकरण (161)-(164) निर्दिष्ट करते हैं कि अन्य पैरामीटर समान रहते हैं, जब तक कि ऑपकोड द्वारा स्पष्ट रूप से नहीं बदला जाता है।

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

निष्कर्ष

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

  • इसे केवल मनुष्यों द्वारा ही समझा जा सकता है, जिसका अर्थ है कि अनुपालन परीक्षण (compliance tests) (opens in a new tab) मैन्युअल रूप से लिखे जाने चाहिए।
  • प्रोग्रामर कंप्यूटर कोड समझते हैं। वे गणितीय संकेतन को समझ भी सकते हैं और नहीं भी।

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