آموزش متادیتا در سالیدیتی

کامپایلر سالیدیتی هنگام تولید بایت کد مورد نیاز برای استقرار قرارداد هوشمند، بخشی از اطلاعات مربوط به کامپایل را نیز به انتهای بایت کد اضافه می‌کند. این اطلاعات تحت عنوان متادیتا (Metadata) شناخته می‌شوند. در این بخش، محتوای متادیتای موجود در بایت کد را بررسی می‌کنیم.

ساده ترین نمونه قرارداد هوشمند

برای شروع، بیایید خروجی کامپایل یکی از ساده ترین قراردادهای ممکن را در سالیدیتی بررسی کنیم:

این قرارداد هیچ عملکرد خاصی ندارد و تنها یک کانستراکتور قابل پرداخت در آن تعریف شده است. حالا با استفاده از دستور زیر کد را کامپایل می‌کنیم تا بایت کد اولیه آن را مشاهده کنیم:
خروجی حاصل به شکل زیر خواهد بود:

برای قراردادی که هیچ کاری انجام نمی‌دهد، این حجم از بایت کد زیاد به نظر می‌رسد. اما دلیل آن چیست؟ بیایید دقیق‌تر بررسی کنیم.

اگر همین کد را با استفاده از گزینه --no-cbor-metadata کامپایل کنیم:

خروجی نهایی بسیار کوچک‌تر خواهد شد:

این تفاوت به‌وضوح نشان می‌دهد که بخش قابل توجهی از بایت‌کد اولیه به‌خاطر اطلاعات متادیتا اضافه شده است. متادیتای CBOR شامل جزئیاتی درباره نسخه کامپایلر، گزینه‌های بهینه سازی، و مسیرهای وارد شده (import paths) در زمان کامپایل می‌باشد.

در ادامه، دقیق‌تر بررسی می‌کنیم که این متادیتا دقیقاً چه اطلاعاتی را در بر می‌گیرد و چه نقشی در فرآیند اجرای قرارداد دارد.

متادیتا در سالیدیتی

کامپایلر سالیدیتی به‌صورت پیش‌فرض، در انتهای «کد اولیه واقعی» (initcode)، یک بخش اضافه از اطلاعات را قرار می‌دهد که به آن متادیتا گفته می‌شود. این متادیتا هنگام پایان اجرای کانستراکتور، همراه با بایت کد روی بلاکچین ذخیره می‌شود. در ادامه، بخش اضافی کد را مشاهده می‌کنید:

دو بایت انتهایی یعنی 0033 به کامپایلر اعلام می‌کند که باید «به اندازه 0x33 بایت به عقب برگرد» این همان بخشی است که متادیتا در آن قرار دارد. به‌عبارت دیگر، تمام کدهایی که بین fe (که اپ‌کدی نامعتبر است و به‌عنوان نشانگر آغاز متادیتا استفاده می‌شود) و 0033 قرار دارند، متعلق به متادیتا هستند.

می‌توانیم با محاسبه، این مقدار را تأیید کنیم:

پس این رشته 0x33 (یا به عبارتی 51 بایت) دقیقاً چیست؟

برای درک بهتر این متادیتا، کافی است یک تغییر بسیار کوچک و ظاهراً بی‌اهمیت در کد منبع ایجاد کنیم. مثلاً تنها افزودن یک کامنت ساده.

تصویر زیر، تفاوت خروجی کامپایل قبل و بعد از اعمال تغییر را نشان می‌دهد:

متادیتای کامپایلر سالیدیتی

در تصویر خروجی کامپایل، قسمت‌هایی که تغییر کرده‌اند زیر خط‌دار شده‌اند، در حالی که منطق اجرایی کد هیچ تفاوتی نکرده است. در بخش بعدی، دقیقاً بررسی خواهیم کرد که این اطلاعات چگونه ساختار یافته‌اند و چه داده‌هایی را درباره کد در خود ذخیره می‌کنند.

رمزگشایی متادیتا

در نگاه اول، ممکن است به نظر برسد که داریم بخش‌هایی از رشته را به‌صورت تصادفی و بدون منطق استخراج می‌کنیم. اما کمی صبر کنید، همه چیز روشن خواهد شد.

بیایید ابتدا بخش هگزادسیمال داخل کادر آبی را بررسی کنیم:

نتیجه، واژه ipfs است.

حالا نوبت به کادر قرمز می‌رسد:

نتیجه این بخش نیز solc است.

این دو خروجی به ما سرنخ می‌دهند که محتوای این داده‌ها چیست: یک هش مربوط به IPFS و نسخه کامپایلر سالیدیتی.

هش IPFS

