اوراکل ها (Oracles) | دیتای خارج از زنجیره در قرارداد هوشمند
اوراکل ها پل ارتباطی بین بلاک چین و دنیای خارج محسوب میشوند و موجب گسترش دامنه فعالیتهای قراردادهای هوشمند میگردند. قراردادهای هوشمند در حالت عادی، فقط قادر به خواندن دیتای on-chain (دیتایی که داخل بلاک چین ثبت شده باشد) هستند. در واقع، اسمارت کانترکت ها دسترسی به دیتای بیرون از بلاک چین ندارند. اما بیشتر دادههای کاربردی، خارج از بلاک چین هستند. اگر بخواهیم از تمام پتانسیل بلاک چین استفاده کنیم، باید به دادههای خارج از زنجیره (off-chain) نیز دسترسی داشته باشیم. این کار توسط اوراکل ها (Oracles) در بلاک چین قابل انجام خواهد بود.
- اوراکل چیست؟
- اوراکل چگونه کار میکند؟
- اوراکل ها چگونه پیادهسازی می شود؟
در این مقاله به تمام سوالات شما درباره اوراکل پاسخ داده شده است.
انواع اوراکل
Oracle ها بر حسب دیتا سورس (Data Source) و روش جمع آوری دیتا، به چند نوع تقسیم بندی می شوند.
- سخت افزاری (Hardware) : دادهها از سختافزار میآیند (سنسور دما)
- نرم افزاری (Software) : دادهها از نرمافزار میآیند (دادههای بازار سهام)
- انسانی (Human) : دادهها توسط نیروی انسانی جمع آوری میشود
اوراکل Chainlink
اوراکل Chainlink به توسعهدهندگان قراردادهای هوشمند این امکان را میدهد که dAppهایی مقیاسپذیری طراحی کنند که امکان ارتباط با دنیای بیرون و استفاده از دیتای off-chain را داشته باشند. در عین حال ویژگی های ذاتی بلاک چین (امنیت و قابلیت اطمینان) نیز حفظ می شود. اوراکل Chainlink در حال حاظر بیشترین پذیرش را از سمت توسعه دهندگان بلاک چین دارد. بیشتر دیتا فیدهای Chainlink فعلا در شبکه اتریوم بوده ولی در حال گسترش به سایر بلاک چین ها می باشد.
در شکل زیر معماری Chainlink را مشاهده می کنید. سرویس خارج از زنجیره با دادههای درخواست شده در یک تراکنش ثانویه به قرارداد هوشمند پاسخ میدهد. به این ترتیب میتوان دادهها را به روش 1به1 دریافت کرد.
دیتا فیدها (Data Feeds)
دیتا فید ها نمونهای از یک شبکه اوراکل غیرمتمرکز هستند. آنها دیتا را از سورسهای مختلفی جمعآوری کرده و آنها را با استفاده از ترکیبی از مدل داده غیرمتمرکز و گزارش خارج از زنجیره، منتشر میکنند. DataFeed ها دادههای زنجیرهای هستند که سریعترین راه برای اتصال قراردادهای هوشمند به دادههای دنیای واقعی و گرفتن دیتای off-chain را در اختیار ما قرار میدهند. قراردادهای هوشمند باید به صورت بلادرنگ در برابر تغییرات دیتاهای off-chain، عکس العمل نشان دهند.
اگر تصمیم دارید در یک پروژه از Chainlink استفاده کنید، باید ماژول Chainlink را با استفاده از NPM به پروژه خود اضافه کنید. برای دیدن فهرست شبکهها و آدرس پراکسی ها، باید صفحه کانترکت دیتا فید را ببینید. همچنین برای انتخاب گرهها و نودهای مورد نیاز در هر پروژه میتوانید از اطلاعات data.chain.link یا Chainlink Market استفاده کنید.
اجزای دیتا فید
اجزای تشکیل دهنده دیتا فید ها عبارتند از:
- مصرفکننده (Consumer)
- پروکسی (Proxy)
- تجمیع کننده (Aggregator)
1- مصرفکننده (Consumer)
مصرفکننده (Consumer) قرارداد هوشمندی است که از Data Feed ها استفاده میکند. اسمارت کانترکت مصرفکننده از Aggregator Interface v3 برای فراخوانی توابع در قرارداد پروکسی (Proxy) و بازیابی اطلاعات از قرارداد تجمیع کننده (Aggregator) استفاده میکند.
2- پروکسی (Proxy)
قراردادهای پروکسی، زنجیرهای هستند که برای یک دیتا فید خاص به جمع کننده اشاره میکنند. استفاده از پراکسیها، تجمیع کننده اصلی را قادر میسازد تا بدون هیچگونه وقفهای در سرویس دهی به قراردادهای مصرفکننده، upgrade شوند. قرارداد پراکسی از یک دیتا فید به دیتا فید دیگر ممکن است متفاوت باشد.
پیکربندی پراکسی
از آنجایی که قراردادهای پراکسی و قرارداد تجمیع کننده هر دو on-chain هستند، میتوانید پیکربندی پراکسی را با خواندن متغیرها از طریق ABI یا استفاده از کاوشگر بلاک چین برای شبکه خود مشاهده کنید. برای مثال، میتوانید پیکربندی پروکسی BTC/USD را در شبکه اتریوم با استفاده از Etherscan مشاهده کنید.
اگر پیکربندی پروکسی BTC/USD را بخوانید، میتوانید تمام توابع و متغیرهایی را که برای آن قرارداد بهطور عمومی در دسترس هستند:
- aggregator (address)
- lastRoundData (function)
- latestAnswer (variable)
- owner (variable)
- latestTimestamp (variable)
برای مشاهده توضیحات مربوط به متغیرها و توابع قرارداد پروکسی، سورس کد دیتا فید مورد نظر را در Etherscan ببینید.
3- تجمیع کننده (Aggregator)
تجمیع کننده، قراردادی است که بهروزرسانیهای دورهای دادهها را از شبکه اوراکل دریافت میکند. تجمیع کنندهها دادههای جمعآوریشده را در زنجیره ذخیره میکنند تا مصرفکنندگان بتوانند آنها را بازیابی کنند و در همان تراکنش بر اساس آن عمل کنند.
پیکربندی تجمیع کننده
اگر آدرس تجمیع کننده تعریف شده در پیکربندی پروکسی را مشاهده کنید، میتوانید پیکربندی تجمیع کننده را مشاهده کنید. کانترکت تجمیع کننده دارای چندین متغیر و تابع است که در برنامه های شما کاربرد خواهد داشت. اگرچه قراردادهای تجمیع کننده برای هر دیتا فید مشابه است، برخی از تجمیع کنندهها متغیرهای متفاوتی دارند. همیشه در تابع aggregator از تابع typeAndVersion استفاده کنید تا نوع تجمیع کننده و نسخه در حال اجرا را تشخیص دهید است. همچنین سورس کد و پیکربندی قرارداد تجمیع کننده را بررسی کنید تا متوجه شوید دیتا فید های خاص چگونه کار میکنند. برای مثال، قرارداد تجمیع کننده BTC/USD در آربیتروم با سایر شبکهها متفاوت است.
کانترکت تجمیع کننده نیز مثل پروکسی، دارای متغیرهای زیر می باشد:
- lastRoundData (function)
- latestAnswer (variable)
- owner (variable)
- latestTimestamp (variable)
میتوانید تابع lastRoundData را مستقیماً در تجمیع کننده فراخوانی کنید. اما بهترین روش استفاده از پروکسی بهجای آن است تا تغییرات در تجمیع کننده روی برنامه شما تأثیری نداشته باشد. قرارداد پروکسی به شما این امکان را می داد تا دادهها را از طریق پروکسی دریافت کنید، حتی اگر تجمیع کننده upgrade شده باشد.
کاربرد دیتا فیدها در گرفتن قیمت ارز (Price Feed)
رایج ترین کاربرد دیتا فید، گرفتن قیمت لحظه ای ارزهای دیجیتال است. این موضوع بهویژه در دیفای (DeFi) صادق است. بهعنوانمثال، Synthetix از Data Feed برای تعیین قیمت ارز در پلتفرم خود استفاده میکند. پلتفرمهای وامدهی و وامگیری مانند AAVE از Data Feed برای اطمینان از ارزش کل وثیقه استفاده میکنند.
سورس کد قرارداد هوشمندی که در زیر مشاهده میکنید، برای گرفتن قیمت یک ارز دیجیتال در سالیدیتی به کمک دیتا فید چین لینک نوشته شده است.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
// SPDX-License-Identifier: MIT pragma solidity ^0.8.7; import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol"; contract PriceConsumerV3 { AggregatorV3Interface internal priceFeed; /** * Network: Kovan * Aggregator: ETH/USD * Address: 0x9326BFA02ADD2366b30bacB125260Af641031331 */ constructor() { priceFeed = AggregatorV3Interface(0x9326BFA02ADD2366b30bacB125260Af641031331); } /** * Returns the latest price */ function getLatestPrice() public view returns (int) { ( /*uint80 roundID*/, int price, /*uint startedAt*/, /*uint timeStamp*/, /*uint80 answeredInRound*/ ) = priceFeed.latestRoundData(); return price; } } |
کاربرد دیتا فیدها در تولید اعداد تصادفی (RNG)
یکی دیگر از کاربردهای data feed چین لینک، تولید اعداد تصادفی در قرارداد هوشمند به روش امن می باشد.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 |
// SPDX-License-Identifier: MIT // An example of a consumer contract that also owns and manages the subscription pragma solidity ^0.8.7; import "@chainlink/contracts/src/v0.8/interfaces/LinkTokenInterface.sol"; import "@chainlink/contracts/src/v0.8/interfaces/VRFCoordinatorV2Interface.sol"; import "@chainlink/contracts/src/v0.8/VRFConsumerBaseV2.sol"; contract VRFv2SubscriptionManager is VRFConsumerBaseV2 { VRFCoordinatorV2Interface COORDINATOR; LinkTokenInterface LINKTOKEN; // Rinkeby coordinator. For other networks, // see https://docs.chain.link/docs/vrf-contracts/#configurations address vrfCoordinator = 0x6168499c0cFfCaCD319c818142124B7A15E857ab; // Rinkeby LINK token contract. For other networks, see // https://docs.chain.link/docs/vrf-contracts/#configurations address link_token_contract = 0x01BE23585060835E02B77ef475b0Cc51aA1e0709; // The gas lane to use, which specifies the maximum gas price to bump to. // For a list of available gas lanes on each network, // see https://docs.chain.link/docs/vrf-contracts/#configurations bytes32 keyHash = 0xd89b2bf150e3b9e13446986e571fb9cab24b13cea0a43ea20a6049a85cc807cc; // A reasonable default is 100000, but this value could be different // on other networks. uint32 callbackGasLimit = 100000; // The default is 3, but you can set this higher. uint16 requestConfirmations = 3; // For this example, retrieve 2 random values in one request. // Cannot exceed VRFCoordinatorV2.MAX_NUM_WORDS. uint32 numWords = 2; // Storage parameters uint256[] public s_randomWords; uint256 public s_requestId; uint64 public s_subscriptionId; address s_owner; constructor() VRFConsumerBaseV2(vrfCoordinator) { COORDINATOR = VRFCoordinatorV2Interface(vrfCoordinator); LINKTOKEN = LinkTokenInterface(link_token_contract); s_owner = msg.sender; //Create a new subscription when you deploy the contract. createNewSubscription(); } // Assumes the subscription is funded sufficiently. function requestRandomWords() external onlyOwner { // Will revert if subscription is not set and funded. s_requestId = COORDINATOR.requestRandomWords( keyHash, s_subscriptionId, requestConfirmations, callbackGasLimit, numWords ); } function fulfillRandomWords( uint256, /* requestId */ uint256[] memory randomWords ) internal override { s_randomWords = randomWords; } // Create a new subscription when the contract is initially deployed. function createNewSubscription() private onlyOwner { s_subscriptionId = COORDINATOR.createSubscription(); // Add this contract as a consumer of its own subscription. COORDINATOR.addConsumer(s_subscriptionId, address(this)); } // Assumes this contract owns link. // 1000000000000000000 = 1 LINK function topUpSubscription(uint256 amount) external onlyOwner { LINKTOKEN.transferAndCall(address(COORDINATOR), amount, abi.encode(s_subscriptionId)); } function addConsumer(address consumerAddress) external onlyOwner { // Add a consumer contract to the subscription. COORDINATOR.addConsumer(s_subscriptionId, consumerAddress); } function removeConsumer(address consumerAddress) external onlyOwner { // Remove a consumer contract from the subscription. COORDINATOR.removeConsumer(s_subscriptionId, consumerAddress); } function cancelSubscription(address receivingWallet) external onlyOwner { // Cancel the subscription and send the remaining LINK to a wallet address. COORDINATOR.cancelSubscription(s_subscriptionId, receivingWallet); s_subscriptionId = 0; } // Transfer this contract's funds to an address. // 1000000000000000000 = 1 LINK function withdraw(uint256 amount, address to) external onlyOwner { LINKTOKEN.transfer(to, amount); } modifier onlyOwner() { require(msg.sender == s_owner); _; } } |
بروزرسانی قرارداد پراکسی و تجمیع کننده
برای تطبیق با ماهیت پویای محیطهای خارج از زنجیره، دیتا فید های زنجیرهای هر از چندگاهی بهروزرسانی میشوند تا ویژگیها و قابلیتهای جدید اعمال شود و همچنین به عوامل خارجی مانند مهاجرت توکنها، تغییر برند پروتکل، رویدادهای شدید بازار، و مشکلات بالادستی دادهها پاسخ دهند. عملیات گره و بهروزرسانیها شامل تغییراتی در پیکربندی تجمیع کننده یا جایگزینی کامل تجمیع کنندهای است که پراکسی استفاده میکند. اگر دیتا فید ها را از طریق پراکسی استفاده کنید، برنامه شما میتواند در طول این تغییرات به کار خود ادامه دهد.
نظارت بر دیتا فید ها
هنگامیکه برنامهها و پروتکلهایی را میسازید که به دیتا فید ها وابسته هستند، نظارت و اقدامات حفاظتی برای محافظت در برابر تأثیر منفی اتفاقات سریع بازار، فعالیتهای مخرب احتمالی در مکانها یا قراردادهای شخص ثالث، تأخیرها و قطعی های احتمالی، ضرورت پیدا می کند. می توانید بر اساس انحرافات در پاسخهایی که دیتا فید ها ارائه میدهند، هشدارهای نظارتی خود را ایجاد کنید.
معایب اوراکل
اوراکل ها علاوه بر مزایای ویژه ای که دارند، معایبی نیز دارند:
1- استفاده از اوراکل هزینه دارد. زیرا برای اجرای معماری اوراکل، نیاز به نگهداری سرور و ارسال تراکنش داریم.
2- اوراکل یک راهحل متمرکز است زیرا ما باید به صداقت سرور اوراکل اعتماد کنیم
3- در استفاده از اوراکل ها باید به امنیت دیتای خارج زنجیره توجه داشته باشیم. چرا که امنیت اوراکل کاملاً در گرو امنیت دیتا سورس آن است. اگر یک dapp از یونی سواپ (Uniswap) بهعنوان اوراکل برای گرفتن قیمت ETH/DAI استفاده کند، مهاجم میتواند با تغییر قیمت در یونی سواپ، قیمت دریافتی توسط Dapp را دستکاری کند. برای اجتناب از این موضوع می توان بهجای تکیهبر یک منبع واحد، دادههای قیمت را از فیدهای قیمت خارجی متعدد جمعآوری نمود (راهکار مورد استفاده در MakerDAO).
درباره مجید شبیری
کارشناس ارشد فناوری اطلاعات از دانشگاه صنعتی امیرکبیر. مدیر و مؤسس "علوم نوین امیرکبیر"، متخصص برنامه نویسی، شبکه، لینوکس و امنیت. از سال 84 همزمان با شروع تحصیلات دانشگاهی، وارد حوزه تخصصی مهندسی نرم افزار شدم و اکنون مشغول تحقیق، توسعه و آموزش در حوزه بلاک چین هستم و معتقدم بلاکچین به زودی فضای کسب و کارها را منقلب خواهد کرد.
نوشته های بیشتر از مجید شبیری
دیدگاهتان را بنویسید