ویرگول
ورودثبت نام
Saman Shahmohamadi
Saman Shahmohamadiبرنامه‌نویس بلاکچین
Saman Shahmohamadi
Saman Shahmohamadi
خواندن ۷ دقیقه·۷ سال پیش

بالاخره اتریوم چطور کار می‌کند؟ (بخش ۳ - تراکنش‌ها، پیام‌ها و بلوک‌ها)

این یک ترجمه آزاد از مقاله‌ای به زبان انگلیسی است. لینک مقاله اصلی در انتهای پست ذکر شده است.

بخش اول

بخش دوم


قبلاً گفتیم که اتریوم یک ماشین حالت تراکنش-پایه است. به بیان دیگر آن‌چه حالت کلی (global state) اتریوم را از یک حالت به حالت بعدی حرکت می‌دهد تراکنش‌هایی است که بین حساب‌های مختلف انجام می‌گیرد.

به ساده‌ترین بیان، یک تراکنش مجموعه‌ای از دستورالعمل‌هاست که توسط یک حساب با مالک بیرونی به وسیله‌ی رمزنگاری امضاء (sign) شده، serialized شده و سپس به شبکه بلاکچین ارسال می‌شود.

در اتریوم دو نوع تراکنش وجود دارد: message call و contract creation (تراکنش‌هایی که یک قرارداد هوشمند جدید ایجاد می‌کنند).

تمام تراکنش‌ها (از هر نوع که باشند) شامل اجزاء زیر هستند:

ـ nonce: تعداد تراکنش‌هایی که تاکنون توسط فرستنده ارسال شده است.

ـ gasPrice: نرخ تبدیل gas به اتر (بر حسب Wei) که مبلغ کارمزد تراکنش با آن محاسبه می‌شود. به یاد داشته باشید که این نرخ توسط خود فرستنده تراکنش تعیین می‌شود.

ـ gasLimit: حداکثر مقدار gas که فرستنده می‌خواهد به عنوان کارمزد اجرای تراکنش بپردازد. این مبلغ پیشاپیش تعیین و پرداخت می‌شود، قبل از آن که هیچ‌گونه پردازشی انجام شده باشد.

ـ to: آدرس دریافت‌کننده. در تراکنشی که یک قرارداد هوشمند جدید ایجاد می‌کند، آدرس حساب قرارداد هنوز وجود ندارد، بنابراین مقدار to خالی است.

ـ value: مبلغ Wei که از فرستنده به گیرنده منتقل می‌شود. در تراکنشی که یک قرارداد هوشمند جدید ایجاد می‌کند، مقدار value معادل موجودی اولیه حساب قرارداد جدید است.
ـ v, r, s: سه پارامتر برای خلق امضایی (signature) که شناسه فرستنده تراکنش است.

ـ init: (فقط در تراکنش‌هایی وجود دارد که قرارداد هوشمند جدید ایجاد می‌کنند) یک قطعه کد EVM است که برای مقدار‌دهی اولیه (initialize) حساب قرارداد جدید به کار می‌رود. init فقط یک‌بار اجرا می‌شود و پس از آن کاربردی ندارد. در اجرای اول init بدنه کد حساب را برمی‌گرداند. قطعه کدی که برای همیشه در حساب قرارداد هوشمند کار گذاشته می‌شود.

ـ data (فیلد دلبخواهی که فقط برای message call ها قابل تعریف است): داده ورودی (یا همان پارامترهای) message call. برای مثال، اگر یک قرارداد هوشمند کار ثبت دامنه‌های جدید را انجام دهد، فراخوانی (call) کردن قرارداد احتمالاً نیاز به ورود داده‌هایی مانند نام دامنه و آدرس IP آن دارد.

در بخش «حساب‌ها» یاد گرفتیم که تراکنش‌ها - هم message call ها و هم contract creation ها - همواره توسط حساب‌های با مالک بیرونی ایجاد و به شبکه بلاکچین ارسال می‌شوند. به بیان دیگر تراکنش‌ها پل‌هایی هستند که جهان خارج را به حالت داخلی اتریوم متصل می‌کنند.

اما آنچه گفتیم به این معنی نیست که قراردادها نمی‌توانند با یکدیگر صحبت کنند (ارتباط برقرار کنند). قراردادها از طریق پیام‌ها (messages) یا تراکنش‌های داخلی (internal transactions) با یکدیگر صحبت می‌کنند. می‌توانیم بگوییم که پیام‌ها یا تراکنش‌های داخلی شبیه تراکنش‌های عادی شبکه هستند، با این تفاوت عمده که برخلاف تراکنش‌های عادی، این تراکنش‌های داخلی توسط حساب‌های دارای مالک بیرونی ایجاد نمی‌شوند. آن‌ها توسط قراردادهای هوشمند ایجاد می‌شوند. آن‌ها شیء های مجازی (virtual object) هایی هستند که برخلاف تراکنش‌ها، serialize نمی‌شوند و فقط در محیط اجرای اتریوم وجود دارند.

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