بخشی از بایت کد که در تصویر با رنگ زرد زیرخط‌دار شده و در کنار آن کادر فیروزه ای قرار دارد، را می‌توان با استفاده از اسکریپت پایتون زیر تحلیل کرد (توجه داشته باشید که این مثال بر اساس نسخه‌ای از کد است که شامل کامنت // nothing می‌باشد):

عبارت Qm...RTEa در واقع هش IPFS متادیتای تولیدشده توسط کامپایلر سالیدیتی است.

بر خلاف بخش‌های قبلی (مثل ipfs یا solc) که به‌صورت ساده با کدگذاری ASCII قابل خواندن بودند، این بخش از داده ها (یعنی کادر زرد و فیروزه‌ای) به‌صورت Base58 رمزگذاری شده‌اند.

به‌طور دقیق‌تر، داده هگزادسیمال "1220...373b" ابتدا به بایت تبدیل می‌شود و سپس با استفاده از استاندارد Base58 به شکل خوانایی مانند Qm... در می‌آید. که فرمت شناخته‌شده‌ای برای هش های IPFS است.

اگر فایل JSON متادیتای خروجی کامپایلر سالیدیتی را مستقیماً روی IPFS بارگذاری کنید، دقیقاً همین هش QmVW2Xyaf... را دریافت خواهید کرد. در ادامه، محتوای این فایل JSON را نیز بررسی خواهیم کرد.

متادیتای json در سالیدیتی

می‌توانیم فایل JSON مربوط به متادیتا را به‌صورت یک فایل واقعی ذخیره کنیم و سپس بررسی کنیم که آیا هش تولیدشده با همان هشی که در پایتون به‌دست آوردیم، مطابقت دارد یا نه. برای این کار، باید ابزار خط فرمان IPFS روی سیستم نصب شده باشد (راهنمای نصب در مستندات رسمی IPFS).

ابتدا پوشه‌ای برای خروجی ایجاد می‌کنیم و سپس کد را کامپایل می‌کنیم:

بعد با استفاده از دستور زیر، هش فایل متادیتا را محاسبه می‌کنیم، بدون اینکه آن را واقعاً روی IPFS بارگذاری کنیم:
همان‌طور که مشاهده می‌کنید، هش به‌دست‌آمده دقیقاً با همان هش QmVW2Xyaf... که در اسکریپت پایتون محاسبه کرده بودیم مطابقت دارد. این تطابق نشان می‌دهد که متادیتای قراردادی که روی بلاکچین ذخیره شده، دقیقاً به فایل JSON خروجی کامپایلر اشاره دارد—و از طریق IPFS می‌توان به آن دسترسی پیدا کرد.

آیا این کار باعث ایجاد برخورد در هش (Hash Collisions) نمی‌شود؟

اگر دو قرارداد هوشمند با کد منبع کاملاً یکسان و تنظیمات یکسان در کامپایلر، سورس تاییدشده خود را روی IPFS قرار دهند، بله. هش های IPFS آن‌ها دقیقاً یکسان خواهد بود. اما این نه‌تنها مشکلی ایجاد نمی‌کند، بلکه اتفاقی کاملاً مطلوب است.

در واقع، ماهیت IPFS دقیقاً بر پایه همین اصل بنا شده است:
هر فایل منحصراً بر اساس محتوای آن شناسایی می‌شود. اگر دو فایل محتوای یکسانی داشته باشند، تنها یک نسخه از آن در شبکه ذخیره می‌شود و این باعث صرفه جویی در فضای ذخیره سازی می‌شود.

از طرف دیگر، در بلاکچین، قراردادهای هوشمند به‌طور یکتا با ترکیب شناسه شبکه (chain ID) و آدرس قرارداد شناسایی می‌شوند، نه با هش IPFS.

بنابراین، اگرچه هش‌های IPFS می‌توانند در موارد مشابه یکسان باشند، اما این به‌هیچ‌وجه به معنای تداخل در شناسایی قراردادها نیست، چون آدرس‌های آن‌ها در شبکه بلاکچین متفاوت است. این طراحی نه‌تنها ایمن است، بلکه بسیار کارآمد نیز هست.

به‌دست آوردن نسخه سالیدیتی از متادیتا

در نهایت، اگر بخش قرارگرفته در کادر نارنجی را بررسی کنیم، متوجه می‌شویم که این قسمت دقیقاً نسخه کامپایلر سالیدیتی را نشان می‌دهد.

با تبدیل این مقادیر هگزادسیمال به عدد، به نتیجه زیر می‌رسیم:

همان‌طور که مشاهده می‌کنید، خروجی به‌درستی نشان می‌دهد که از نسخه 0.8.20 سالیدیتی استفاده کرده‌ایم.

چرا متادیتا در قراردادهای هوشمند وجود دارد؟

افزودن متادیتا به قرارداد هوشمند، حدود ۵۳ بایت اضافی به اندازه بایت کد اضافه می‌کند. این افزایش، هزینه استقرار قرارداد را بیشتر می‌کند:

  • ۱۰,۶۰۰ گس برای ذخیره سازی بایت کد اضافی (۲۰۰ گس برای هر بایت)

  • به‌علاوه هزینه calldata:

    • ۱۶ گس برای هر بایت غیرصفر

    • ۴ گس برای هر بایت صفر
      که مجموعاً تا حدود ۸۴۸ گس دیگر به‌صورت تقریبی اضافه می‌شود.

با وجود این افزایش هزینه، چرا همچنان متادیتا را اضافه می‌کنند؟

متادیتایی که کامپایلر تولید می‌کند، شامل یک فایل JSON است که در آن هش کد منبع قرارداد ذخیره شده. این ساختار درک بهتری از فرآیند استقرار ایجاد می‌کند و برای افرادی که در مسیر یادگیری آموزش برنامه نویسی و توسعه قراردادهای هوشمند هستند، اهمیت زیادی دارد؛ چون اجازه می‌دهد کد مستقرشده را با سورس‌کد اصلی مطابقت دهند و به‌صورت دقیق آن را تأیید کنند.

اگر حتی یک کاراکتر از کد منبع تغییر کند، مثلاً فقط یک کامنت یا فاصله، هش فایل JSON تغییر می‌کند و در نتیجه هش IPFS آن نیز متفاوت خواهد بود.

به‌این‌ترتیب، متادیتا ابزاری ضروری برای ایجاد شفافیت و تضمین صحت و اصالت سورس کد قرارداد هوشمند در محیطی غیرقابل‌تغییر مانند بلاکچین است. این سازوکار، پایه‌گذار مفهوم «کد تأییدشده» (Verified Source Code) در پلتفرم‌هایی مانند Etherscan می‌باشد.

یک ترفند عجیب برای کاهش گس با استفاده از هش IPFS

یکی از روش‌های واضح برای کاهش هزینه گس هنگام استقرار قرارداد، استفاده از گزینه --no-cbor-metadata در کامپایلر سالیدیتی است. این گزینه باعث می‌شود متادیتا در انتهای بایت‌کد قرار نگیرد و در نتیجه اندازه بایت کد و هزینه گس کمتر شود.

اما اگر به متادیتا نیاز دارید—مثلاً برای تأیید رسمی قرارداد (Contract Verification)—باز هم می‌توانید هزینه گس را کاهش دهید، آن هم با استفاده از یک ترفند کمتر شناخته‌شده: معدن‌کاوی (Mining) برای هش های IPFS بهینه از نظر گس.

چطور این ترفند کار می‌کند؟

وقتی قرارداد را استقرار می‌دهید، متادیتا (که شامل هش IPFS است) به انتهای بایت کد اضافه می‌شود و در قالب کال دیتا (calldata) به شبکه ارسال می‌شود. در این کال دیتا:

  • هر بایت صفر فقط ۴ گس مصرف می‌کند

  • اما هر بایت غیرصفر برابر با ۱۶ گس هزینه دارد

بنابراین اگر بتوانید کاری کنید که هش IPFS شما تعداد زیادی بایت صفر در خروجی هگزادسیمال داشته باشد، می‌توانید هزینه گس را کاهش دهید.

چطور به چنین هشی برسیم؟

از آنجایی که هش IPFS به صورت غیرمستقیم از سورس‌کد (همراه با کامنت‌ها) محاسبه می‌شود، می‌توان با تغییر محتویات کامنت‌ها، مثل افزودن یا تغییر جملات بی‌تأثیر در منطق، سعی کرد به هشی برسید که مقدار زیادی صفر در خروجی هگزادسیمال خود دارد.

نکته مهم: ما به دنبال صفر در نمایش هگزادسیمال هش هستیم، نه در نسخه Base58 آن (مثل Qm...). زیرا آن چیزی که روی بلاکچین ثبت می‌شود، نسخه هگزادسیمال است.

 

5/5 - (1 امتیاز)

راستی! برای دریافت مطالب جدید در کانال تلگرام یا پیج اینستاگرام سورس باران عضو شوید.

پکیج جامع و پروژه محور ASP.NET MVC + طراحی فروشگاه اینترنتی فروش فایل
  • انتشار: ۵ مرداد ۱۴۰۴

دسته بندی موضوعات

آخرین محصولات فروشگاه

مشاهده همه

نظرات

بازخوردهای خود را برای ما ارسال کنید