---
title: "येलो पेपर के EVM विनिर्देशों को समझना"
description: "येलो पेपर के उस हिस्से को समझना, जो इथेरियम के लिए औपचारिक विनिर्देश है, और इथेरियम वर्चुअल मशीन (EVM) की व्याख्या करता है।"
author: "qbzzt"
tags: ["evm"]
skill: intermediate
breadcrumb: "येलो पेपर EVM"
lang: hi
published: 2022-05-15
---

[येलो पेपर](https://ethereum.github.io/yellowpaper/paper.pdf) इथेरियम के लिए औपचारिक विनिर्देश है। जहां [EIP प्रक्रिया](/eips/) द्वारा संशोधन किया गया है उसे छोड़कर, इसमें हर चीज़ कैसे काम करती है इसका सटीक विवरण शामिल है। इसे एक गणितीय पेपर के रूप में लिखा गया है, जिसमें ऐसी शब्दावली शामिल है जिससे प्रोग्रामर शायद परिचित न हों। इस पेपर में आप सीखेंगे कि इसे कैसे पढ़ा जाए, और इसके विस्तार से अन्य संबंधित गणितीय पेपरों को भी।

## कौन सा येलो पेपर? {#which-yellow-paper}

इथेरियम में लगभग हर दूसरी चीज़ की तरह, येलो पेपर भी समय के साथ विकसित होता है। किसी विशिष्ट संस्करण का संदर्भ देने में सक्षम होने के लिए, मैंने [लिखते समय वर्तमान संस्करण](https://ethereum.github.io/yellowpaper/paper.pdf) अपलोड किया है। मेरे द्वारा उपयोग किए जाने वाले अनुभाग, पृष्ठ और समीकरण संख्याएँ उसी संस्करण को संदर्भित करेंगी। इस दस्तावेज़ को पढ़ते समय इसे एक अलग विंडो में खुला रखना एक अच्छा विचार है।

### EVM क्यों? {#why-the-evm}

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

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

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

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

एक [ट्यूरिंग मशीन (Turing machine)](https://en.wikipedia.org/wiki/Turing_machine) एक कम्प्यूटेशनल मॉडल है। अनिवार्य रूप से, यह एक कंप्यूटर का सरलीकृत संस्करण है, जो यह साबित करता है कि इसमें गणना चलाने की वही क्षमता है जो एक सामान्य कंप्यूटर कर सकता है (वह सब कुछ जो एक कंप्यूटर गणना कर सकता है, एक ट्यूरिंग मशीन गणना कर सकती है और इसके विपरीत)। यह मॉडल इस बारे में विभिन्न प्रमेयों को साबित करना आसान बनाता है कि क्या गणना योग्य है और क्या नहीं।

[ट्यूरिंग-पूर्ण (Turing-complete)](https://en.wikipedia.org/wiki/Turing_completeness) शब्द का अर्थ एक ऐसा कंप्यूटर है जो ट्यूरिंग मशीन के समान गणना चला सकता है। ट्यूरिंग मशीनें अनंत लूप (infinite loops) में जा सकती हैं, और EVM ऐसा नहीं कर सकता क्योंकि इसकी गैस खत्म हो जाएगी, इसलिए यह केवल अर्ध-ट्यूरिंग-पूर्ण (quasi-Turing-complete) है।
## 9.1 मूल बातें {#91-basics}

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

एक [स्टैक मशीन](https://en.wikipedia.org/wiki/Stack_machine) एक ऐसा कंप्यूटर है जो मध्यवर्ती डेटा को रजिस्टरों में नहीं, बल्कि एक [**स्टैक**](<https://en.wikipedia.org/wiki/Stack_(abstract_data_type)>) में संग्रहीत करता है। यह वर्चुअल मशीनों के लिए पसंदीदा आर्किटेक्चर है क्योंकि इसे लागू करना आसान है जिसका अर्थ है कि बग और सुरक्षा कमजोरियों की संभावना बहुत कम है। स्टैक में मेमोरी को 256-बिट शब्दों (words) में विभाजित किया गया है। इसे इसलिए चुना गया था क्योंकि यह इथेरियम के मुख्य क्रिप्टोग्राफ़िक संचालन जैसे केकाक-256 हैशिंग और दीर्घवृत्तीय वक्र गणनाओं के लिए सुविधाजनक है। स्टैक का अधिकतम आकार 1024 आइटम (1024 x 256 बिट्स) है। जब ऑपकोड निष्पादित होते हैं तो वे आमतौर पर स्टैक से अपने पैरामीटर प्राप्त कर रहे होते हैं। स्टैक में तत्वों को पुनर्गठित करने के लिए विशेष रूप से ऑपकोड हैं जैसे `POP` (स्टैक के शीर्ष से आइटम हटाता है), `DUP_N` (स्टैक में Nवें आइटम की नकल करता है), आदि।

EVM में एक अस्थिर (volatile) स्थान भी होता है जिसे **मेमोरी** कहा जाता है जिसका उपयोग निष्पादन के दौरान डेटा संग्रहीत करने के लिए किया जाता है। यह मेमोरी 32-बाइट शब्दों में व्यवस्थित होती है। सभी मेमोरी स्थान शून्य पर प्रारंभ (initialized) किए जाते हैं। यदि आप मेमोरी में एक शब्द जोड़ने के लिए इस [Yul](https://docs.soliditylang.org/en/latest/yul.html) कोड को निष्पादित करते हैं, तो यह शब्द में खाली स्थान को शून्य से भरकर 32 बाइट्स मेमोरी भर देगा, यानी, यह एक शब्द बनाता है - स्थान 0-29 में शून्य के साथ, 30 में 0x60, और 31 में 0xA7।

```yul
mstore(0, 0x60A7)
```

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

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

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

मानक [वॉन न्यूमैन आर्किटेक्चर](https://en.wikipedia.org/wiki/Von_Neumann_architecture) कोड और डेटा को एक ही मेमोरी में संग्रहीत करता है। EVM सुरक्षा कारणों से इस मानक का पालन नहीं करता है - अस्थिर मेमोरी साझा करने से प्रोग्राम कोड को बदलना संभव हो जाता है। इसके बजाय, कोड को स्टोरेज में सहेजा जाता है।

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

- जब एक अनुबंध दूसरा अनुबंध बनाता है ([`CREATE`](https://www.evm.codes/#f0) या [`CREATE2`](https://www.evm.codes/#f5) का उपयोग करके), तो अनुबंध कंस्ट्रक्टर के लिए कोड मेमोरी से आता है।
- _किसी भी_ अनुबंध के निर्माण के दौरान, कंस्ट्रक्टर कोड चलता है और फिर वास्तविक अनुबंध के कोड के साथ वापस आता है, वह भी मेमोरी से।

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

## 9.2 शुल्क अवलोकन {#92-fees-overview}

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

### ऑपकोड लागत

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

उदाहरण के लिए, ऑपकोड [`CALLDATACOPY`](https://www.evm.codes/#37) समूह _W<sub>copy</sub>_ का सदस्य है। उस समूह के लिए ऑपकोड लागत _G<sub>verylow</sub>+G<sub>copy</sub>×⌈μ<sub>s</sub>[2]÷32⌉_ है। परिशिष्ट G को देखते हुए, हम देखते हैं कि दोनों स्थिरांक 3 हैं, जो हमें _3+3×⌈μ<sub>s</sub>[2]÷32⌉_ देता है।

हमें अभी भी व्यंजक _⌈μ<sub>s</sub>[2]÷32⌉_ को समझने की आवश्यकता है। सबसे बाहरी भाग, _⌈ \<value\> ⌉_ सीलिंग फ़ंक्शन (ceiling function) है, एक ऐसा फ़ंक्शन जो किसी मान को दिए जाने पर सबसे छोटा पूर्णांक लौटाता है जो अभी भी मान से छोटा नहीं है। उदाहरण के लिए, _⌈2.5⌉ = ⌈3⌉ = 3_। आंतरिक भाग _μ<sub>s</sub>[2]÷32_ है। पृष्ठ 3 पर अनुभाग 3 (परंपराएं) को देखते हुए, _μ_ मशीन स्थिति है। मशीन स्थिति को पृष्ठ 15 पर अनुभाग 9.4.1 में परिभाषित किया गया है। उस अनुभाग के अनुसार, मशीन स्थिति मापदंडों में से एक स्टैक के लिए _s_ है। इन सबको एक साथ रखने पर, ऐसा लगता है कि _μ<sub>s</sub>[2]_ स्टैक में स्थान #2 है। [ऑपकोड](https://www.evm.codes/#37) को देखते हुए, स्टैक में स्थान #2 बाइट्स में डेटा का आकार है। समूह W<sub>copy</sub> में अन्य ऑपकोड, [`CODECOPY`](https://www.evm.codes/#39) और [`RETURNDATACOPY`](https://www.evm.codes/#3e) को देखते हुए, उनके पास भी उसी स्थान पर डेटा का आकार है। इसलिए _⌈μ<sub>s</sub>[2]÷32⌉_ कॉपी किए जा रहे डेटा को संग्रहीत करने के लिए आवश्यक 32 बाइट शब्दों की संख्या है। सब कुछ एक साथ रखने पर, [`CALLDATACOPY`](https://www.evm.codes/#37) की अंतर्निहित लागत 3 गैस और कॉपी किए जा रहे डेटा के प्रति शब्द 3 है।
### रनिंग लागत {#running-cost}

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

- [`CREATE`](https://www.evm.codes/#f0) और [`CREATE2`](https://www.evm.codes/#f5) के मामले में, नए अनुबंध के लिए कंस्ट्रक्टर।
- [`CALL`](https://www.evm.codes/#f1), [`CALLCODE`](https://www.evm.codes/#f2), [`STATICCALL`](https://www.evm.codes/#fa), या [`DELEGATECALL`](https://www.evm.codes/#f4) के मामले में, वह अनुबंध जिसे हम कॉल करते हैं।

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

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

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

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

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

[गैस के बारे में और पढ़ें](/developers/docs/gas/)।
## 9.3 निष्पादन वातावरण

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

| पैरामीटर | डेटा तक पहुंचने के लिए ऑपकोड | डेटा तक पहुंचने के लिए Solidity कोड |
| --------------- | ---------------------------------------------------------------------------------------------------------------- | ---------------------------------------- |
| _I<sub>a</sub>_ | [`ADDRESS`](https://www.evm.codes/#30)                                                                           | `address(this)`                          |
| _I<sub>o</sub>_ | [`ORIGIN`](https://www.evm.codes/#32)                                                                            | `tx.origin`                              |
| _I<sub>p</sub>_ | [`GASPRICE`](https://www.evm.codes/#3a)                                                                          | `tx.gasprice`                            |
| _I<sub>d</sub>_ | [`CALLDATALOAD`](https://www.evm.codes/#35), आदि।                                                                | `msg.data`                               |
| _I<sub>s</sub>_ | [`CALLER`](https://www.evm.codes/#33)                                                                            | `msg.sender`                             |
| _I<sub>v</sub>_ | [`CALLVALUE`](https://www.evm.codes/#34)                                                                         | `msg.value`                              |
| _I<sub>b</sub>_ | [`CODECOPY`](https://www.evm.codes/#39)                                                                          | `address(this).code`                     |
| _I<sub>H</sub>_ | ब्लॉक हेडर फ़ील्ड, जैसे [`NUMBER`](https://www.evm.codes/#43) और [`DIFFICULTY`](https://www.evm.codes/#44) | `block.number`, `block.difficulty`, आदि। |
| _I<sub>e</sub>_ | अनुबंधों के बीच कॉल के लिए कॉल स्टैक की गहराई (अनुबंध निर्माण सहित)                                |
| _I<sub>w</sub>_ | क्या EVM को स्थिति बदलने की अनुमति है, या यह स्थिर रूप से (statically) चल रहा है                                                  |

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

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

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

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

| प्रतीक           | प्रारंभिक मान | अर्थ                                                                                                                                                                                                                                                     |
| ---------------- | ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| _μ<sub>g</sub>_  | _g_           | शेष गैस                                                                                                                                                                                                                                               |
| _μ<sub>pc</sub>_ | _0_           | प्रोग्राम काउंटर, निष्पादित करने के लिए अगले निर्देश का पता                                                                                                                                                                                             |
| _μ<sub>m</sub>_  | _(0, 0, ...)_ | मेमोरी, सभी शून्यों पर प्रारंभ (initialized) की गई                                                                                                                                                                                                                            |
| _μ<sub>i</sub>_  | _0_           | उपयोग किया गया उच्चतम मेमोरी स्थान                                                                                                                                                                                                                                |
| _μ<sub>s</sub>_  | _()_          | स्टैक, प्रारंभ में खाली                                                                                                                                                                                                                                  |
| _μ<sub>o</sub>_  | _∅_           | आउटपुट, खाली सेट जब तक कि हम रिटर्न डेटा ([`RETURN`](https://www.evm.codes/#f3) या [`REVERT`](https://www.evm.codes/#fd)) के साथ या इसके बिना ([`STOP`](https://www.evm.codes/#00) या [`SELFDESTRUCT`](https://www.evm.codes/#ff)) नहीं रुकते। |

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

1.  `Z(σ,μ,A,I)`। Z एक ऐसे फ़ंक्शन का प्रतिनिधित्व करता है जो परीक्षण करता है कि क्या कोई ऑपरेशन अमान्य स्थिति संक्रमण (invalid state transition) बनाता है ([असाधारण हॉल्टिंग (exceptional halting)](#942-exceptional-halt) देखें)। यदि यह सत्य (True) का मूल्यांकन करता है, तो नई स्थिति पुरानी स्थिति के समान होती है (सिवाय इसके कि गैस जल जाती है) क्योंकि परिवर्तनों को लागू नहीं किया गया है।
2.  यदि निष्पादित किया जा रहा ऑपकोड [`REVERT`](https://www.evm.codes/#fd) है, तो नई स्थिति पुरानी स्थिति के समान है, कुछ गैस खो जाती है।
3.  यदि ऑपरेशनों का क्रम समाप्त हो गया है, जैसा कि [`RETURN`](https://www.evm.codes/#f3) द्वारा दर्शाया गया है, तो स्थिति को नई स्थिति में अपडेट किया जाता है।
4.  यदि हम अंत स्थितियों 1-3 में से किसी एक पर नहीं हैं, तो चलना जारी रखें।
## 9.4.1 मशीन स्थिति {#941-machine-state}

यह अनुभाग मशीन की स्थिति को अधिक विस्तार से समझाता है। यह निर्दिष्ट करता है कि _w_ वर्तमान ऑपकोड है। यदि _μ<sub>pc</sub>_ कोड की लंबाई _||I<sub>b</sub>||_ से कम है, तो वह बाइट (_I<sub>b</sub>[μ<sub>pc</sub>]_) ऑपकोड है। अन्यथा, ऑपकोड को [`STOP`](https://www.evm.codes/#00) के रूप में परिभाषित किया गया है।

चूंकि यह एक [स्टैक मशीन](https://en.wikipedia.org/wiki/Stack_machine) है, इसलिए हमें प्रत्येक ऑपकोड द्वारा बाहर निकाले गए (popped out) (_δ_) और अंदर धकेले गए (pushed in) (_α_) आइटमों की संख्या पर नज़र रखने की आवश्यकता है।

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

यह अनुभाग _Z_ फ़ंक्शन को परिभाषित करता है, जो यह निर्दिष्ट करता है कि हमारे पास असामान्य समाप्ति (abnormal termination) कब होती है। यह एक [बूलियन (Boolean)](https://en.wikipedia.org/wiki/Boolean_data_type) फ़ंक्शन है, इसलिए यह [तार्किक OR (logical or) के लिए _∨_](https://en.wikipedia.org/wiki/Logical_disjunction) और [तार्किक AND (logical and) के लिए _∧_](https://en.wikipedia.org/wiki/Logical_conjunction) का उपयोग करता है।

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

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

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

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

- **_w = JUMP ∧ μ<sub>s</sub>[0]∉D(I<sub>b</sub>)_**
  ऑपकोड [`JUMP`](https://www.evm.codes/#56) है और पता [`JUMPDEST`](https://www.evm.codes/#5b) नहीं है। जंप (Jumps) _केवल_ तभी मान्य होते हैं जब गंतव्य (destination) [`JUMPDEST`](https://www.evm.codes/#5b) हो।

- **_w = JUMPI ∧ μ<sub>s</sub>[1]≠0 ∧ μ<sub>s</sub>[0] ∉ D(I<sub>b</sub>)_**
  ऑपकोड [`JUMPI`](https://www.evm.codes/#57) है, स्थिति सत्य (गैर शून्य) है इसलिए जंप होना चाहिए, और पता [`JUMPDEST`](https://www.evm.codes/#5b) नहीं है। जंप _केवल_ तभी मान्य होते हैं जब गंतव्य [`JUMPDEST`](https://www.evm.codes/#5b) हो。

- **_w = RETURNDATACOPY ∧ μ<sub>s</sub>[1]+μ<sub>s</sub>[2]>|| μ<sub>o</sub> ||_**
  ऑपकोड [`RETURNDATACOPY`](https://www.evm.codes/#3e) है। इस ऑपकोड में स्टैक तत्व _μ<sub>s</sub>[1]_ रिटर्न डेटा बफ़र में पढ़ने के लिए ऑफ़सेट है, और स्टैक तत्व _μ<sub>s</sub>[2]_ डेटा की लंबाई है। यह स्थिति तब होती है जब आप रिटर्न डेटा बफ़र के अंत से आगे पढ़ने का प्रयास करते हैं। ध्यान दें कि कॉल डेटा या स्वयं कोड के लिए ऐसी कोई स्थिति नहीं है। जब आप उन बफ़र्स के अंत से आगे पढ़ने का प्रयास करते हैं तो आपको केवल शून्य मिलते हैं।

- **_|| μ<sub>s</sub> || - δ<sub>w</sub> + α<sub>w</sub> > 1024_**

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

- **_¬I<sub>w</sub> ∧ W(w,μ)_**
  क्या हम स्थिर रूप से (statically) चल रहे हैं ([¬ निषेध (negation) है](https://en.wikipedia.org/wiki/Negation) और _I<sub>w</sub>_ सत्य है जब हमें ब्लॉकचेन स्थिति बदलने की अनुमति होती है)? यदि ऐसा है, और हम स्थिति बदलने वाले ऑपरेशन का प्रयास कर रहे हैं, तो यह नहीं हो सकता।

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

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

  - **_LOG0≤w ∧ w≤LOG4_**
    यदि हमें स्थिर रूप से कॉल किया जाता है तो हम लॉग प्रविष्टियां (log entries) उत्सर्जित (emit) नहीं कर सकते हैं।
    लॉग ऑपकोड सभी [`LOG0` (A0)](https://www.evm.codes/#a0) और [`LOG4` (A4)](https://www.evm.codes/#a4) के बीच की सीमा में हैं।
    लॉग ऑपकोड के बाद की संख्या निर्दिष्ट करती है कि लॉग प्रविष्टि में कितने विषय (topics) शामिल हैं।
  - **_w=CALL ∧ μ<sub>s</sub>[2]≠0_**
    जब आप स्थिर (static) होते हैं तो आप किसी अन्य अनुबंध को कॉल कर सकते हैं, लेकिन यदि आप ऐसा करते हैं तो आप उसे ETH ट्रांसफर नहीं कर सकते।

- **_w = SSTORE ∧ μ<sub>g</sub> ≤ G<sub>callstipend</sub>_**
  आप [`SSTORE`](https://www.evm.codes/#55) नहीं चला सकते जब तक कि आपके पास G<sub>callstipend</sub> (परिशिष्ट G में 2300 के रूप में परिभाषित) से अधिक गैस न हो।
## 9.4.3 जंप डेस्टिनेशन की वैधता (Jump Destination Validity)

यहाँ हम औपचारिक रूप से परिभाषित करते हैं कि [`JUMPDEST`](https://www.evm.codes/#5b) ऑपकोड क्या हैं। हम केवल बाइट मान 0x5B की तलाश नहीं कर सकते, क्योंकि यह PUSH के अंदर हो सकता है (और इसलिए यह डेटा होगा, ऑपकोड नहीं)।

समीकरण (162) में हम एक फ़ंक्शन, _N(i,w)_ को परिभाषित करते हैं। पहला पैरामीटर, _i_, ऑपकोड का स्थान है। दूसरा, _w_, स्वयं ऑपकोड है। यदि _w∈[PUSH1, PUSH32]_ है, तो इसका मतलब है कि ऑपकोड एक PUSH है (वर्गाकार कोष्ठक एक सीमा को परिभाषित करते हैं जिसमें अंतिम बिंदु शामिल होते हैं)। यदि ऐसा है तो अगला ऑपकोड _i+2+(w−PUSH1)_ पर है। [`PUSH1`](https://www.evm.codes/#60) के लिए हमें दो बाइट्स (स्वयं PUSH और एक बाइट मान) आगे बढ़ना होगा, [`PUSH2`](https://www.evm.codes/#61) के लिए हमें तीन बाइट्स आगे बढ़ना होगा क्योंकि यह दो बाइट का मान है, आदि। अन्य सभी EVM ऑपकोड केवल एक बाइट लंबे होते हैं, इसलिए अन्य सभी मामलों में _N(i,w)=i+1_ होता है।

इस फ़ंक्शन का उपयोग समीकरण (161) में _D<sub>J</sub>(c,i)_ को परिभाषित करने के लिए किया जाता है, जो कोड _c_ में सभी वैध जंप डेस्टिनेशन का [सेट](<https://en.wikipedia.org/wiki/Set_(mathematics)>) है, जो ऑपकोड स्थान _i_ से शुरू होता है। यह फ़ंक्शन पुनरावर्ती (recursively) रूप से परिभाषित किया गया है। यदि _i≥||c||_ है, तो इसका मतलब है कि हम कोड के अंत में या उसके बाद हैं। हमें कोई और जंप डेस्टिनेशन नहीं मिलने वाला है, इसलिए बस खाली सेट लौटाएं।

अन्य सभी मामलों में हम अगले ऑपकोड पर जाकर और उससे शुरू होने वाले सेट को प्राप्त करके बाकी कोड को देखते हैं। _c[i]_ वर्तमान ऑपकोड है, इसलिए _N(i,c[i])_ अगले ऑपकोड का स्थान है। इसलिए _D<sub>J</sub>(c,N(i,c[i]))_ वैध जंप डेस्टिनेशन का सेट है जो अगले ऑपकोड से शुरू होता है। यदि वर्तमान ऑपकोड `JUMPDEST` नहीं है, तो बस उस सेट को लौटाएं। यदि यह `JUMPDEST` है, तो इसे परिणाम सेट में शामिल करें और उसे लौटाएं।
## 9.4.4 सामान्य हॉल्टिंग {#944-normal-halt}

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

- यदि हम हॉल्ट ऑपकोड में नहीं हैं, तो _∅_, खाली सेट लौटाएं। परंपरा के अनुसार, इस मान की व्याख्या बूलियन असत्य (false) के रूप में की जाती है।
- यदि हमारे पास एक हॉल्ट ऑपकोड है जो आउटपुट उत्पन्न नहीं करता है (या तो [`STOP`](https://www.evm.codes/#00) या [`SELFDESTRUCT`](https://www.evm.codes/#ff)), तो रिटर्न मान के रूप में शून्य बाइट्स आकार का अनुक्रम लौटाएं। ध्यान दें कि यह खाली सेट से बहुत अलग है। इस मान का अर्थ है कि EVM वास्तव में रुक गया था, बस पढ़ने के लिए कोई रिटर्न डेटा नहीं है।
- यदि हमारे पास एक हॉल्ट ऑपकोड है जो आउटपुट उत्पन्न करता है (या तो [`RETURN`](https://www.evm.codes/#f3) या [`REVERT`](https://www.evm.codes/#fd)), तो उस ऑपकोड द्वारा निर्दिष्ट बाइट्स का अनुक्रम लौटाएं। यह अनुक्रम मेमोरी से लिया गया है, स्टैक के शीर्ष पर मान (_μ<sub>s</sub>[0]_) पहला बाइट है, और इसके बाद का मान (_μ<sub>s</sub>[1]_) लंबाई है।

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

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

उदाहरण के लिए, आइए [`ADD`](https://www.evm.codes/#01) ऑपकोड को देखें।

| मान | निमोनिक | δ   | α   | विवरण                                               |
| ----: | -------- | --- | --- | --------------------------------------------------------- |
|  0x01 | ADD      | 2   | 1   | जोड़ संचालन।                                       |
|       |          |     |     | _μ′<sub>s</sub>[0] ≡ μ<sub>s</sub>[0] + μ<sub>s</sub>[1]_

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

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

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

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

| मान | निमोनिक  | δ   | α   | विवरण                                                                                                |
| ----: | --------- | --- | --- | ---------------------------------------------------------------------------------------------------------- |
|  0x20 | KECCAK256 | 2   | 1   | केकाक-256 हैश की गणना करें।                                                                                   |
|       |           |     |     | _μ′<sub>s</sub>[0] ≡ KEC(μ<sub>m</sub>[μ<sub>s</sub>[0] . . . (μ<sub>s</sub>[0] + μ<sub>s</sub>[1] − 1)])_ |
|       |           |     |     | _μ′<sub>i</sub> ≡ M(μ<sub>i</sub>,μ<sub>s</sub>[0],μ<sub>s</sub>[1])_                                      |

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

| मान | निमोनिक | δ   | α   | विवरण                       |
| ----: | -------- | --- | --- | --------------------------------- |
|  0x31 | BALANCE  | 1   | 1   | दिए गए खाते का बैलेंस प्राप्त करें। |
|       |          |     |     | ...                               |

जिस पते का बैलेंस हमें खोजना है वह _μ<sub>s</sub>[0] mod 2<sup>160</sup>_ है। स्टैक का शीर्ष पता है, लेकिन चूंकि पते केवल 160 बिट्स के होते हैं, इसलिए हम 2<sup>160</sup> के [मॉड्यूलो (modulo)](https://en.wikipedia.org/wiki/Modulo_operation) मान की गणना करते हैं。

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

दूसरा समीकरण, _A'<sub>a</sub> ≡ A<sub>a</sub> ∪ \{μ<sub>s</sub>[0] mod 2<sup>160</sup>\}_, वार्म स्टोरेज (वह स्टोरेज जिसे हाल ही में एक्सेस किया गया है और जिसके कैश होने की संभावना है) और कोल्ड स्टोरेज (वह स्टोरेज जिसे एक्सेस नहीं किया गया है और जिसके धीमे स्टोरेज में होने की संभावना है जिसे पुनर्प्राप्त करना अधिक महंगा है) तक पहुंच के बीच लागत में अंतर से संबंधित है। _A<sub>a</sub>_ लेन-देन द्वारा पहले एक्सेस किए गए पतों की सूची है, जिसे एक्सेस करना इसलिए सस्ता होना चाहिए, जैसा कि पृष्ठ 9 पर अनुभाग 6.1 में परिभाषित किया गया है। आप इस विषय के बारे में [EIP-2929](https://eips.ethereum.org/EIPS/eip-2929) में अधिक पढ़ सकते हैं।

| मान | निमोनिक | δ   | α   | विवरण                             |
| ----: | -------- | --- | --- | --------------------------------------- |
|  0x8F | DUP16    | 16  | 17  | 16वें स्टैक आइटम की नकल करें।              |
|       |          |     |     | _μ′<sub>s</sub>[0] ≡ μ<sub>s</sub>[15]_ |

ध्यान दें कि किसी भी स्टैक आइटम का उपयोग करने के लिए, हमें इसे बाहर निकालना (pop) होगा, जिसका अर्थ है कि हमें इसके ऊपर के सभी स्टैक आइटमों को भी बाहर निकालना होगा। [`DUP<n>`](https://www.evm.codes/#8f) और [`SWAP<n>`](https://www.evm.codes/#9f) के मामले में, इसका मतलब है कि सोलह मानों तक को बाहर निकालना और फिर वापस धकेलना (push) होगा।
## 9.5 निष्पादन चक्र (The execution cycle)

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

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

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

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

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

इसके साथ ही EVM पूरी तरह से परिभाषित हो जाता है।
## निष्कर्ष {#conclusion}

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

- इसे केवल मनुष्यों द्वारा ही समझा जा सकता है, जिसका अर्थ है कि [अनुपालन परीक्षण (compliance tests)](https://github.com/ethereum/tests) मैन्युअल रूप से लिखे जाने चाहिए।
- प्रोग्रामर कंप्यूटर कोड समझते हैं।
  वे गणितीय संकेतन को समझ भी सकते हैं और नहीं भी।

शायद इन्हीं कारणों से, नए [सर्वसम्मति परत विनिर्देश](https://github.com/ethereum/consensus-specs/blob/master/tests/core/pyspec/README.md) Python में लिखे गए हैं। [Python में निष्पादन परत विनिर्देश](https://ethereum.github.io/execution-specs) हैं, लेकिन वे पूर्ण नहीं हैं। जब तक कि पूरा येलो पेपर भी Python या किसी समान भाषा में अनुवादित नहीं हो जाता, तब तक येलो पेपर सेवा में बना रहेगा, और इसे पढ़ने में सक्षम होना मददगार है।
