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

ইয়েলো পেপারের ইভিএম (EVM) স্পেসিফিকেশন বোঝা

evm
ইন্টারমিডিয়েট
qbzzt
15 মে, 2022
17 মিনিট পড়া

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

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

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

ইভিএম (EVM) কেন?

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

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

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

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

একটি টুরিং মেশিন (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) বিভক্ত। এটি বেছে নেওয়া হয়েছিল কারণ এটি ইথেরিয়ামের মূল ক্রিপ্টোগ্রাফিক অপারেশন যেমন Keccak-256 হ্যাশিং এবং উপবৃত্তাকার বক্ররেখা (elliptic curve) কম্পিউটেশনের জন্য সুবিধাজনক। স্ট্যাকের সর্বোচ্চ আকার হলো 1024 আইটেম (1024 x 256 বিট)। যখন অপকোডগুলো এক্সিকিউট করা হয়, তখন তারা সাধারণত স্ট্যাক থেকে তাদের প্যারামিটারগুলো গ্রহণ করে। স্ট্যাকের উপাদানগুলো পুনর্গঠন করার জন্য বিশেষভাবে অপকোড রয়েছে যেমন POP (স্ট্যাকের শীর্ষ থেকে আইটেম সরিয়ে দেয়), DUP_N (স্ট্যাকের N-তম আইটেম ডুপ্লিকেট করে) ইত্যাদি।

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

1mstore(0, 0x60A7)

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

EVM-এর একটি পৃথক নন-ভোলাটাইল স্টোরেজ মডেলও রয়েছে যা সিস্টেম স্টেটের অংশ হিসেবে রক্ষণাবেক্ষণ করা হয় - এই মেমরিটি শব্দ অ্যারেতে (word arrays) সংগঠিত হয় (স্ট্যাকের শব্দ-অ্যাড্রেসযোগ্য বাইট অ্যারের বিপরীতে)। এই স্টোরেজেই কন্ট্রাক্টগুলো স্থায়ী ডেটা রাখে - একটি কন্ট্রাক্ট কেবল তার নিজস্ব স্টোরেজের সাথেই ইন্টারঅ্যাক্ট করতে পারে। স্টোরেজ কি-ভ্যালু (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) ব্যবহার করে), তখন কন্ট্রাক্ট কনস্ট্রাক্টরের কোড মেমরি থেকে আসে।
  • যেকোনো কন্ট্রাক্ট তৈরির সময়, কনস্ট্রাক্টর কোড রান করে এবং তারপর আসল কন্ট্রাক্টের কোড নিয়ে রিটার্ন করে, যা মেমরি থেকেও আসে।

এক্সেপশনাল এক্সিকিউশন পরিভাষাটির অর্থ হলো এমন একটি এক্সেপশন যা বর্তমান কন্ট্রাক্টের এক্সিকিউশন বন্ধ করে দেয়।

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> ⌉ হলো সিলিং ফাংশন, এমন একটি ফাংশন যা একটি ভ্যালু দেওয়া হলে সবচেয়ে ছোট পূর্ণসংখ্যা রিটার্ন করে যা এখনও ভ্যালুটির চেয়ে ছোট নয়। উদাহরণস্বরূপ, ⌈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 বাইট শব্দের (words) সংখ্যা। সবকিছু একসাথে রাখলে, CALLDATACOPY (opens in a new tab)-এর অন্তর্নিহিত খরচ হলো 3 গ্যাস এবং কপি করা ডেটার প্রতি শব্দের জন্য 3।

রানিং খরচ

আমরা যে কোডটি কল করছি তা চালানোর খরচ।

মেমরি সম্প্রসারণের খরচ

মেমরি সম্প্রসারণের খরচ (যদি প্রয়োজন হয়)।

সমীকরণ 324-এ, এই ভ্যালুটি Cmemi')-Cmemi) হিসেবে লেখা হয়েছে। আবার সেকশন 9.4.1-এর দিকে তাকালে, আমরা দেখতে পাই যে μi হলো মেমরিতে শব্দের (words) সংখ্যা। সুতরাং μi হলো অপকোডের আগে মেমরিতে শব্দের সংখ্যা এবং μi' হলো অপকোডের পরে মেমরিতে শব্দের সংখ্যা।

