মূল কন্টেন্টে যান

ইয়েলো পেপারের EVM স্পেসিফিকেশন বোঝা

evm
মধ্যবর্তী
qbzzt
15 মে, 2022
17 মিনিট পড়ার সময়

ইয়েলো পেপার (opens in a new tab) হলো ইথেরিয়ামের আনুষ্ঠানিক স্পেসিফিকেশন। EIP প্রক্রিয়া দ্বারা সংশোধিত স্থানগুলো ছাড়া, এটি সবকিছু কীভাবে কাজ করে তার সঠিক বিবরণ ধারণ করে। এটি একটি গাণিতিক পেপার হিসেবে লেখা হয়েছে, যার মধ্যে এমন পরিভাষা রয়েছে যা প্রোগ্রামারদের কাছে পরিচিত নাও হতে পারে। এই পেপারে আপনি শিখবেন কীভাবে এটি পড়তে হয় এবং এর পাশাপাশি অন্যান্য সম্পর্কিত গাণিতিক পেপারগুলোও পড়তে হয়।

কোন ইয়েলো পেপার?

ইথেরিয়ামের প্রায় অন্য সবকিছুর মতো, ইয়েলো পেপারও সময়ের সাথে সাথে বিবর্তিত হয়। একটি নির্দিষ্ট সংস্করণ উল্লেখ করতে সক্ষম হওয়ার জন্য, আমি লেখার সময়কার বর্তমান সংস্করণটি আপলোড করেছি। আমি যে বিভাগ, পৃষ্ঠা এবং সমীকরণ নম্বরগুলো ব্যবহার করব তা ওই সংস্করণটিকে নির্দেশ করবে। এই ডকুমেন্টটি পড়ার সময় এটি অন্য একটি উইন্ডোতে খোলা রাখা ভালো।

EVM কেন?

মূল ইয়েলো পেপারটি ইথেরিয়ামের বিকাশের একেবারে শুরুতেই লেখা হয়েছিল। এটি মূল প্রুফ-অফ-ওয়ার্ক (PoW) ভিত্তিক কনসেনসাস মেকানিজম বর্ণনা করে যা প্রাথমিকভাবে নেটওয়ার্ক সুরক্ষিত করতে ব্যবহৃত হয়েছিল। যাইহোক, ইথেরিয়াম প্রুফ-অফ-ওয়ার্ক বন্ধ করে দেয় এবং 2022 সালের সেপ্টেম্বরে প্রুফ-অফ-স্টেক (PoS) ভিত্তিক ঐক্যমত ব্যবহার শুরু করে। এই টিউটোরিয়ালটি ইয়েলো পেপারের সেই অংশগুলোর ওপর ফোকাস করবে যা ইথেরিয়াম ভার্চুয়াল মেশিনকে সংজ্ঞায়িত করে। প্রুফ-অফ-স্টেক-এ রূপান্তরের ফলে EVM অপরিবর্তিত ছিল (DIFFICULTY অপকোডের রিটার্ন ভ্যালু ছাড়া)।

9 এক্সিকিউশন মডেল

এই বিভাগে (পৃষ্ঠা 12-14) EVM-এর বেশিরভাগ সংজ্ঞা অন্তর্ভুক্ত রয়েছে।

সিস্টেম স্টেট (system state) শব্দটির মধ্যে সিস্টেমটি চালানোর জন্য আপনার যা কিছু জানা প্রয়োজন তার সবকিছু অন্তর্ভুক্ত রয়েছে। একটি সাধারণ কম্পিউটারে, এর অর্থ হলো মেমরি, রেজিস্টারের বিষয়বস্তু ইত্যাদি।

একটি টুরিং মেশিন (opens in a new tab) হলো একটি কম্পিউটেশনাল মডেল। মূলত, এটি একটি কম্পিউটারের সরলীকৃত সংস্করণ, যা একটি সাধারণ কম্পিউটারের মতো একই কম্পিউটেশন চালানোর ক্ষমতা রাখে বলে প্রমাণিত (একটি কম্পিউটার যা কিছু গণনা করতে পারে একটি টুরিং মেশিনও তা গণনা করতে পারে এবং এর বিপরীতটিও সত্য)। এই মডেলটি কী গণনাযোগ্য এবং কী নয় সে সম্পর্কে বিভিন্ন উপপাদ্য প্রমাণ করা সহজ করে তোলে।

টুরিং-কমপ্লিট (opens in a new tab) শব্দটি এমন একটি কম্পিউটারকে বোঝায় যা টুরিং মেশিনের মতো একই গণনা চালাতে পারে। টুরিং মেশিনগুলো অসীম লুপে (infinite loops) আটকে যেতে পারে, কিন্তু EVM পারে না কারণ এর গ্যাস ফুরিয়ে যাবে, তাই এটি কেবল আধা-টুরিং-কমপ্লিট (quasi-Turing-complete)।