یک نکته قابل توجه: تراکنش‌های داخلی یا همان پیام‌ها gasLimit ندارند. به این خاطر که gas limit توسط ایجادکننده تراکنش اصلی (که یک حساب دارای مالک بیرونی است) معین می‌شود. مقدار gas limit که حساب با مالک بیرونی معین می‌کند باید برای انجام تراکنش (و از جمله برای اجرای همه زیرعملیات‌هایی که در اجرای تراکنش ضروری هستند، مانند ارسال پیام به دیگر قراردادها) کافی باشد. اگر در زنجیره تراکنش‌ها و پیام‌ها، اجرای یک پیام مشخص با کمبود gas مواجه شود، اجرای آن پیام و نیز اجرای همه پیام‌هایی که در نتیجه اجرای آن پیام ارسال شده‌اند، بازگردانی (revert) می‌شود. با این وجود اجرای تراکنش اصلی بازگردانی نمی‌شود.

بلوک‌ها

همه تراکنش‌ها در بلوک‌ها گروه‌بندی می‌شوند. یک بلاکچین حاوی مجموعه‌ای از این بلوک‌هاست که به یکدیگر زنجیر شده‌اند.

در اتریوم یک بلاک از اجزای زیر تشکیل می‌شود:

  • block header
  • اطلاعاتی درباره مجموعه تراکنش‌هایی که در بلوک موجود است
  • مجموعه‌ای از دیگر block header های بلوک‌های ommer بلوک فعلی

توضیحی درباره Ommer ها

یک ommer بلوکی است که والد آن برابر است با والدِ والدِ بلوک فعلی. بگذارید یک نگاه سریع به چیستی و کارکرد ommer ها بیندازیم و ببینیم چرا یک بلوک حاوی هدرِ بلوک‌های ommer خود است.

به خاطر نحوه ساخت اتریوم، فاصله زمانی بین بلوک‌ها (حدود ۱۵ ثانیه) بسیار کمتر از دیگر بلاکچین‌ها مانند بیت‌کوین (حدود ۱۰ دقیقه) است. این ویژگی موجب پردازش سریع‌تر تراکنش‌ها می‌شود. با این وجود یکی از معایب این فاصله زمانی کوتاه این است که راه‌حل‌های رقیب بیشتری برای هر بلوک توسط ماینرها یافت می‌شود. این بلوک‌های رقیب با نام "Orphaned Blocks" نیز شناخته می‌شوند (بلوک‌هایی که ماین شده‌اند اما وارد زنجیره اصلی یا main chain نمی‌شوند).

فایده ommer ها این است که دادن پاداش به ماینرها برای افزودن این بلوک‌های orphaned را ممکن می‌کنند. ommer هایی که ماینرها اضافه می‌کنند باید معتبر باشد، یعنی به تعداد ۶ بلوک یا کمتر از آخرین بلوک فاصله داشته باشند. پس از ۶ بلوک بلوک‌های orphaned دیگر قابل ارجاع نیستند.

پاداشی که به ماینرها بابت بلوک‌های ommer داده می‌شود نسبت به بلوک‌های کامل (full block) کمتر است.

Block Header

بگذارید برای یک لحظه به بلوک‌ها برگردیم. قبلاً اشاره کردیم که هر بلوک یک block header دارد، اما این block header دقیقاً چیست؟

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

  • ـ parentHash: مقدار هش header بلوکِ والد (این همان چیزی است که بلوک را به زنجیره متصل می‌کند و blockchain را می‌سازد)
  • ـ ommersHash: مقدار هش لیست تمام ommer های بلاک فعلی
  • ـ beneficiary: آدرس حسابی که کارمزد ماینینگ این بلوک را دریافت می‌کند (آدرس حساب ماینر)
  • ـ stateRoot: مقدار هش گره ریشه درخت حالت (به یاد دارید که یاد گرفتیم درخت حالت چطور در header ذخیره می‌شود و به light node ها در اعتبارسنجی تغییرات حالت کمک می‌کند)
  • ـ transactionsRoot: مقدار هش گره ریشه درختی که حاوی تمام تراکنش‌های درون بلوک است
  • ـ receiptsRoot: مقدار هش گره ریشه درختی که حاوی رسید تراکنش‌های درون بلوک است
  • ـ logsBloom: یک Bloom filter که حاوی اطلاعات log است
  • ـ difficulty: سطح سختی (difficulty) بلوک فعلی
  • ـ number: شماره بلوک فعلی (مقدار آن برای genesis block صفر است؛ شماره بلوک به ازای هر بلوک یک عدد افزایش می‌یابد)
  • ـ gasLimit: مقدار کنونی gasLimit برای هر بلوک
  • ـ gasUsed: مجموع مقدار gas تمام تراکنش‌های درون بلوک
  • ـ timestamp: زمان ایجاد بلوک
  • ـ extraData: داده‌های اضافی مرتبط با بلوک
  • ـ mixHash: هشی که وقتی با nonce ترکیب شود اثبات می‌کند که برای ایجاد این بلوک پردازش (کار) کافی انجام شده است
  • ـ nonce: به mixHash نگاه کنید

