ماشین حالت (State Machine) یک روش مناسب، کاربردی و آسان جهت اعمال گردش کار در زبان برنامه نویسی قراردادهای هوشمند مبتنی بر بلاک چین اتریوم (سالیدیتی یا Solidity) است. سالیدیتی می تواند ویژگی اصلاح کننده تابع مفیدی را که روشی ایدهآل برای پیادهسازی مناسب بررسی حالت کنونی قبل از تغییر حالت ماشین حالت است، ارائه کند. در این مقاله قصد داریم راجع به ماشین حالت در سالیدیتی صحبت کنیم.
ماشین حالت در سالیدیتی
ماشین حالت به صورت همواره، در یک حالت قرار دارد و انتقال آن با تغییر ورودی یا خروجی بین حالت های مختلف صورت می گیرد. در رابطه با قراردادهای هوشمند سالیدیتی، برای این که تغییری در حالت ایجاد شود، یک پیام از حسابی دیگر به تابع قرارداد ارسال می شود. در صورتی که ورودی برای حالت کنونی دارای اعتبار باشد، ماشین حالت به حالت جدید منتقل می شود. در واقع می توان گفت ماشین های حالت برای کنترل گردش کار در قراردادهای سالیدتی یک روش ایده آل و مناسب است.
قراردادی را در نظر بگیرید که باید از حالت اولیه، طی چندین حالت میانی، به حالت نهایی خود در طول عمر خود تغییر کند. در هر یک از حالت ها، قرارداد باید به شیوه ای متفاوت رفتار کند و عملکردهای متفاوتی را برای کاربران خود ارائه دهد. رفتار توصیف شده را می توان در موارد متعددی مشاهده کرد: حراج، قمار، تامین مالی جمعی و بسیاری موارد دیگر. حتی مستندات Solidity با فهرست کردن آن به عنوان یکی از الگوهای رایج، متعارف بودن آن را تأیید می کند. راه های مختلفی وجود دارد که یک حالت می تواند به حالت دیگر تبدیل شود. گاهی اوقات یک حالت با پایان یک تابع به پایان می رسد، زمانی دیگر قرار است وضعیت پس از مدت زمان مشخصی تغییر کند.
الگویی با عملکردی که در بالا توضیح داده شد قبلاً توسط گاما و همکاران فرموله شده است (1995) اما اجرای آن بر روی یک زنجیره بلوکی بسیار جالب است. این موضوع به این دلیل است که یک بلاک چین خود یک سیستم انتقال حالت است که در آن یک حالت اولیه در ترکیب با یک تراکنش یک حالت جدید به عنوان خروجی دارد.
منظور از ماشین مجازی اتریوم چیست؟ برای خوااندن مطلب کلیک کنید.
نمودار ماشین حالت UML
نمودار بالا یک نمودار ماشین حالت UML است که مستطیل ها، حالت ها و فلش ها، انتقال ها را بیان می کنند و نوشته روی فلش ها نیز رویدادهای فعال کننده ای هستند که امکان انتقال را فراهم می سازند.
مدل ماشین حالت سالیدیتی
جابجایی ماشین حالت، از طریق توابع انتقال میان حالت های تعریف شده در قرارداد صورت می گیرد. در تصویر پایین بخشی از قرارداد توسعه یافته سالیدیتی قابل مشاهده است:
می توان مشاهده کرد که حالت کنونی، حالت های جدید و توابع انتقال مستقیما وارد نمودار ماشین حالت می شوند. دارنده اطلاعات یا (Data Owner) به طرفی گفته می شود که داده ها و اطلاعات را در اختیار دارد. دارنده قرارداد می تواند با دارنده اطلاعات متفاوت باشد. درخواست کننده اطلاعات یا Data Requester نیز به طرفی گفته می شود که مایل به استفاده از اطلاعات است.
قراردادهای دارای پشتیبانی
این نقش ها در قراردادهای رایج وجود دارند، بنابراین می توان از کلاس های پایه برای این نقش ها و نقش های رایج در Domain (دامنه)، در طی توسعه قرارداد استفاده کرد. از این روش می توان برای آزمایش کد استفاده کرد اما برای تولید کد، توصیه نمی شود.
کلاس پایه DataOwner، دربرگیرنده اقدامات کلی اصلاح کننده تابع (onlyDataOwner) و دارنده اطلاعات مانند سازنده (Constructor) می باشد.
سایر توابع مانند changeDataOwner نیز برای کمک به توسعه سریع تر قراردادهای آزمایشی ممکن است ارائه شوند. کلاس پایه DataRequester و کلاس های پایه دیگر، شبیه به هم هستند. همچنین می توان اصلاح کننده های تابع را از کلاس های پایه به قرارداد اضافه کرد.
کلاس های پایه DataRequester و DataOwner حتما باید در ابتدای سازنده قرارداد قرار بگیرند. همچنین به عنوان مولفه قرارداد، حساب یا همان آدرس هر دو طرف یا یکی از طرفین را می توان وارد کرد. در صورتی که حساب شامل مولفه ای نباشد یعنی میزان آن صفر باشد، باید از حساب msg.sender که دارنده قرارداد می باشد، استفاده شود. البته منطقی نیست که DataRequester و DataOwner یک حساب باشند به همین دلیل باید شرایطی را در کد سازنده بررسی کرد.
ذخیره سازی اطلاعات در بلاک چین
در این بخش باید سوالات درخواست کننده اطلاعات را ذخیره کرد و منتظر دارنده اطلاعات ماند تا سوالات را دریافت نماید. مطابق تصویر پایین هم سوال و هم پاسخ در یک رشته اطلاعات مشترک در قرارداد ذخیره شده است:
همچین این امکان وجود دارد که از یک رشته اطلاعات مشترک استفاده کرد زیرا ماشین حالت اطمینان حاصل می کند که فقط یک استفاده از رشته در هر لحظه نیاز دارد. همچنین به دلیل گران بودن فضای ذخیره سازی، استفاده حداقلی از فضای ذخیره سازی صورت می گیرد.
برای آشنایی با زبان برنامه نویسی Vyper که ماشین مجازی اتریوم را هدف قرار می دهد، روی لینک مربوط کلیک کنید.
ماشین حالت سلسله مراتبی
در راهکار فعلی یکی از مسائل موجود این است که به هیچ وجه امکان فسخ قرارداد وجود ندارد و نمی توان سرمایه را به دارنده قرارداد برگرداند.
با فرض اینکه در هر زمان می توان این مورد را انجام داد، می توان پس از طراحی ماشین حالت سلسه مراتبی، این راهکار را پیاده سازی کرد:
این مورد با وراثت (inheritance) از کلاس پایه ContractOwner در قرارداد به آسانی قابل پیاده سازی می باشد. همچنین دارنده قرارداد را به صورت خودکار ثبت می کند و اصلاح کننده onlyContractOwner را ارائه می کند. تابع selfdestruct سالیدیتی، از طریق فسخ تابع، اتر را به حساب مورد نظر برمی گرداند.
آزمایش قرارداد
می توان در یک بلاک چین، آزمایش قرارداد را اجرا کرد. برای انجام این کار، اجرا در شبکه آزمایشی ایده مناسبی است. همچنین سازنده قرارداد، ۲ پارامتر حساب DataOwner و حساب DataRequester را دارد. می توان با ایجاد حساب های پروکسی، آزمایش به صورت خودکار را تسهیل کرد که می توانند اقدامات DataOwner و DataRequester را انجام دهند.
قرارداد پروکسی DataRequester، توابع setQuestion و getAnswer را ارائه می دهد. ایجاد حساب های پروکسی و پس از آن قرارداد اصلی، توسط خود قرارداد آزمایش، صورت می گیرد.
مصرف گس
مصرف گس در هر دوره برای عمل مستمر پرسیدن سوال 20 کاراکتری و دریافت پاسخ 20 کاراکتری به صورت بلافاصله، به طور تقریبی 85000 گس می باشد. البته بار اول، مصرف گس بیشتر است، به این دلیل که فضای اختصاص یافته برای رشته اطلاعات، در فضای ذخیره سازی قرار دارد. پاسخ های بعدی فقط رشته اطلاعات قبلی را به روز می کند. همچنین مصرف گس بستگی به طول رشته دارد. یک رشته حاوی اطلاعات، نسبت به رشته بدون اطلاعات، میزان گس بیشتری را مصرف می کند. زیرا آدرس رشته باید مانند کاراکترهای رشته ذخیره شود.
راهکار جایگزین استفاده کننده از رویدادها
اگر کاربران تصمیم بگیرند که قرارداد اصلی آنها، پس از دریافت سوال یا پاسخی، به حذف رویدادها بپردازد، ماشین حالت، قابل ساده سازی می باشد. همچنین مدیریت و کنترل رویدادها توسط کد برنامه غیرمتمرکز صورت می گیرد نه توسط یک قرارداد دیگر.
مشکلات ماشین حالت
اگر درخواست کننده اطلاعات بخواهد دومین سوال را بپرسد تا زمانی که سوال اول جواب داده نشده باشد، این فرآیند ادامه نمی یابد. بنابراین باعث می شود که قرارداد به دلیل دست و پا گیر بودن تا آستانه بلااستفاده بودن برود. البته روش های مختلفی برای رفع این مشکل شناخته شده است. به طور مثال اجرای چند قرارداد با اجرای صف سوالات و پاسخ ها یکی از این راه حل ها می باشد.
سخن پایانی
در این مقاله به بررسی کاربردهای ماشین حالت در سالیدیتی و همچنین مشکلات ماشین حالت پرداختیم و به این نتیجه رسیدیم که آزمایش ماشین حالت و ماشین سالیدیتی آسان می باشد. همچنین گس ماشین حالت در مقایسه با هزینه ذخیرهسازی اطلاعات مصرف کمتری دارد. البته شاید ذخیرهسازی برون زنجیرهای اطلاعات هزینه پایین تری داشته باشد.