در این نوشته که برگرفته از یکی از پروژههای ما در درس امنیت تجارت الکترونیکی است، میخواهیم شما را با زنجیره قالبهای Ethereum و مفاهیم پایه آن آشنا کنیم. به طور خاص کارهای زیر را به صورت گام به گام انجام میدهیم:
پیشنهاد میکنم پس از این نوشته، نوشته دیگر با عنوان سالیدیتی از ایده تا عمل در یک هفته را بخوانید.
زنجیره قالبها نوعی دفتر کل توزیع شده (distributed ledger) است که توسط گرهها در یک شبکه همتا به همتا (peer-to-peer / P2P) نگهداری میشود. قالبها متشکل از یک یا چند تراکنش هستند که در صورت اجماع اعضای شبکه به زنجیره افزوده میشوند. هر قالب با استفاده از عبارت درهم منحصر به فرد به قالب قبلی خود متصل میشود و به این طریق یک زنجیره از قالبها پدید میآید. تعاملات (تراکنشهای) افراد با این دفتر کل به صورت تنها افزودنی، تغییر ناپذیر و امن شده با استفاده از رمزنگاری قدرتمند است.
اتریوم (Ethereum) یک سکوی زنجیره قالبهای متنباز است که به هرکس این اجازه را میدهد تا برنامه توزیع شده (dApp) یا اصطلاحاً قرارداد هوشمند (smart contract) بسازد یا از آن استفاده کند. دو نوع حساب (account) در اتریوم وجود دارد:
https://etherscan.io/address/0x2d7c76202834a11a99576acf2ca95a7e66928ba0
https://etherscan.io/address/0x900d0881a2e85a8e4076412ad1cefbe2d39c566c
قراردادهای هوشمند بر روی زنجیره قالبهای اتریوم نگهداری و توسط تمام اعضای شبکه به صورت یکسان و مضاعف اجرا میشوند. این قراردادها مشابه کلاسهای ++C و جاوا هستند و پس از کامپایل به صورت بایتکد درمیآیند. این بایتکدها بر روی ماشین مجازی اتریوم (EVM) اجرا میشوند. یک قرارداد هوشمند موارد زیر را در بر میگیرند:
یک نمونه (instance) از قرارداد هوشمند طی مراحل زیر ساخته میشود:
بنابراین هر نمونه از قرارداد هوشمند یک آدرس منحصر به فرد دارد و هنگام اجرا، این آدرس فراخوانی میشود. مراحل فراخوانی مشابه ایجاد است؛ با این تفاوت که قالب جدید، تغییرات ناشی از اجرا بر روی موجودی حسابها و متغیرهای قراردادها را در خود دارد:
زنجیره قالب اصلی (main network) اتریوم برای همگان قابل دسترسی است و میتوانند با خرج کردن مقدار مناسب از رمزارز رایج اتریوم یعنی اتر (Ether)، از آن استفاده کنند و بر روی آن قرارداد هوشمند بگذارند یا تراکنش اجرا کنند. نگهداری زنجیره قالب اصلی نیاز به مقادیر قابل توجهی از توان محاسباتی دارد و همه تراکنشها و قراردادهای موجود بر روی آن برای همگان قابل مشاهده است. علاوه بر زنجیره اصلی، تعدادی زنجیره آزمایشی (test network) نیز برای کاربردهای تحقیق و توسعه موجود هستند که اتر موجود بر روی آن ارزش خاصی ندارد. طبق آخرین آمار مربوط به امروز (۱۶ شهریور ۱۴۰۰)، شبکه اصلی اتریوم بیش از ۳،۶۸۵ عضو داشته است؛ در حالی که شبکه آزمایشی Ropsten با تنها چند گره نگهداری میشود. امکان راهاندازی زنجیره قالبهای خصوصی یا محلی هم وجود دارد که گرههای عضو آن تحت نظر سازمان متبوع است.
توجه: در این نوشته تمام فعالیتها بر روی یک شبکه آزمایشی اتریوم انجام میشود و لازم نیست برای آنها اتر واقعی خرج کنید. اتری که در شبکه آزمایشی با آن کار میکنید هیچ ارزش مالی ندارد!
برای کار کردن با اتریوم باید از یک کیف پول استفاده کنید. مهمترین وظیفه کیف پول حفاظت از کلید خصوصی مالک است. کیف پولهای مختلفی وجود دارد که در این بخش از افزونه مرورگر MetaMask که بر روی مرورگرهای Firefox, Chrome, Opera یا Brave کار میکنیم.
گام ۱. با مراجعه به آدرس https://metamask.io افزونه MetaMask مناسب مرورگر خود را نصب کنید.
گام ۲. با فعال شدن افزونه، مراحل ایجاد یک کیف پول جدید را طی کنید.
توجه: ما در این نوشته از روش اتصال قدیمیتر MetaMask به صفحات وب استفاده میکنیم. به این منظور باید افزونه MetaMask Legacy Web3 را هم نصب کنید. (لینک کروم را گذاشتم. برای بقیه مرورگرها هم هست!)
در صورتی که به صورت موفقیت آمیز کیف پول خود را ایجاد کرده باشید، تصویری مشابه شکل زیر مشاهده خواهید کرد که در آن آدرس شما و موجودی حساب (صفر) قابل مشاهده است.
گام ۳. به صورت پیشفرض شبکه اصلی اتریوم (Main Ethereum Network) برای فعالیت انتخاب شده است. از قسمت بالا سمت راست پنجره، شبکه را به شبکه آزمایشی Ropsten تغییر دهید.
گام۴. آدرس کیف پول خود را در گزارش بگذارید. برای این منظور میتوانید ماوس را برروی آدرس کیف پول در قسمت بالا سمت راست برده و بر روی نماد Copy to clipboard اشاره کنید.
گام۵. به شیر آب Ropsten به آدرس https://faucet.ropsten.be مراجعه کنید و با دادن آدرس حساب خود اتر آزمایشی دریافت کنید. در این صورت، پیامی مبنی بر ارسال اتر به حساب خود مشاهده میکنید که شامل یک آدرس تراکنش نیز میباشد (تصویر پایین). با کلیک کردن برروی درهم شده تراکنش، به صفحه جزییات تراکنش هدایت میشوید.
Test ETH sent to 0x63e54004e1f117C06Efdb692F932a2D47b95b7E3
Transaction hash 0xb470d082351471c8b2f4a0fc7253793053147de9694122460d6c3f67fc36d3b9
گام۶. در صفحه MetaMask به منظور ارسال Ether به یک حساب دیگر، روی گزینه Send کلیک کنید. اگر دوست داشتید محض امتحان، آدرس مقصد زیر را وارد کنید:
0x15114838531074F04680FaA4fb9d0AC6409ce4d2
سپس یک مقدار دلخواه را به عنوان مبلغ وارد کنید و Transaction Fee را مشخص کنید. همانطور که از گزینهها مشخص است، اگر بخواهید تراکنش سریعتر در زنجیره قالب قرار گیرد باید اتر بیشتری مصرف کنید. سپس برروی Next کلیک کنید. در صفحه بعد، جزییات تراکنش به منظور تأیید نمایش داده میشود. روی گزینه Confirm کلیک کنید.
گام۷. مدتی صبر کنید تا تراکنش شما در زنجیره قالب ثبت شود (در صفحه اول MetaMask وضعیت تراکنش از PENDING به CONFIRMED تغییر کند.) سپس برروی تراکنش کلیک کرده و در جزییات نمایش داده شده روی
View on Etherscan کلیک کنید تا جزئیات بیشتری را در مورد این تراکنش مشاهده کنید.
زبان اصلی نوشتن قراردادهای هوشمند در شبکه اتریوم، Solidity است. ساختار کلی قراردادهای هوشمند در این زبان به صورت زیر است:
pragma solidity 0.4.24 contract ContractName { <variable declaration> <mappings> <constructor> <functions> <modifiers> }
خط اول، نسخه Solidity برای اجرای این قرارداد را نشان میدهد. در خط بعد قرارداد هوشمند تعریف میشود که داخل آن متغیرها، توابع و غیره تعریف میشوند. برای نمونه قرارداد هوشمند زیر را درنظر بگیرید:
contract OwnedToken{ TokenCreator creator; address owner; byte32 name; constructor(byte32 _name) public { owner = msg.sender; creator = TokenCreator(msg.sender); name = _name; } } contract TokenCreator {…}
در یک فایل Solidity میتوان بیش از یک قرارداد هوشمند داشت. در اینجا دو قرارداد به نامهای OwnedToken و TokenCreator تعریف شدهاند. همانطور که در خط دوم مشاهده میکنید، میتوان یک قرارداد را داخل قرارداد دیگر استفاده کرد (البته باید آدرس همدیگر را داشته باشند!). دو خط بعدی، تعریف متغیرهای owner و name است که به ترتیب برای نگهداری آدرس مالک قرارداد و نام قرارداد استفاده میشوند. بعد از آن constructor قرار دارد. این تابع تنها یکبار در زمانی که قرارداد بر روی شبکه قرار میگیرد اجرا میشود. در خط ۶ آدرسی که با استفاده از آن قرارداد هوشمند در شبکه قرار گرفته است ذخیره میشود. هنگام قراردادن قرارداد میتوان مقدار اولیه متغیرهای آن را هم تنظیم کرد. مثلا در اینجا از طریق آرگومان name_ در خط ۸، متغیر name مقدار اولیه میگیرد.
در ادامه، از ابزار remix برای نوشتن قرارداد هوشمند استفاده میکنیم. این ابزار متنباز و برخط است، و بدون نیاز به نصب، در محیط مرورگر اجرا میشود.
گام ۸. صفحه ابزار Remix را در مرورگر خود باز کنید. در صفحه اصلی، ابتدا از قسمت Environments، گزینه مربوط به زبان Solidity را انتخاب کنید. سپس از نوار سمت چپ، روی گزینه File Explorers کلیک کنید و سپس، Create new file را انتخاب کنید و در پنجره باز شده یک نام برای قرارداد هوشمند خود انتخاب کنید. مشاهده میکنید که فایل قرارداد تازه ساخته شده شما در بخش Browser نمایان میشود.
گام ۹. قطعه کد زیر را وارد کنید (شماره خطها را حذف کنید!)
pragma solidity 0.5.1; contract Messenger{ address owner; string[] messages; constructor() public { owner = msg.sender; } function add(string memory newMessage) public { require(msg.sender == owner); messages.push(newMessage); } function count() view public returns(uint) { return messages.length; } function getMessage(uint index) view public returns(string memory) { return messages[index]; } }
توضیح: در دو خط اول متغیرهایی از نوع address و آرایه string با نامهای owner و messages ایجاد میکنیم. در خط بعدی constructor را ایجاد میکنیم. در اولین خط constructor مقدار متغیر owner را برابر با شناسه کسی که قرارداد خود را در شبکه قرار داده قرار میدهیم (متغیر msg.sender). در خط بعدی یک تابع public تعریف میکنیم. در اولین خط تابع شرطی تعریف میکنیم که ارسال کننده پیام حتماً باید مالک قرارداد هوشمند باشد. در خط بعد پیام دریافتی را به آرایهای از پیامها اضافه میکنیم. در خط بعدی یک تابع جدید تعریف میکنیم که یک پیام را با استفاده از index بازمیگرداند.
گام ۱۰. پیشنهاد میکنم مطالب زیر را در خصوص زبان Solidity مطالعه کنید:
اگر میخواهید با خود زبان سالیدیتی بیشتر آشنا شوید، پیشنهاد میکنم به صفحه سالیدیتی با مثال از سایت رسمی این زبان مراجعه کنید.
گام ۱۱. از نوار سمت چپ، روی Solidity Compiler کلیک کنید. سپس گزینه Compile filename.sol را انتخاب کنید تا قرارداد هوشمند کامپایل شود:
همانطور که در این شکل مشاهده میشود، نسخه کامپایلر منطبق با نسخه قرارداد هوشمند ما است.
گام ۱۲. از نوار سمت چپ، روی Deploy & run transactions کلیک کنید، محیط اجرا را برروی JavaScript VM قرار دهید، و گزینه Deploy را انتخاب کنید. نتیجه کار در پایین (بخش Deployed contracts) قابل مشاهده است. (شکل زیر)
توضیح: محیط اجرای Javascript VM در remix و مرورگرتان کار میکند و تعدادی حساب آزمایشی با موجودی ۱۰۰ اتر در اختیار شما میگذارد که میتوانید با استفاده از آنها اجرای قرارداد را آزمایش کنید. میتوانید با تغییر Account، حساب جاری را تغییر دهید.
گام ۱۳. در بخش Deployed contracts در فضای جلوی تابع add یک رشته دلخواه تایپ کنید و بر روی دکمه add کلیک کنید. فراموش نکنید که رشته خود را داخل گیومه (") قرار دهید. نتیجه اجرا در پنجره پایین وسط صفحه با یک علامت نشان داده شده است. اگر بر روی علامت فلش سمت چپ سطر مربوطه کلیک کنید، جدولی شامل جزئیات کامل ظاهر میشود.
گام ۱۴. چند رشته تصادفی دیگر را اضافه کنید، و از توابع count و getMessage استفاده کنید.
گام۱۵. Account خود را از بالای قسمت Deploy & run transactions عوض کنید و یک حساب دیگر به جز حسابی که با آن قرارداد هوشمند را در شبکه قرار دادهاید انتخاب کنید. سعی کنید با این اکانت، تابع add را با یک رشته دلخواه فراخوانی کنید. اینجا یک خطا اتفاق میافتد. اگر گفتید چرا؟
در این بخش میخواهیم قرارداد هوشمند Messenger (بخش دوم) را بر روی شبکه آزمایشی Ropsten قراردهیم تا در شرایطی نزدیکتر به واقعیت با آن کار کنیم. همچنین جهت ایجاد شفافیت بیشتر، کد منبع قرارداد را از طریق سایت Etherscan منتشر میکنیم.
گام ۱۶. در remix، کد Messenger.sol را باز کنید و پس از کامپایل کردن آن، از نوار سمت چپ روی Deploy & run transactions کلیک کنید و محیط اجرا را به Injected Web3 تغییر دهید.
گام ۱۷. در اینجا MetaMask صفحهای را به شما نمایش میدهد که اجازه اتصال remix به MetaMask را میگیرد. اجازه را صادر کنید.
توضیح: با این کار کلیه تراکنشها از طریق کیف پولی که در مرورگرتان است با شبکه (آزمایشی) اتریوم انجام میشود و حساب جاری، به حساب شما که تحت مدیریت MetaMask است تغییر میکند.
گام ۱۸. گزینه Deploy را انتخاب کنید. در این صورت MetaMask تاییدیه تراکنش را از شما میگیرد.
گام ۱۹. پس از انتشار قرارداد، لینک مشاهده تراکنش مربوطه روی Etherscan در پنجره پایین صفحه نمایش داده خواهد شد (مانند تصویر زیر).
توجه: با مراجعه به افزونه MetaMask میتوانید تراکنش خود را در بخش History نیز مشاهده کنید و با کلیک کردن بر روی تراکنش جزییات بیشتری از آن نمایش داده خواهد شد.
گام ۲۰. برای بدست آوردن آدرس قرارداد باید از قسمت Deploy & run transactions به بخش Deployed Contracts مراجعه کنید. سپس بر روی نماد Clipboard کنار نام قرارداد خود کلیک کنید تا آدرس در حافظه کپی شود.
گام ۲۱. قرارداد نویسان میتوانند به صورت اختیاری کد منبع قراردادشان را هم منتشر کنند. ما هم میخواهیم همین کار را بکنیم. به این منظور، به اینجا مراجعه کنید و آدرس قرارداد خود، و سایر اطلاعات لازم را تکمیل کنید. سپس گزینه Continue را انتخاب کنید.
گام ۲۲. در صفحه جدید (Contract Source Code)، کد قرارداد را وارد کنید و نهایتاً گزینه Verify and Publish را انتخاب کنید. پس از انجام عملیات، صفحه Compiler Output نمایش داده میشود که در آن مشخص شده است که قرارداد شما به صورت موفقیت آمیزی وارسی و منتشر شده است.
توجه: از این پس،هر مراجعه کنندهای به سایت Etherscan با مراجعه به صفحه قرارداد شما میتواند از بخش Code، کد منبع قرارداد را مشاهده نماید (مشابه شکل زیر که متن قرارداد معروف TheDAO را نشان میدهد.)
تا این لحظه قرارداد هوشمند خود را در شبکه آزمایشی Ropsten قرار دادهاید. برای اینکه دیگران نیز بتوانند قرارداد را اجرا کنند باید از نحوه فراخوانی آن مطلع باشند. این اطلاعات در قالب واسط باینری برنامه (Application Binary Interface / ABI) بیان میشود. این واسط چگونگی تبدیل فراخوانیهای متدها به کد EVM را تعیین میکند و بایستی توسط سازنده قرارداد در اختیار استفاده کنندگان قرار گیرد. در این بخش چگونگی دسترسی به ABI قرارداد و نیز استفاده از آن را تمرین میکنیم. افزونه MetaMask امکان فراخوانی قراردادهای هوشمند را ندارد. به این منظور از قابلیت کیف پول برخط MyEtherWallet در ترکیب با MetaMask استفاده میکنیم (این روش سادهترین روش ممکن نیست؛ ما برای مقاصد آموزشی این روش را انتخاب کردهایم.)
گام ۲۳. در remix به قسمت Solidity Compiler مراجعه کنید و در پایین تب، گزینه را انتخاب کنید. محتویات Clipboard که حاوی ABI قرارداد است را در گزارش خود بیاورید.
توجه: در صورتی که کد منبع قراردادی مانند کاری که پیشتر در انتهای بخش سوم انجام دادیم بر روی Etherscan موجود باشد، میتوان ABI را نیز از همان سایت دریافت کرد.
گام ۲۴. به سایت MyEtherWallet مراجعه کنید و گزینه Access My Wallet را انتخاب کنید. در صفحه بعدی، اتصال به کیف پول MetaMask (گزینه MEW CX) را انتخاب کنید و پس از تأیید شرایط استفاده، اجازه اتصال MyEtherWallet به MetaMask را صادر نمایید.
گام ۲۵. از منوی سمت چپ، گزینه Contract را انتخاب کنید (شکل زیر)
گام ۲۶. در بخش Contract Address، مقدار زیر را به صورت نمونه وارد کنید:
0xd376b8f069EB545E747054aA5DcDD64Bac717B7a
این قرارداد مخصوص این نوشته ایجاد شده است و قرار است طی آن به این نوشته رأی مثبت (Like) یا منفی (Dislike) بدهید. در بخش ABI هم مقدار زیر را وارد کنید:
[{"constant":false,"inputs":[{"name":"proposal","type":"uint256"}],"name":"vote","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"proposals","outputs":[{"name":"name","type":"string"},{"name":"voteCount","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"chairperson","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"to","type":"address"}],"name":"delegate","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"winningProposal","outputs":[{"name":"winningProposal_","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"voter","type":"address"}],"name":"giveRightToVote","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"voters","outputs":[{"name":"weight","type":"uint256"},{"name":"voted","type":"bool"},{"name":"delegate","type":"address"},{"name":"vote","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"winnerName","outputs":[{"name":"winnerName_","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"}]
گام ۲۷. رأی خود را ارسال کنید:
چطور بود؟
در این بخش میخواهیم از طریق کد، مقداری اتر به آدرس دلخواه انتقال دهیم. بنابراین کد ما باید به زنجیره قالبها متصل شود و بر روی آن تراکنش انجام دهد. در زبانهای مختلف امکاناتی گذاشته شده است که یکی از معروفترین آنها، کتابخانه Web3 برای زبان Javascript است. MetaMask به صورت پیشفرض کد این کتابخانه را در تمام صفحاتی که توسط مرورگر باز میشود میگذارد و از همین طریق تاکنون remix و MyEtherWallet به حساب شما دسترسی پیدا میکردند. کد Javascript بایستی بر روی یک سرور وب HTTP قرار گرفته باشد و در صورتی که آن را از یک فایل محلی (بدون پروتکل HTTP) در مرورگر باز کنید نتیجهای نخواهد داشت!
در ادامه میخواهیم یک سرویسدهنده وب را راهاندازی کنیم. برای این منظور، از برنامه BusyBox استفاده میکنیم. در صورتی که از سیستمعامل ویندوز استفاده میکنید، نسخه اجرایی را از اینجا دریافت کنید. در صورتی هم که از سیستم عامل اوبونتو استفاده میکنید دستور زیر را اجرا کنید تا نصب شود:
sudo apt-get install busybox
گام ۲۸. یک پوشه دلخواه ایجاد کرده و داخل آن یک فایل با عنوان index.html ایجاد کنید و محتوای آن را متن زیر قرار دهید:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <script type="text/javascript" src="code.js"> </head> <body> <h1>Send Ether using Web3js</h1> <p>Type the amount and address, then press Send.</p> <p>Amount (wei):<br> <input type="text" id="amount" value="0"></p> <p>Address:<br> <input type="text" id="address" value="0x"></p> <input type="submit" value="Send!" ="send()"> <div> <h2>Output:</h2> <p id="log"> </p> </div> </body> </html>
گام ۲۹. در همان پوشه یک فایل دیگر به نام code.js ایجاد کنید و محتوای آن را موارد زیر قرار دهید:
function mylog(htm) { document.getElementById('log').insertAdjacentHTML('beforebegin', '<p>'+htm+'</p>'); } async function myconnect() { if (window.ethereum) { window.web3 = new Web3(ethereum); try { await ethereum.enable(); } catch (error) { console.error(error); } } else if (window.web3) { window.web3 = new Web3(web3.currentProvider); } else { windows.alert('Non-Ethereum browser detected. You should consider trying'+ 'MetaMask!'); } } myconnect(); function send() { web3.eth.sendTransaction({ from: web3.eth.accounts[0], to: document.getElementById('address').value, value: document.getElementById('amount').value }, function(error, hash){ if(error) { console.error(error); mylog(error.message); } else { var htm = "Sent! Transaction hash: <a target='_blank'" + "href='https://ropsten.etherscan.io/tx/"+hash+"'>"+hash+"</a>" mylog(htm); } }); }
گام ۳۰. محتویات پوشه را بر روی وب سرور بگذارید. در محیط خط فرمان و پوشه مربوطه دستور زیر را اجرا کنید تا یک وبسرور روی درگاه ۸۰۰۰ اجرا شود (بعداً میتوانید با دستور busybox pkill httpd این وبسرور را غیرفعال کنید.)
busybox httpd -p 127.0.0.1:8000
به منظور بازکردن صفحه index.html باید آدرس http://127.0.0.1:8000 را در مرورگر وارد کنید.
گام ۳۱. صفحه index.html را در مرورگر باز کنید و اجازه اتصال صفحه به MetaMask را بدهید.
گام ۳۲. در صفحه وب باز شده مبلغ و آدرس گیرنده دلخواهی را وارد کنید و روی دکمه Send کلیک کنید تا درخواست ارسال اتر ایجاد شود. MetaMask اجازه ارسال اتر از حساب شما را میگیرد. میتوانید اتر آزمایشی را به این آدرس بفرستید:
0x15114838531074F04680FaA4fb9d0AC6409ce4d2
گام ۳۳. صبر کنید تا تراکنش CONFIRM شود.
زیاد سخت نبود! نه؟
در این نوشته به صورت گام به گام با اتریوم و قراردادهای هوشمند آشنا شدید، کیف پول ساختید، اتر گرفتید و فرستادید، قرارداد هوشمند ساختید، به این نوشته رأی دادید و در پایان هم یک برنامه JavaScript خیلی ابتدایی برای تعامل با شبکه اتریوم نوشتید. الان باید اصول را فهمیده باشید چون خیلی سطح پایین کارها را انجام دادهاید. یک کتابخانه حرفهای به اسم Truffle Suite برای توسعه قراردادهای هوشمند به زبان سالیدیتی و تعامل با آنها از جاوا اسکریپت هست و میتوانید به جای BusyBox از NodeJS استفاده کنید. به این منظور، نوشته دیگرم با عنوان سالیدیتی از ایده تا عمل در یک هفته را بخوانید.
پینوشت: در تهیه این نوشته از دانشجویان گرامی که دستیار درس امنیت تجارت الکترونیکی در ترمهای مختلف بودهاند یا به من محبت داشتهاند کمک گرفتهام. شایسته است نامی از ایشان در اینجا ببرم: آقایان و خانمها مهندس یاشار نصابیان، مرتضی امیرمحسنی، نسیبه محمدزاده، و محمد رجبینسب.