توجه کنید که هر block header حاوی سه ساختار درختی است:

  • state (stateRoot)
  • transactions (transactionsRoot)
  • receipts (receiptsRoot)

این ساختارهای درختی همان درخت‌های مرکلی هستند که قبلاً در مورد آن‌ها توضیح دادیم.

در ادامه چند اصطلاح که در توضیحات بالا به کار رفته را شفافتر توضیح می‌دهیم.

Logs

اتریوم برای ردیابی تراکنش‌ها و پیام‌های مختلف امکان ایجاد لاگ‌ها را فراهم کرده است. یک قرارداد هوشمند می‌تواند با تعریف رخدادهای (event) مختلف در شرایط مشخص لاگ‌های مرتبط با آن رخدادها را تولید کند.

یک لاگ شامل اطلاعات زیر است:

  • آدرس حساب ایجادکننده لاگ
  • مجموعه‌ای از تاپیک‌ها (topics) که نشان‌دهنده‌ رخدادهای مختلفی است که توسط آن تراکنش انجام شده است
  • داده‌های مرتبط با این رخدادها

لاگ‌ها در یک Bloom filter ذخیره می‌شوند که می‌تواند حجم نامحدودی از اطلاعات لاگ را به شکلی کارامد نگهداری کند.

رسید تراکنش (Transaction receipt)

لاگ‌های هر تراکنش در header بلوک آن تراکنش ذخیره می‌شود و لاگ‌های ایجاد شده در هر تراکنش از طریق رسید تراکنش قابل دسترسی است. اتریوم برای هر تراکنش یک رسید ایجاد می‌کند که حاوی اطلاعات مشخصی درباره آن تراکنش است:

  • شماره بلوک
  • هش بلوک
  • هش تراکنش
  • مقدار gas مصرف شده توسط تراکنش
  • مجموع gas مصرف شده در بلوک فعلی بعد از اجرای این تراکنش
  • لاگ‌های ایجاد شده در تراکنش
  • و ...

سختی بلوک (Block difficulty)

سختی یک بلوک پارامتری است که برای حفظ زمان تعیین شده برای اعتبارسنجی بلوک‌ها (۱۵ ثانیه) به کار می‌رود. بلوک اولیه (genesis block) سختی‌ای معادل ۱۳۱۰۷۲ دارد، و برای محاسبه سختی بلوک‌های بعدی یک فرمول مشخص به کار می‌رود. در جریان تایید بلوک‌ها اگر یک بلوک سریعتر از بلوک قبلی (یعنی در زمانی کمتر از ۱۵ ثانیه) تایید شود، پروتکل اتریوم سختی آن بلوک را افزایش می‌دهد (تا زمان تایید بلوک به حدود ۱۵ ثانیه افزایش یابد).

سختی بلوک بر nonce تاثیر می‌گذارد، nonce هشی است که در جریان ماینینگ طبق الگوریتم اثبات کار باید توسط ماینر محاسبه شود.

رابطه بین سختی بلوک و nonce با فرمول ریاضی زیر بیان می‌شود:

سختی شبکه با Hd نمایش داده شده.

تنها راه پیدا کردن مقدار nonce ای که با حد در نظر گرفته شده برای سختی بلوک مطابقت کند، محاسبه تک تک مقادیر ممکن با استفاده از الگوریتم اثبات کار است. زمان مورد انتظار برای پیدا کردن یک راه‌حل با سختی بلوک متناسب است - هر چه مقدار سختی بالاتر باشد، پیدا کردن یک nonce معتبر دشوارتر است، و در نتیجه تایید بلوک سخت‌تر خواهد بود و این باعث افزایش زمان لازم برای تایید بلوک جدید می‌شود. بنابراین با تنظیم سختی یک بلوک، پروتکل اتریوم می‌تواند زمان تایید بلوک را تنظیم کند.

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

هر دوی این تغییرات (کاهش سختی - کاهش زمان و افزایش سختی - افزایش زمان) برای آن انجام می‌شوند که میانگین زمان تایید بلوک‌ها در حدود ۱۵ ثانیه باقی بماند.

(ادامه دارد...)

منبع: https://medium.com/@preethikasireddy/how-does-ethereum-work-anyway-22d1df506369


اتریومبلاک‌چینethereumblockchain
۸
۲
Saman Shahmohamadi
Saman Shahmohamadi
برنامه‌نویس بلاکچین
شاید از این پست‌ها خوشتان بیاید