9.1 বেসিকস

এই বিভাগটি EVM-এর বেসিকস এবং অন্যান্য কম্পিউটেশনাল মডেলের সাথে এর তুলনা কীভাবে করা যায় তা তুলে ধরে।

একটি স্ট্যাক মেশিন (opens in a new tab) হলো এমন একটি কম্পিউটার যা মধ্যবর্তী ডেটা রেজিস্টারে নয়, বরং একটি স্ট্যাকে (opens in a new tab) সংরক্ষণ করে। এটি ভার্চুয়াল মেশিনগুলোর জন্য পছন্দের আর্কিটেকচার কারণ এটি বাস্তবায়ন করা সহজ, যার অর্থ হলো বাগ এবং নিরাপত্তা দুর্বলতার সম্ভাবনা অনেক কম। স্ট্যাকের মেমরি 256-বিট শব্দে (words) বিভক্ত। এটি বেছে নেওয়া হয়েছিল কারণ এটি ইথেরিয়ামের মূল ক্রিপ্টোগ্রাফিক ক্রিয়াকলাপ যেমন কেক্যাক-২৫৬ হ্যাশিং এবং উপবৃত্তাকার বক্ররেখা গণনার জন্য সুবিধাজনক। স্ট্যাকের সর্বোচ্চ আকার হলো 1024টি আইটেম (1024 x 256 বিট)। যখন অপকোডগুলো এক্সিকিউট করা হয় তখন তারা সাধারণত স্ট্যাক থেকে তাদের প্যারামিটারগুলো পায়। স্ট্যাকের উপাদানগুলো পুনর্গঠন করার জন্য বিশেষভাবে অপকোড রয়েছে যেমন POP (স্ট্যাকের শীর্ষ থেকে আইটেম সরিয়ে দেয়), DUP_N (স্ট্যাকের N-তম আইটেম ডুপ্লিকেট করে), ইত্যাদি।

EVM-এ মেমরি নামক একটি ভোলাটাইল স্পেসও রয়েছে যা এক্সিকিউশনের সময় ডেটা সংরক্ষণ করতে ব্যবহৃত হয়। এই মেমরিটি 32-বাইট শব্দে সংগঠিত। সমস্ত মেমরি লোকেশন শূন্যতে (zero) ইনিশিয়ালাইজ করা হয়। আপনি যদি মেমরিতে একটি শব্দ যোগ করতে এই Yul (opens in a new tab) কোডটি এক্সিকিউট করেন, তবে এটি শব্দের খালি জায়গাটি শূন্য দিয়ে পূরণ করে 32 বাইট মেমরি পূর্ণ করবে, অর্থাৎ, এটি একটি শব্দ তৈরি করে - যার 0-29 লোকেশনে শূন্য, 30-এ 0x60 এবং 31-এ 0xA7 থাকে।

mstore(0, 0x60A7)

mstore হলো মেমরির সাথে ইন্টারঅ্যাক্ট করার জন্য EVM দ্বারা প্রদত্ত তিনটি অপকোডের মধ্যে একটি - এটি মেমরিতে একটি শব্দ লোড করে। অন্য দুটি হলো mstore8 যা মেমরিতে একটি একক বাইট লোড করে এবং mload যা মেমরি থেকে স্ট্যাকে একটি শব্দ স্থানান্তর করে।

EVM-এর একটি পৃথক নন-ভোলাটাইল স্টোরেজ মডেলও রয়েছে যা সিস্টেম স্টেটের অংশ হিসেবে রক্ষণাবেক্ষণ করা হয় - এই মেমরিটি ওয়ার্ড অ্যারেতে (স্ট্যাকের ওয়ার্ড-অ্যাড্রেসেবল বাইট অ্যারের বিপরীতে) সংগঠিত হয়। এই স্টোরেজেই কন্ট্রাক্টগুলো স্থায়ী ডেটা রাখে - একটি কন্ট্রাক্ট কেবল তার নিজস্ব স্টোরেজের সাথেই ইন্টারঅ্যাক্ট করতে পারে। স্টোরেজ কী-ভ্যালু (key-value) ম্যাপিংয়ে সংগঠিত হয়।