Cmem ফাংশনটি সমীকরণ 326-এ সংজ্ঞায়িত করা হয়েছে: Cmem(a) = Gmemory × a + ⌊a2 ÷ 512⌋⌊x⌋ হলো ফ্লোর ফাংশন, এমন একটি ফাংশন যা একটি ভ্যালু দেওয়া হলে সবচেয়ে বড় পূর্ণসংখ্যা রিটার্ন করে যা এখনও ভ্যালুটির চেয়ে বড় নয়। উদাহরণস্বরূপ, ⌊2.5⌋ = ⌊2⌋ = 2. যখন a < √512, a2 < 512, এবং ফ্লোর ফাংশনের ফলাফল শূন্য হয়। সুতরাং প্রথম 22টি শব্দের (704 বাইট) জন্য, প্রয়োজনীয় মেমরি শব্দের সংখ্যার সাথে খরচ রৈখিকভাবে (linearly) বৃদ্ধি পায়। সেই বিন্দুর পরে ⌊a2 ÷ 512⌋ পজিটিভ হয়। যখন প্রয়োজনীয় মেমরি যথেষ্ট বেশি হয়, তখন গ্যাস খরচ মেমরির পরিমাণের বর্গের সমানুপাতিক হয়।

নোট করুন যে এই ফ্যাক্টরগুলো কেবল অন্তর্নিহিত গ্যাস খরচকে প্রভাবিত করে - এটি ফি মার্কেট বা ভ্যালিডেটরস-দের টিপস বিবেচনা করে না যা নির্ধারণ করে যে একজন এন্ড-ইউজারকে কত টাকা দিতে হবে - এটি কেবল EVM-এ একটি নির্দিষ্ট অপারেশন চালানোর প্রাথমিক খরচ।

গ্যাস সম্পর্কে আরও পড়ুন

9.3 এক্সিকিউশন এনভায়রনমেন্ট

এক্সিকিউশন এনভায়রনমেন্ট হলো একটি টুপল (tuple), I, যার মধ্যে এমন তথ্য অন্তর্ভুক্ত থাকে যা ব্লকচেইন স্টেট বা EVM-এর অংশ নয়।

প্যারামিটারডেটা অ্যাক্সেস করার অপকোডডেটা অ্যাক্সেস করার সলিডিটি কোড
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কন্ট্রাক্টগুলোর মধ্যে কলের জন্য কল স্ট্যাকের গভীরতা (কন্ট্রাক্ট তৈরি সহ)
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) ব্যবহার করে।

যদি এই শর্তগুলোর কোনোটি সত্য হয় তবে আমাদের একটি এক্সেপশনাল হল্ট ঘটে:

  • μ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] হলো ডেটার দৈর্ঘ্য। এই শর্তটি তখন ঘটে যখন আপনি রিটার্ন ডেটা বাফারের শেষের বাইরে পড়ার চেষ্টা করেন। নোট করুন যে calldata বা কোডের জন্য অনুরূপ কোনো শর্ত নেই। যখন আপনি সেই বাফারগুলোর শেষের বাইরে পড়ার চেষ্টা করেন তখন আপনি কেবল শূন্য পান।

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

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

ভ্যালুনেমোনিকδαবিবরণ
0x20KECCAK25621Keccak-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 বিটের হয়, তাই আমরা ভ্যালুটি মডুলো (opens in a new tab) 2160 হিসাব করি।

যদি σ[μs[0] mod 2160] ≠ ∅ হয়, তার মানে এই অ্যাড্রেস সম্পর্কে তথ্য রয়েছে। সেই ক্ষেত্রে, σ[μs[0] mod 2160]b হলো সেই অ্যাড্রেসের ব্যালেন্স। যদি σ[μs[0] mod 2160] = ∅ হয়, তার মানে এই অ্যাড্রেসটি আনইনিশিয়ালাইজড এবং ব্যালেন্স শূন্য। আপনি পৃষ্ঠা 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 সম্পূর্ণরূপে সংজ্ঞায়িত করা হয়েছে।

উপসংহার

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

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

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

পেজ সর্বশেষ আপডেট: 3 মার্চ, 2026

এই টিউটোরিয়ালটি কি সহায়ক ছিল?