یلو پیپر کی EVM تفصیلات کو سمجھنا
یلو پیپر (نئے ٹیب میں کھلتا ہے) ایتھیریم کے لیے باضابطہ تفصیلات ہے۔ سوائے ان جگہوں کے جہاں EIP عمل کے ذریعے ترمیم کی گئی ہو، اس میں ہر چیز کے کام کرنے کے طریقے کی قطعی وضاحت موجود ہے۔ یہ ایک ریاضیاتی مقالے کے طور پر لکھا گیا ہے، جس میں ایسی اصطلاحات شامل ہیں جن سے پروگرامرز شاید واقف نہ ہوں۔ اس مقالے میں آپ اسے پڑھنا سیکھیں گے، اور اس کی توسیع کے طور پر دیگر متعلقہ ریاضیاتی مقالے بھی۔
کون سا یلو پیپر؟
ایتھیریم میں تقریباً ہر دوسری چیز کی طرح، یلو پیپر بھی وقت کے ساتھ ساتھ ارتقاء پذیر ہوتا ہے۔ کسی مخصوص ورژن کا حوالہ دینے کے قابل ہونے کے لیے، میں نے لکھتے وقت کا موجودہ ورژن (نئے ٹیب میں کھلتا ہے) اپ لوڈ کر دیا ہے۔ میں جو سیکشن، صفحہ، اور مساوات کے نمبر استعمال کروں گا وہ اسی ورژن کا حوالہ دیں گے۔ اس دستاویز کو پڑھتے وقت اسے کسی دوسری ونڈو میں کھلا رکھنا ایک اچھا خیال ہے۔
EVM کیوں؟
اصل یلو پیپر ایتھیریم کی ترقی کے بالکل آغاز میں لکھا گیا تھا۔ یہ اصل ثبوتِ کار (PoW) پر مبنی اتفاق رائے کا طریقہ کار بیان کرتا ہے جو اصل میں نیٹ ورک کو محفوظ بنانے کے لیے استعمال کیا گیا تھا۔ تاہم، ایتھیریم نے ثبوتِ کار (PoW) کو بند کر دیا اور September 2022 میں حصہ داری کا ثبوت (PoS) پر مبنی اتفاق رائے کا استعمال شروع کر دیا۔ یہ ٹیوٹوریل یلو پیپر کے ان حصوں پر توجہ مرکوز کرے گا جو ایتھیریم ورچوئل مشین کی وضاحت کرتے ہیں۔ EVM حصہ داری کا ثبوت (PoS) کی طرف منتقلی سے غیر تبدیل شدہ رہا (سوائے DIFFICULTY آپ کوڈ کی واپسی کی قدر کے)۔
9 Execution model
This section (p. 14-16) includes most of the definition of the EVM.
The term system state includes everything you need to know about the system to run it. In a typical computer, this means the memory, content of registers, etc.
A Turing machine (نئے ٹیب میں کھلتا ہے) is a computational model. Essentially, it is a simplified version of a computer, which is proved to have the same ability to run computations that a normal computer can (everything that a computer can calculate a Turing machine can calculate and vice versa). This model makes it easier to prove various theorems about what is and what isn't computable.
The term Turing-complete (نئے ٹیب میں کھلتا ہے) means a computer that can run the same calculations as a Turing machine. Turing machines can get into infinite loops, and the EVM cannot because it would run out of gas, so it's only quasi-Turing-complete.
9.1 بنیادی باتیں
یہ سیکشن EVM کی بنیادی باتیں فراہم کرتا ہے اور یہ بتاتا ہے کہ اس کا دیگر کمپیوٹیشنل ماڈلز سے کیسے موازنہ کیا جاتا ہے۔
ایک اسٹیک مشین (نئے ٹیب میں کھلتا ہے) ایک ایسا کمپیوٹر ہے جو درمیانی ڈیٹا کو رجسٹرز میں نہیں، بلکہ ایک اسٹیک (نئے ٹیب میں کھلتا ہے) میں محفوظ کرتا ہے۔ یہ ورچوئل مشینوں کے لیے ترجیحی فن تعمیر ہے کیونکہ اسے نافذ کرنا آسان ہے جس کا مطلب ہے کہ بگز اور سیکیورٹی کے خطرات کا امکان بہت کم ہوتا ہے۔ اسٹیک میں میموری کو 256-bit الفاظ میں تقسیم کیا گیا ہے۔ اسے اس لیے منتخب کیا گیا تھا کیونکہ یہ ایتھیریم کے بنیادی کرپٹوگرافک آپریشنز جیسے کیچاک-۲۵۶ ہیشنگ اور بیضوی منحنی کے حساب کتاب کے لیے آسان ہے۔ اسٹیک کا زیادہ سے زیادہ سائز 1024 آئٹمز (1024 x 256 bits) ہے۔ جب آپ کوڈز پر عمل درآمد کیا جاتا ہے تو وہ عام طور پر اپنے پیرامیٹرز اسٹیک سے حاصل کر رہے ہوتے ہیں۔ اسٹیک میں عناصر کو دوبارہ ترتیب دینے کے لیے خاص طور پر آپ کوڈز موجود ہیں جیسے POP (اسٹیک کے اوپری حصے سے آئٹم کو ہٹاتا ہے)، DUP_N (اسٹیک میں N ویں آئٹم کی نقل بناتا ہے)، وغیرہ۔
EVM میں ایک غیر مستقل جگہ بھی ہوتی ہے جسے میموری کہا جاتا ہے جو عمل درآمد کے دوران ڈیٹا کو محفوظ کرنے کے لیے استعمال ہوتی ہے۔ یہ میموری 32-byte الفاظ میں ترتیب دی گئی ہے۔ تمام میموری کے مقامات کو صفر پر شروع کیا جاتا ہے۔ اگر آپ میموری میں ایک لفظ شامل کرنے کے لیے اس Yul (نئے ٹیب میں کھلتا ہے) کوڈ پر عمل درآمد کرتے ہیں، تو یہ لفظ میں خالی جگہ کو صفر سے بھر کر میموری کے 32 bytes کو پُر کر دے گا، یعنی یہ ایک لفظ بناتا ہے - جس میں مقامات 0-29 پر صفر، 30 پر 0x60، اور 31 پر 0xA7 ہوتا ہے۔
mstore(0, 0x60A7)
mstore ان تین آپ کوڈز میں سے ایک ہے جو EVM میموری کے ساتھ تعامل کے لیے فراہم کرتا ہے - یہ میموری میں ایک لفظ لوڈ کرتا ہے۔ دیگر دو mstore8 ہیں جو میموری میں ایک بائٹ لوڈ کرتا ہے، اور mload جو میموری سے اسٹیک میں ایک لفظ منتقل کرتا ہے۔
EVM میں ایک الگ غیر متزلزل اسٹوریج ماڈل بھی ہے جسے سسٹم کی حالت کے حصے کے طور پر برقرار رکھا جاتا ہے - یہ میموری الفاظ کی صفوں (اسٹیک میں ورڈ-ایڈریس ایبل بائٹ صفوں کے برعکس) میں ترتیب دی گئی ہے۔ یہ اسٹوریج وہ جگہ ہے جہاں کنٹریکٹس مستقل ڈیٹا رکھتے ہیں - ایک کنٹریکٹ صرف اپنے اسٹوریج کے ساتھ تعامل کر سکتا ہے۔ اسٹوریج کو کلید-قدر کی میپنگز میں ترتیب دیا گیا ہے۔
اگرچہ یلو پیپر کے اس حصے میں اس کا ذکر نہیں کیا گیا ہے، لیکن یہ جاننا بھی مفید ہے کہ میموری کی ایک چوتھی قسم بھی ہے۔ کال ڈیٹا بائٹ-ایڈریس ایبل صرف پڑھنے کے قابل میموری ہے جو ٹرانزیکشن کے data پیرامیٹر کے ساتھ پاس کی گئی قدر کو محفوظ کرنے کے لیے استعمال ہوتی ہے۔ EVM کے پاس calldata کو منظم کرنے کے لیے مخصوص آپ کوڈز ہیں۔ calldatasize ڈیٹا کا سائز واپس کرتا ہے۔ calldataload ڈیٹا کو اسٹیک میں لوڈ کرتا ہے۔ calldatacopy ڈیٹا کو میموری میں کاپی کرتا ہے۔
معیاری وان نیومین فن تعمیر (نئے ٹیب میں کھلتا ہے) کوڈ اور ڈیٹا کو ایک ہی میموری میں محفوظ کرتا ہے۔ EVM سیکیورٹی وجوہات کی بنا پر اس معیار کی پیروی نہیں کرتا ہے - غیر مستقل میموری کا اشتراک پروگرام کوڈ کو تبدیل کرنا ممکن بناتا ہے۔ اس کے بجائے، کوڈ کو اسٹوریج میں محفوظ کیا جاتا ہے۔
صرف دو صورتیں ہیں جن میں کوڈ پر میموری سے عمل درآمد کیا جاتا ہے:
- جب ایک کنٹریکٹ دوسرا کنٹریکٹ بناتا ہے (
CREATE(نئے ٹیب میں کھلتا ہے) یاCREATE2(نئے ٹیب میں کھلتا ہے) کا استعمال کرتے ہوئے)، تو کنٹریکٹ کنسٹرکٹر کا کوڈ میموری سے آتا ہے۔ - کسی بھی کنٹریکٹ کی تخلیق کے دوران، کنسٹرکٹر کوڈ چلتا ہے اور پھر اصل کنٹریکٹ کے کوڈ کے ساتھ واپس آتا ہے، وہ بھی میموری سے۔
اصطلاح غیر معمولی عمل درآمد کا مطلب ایک ایسی استثنا ہے جو موجودہ کنٹریکٹ کے عمل درآمد کو روکنے کا سبب بنتی ہے۔
9.2 فیس کا جائزہ
یہ سیکشن بتاتا ہے کہ گیس کی فیس کا حساب کیسے لگایا جاتا ہے۔ اس کی تین لاگتیں ہیں:
Opcode cost
The inherent cost of the specific opcode. To get this value, find the cost group of the opcode in Appendix H (p. 29, under equation (329)), and find the cost group in equation (326). This gives you a cost function, which in most cases uses parameters from Appendix G (p. 28).
For example, the opcode CALLDATACOPY (نئے ٹیب میں کھلتا ہے) is a member of group Wcopy. The opcode cost for that group is Gverylow+Gcopy×⌈μs[2]÷32⌉. Looking at Appendix G, we see that both constants are 3, which gives us 3+3×⌈μs[2]÷32⌉.
We still need to decipher the expression ⌈μs[2]÷32⌉. The outmost part, ⌈ <value> ⌉ is the ceiling function, a function that given a value returns the smallest integer that is still not smaller than the value. For example, ⌈2.5⌉ = ⌈3⌉ = 3. The inner part is μs[2]÷32. Looking at section 3 (Conventions) on p. 3, μ is the machine state. The machine state is defined in section 9.4.1 on p. 15. According to that section, one of the machine state parameters is s for the stack. Putting it all together, it seems that μs[2] is location #2 in the stack. Looking at the opcode (نئے ٹیب میں کھلتا ہے), location #2 in the stack is the size of the data in bytes. Looking at the other opcodes in group Wcopy, CODECOPY (نئے ٹیب میں کھلتا ہے) and RETURNDATACOPY (نئے ٹیب میں کھلتا ہے), they also have a size of data in the same location. So ⌈μs[2]÷32⌉ is the number of 32 byte words required to store the data being copied. Putting everything together, the inherent cost of CALLDATACOPY (نئے ٹیب میں کھلتا ہے) is 3 gas plus 3 per word of data being copied.
چلانے کی لاگت
اس کوڈ کو چلانے کی لاگت جسے ہم کال کر رہے ہیں۔
CREATE(نئے ٹیب میں کھلتا ہے) اورCREATE2(نئے ٹیب میں کھلتا ہے) کے معاملے میں، نئے کنٹریکٹ کے لیے کنسٹرکٹر۔CALL(نئے ٹیب میں کھلتا ہے)،CALLCODE(نئے ٹیب میں کھلتا ہے)،STATICCALL(نئے ٹیب میں کھلتا ہے)، یاDELEGATECALL(نئے ٹیب میں کھلتا ہے) کے معاملے میں، وہ کنٹریکٹ جسے ہم کال کرتے ہیں۔
Expanding memory cost
The cost of expanding memory (if necessary).
In equation 326, this value is written as Cmem(μi')-Cmem(μi). Looking at section 9.4.1 again, we see that μi is the number of words in memory. So μi is the number of words in memory before the opcode and μi' is the number of words in memory after the opcode.
The function Cmem is defined in equation 328: Cmem(a) = Gmemory × a + ⌊a2 ÷ 512⌋. ⌊x⌋ is the floor function, a function that given a value returns the largest integer that is still not larger than the value. For example, ⌊2.5⌋ = ⌊2⌋ = 2. When a < √512, a2 < 512, and the result of the floor function is zero. So for the first 22 words (704 bytes), the cost rises linearly with the number of memory words required. Beyond that point ⌊a2 ÷ 512⌋ is positive. When the memory required is high enough the gas cost is proportional to the square of the amount of memory.
Note that these factors only influence the inherent gas cost - it does not take into account the fee market or tips to validators that determine how much an end user is required to pay - this is just the raw cost of running a particular operation on the EVM.
9.3 Execution environment
The execution environment is a tuple, I, that includes information that isn't part of the blockchain state or the EVM.
| Parameter | Opcode to access the data | Solidity code to access the data |
|---|---|---|
| Ia | ADDRESS (نئے ٹیب میں کھلتا ہے) | address(this) |
| Io | ORIGIN (نئے ٹیب میں کھلتا ہے) | tx.origin |
| Ip | GASPRICE (نئے ٹیب میں کھلتا ہے) | tx.gasprice |
| Id | CALLDATALOAD (نئے ٹیب میں کھلتا ہے), etc. | msg.data |
| Is | CALLER (نئے ٹیب میں کھلتا ہے) | msg.sender |
| Iv | CALLVALUE (نئے ٹیب میں کھلتا ہے) | msg.value |
| Ib | CODECOPY (نئے ٹیب میں کھلتا ہے) | address(this).code |
| IH | Block header fields, such as NUMBER (نئے ٹیب میں کھلتا ہے) and DIFFICULTY (نئے ٹیب میں کھلتا ہے) | block.number, block.difficulty, etc. |
| Ie | Depth of the call stack for calls between contracts (including contract creation) | |
| Iw | Is the EVM allowed to change state, or is it running statically |
A few other parameters are necessary to understand the rest of section 9:
| Parameter | Defined in section | Meaning |
|---|---|---|
| σ | 2 (p. 2, equation 1) | The state of the blockchain |
| g | 9.3 (p. 14) | Remaining gas |
| A | 6.1 (p. 9) | Accrued substate (changes scheduled for when the transaction ends) |
| o | 9.3 (p. 14) | Output - the returned result in the case of internal transaction (when one contract calls another) and calls to view functions (when you are just asking for information, so there is no need to wait for a transaction) |
9.4 Execution overview
Now that have all the preliminaries, we can finally start working on how the EVM works.
Equations 146-151 give us the initial conditions for running the EVM:
| Symbol | Initial value | Meaning |
|---|---|---|
| μg | g | Gas remaining |
| μpc | 0 | Program counter, the address of the next instruction to execute |
| μm | (0, 0, ...) | Memory, initialized to all zeros |
| μi | 0 | Highest memory location used |
| μs | () | The stack, initially empty |
| μo | ∅ | The output, empty set until and unless we stop either with return data (RETURN (نئے ٹیب میں کھلتا ہے) or REVERT (نئے ٹیب میں کھلتا ہے)) or without it (STOP (نئے ٹیب میں کھلتا ہے) or SELFDESTRUCT (نئے ٹیب میں کھلتا ہے)). |
Equation 152 tells us there are four possible conditions at each point in time during execution, and what to do with them:
Z(σ,μ,A,I). Z represents a function that tests whether an operation creates an invalid state transition (see exceptional halting). If it evaluates to True, the new state is identical to the old one (except gas gets burned) because the changes have not been implemented.- If the opcode being executed is
REVERT(نئے ٹیب میں کھلتا ہے), the new state is the same as the old state, some gas is lost. - If the sequence of operations is finished, as signified by a
RETURN(نئے ٹیب میں کھلتا ہے)), the state is updated to the new state. - If we aren't at one of the end conditions 1-3, continue running.
9.4.1 مشین کی حالت
یہ سیکشن مشین کی حالت کو مزید تفصیل سے بیان کرتا ہے۔ یہ بتاتا ہے کہ w موجودہ آپ کوڈ ہے۔ اگر μpc کوڈ کی لمبائی ||Ib|| سے کم ہے، تو وہ بائٹ (Ib[μpc]) آپ کوڈ ہے۔ بصورت دیگر، آپ کوڈ کو STOP (نئے ٹیب میں کھلتا ہے) کے طور پر بیان کیا جاتا ہے۔
چونکہ یہ ایک اسٹیک مشین (نئے ٹیب میں کھلتا ہے) ہے، اس لیے ہمیں ہر آپ کوڈ کے ذریعے نکالے گئے (δ) اور ڈالے گئے (α) آئٹمز کی تعداد کا ٹریک رکھنے کی ضرورت ہے۔
9.4.2 Exceptional Halting
This section defines the Z function, which specifies when we have an abnormal termination. This is a Boolean (نئے ٹیب میں کھلتا ہے) function, so it uses ∨ for a logical or (نئے ٹیب میں کھلتا ہے) and ∧ for a logical and (نئے ٹیب میں کھلتا ہے).
We have an exceptional halt if any of these conditions is true:
-
μg < C(σ,μ,A,I) As we saw in section 9.2, C is the function that specifies the gas cost. There isn't enough gas left to cover the next opcode.
-
δw=∅ If the number of items popped for an opcode is undefined, then the opcode itself is undefined.
-
|| μs || < δw Stack underflow, not enough items in the stack for the current opcode.
-
w = JUMP ∧ μs[0]∉D(Ib) The opcode is
JUMP(نئے ٹیب میں کھلتا ہے) and the address is not aJUMPDEST(نئے ٹیب میں کھلتا ہے). Jumps are only valid when the destination is aJUMPDEST(نئے ٹیب میں کھلتا ہے). -
w = JUMPI ∧ μs[1]≠0 ∧ μs[0] ∉ D(Ib) The opcode is
JUMPI(نئے ٹیب میں کھلتا ہے), the condition is true (non zero) so the jump should happen, and the address is not aJUMPDEST(نئے ٹیب میں کھلتا ہے). Jumps are only valid when the destination is aJUMPDEST(نئے ٹیب میں کھلتا ہے). -
w = RETURNDATACOPY ∧ μs[1]+μs[2]>|| μo || The opcode is
RETURNDATACOPY(نئے ٹیب میں کھلتا ہے). In this opcode stack element μs[1] is the offset to read from in the return data buffer, and stack element μs[2] is the length of data. This condition occurs when you try to read beyond the end of the return data buffer. Note that there isn't a similar condition for the calldata or for the code itself. When you try to read beyond the end of those buffers you just get zeros. -
|| μs || - δw + αw > 1024
Stack overflow. If running the opcode will result in a stack of over 1024 items, abort.
-
¬Iw ∧ W(w,μ) Are we running statically (¬ is negation (نئے ٹیب میں کھلتا ہے) and Iw is true when we are allowed to change the blockchain state)? If so, and we're trying a state changing operation, it can't happen.
The function W(w,μ) is defined later in equation 159. W(w,μ) is true if one of these conditions is true:
-
w ∈ {CREATE, CREATE2, SSTORE, SELFDESTRUCT} These opcodes change the state, either by creating a new contract, storing a value, or destroying the current contract.
-
LOG0≤w ∧ w≤LOG4 If we are called statically we cannot emit log entries. The log opcodes are all in the range between
LOG0(A0) (نئے ٹیب میں کھلتا ہے) andLOG4(A4) (نئے ٹیب میں کھلتا ہے). The number after the log opcode specifies how many topics the log entry contains. -
w=CALL ∧ μs[2]≠0 You can call another contract when you're static, but if you do you cannot transfer ETH to it.
-
-
w = SSTORE ∧ μg ≤ Gcallstipend You cannot run
SSTORE(نئے ٹیب میں کھلتا ہے) unless you have more than Gcallstipend (defined as 2300 in Appendix G) gas.
9.4.3 Jump Destination Validity
Here we formally define what are the JUMPDEST (نئے ٹیب میں کھلتا ہے) opcodes. We cannot just look for byte value 0x5B, because it might be inside a PUSH (and therefore data and not an opcode).
In equation (162) we define a function, N(i,w). The first parameter, i, is the opcode's location. The second, w, is the opcode itself. If w∈[PUSH1, PUSH32] that means the opcode is a PUSH (square brackets define a range that includes the endpoints). If that case the next opcode is at i+2+(w−PUSH1). For PUSH1 (نئے ٹیب میں کھلتا ہے) we need to advance by two bytes (the PUSH itself and the one byte value), for PUSH2 (نئے ٹیب میں کھلتا ہے) we need to advance by three bytes because it's a two byte value, etc. All other EVM opcodes are just one byte long, so in all other cases N(i,w)=i+1.
This function is used in equation (161) to define DJ(c,i), which is the set (نئے ٹیب میں کھلتا ہے) of all valid jump destinations in code c, starting with opcode location i. This function is defined recursively. If i≥||c||, that means that we're at or after the end of the code. We are not going to find any more jump destinations, so just return the empty set.
In all other cases we look at the rest of the code by going to the next opcode and getting the set starting from it. c[i] is the current opcode, so N(i,c[i]) is the location of the next opcode. DJ(c,N(i,c[i])) is therefore the set of valid jump destinations that starts at the next opcode. If the current opcode isn't a JUMPDEST, just return that set. If it is JUMPDEST, include it in the result set and return that.
9.4.4 عام رکاوٹ
رکاوٹ کا فنکشن H، تین قسم کی قدریں واپس کر سکتا ہے۔
- اگر ہم ہالٹ آپ کوڈ میں نہیں ہیں، تو ∅، خالی سیٹ واپس کریں۔ روایت کے مطابق، اس قدر کی تشریح بولین غلط (false) کے طور پر کی جاتی ہے۔
- اگر ہمارے پاس ایک ہالٹ آپ کوڈ ہے جو آؤٹ پٹ پیدا نہیں کرتا ہے (یا تو
STOP(نئے ٹیب میں کھلتا ہے) یاSELFDESTRUCT(نئے ٹیب میں کھلتا ہے))، تو واپسی کی قدر کے طور پر صفر بائٹس کے سائز کی ترتیب واپس کریں۔ نوٹ کریں کہ یہ خالی سیٹ سے بہت مختلف ہے۔ اس قدر کا مطلب ہے کہ EVM واقعی رک گیا تھا، بس پڑھنے کے لیے کوئی واپسی کا ڈیٹا نہیں ہے۔ - اگر ہمارے پاس ایک ہالٹ آپ کوڈ ہے جو آؤٹ پٹ پیدا کرتا ہے (یا تو
RETURN(نئے ٹیب میں کھلتا ہے) یاREVERT(نئے ٹیب میں کھلتا ہے))، تو اس آپ کوڈ کے ذریعے بتائی گئی بائٹس کی ترتیب واپس کریں۔ یہ ترتیب میموری سے لی گئی ہے، اسٹیک کے اوپری حصے کی قدر (μs[0]) پہلی بائٹ ہے، اور اس کے بعد کی قدر (μs[1]) لمبائی ہے۔
H.2 ہدایات کا مجموعہ
اس سے پہلے کہ ہم EVM کے آخری ذیلی حصے، 9.5 کی طرف بڑھیں، آئیے خود ہدایات پر ایک نظر ڈالتے ہیں۔ ان کی وضاحت ضمیمہ H.2 میں کی گئی ہے جو صفحہ 30 سے شروع ہوتا ہے۔ کوئی بھی چیز جس کے بارے میں یہ واضح نہیں کیا گیا کہ وہ اس مخصوص آپ کوڈ کے ساتھ تبدیل ہو رہی ہے، اس کے بارے میں توقع کی جاتی ہے کہ وہ ویسے ہی رہے گی۔ جو متغیرات تبدیل ہوتے ہیں انہیں <something>′ کے طور پر واضح کیا جاتا ہے۔
مثال کے طور پر، آئیے ADD (نئے ٹیب میں کھلتا ہے) آپ کوڈ پر ایک نظر ڈالتے ہیں۔
| قدر | نیمونک | δ | α | تفصیل |
|---|---|---|---|---|
| 0x01 | ADD | 2 | 1 | جمع کا عمل۔ |
| μ′s[0] ≡ μs[0] + μs[1] |
δ ان اقدار کی تعداد ہے جو ہم اسٹیک سے نکالتے (pop) ہیں۔ اس صورت میں دو، کیونکہ ہم اوپر کی دو اقدار کو جمع کر رہے ہیں۔
α ان اقدار کی تعداد ہے جو ہم واپس ڈالتے (push) ہیں۔ اس صورت میں ایک، یعنی مجموعہ۔
لہذا نیا اسٹیک ٹاپ (μ′s[0]) پرانے اسٹیک ٹاپ (μs[0]) اور اس کے نیچے موجود پرانی قدر (μs[1]) کا مجموعہ ہے۔
تمام آپ کوڈز کی ایک طویل اور بورنگ فہرست پر نظر ڈالنے کے بجائے، یہ مضمون صرف ان آپ کوڈز کی وضاحت کرتا ہے جو کچھ نیا متعارف کراتے ہیں۔
| قدر | نیمونک | δ | α | تفصیل |
|---|---|---|---|---|
| 0x20 | KECCAK256 | 2 | 1 | کیچاک-۲۵۶ ہیش کا حساب لگائیں۔ |
| μ′s[0] ≡ KEC(μm[μs[0] . . . (μs[0] + μs[1] − 1)]) | ||||
| μ′i ≡ M(μi,μs[0],μs[1]) |
یہ پہلا آپ کوڈ ہے جو میموری تک رسائی حاصل کرتا ہے (اس صورت میں، صرف پڑھنے کے لیے)۔ تاہم، یہ میموری کی موجودہ حدود سے آگے بڑھ سکتا ہے، اس لیے ہمیں μi کو اپ ڈیٹ کرنے کی ضرورت ہے۔ ہم یہ صفحہ 30 پر مساوات 330 میں بیان کردہ M فنکشن کا استعمال کرتے ہوئے کرتے ہیں۔
| قدر | نیمونک | δ | α | تفصیل |
|---|---|---|---|---|
| 0x31 | BALANCE | 1 | 1 | دیے گئے اکاؤنٹ کا بیلنس حاصل کریں۔ |
| ... |
وہ پتہ جس کا بیلنس ہمیں تلاش کرنے کی ضرورت ہے وہ μs[0] mod 2160 ہے۔ اسٹیک کا اوپری حصہ پتہ ہے، لیکن چونکہ پتے صرف 160 bits کے ہوتے ہیں، اس لیے ہم قدر کا ماڈیولو (modulo) (نئے ٹیب میں کھلتا ہے) 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}، گرم اسٹوریج (وہ اسٹوریج جس تک حال ہی میں رسائی حاصل کی گئی ہو اور جس کے کیشے (cached) ہونے کا امکان ہو) اور ٹھنڈے اسٹوریج (وہ اسٹوریج جس تک رسائی حاصل نہ کی گئی ہو اور جس کے سست اسٹوریج میں ہونے کا امکان ہو جسے بازیافت کرنا زیادہ مہنگا ہو) تک رسائی کی لاگت میں فرق سے متعلق ہے۔ Aa ان پتوں کی فہرست ہے جن تک ٹرانزیکشن کے ذریعے پہلے رسائی حاصل کی گئی تھی، اس لیے ان تک رسائی سستی ہونی چاہیے، جیسا کہ صفحہ 9 پر سیکشن 6.1 میں بیان کیا گیا ہے۔ آپ اس موضوع کے بارے میں مزید EIP-2929 (نئے ٹیب میں کھلتا ہے) میں پڑھ سکتے ہیں۔
| قدر | نیمونک | δ | α | تفصیل |
|---|---|---|---|---|
| 0x8F | DUP16 | 16 | 17 | اسٹیک کے 16 ویں آئٹم کی نقل بنائیں۔ |
| μ′s[0] ≡ μs[15] |
نوٹ کریں کہ کسی بھی اسٹیک آئٹم کو استعمال کرنے کے لیے، ہمیں اسے نکالنا (pop) پڑتا ہے، جس کا مطلب ہے کہ ہمیں اس کے اوپر موجود تمام اسٹیک آئٹمز کو بھی نکالنا ہوگا۔ DUP<n> (نئے ٹیب میں کھلتا ہے) اور SWAP<n> (نئے ٹیب میں کھلتا ہے) کے معاملے میں، اس کا مطلب ہے کہ سولہ اقدار تک کو نکالنا اور پھر واپس ڈالنا (push) پڑتا ہے۔
9.5 عمل درآمد کا چکر
اب چونکہ ہمارے پاس تمام حصے موجود ہیں، ہم بالآخر سمجھ سکتے ہیں کہ EVM کے عمل درآمد کے چکر کو کس طرح دستاویزی شکل دی گئی ہے۔
مساوات (164) کہتی ہے کہ دی گئی حالت کے مطابق:
- σ (عالمی بلاک چین کی حالت)
- μ (EVM کی حالت)
- A (ذیلی حالت، وہ تبدیلیاں جو ٹرانزیکشن کے ختم ہونے پر ہوں گی)
- I (عمل درآمد کا ماحول)
نئی حالت (σ', μ', A', I') ہے۔
مساوات (165)-(167) اسٹیک اور ایک آپ کوڈ (μs) کی وجہ سے اس میں ہونے والی تبدیلی کی وضاحت کرتی ہیں۔ مساوات (168) گیس (μg) میں تبدیلی ہے۔ مساوات (169) پروگرام کاؤنٹر (μpc) میں تبدیلی ہے۔ آخر میں، مساوات (170)-(173) یہ واضح کرتی ہیں کہ دیگر پیرامیٹرز ویسے ہی رہتے ہیں، جب تک کہ آپ کوڈ کے ذریعے واضح طور پر تبدیل نہ کیے جائیں۔
اس کے ساتھ EVM کی مکمل وضاحت ہو جاتی ہے۔
نتیجہ
ریاضیاتی اشارے قطعی ہیں اور انہوں نے یلو پیپر کو ایتھیریم کی ہر تفصیل بتانے کی اجازت دی ہے۔ تاہم، اس کی کچھ خامیاں ہیں:
- اسے صرف انسان ہی سمجھ سکتے ہیں، جس کا مطلب ہے کہ تعمیل کے ٹیسٹ (نئے ٹیب میں کھلتا ہے) دستی طور پر لکھے جانے چاہئیں۔
- پروگرامرز کمپیوٹر کوڈ کو سمجھتے ہیں۔ وہ ریاضیاتی اشارے کو سمجھ بھی سکتے ہیں اور نہیں بھی۔
شاید انہی وجوہات کی بنا پر، نئی اتفاق رائے کی تہہ کی تفصیلات (نئے ٹیب میں کھلتا ہے) Python میں لکھی گئی ہیں۔ Python میں عمل درآمد کی تہہ کی تفصیلات (نئے ٹیب میں کھلتا ہے) موجود ہیں، لیکن وہ مکمل نہیں ہیں۔ جب تک کہ پورا یلو پیپر بھی Python یا اس جیسی کسی زبان میں ترجمہ نہیں ہو جاتا، یلو پیپر سروس میں رہے گا، اور اسے پڑھنے کے قابل ہونا مددگار ہے۔