परिचय
EIP-150, या Ethereum Improvement Proposal 150, Ethereum ब्लॉकचेन के लिए एक प्रोटोकॉल अपग्रेड है। इसे 18 मार्च, 2016 को प्रस्तावित किया गया था, और 20 जुलाई, 2016 को Ethereum Byzantium हार्ड फोर्क (hard fork) के हिस्से के रूप में लागू किया गया था। प्रोटोकॉल में कई बदलाव किए गए थे, लेकिन हम इसके द्वारा पेश किए गए 63/64 नियम पर ध्यान केंद्रित करेंगे।
EIP-150 की बारीकियों में जाने से पहले, Ethereum में gas और contract calls की अवधारणा को समझना महत्वपूर्ण है।
लेखक
यह लेख RareSkills Technical Writing Program के हिस्से के रूप में tanim0la (Twitter) द्वारा सह-लिखा गया था।
Ethereum में gas की अवधारणा
Gas उस कम्प्यूटेशनल शक्ति को मापने की एक इकाई है जो Ethereum Virtual Machine (EVM) पर किसी विशेष ऑपरेशन या कॉन्ट्रैक्ट को निष्पादित (execute) करने के लिए आवश्यक होती है।
EVM पर प्रत्येक ऑपरेशन या कॉन्ट्रैक्ट को निष्पादित करने के लिए एक निश्चित मात्रा में gas की आवश्यकता होती है, जिसका भुगतान उपयोगकर्ता द्वारा Ether के रूप में किया जाना चाहिए। जब भी कोई उपयोगकर्ता किसी लेनदेन (transaction) की शुरुआत करता है, तो वे अपने लेनदेन द्वारा किए गए सभी ऑपरेशनों की संचयी लागतों (cumulative costs) को कवर करने के लिए बाध्य होते हैं।
एक बुनियादी Ethereum ट्रांसफर के लिए, ऐसे ऑपरेशन की लागत ठीक 21,000 gas होती है; हालाँकि, अधिक जटिल ऑपरेशनों के लिए काफी अधिक संख्या में gas इकाइयों की आवश्यकता हो सकती है, जो संभावित रूप से लाखों में हो सकती है।
Contract Calls
Ethereum में, एक कॉन्ट्रैक्ट (जिसे “caller” के रूप में जाना जाता है) में विशेष opcodes जैसे CALL, STATICCALL और DELEGATECALL के माध्यम से अन्य कॉन्ट्रैक्ट्स (जिन्हें “callees” कहा जाता है) को इनवोक (invoke) करने की क्षमता होती है। जब ऐसा होता है, तो “callees” को एक विशिष्ट मात्रा में gas प्राप्त होती है, जो उस gas के समान होती है जो उन्हें सीधे किसी लेनदेन के माध्यम से कॉल किए जाने पर प्राप्त होती।
आवंटित gas की मात्रा आंशिक रूप से caller द्वारा निर्धारित की जाती है, जैसा कि opcode पैरामीटर में निर्दिष्ट है। अधिक जानकारी के लिए, उदाहरण के रूप में यहाँ प्रदान की गई CALL स्पेसिफिकेशन देखें। यदि किसी callee को अपर्याप्त मात्रा में gas प्राप्त होती है, तो उसके ऑपरेशन रिवर्ट (revert) हो जाते हैं, जिससे “out of gas” एक्सेप्शन ट्रिगर होता है।
EIP-150 की स्पेसिफिकेशन
पहले, एक caller उन्हें प्रदान की गई सभी gas को callee को भेज सकता था। हालाँकि, इसने कॉन्ट्रैक्ट्स द्वारा अन्य कॉन्ट्रैक्ट्स को कॉल करने की संभावित रूप से अंतहीन श्रृंखला की अनुमति दी, क्योंकि प्रत्येक कॉल की gas लागत कम थी।
Ethereum नोड के कार्यान्वयन में “stack too deep” समस्या को उत्पन्न होने से रोकने के लिए, अधिकतम गहराई (depth) 1024 तक सीमित कर दी गई थी, जो आज भी लागू है। जब यह गहराई पहुँच जाती है, तो अंतिम कॉल रिवर्ट हो जाएगी।
परिणामस्वरूप, लेनदेन साइनर्स (transaction signers) के पास यह गारंटी देने की क्षमता थी कि एक विशेष कॉल रिवर्ट हो जाएगी, इसके लिए वे वांछित स्मार्ट कॉन्ट्रैक्ट को कॉल करने से पहले लेनदेन को कॉल्स के एक क्रम से गुजारते थे जब तक कि यह 1023 की गहराई तक नहीं पहुँच जाता। इस प्रकार के हमले को “Call Depth Attack” कहा जाता है।
यहाँ एक कॉन्ट्रैक्ट का उदाहरण दिया गया है जो इस हमले के प्रति संवेदनशील (vulnerable) होगा:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.5;
// DO NOT USE!!!
contract Auction {
address highestBidder;
uint256 highestBid;
function bid() external payable {
if (msg.value < highestBid) revert();
if (highestBidder != address(0)) {
payable(highestBidder).send(highestBid); // refund previous bidder
}
highestBidder = msg.sender;
highestBid = msg.value;
}
}
EIP-150 के लागू होने से पहले, ऊपर दिया गया कॉन्ट्रैक्ट “Call Depth Attack” के प्रति संवेदनशील हो सकता था। ऐसा इसलिए है क्योंकि एक दुर्भावनापूर्ण बोली लगाने वाला खुद को एक रिकर्सिव कॉल (recursive call) शुरू कर सकता है, जिससे bid() फ़ंक्शन को कॉल करने से पहले स्टैक की गहराई 1023 तक बढ़ जाती है। परिणामस्वरूप, send(highestBid) कॉल चुपचाप विफल हो जाएगी, जिसका अर्थ है कि पिछले बोली लगाने वाले को रिफंड नहीं मिलेगा, जबकि नया बोली लगाने वाला अभी भी उच्चतम बोली लगाने वाला बन जाएगा।
EIP-150 में प्रस्तुत किया गया समाधान callee के कॉन्ट्रैक्ट को कॉल करने के बाद caller कॉन्ट्रैक्ट के भीतर उपलब्ध gas का एक हिस्सा आरक्षित (reserve) करना था (अर्थात कॉल पैरेंट के 63/64 से अधिक gas का उपभोग नहीं कर सकती है)।
पैरेंट के लिए आरक्षित gas का सूत्र:
Reserved portion of the available gas = available gas at Stack depth N - ((63/64) * available gas at Stack depth N)
आइए उपरोक्त सूत्र का परीक्षण करें!
Assume: available gas at Stack depth 0 = 1000
Reserved portion of the available gas = 1000 - ((63/64) * 1000) = 15
63/64 नियम: वह Gas जो callee प्राप्त कर सकता है
नीचे दिया गया सूत्र किसी भी स्टैक गहराई पर उपलब्ध gas की गणना करता है। इसके अलावा, उपलब्ध gas स्टैक की गहराई के व्युत्क्रमानुपाती (inversely proportional) होती है (स्टैक की गहराई जितनी अधिक होगी, उपलब्ध gas उतनी ही कम होगी)।
Gas available at Stack depth 0 = Initial gas available * (63/64)^0
Gas available at Stack depth 1 = Initial gas available * (63/64)^1
Gas available at Stack depth 2 = Initial gas available * (63/64)^2
Gas available at Stack depth 3 = Initial gas available * (63/64)^3
.
.
.
Gas available at Stack depth N = Initial gas available * (63/64)^N
यहाँ कुछ उदाहरण मान दिए गए हैं।
Assume; Initial gas available = 3000
Gas available at Stack depth 10 = 3000 * (63/64)^10 = 2562
Gas available at Stack depth 20 = 3000 * (63/64)^20 = 2189