যদিও ইয়েলো পেপারের এই বিভাগে এটি উল্লেখ করা হয়নি, তবে এটি জানাও দরকারী যে চতুর্থ ধরণের একটি মেমরি রয়েছে। কল ডেটা (Calldata) হলো বাইট-অ্যাড্রেসেবল রিড-অনলি মেমরি যা একটি ট্রানজ্যাকশনের data প্যারামিটারের সাথে পাস করা মান সংরক্ষণ করতে ব্যবহৃত হয়। calldata পরিচালনা করার জন্য EVM-এর নির্দিষ্ট অপকোড রয়েছে। 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 নম্বর বিভাগের (Conventions) দিকে তাকালে, μ হলো মেশিন স্টেট। মেশিন স্টেটটি পৃষ্ঠা 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 বাইট) জন্য, প্রয়োজনীয় মেমরি শব্দের সংখ্যার সাথে খরচ রৈখিকভাবে (linearly) বৃদ্ধি পায়। সেই বিন্দুর পরে ⌊a2 ÷ 512⌋ ধনাত্মক হয়। যখন প্রয়োজনীয় মেমরি যথেষ্ট বেশি হয়, তখন গ্যাস খরচ মেমরির পরিমাণের বর্গের সমানুপাতিক হয়।

দ্রষ্টব্য যে এই বিষয়গুলো কেবল অন্তর্নিহিত গ্যাস খরচকে প্রভাবিত করে - এটি ফি মার্কেট বা ভ্যালিডেটরদের টিপস বিবেচনা করে না যা নির্ধারণ করে যে একজন শেষ ব্যবহারকারীকে (end user) কত টাকা দিতে হবে - এটি কেবল 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), etc.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, etc.
Ieকন্ট্রাক্টগুলোর মধ্যে কলের জন্য কল স্ট্যাকের গভীরতা (কন্ট্রাক্ট তৈরি সহ)
IwEVM-কে কি স্টেট পরিবর্তন করার অনুমতি দেওয়া হয়েছে, নাকি এটি স্ট্যাটিকভাবে চলছে

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), তাই আমাদের প্রতিটি অপকোড দ্বারা পপ আউট (δ) এবং পুশ ইন (α) করা আইটেমগুলোর সংখ্যার ট্র্যাক রাখতে হবে।

9.4.2 অস্বাভাবিক হল্টিং