प्रत्येक अतिरिक्त गहराई स्तर पर gas में तेजी से कमी के कारण, रिकर्सिव गहराई स्वाभाविक रूप से सीमित हो जाएगी। हालाँकि वर्तमान Ethereum कार्यान्वयन में स्टैक गहराई 1024 की सीमा अभी भी मौजूद है, यह व्यावहारिक रूप से अप्राप्य है।
पहले उल्लेखित संशोधन के अलावा, EIP-150 ने CALL* opcodes में भी एक बदलाव पेश किया जहाँ प्रदान की गई gas अब एक सख्त मान (strict value) के बजाय एक अधिकतम मान (maximum value) है। इसका मतलब है कि यदि कॉल किए जा रहे कॉन्ट्रैक्ट (callee) में उपलब्ध gas opcode को दिए गए निर्दिष्ट मान से कम है, तो कॉल विफल होने के बजाय कम मात्रा में gas के साथ आगे बढ़ेगी, जो पिछले संस्करणों में नहीं था।
निष्कर्ष
संक्षेप में, Call Depth Attack को रोकने के लिए EIP-150 को पेश किया गया था। यह 63/64 नियम स्पेसिफिकेशन को लागू करके ऐसा करता है, इसके निहितार्थ (implications) यह हैं कि किसी कॉल में सभी gas left को स्पष्ट रूप से फॉरवर्ड करते समय भी, एक अंश अभी भी कॉलिंग कॉन्ट्रैक्ट के लिए आरक्षित रहेगा।
और जानें
EVM और Ethereum प्रोटोकॉल की व्यापक समझ विकसित करने के लिए हमारे Solidity Bootcamp से जुड़ें।
मूल रूप से 23 मार्च, 2023 को प्रकाशित