এই বিভাগটি Z ফাংশনকে সংজ্ঞায়িত করে, যা নির্দিষ্ট করে কখন আমাদের একটি অস্বাভাবিক সমাপ্তি (abnormal termination) ঘটে। এটি একটি বুলিয়ান (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টির বেশি আইটেমের স্ট্যাক তৈরি হয়, তবে বাতিল করুন।

  • ¬Iw ∧ W(w,μ) আমরা কি স্ট্যাটিকভাবে চালাচ্ছি (¬ হলো নেগেশন (opens in a new tab) এবং Iw সত্য হয় যখন আমাদের ব্লকচেইন স্টেট পরিবর্তন করার অনুমতি দেওয়া হয়)? যদি তাই হয়, এবং আমরা একটি স্টেট পরিবর্তনকারী অপারেশন করার চেষ্টা করছি, তবে এটি ঘটতে পারে না।

    W(w,μ) ফাংশনটি পরে সমীকরণ 150-এ সংজ্ঞায়িত করা হয়েছে। W(w,μ) সত্য হবে যদি এই শর্তগুলোর মধ্যে একটি সত্য হয়:

    • w ∈ {CREATE, CREATE2, SSTORE, SELFDESTRUCT} এই অপকোডগুলো স্টেট পরিবর্তন করে, হয় একটি নতুন কন্ট্রাক্ট তৈরি করে, একটি মান সংরক্ষণ করে, অথবা বর্তমান কন্ট্রাক্টটি ধ্বংস করে।

    • LOG0≤w ∧ w≤LOG4 যদি আমাদের স্ট্যাটিকভাবে কল করা হয় তবে আমরা লগ এন্ট্রিগুলো নির্গত করতে পারি না। লগ অপকোডগুলো সবই LOG0 (A0) (opens in a new tab) এবং LOG4 (A4) (opens in a new tab)-এর মধ্যবর্তী রেঞ্জে থাকে। লগ অপকোডের পরের সংখ্যাটি নির্দিষ্ট করে যে লগ এন্ট্রিতে কতগুলো টপিক রয়েছে।

    • w=CALL ∧ μs[2]≠0 আপনি স্ট্যাটিক থাকা অবস্থায় অন্য একটি কন্ট্রাক্ট কল করতে পারেন, তবে আপনি যদি তা করেন তবে আপনি এতে ETH হস্তান্তর করতে পারবেন না।

  • w = SSTORE ∧ μg ≤ Gcallstipend আপনার কাছে Gcallstipend (পরিশিষ্ট G-এ 2300 হিসেবে সংজ্ঞায়িত) গ্যাসের বেশি না থাকলে আপনি SSTORE (opens in a new tab) চালাতে পারবেন না।

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-এ অপকোড লোকেশন i থেকে শুরু হওয়া সমস্ত বৈধ জাম্প গন্তব্যের সেট (opens in a new tab)। এই ফাংশনটি রিকার্সিভভাবে (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-এ শুরু হয়। সেই নির্দিষ্ট অপকোডের সাথে পরিবর্তনশীল হিসেবে নির্দিষ্ট করা হয়নি এমন যেকোনো কিছু একই থাকবে বলে আশা করা হয়। যে ভেরিয়েবলগুলো পরিবর্তিত হয় সেগুলো <something>′ হিসেবে নির্দিষ্ট করা হয়।

উদাহরণস্বরূপ, আসুন ADD (opens in a new tab) অপকোডটি দেখি।

মাননেমোনিকδαবিবরণ
0x01ADD21যোগের অপারেশন।
μ′s[0] ≡ μs[0] + μs[1]

δ হলো স্ট্যাক থেকে আমরা যে মানগুলো পপ করি তার সংখ্যা। এই ক্ষেত্রে দুটি, কারণ আমরা শীর্ষ দুটি মান যোগ করছি।

α হলো আমরা যে মানগুলো পুশ ব্যাক করি তার সংখ্যা। এই ক্ষেত্রে একটি, যোগফল।

সুতরাং নতুন স্ট্যাকের শীর্ষ (μ′s[0]) হলো পুরানো স্ট্যাকের শীর্ষ (μs[0]) এবং এর নীচের পুরানো মানের (μs[1]) যোগফল।

একটি "চোখ ধাঁধানো তালিকা" দিয়ে সমস্ত অপকোডগুলো দেখার পরিবর্তে, এই নিবন্ধটি কেবল সেই অপকোডগুলো ব্যাখ্যা করে যা নতুন কিছু প্রবর্তন করে।

মাননেমোনিকδαবিবরণ
0x20KECCAK25621কেক্যাক-২৫৬ হ্যাশ গণনা করুন।
μ′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 বিটের, তাই আমরা মডুলো (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-এর এক্সিকিউশন সাইকেল (execution cycle) নথিভুক্ত করা হয়।

সমীকরণ (155) বলে যে স্টেট দেওয়া হলে:

  • σ (গ্লোবাল ব্লকচেইন স্টেট)
  • μ (EVM স্টেট)
  • A (সাবস্টেট, ট্রানজ্যাকশন শেষ হলে যে পরিবর্তনগুলো ঘটবে)
  • I (এক্সিকিউশন এনভায়রনমেন্ট)

নতুন স্টেটটি হলো (σ', μ', A', I')

সমীকরণ (156)-(158) স্ট্যাক এবং একটি অপকোডের (μs) কারণে এতে হওয়া পরিবর্তনকে সংজ্ঞায়িত করে। সমীকরণ (159) হলো গ্যাসের পরিবর্তন (μg)। সমীকরণ (160) হলো প্রোগ্রাম কাউন্টারের পরিবর্তন (μpc)। অবশেষে, সমীকরণ (161)-(164) নির্দিষ্ট করে যে অন্যান্য প্যারামিটারগুলো একই থাকে, যদি না অপকোড দ্বারা স্পষ্টভাবে পরিবর্তন করা হয়।

এর মাধ্যমে EVM সম্পূর্ণরূপে সংজ্ঞায়িত করা হয়েছে।

উপসংহার

গাণিতিক স্বরলিপি (Mathematical notation) সুনির্দিষ্ট এবং এটি ইয়েলো পেপারকে ইথেরিয়ামের প্রতিটি বিবরণ নির্দিষ্ট করার অনুমতি দিয়েছে। যাইহোক, এর কিছু অসুবিধাও রয়েছে:

  • এটি কেবল মানুষের দ্বারাই বোঝা সম্ভব, যার অর্থ হলো কমপ্লায়েন্স টেস্টগুলো (opens in a new tab) ম্যানুয়ালি লিখতে হবে।
  • প্রোগ্রামাররা কম্পিউটার কোড বোঝেন। তারা গাণিতিক স্বরলিপি বুঝতেও পারেন বা নাও বুঝতে পারেন।

সম্ভবত এই কারণগুলোর জন্যই, নতুন কনসেনসাস লেয়ার স্পেসিফিকেশনগুলো (opens in a new tab) Python-এ লেখা হয়েছে। Python-এ এক্সিকিউশন লেয়ার স্পেসিফিকেশন (opens in a new tab) রয়েছে, তবে সেগুলো সম্পূর্ণ নয়। যতক্ষণ না সম্পূর্ণ ইয়েলো পেপারটিও Python বা অনুরূপ কোনো ভাষায় অনুবাদ করা হচ্ছে, ততক্ষণ ইয়েলো পেপারটি পরিষেবাতে অব্যাহত থাকবে এবং এটি পড়তে পারা সহায়ক।