Oracles
Son düzenleme: , Invalid DateTime
Kâhinler, akıllı sözleşmelerinizdeki verileri sorgulayabilmeniz için Ethereum'u zincir dışı ve gerçek dünya bilgilerine bağlayan veri akışlarıdır. Örneğin, tahmin piyasası uygulamaları, olaylara dayalı olarak ödemeleri tamamlamak için kâhinleri kullanır. Bir tahmin piyasası, Amerika Birleşik Devletleri'nin bir sonraki başkanına ETH'nize bahse girmenizi isteyebilir. Sonucu onaylamak ve kazananlara ödeme yapmak için bir kâhin kullanırlar.
Ön koşullar
Düğümlere, mutabakat mekanizmalarına ve özellikle olaylar olmak üzere akıllı sözleşme anatomisine aşina olduğunuzdan emin olun.
Kâhin nedir
Kâhin, blok zinciri ile gerçek dünya arasında bir köprüdür. Akıllı sözleşmelerinize bilgi almak için sorgulayabileceğiniz zincir üstü API görevi görürler. Bu, fiyat bilgisinden hava durumu raporlarına kadar her şey olabilir. Kâhinler, verileri gerçek dünyaya "göndermek" için iki yönlü olarak da kullanılabilir.
Patrick'in Kâhinler hakkındaki açıklamasını izleyin:
Bunlar neden gereklidir?
Ethereum gibi bir blok zinciri ile her işlemi tekrar yapmak ve aynı sonucu garanti etmek için ağdaki her düğüme ihtiyacınız vardır. API'ler potansiyel olarak değişken veriler sunar. Bir fiyat API'si kullanarak kabul edilmiş bir $USD değerine dayalı olarak ETH gönderiyorsanız, sorgu bir günden diğerine farklı bir sonuç döndürür. Ayrıca API hack'lenebilir veya kullanımdan kaldırılabilir. Bu olursa, ağdaki düğümler Ethereum'un mevcut durumu üzerinde anlaşamaz ve mutabakatı etkin bir şekilde bozar.
Kâhinler, bu sorunu verileri blok zincirine göndererek çözer. Bu nedenle, işlemi yeniden yürüten herhangi bir düğüm, herkesin görmesi için gönderilen aynı değişmez verileri kullanacaktır. Bunu yapmak için, bir kâhin tipik olarak bir akıllı sözleşmeden ve API'leri sorgulayabilen ve ardından akıllı sözleşmenin verilerini güncellemek için periyodik olarak işlemler gönderebilen bazı zincir dışı bileşenlerden oluşur.
Kâhin sorunu
Bahsettiğimiz gibi, Ethereum işlemleri zincir dışı verilere doğrudan erişemez. Aynı zamanda, veri sağlamak için tek bir gerçek kaynağına güvenmek güvenli değildir ve akıllı bir sözleşmenin merkeziyetsizliğini geçersiz kılar. Bu, kâhin problemi olarak bilinir.
Birden çok veri kaynağından veri alan merkeziyetsiz bir kâhin kullanarak Kâhin probleminden kaçınabiliriz; bir veri kaynağı saldırıya uğrarsa veya başarısız olursa, akıllı sözleşme amaçlandığı gibi çalışmaya devam eder.
Güvenlik
Bir kâhin, yalnızca kendi veri kaynakları kadar güvenlidir. Bir dapp, ETH/DAI fiyat beslemesi için bir kâhin olarak Uniswap'i kullanırsa bir saldırgan, dapp'in mevcut fiyat anlayışını manipüle etmek için Uniswap'teki fiyatı hareket ettirebilir. Bununla nasıl mücadele edileceğine dair bir örnek, MakerDAO tarafından kullanılan, sadece tek bir kaynağa güvenmek yerine birçok harici fiyat beslemelerinden fiyat verilerini toplayan bir besleme sistemidir(opens in a new tab).
Mimari
Bu, basit bir Kâhin mimarisinin bir örneğidir, ancak zincir dışı hesaplamayı tetiklemek için bundan daha fazla yol vardır.
- Akıllı sözleşme olayınızla bir kayıt yayınlayın
- Zincir dışı bir hizmet (genellikle JSON-RPC
eth_subscribe
komutu gibi bir şey kullanarak) bu belirli günlüklere abone olmuştur. - Zincir dışı hizmet, kayıtlarda tanımlanan bazı görevleri yerine getirmeye devam eder.
- Zincir dışı hizmet, akıllı sözleşmeye ikincil bir işlemde istenen verilerle yanıt verir.
Verileri 1'e 1 şeklinde böyle alabilirsiniz ancak güvenliği artırmak için zincir dışı verileri toplama şeklinizi merkeziyetsizleştirmek isteyebilirsiniz.
Bir sonraki adım, farklı API'lere ve kaynaklara bu çağrıları yapan ve zincirdeki verileri toplayan bu düğümlerden oluşan bir ağa sahip olmak olabilir.
Chainlink Zincir Dışı Raporlaması(opens in a new tab) (Chainlink OCR), zincir dışı kâhin ağının birbirleriyle iletişim kurması, yanıtlarını kriptografik olarak imzalaması, yanıtlarını zincir dışı olarak toplaması ve sonuçta zincir üstünde yalnızca bir işlem göndermesi ile bu metodolojiyi geliştirdi. Bu şekilde daha az gaz harcanmasının yanı sıra her düğüm, işlemin kendi bölümünü imzaladığı ve işlemi gönderen düğüm tarafından değiştirilemez hâle getirdiği için merkeziyetsiz veri garantisine sahip olursunuz. Düğüm işlem yapmazsa yükseltme politikası devreye girer ve sonraki düğüm işlemi gönderir.
Kullanım
Chainlink gibi hizmetleri kullanarak, halihazırda gerçek dünyadan alınmış ve bir araya getirilmiş zincir üzerindeki merkeziyetsiz verileri referans verebilirsiniz. Merkeziyetsiz veriler için bir tür ortak ortak alan gibidir. Aradığınız herhangi bir özelleştirilmiş veriyi elde etmek için kendi modüler kâhin ağlarınızı da oluşturabilirsiniz. Ek olarak, zincir dışı hesaplama yapabilir ve gerçek dünyaya da bilgi gönderebilirsiniz. Chainlink şunları yapabilmeniz için altyapılara sahiptir:
- Sözleşmenizde kripto fiyat bilgileri alın(opens in a new tab)
- Doğrulanabilir rastgele sayılar oluşturun (oyunlar için kullanışlıdır)(opens in a new tab)
- Harici API'leri çağırma(opens in a new tab) - Bunun yeni bir kullanımı, wBTC rezervlerini kontrol etmektir(opens in a new tab)
Bir Chainlink fiyat beslemesi kullanarak akıllı sözleşmenizde en son ETH fiyatını nasıl alacağınıza dair bir örnek:
Chainlink Bilgi Beslemeleri
1pragma solidity ^0.6.7;23import "@chainlink/contracts/src/v0.6/interfaces/AggregatorV3Interface.sol";45contract PriceConsumerV3 {67 AggregatorV3Interface internal priceFeed;89 /**10 * Network: Kovan11 * Aggregator: ETH/USD12 * Address: 0x9326BFA02ADD2366b30bacB125260Af64103133113 */14 constructor() public {15 priceFeed = AggregatorV3Interface(0x9326BFA02ADD2366b30bacB125260Af641031331);16 }1718 /**19 * Returns the latest price20 */21 function getLatestPrice() public view returns (int) {22 (23 uint80 roundID,24 int price,25 uint startedAt,26 uint timeStamp,27 uint80 answeredInRound28 ) = priceFeed.latestRoundData();29 return price;30 }31}32Tümünü gösterKopyala
Bunu, bu bağlantı ile remix'te test edebilirsiniz(opens in a new tab)
Belgeleri görüntüle(opens in a new tab)
Chainlink VRF
Chainlink VRF (Doğrulanabilir Rastgele İşlev), akıllı sözleşmeler için tasarlanmış, kanıtlanabilir şekilde adil ve doğrulanabilir bir rastgelelik kaynağıdır. Akıllı sözleşme geliştiricileri, öngörülemeyen sonuçlara dayanan herhangi bir uygulama için güvenilir akıllı sözleşmeler oluşturmak üzere kurcalamaya karşı korumalı rastgele sayı oluşturma (RNG) olarak Chainlink VRF'yi kullanabilir:
- Blok zinciri oyunları ve NFT'ler
- Görevlerin ve kaynakların rastgele atanması (örneğin yargıçların davalara rastgele atanması)
- Mutabakat mekanizmaları için temsili bir örnek seçme
Blok zincirleri deterministik olduğu için Rrastgele sayılar zordur.
Chainlink Kâhinleri ile veri akışlarının dışında çalışmak, Chainlink ile çalışmanın talep ve alma döngüsünü(opens in a new tab) takip eder. Yanıtları döndürmek için Kâhin sağlayıcılarına Kâhin gazı göndermek için LINK token'ını kullanırlar. LINK token, özellikle kâhinlerle çalışmak üzere tasarlanmıştır ve ERC-20 ile geriye dönük uyumlu olan yükseltilmiş ERC-677 token'ı temel alır. Aşağıdaki kod, Kovan test ağında dağıtılırsa kriptografik olarak kanıtlanmış bir rastgele sayı alır. Talepte bulunmak için sözleşmeyi, Kovan LINK Faucet(opens in a new tab)'ten alabileceğiniz bir test ağı LINK token'ı ile finanse edin.
12pragma solidity 0.6.6;34import "@chainlink/contracts/src/v0.6/VRFConsumerBase.sol";56contract RandomNumberConsumer is VRFConsumerBase {78 bytes32 internal keyHash;9 uint256 internal fee;1011 uint256 public randomResult;1213 /**14 * Constructor inherits VRFConsumerBase15 *16 * Network: Kovan17 * Chainlink VRF Coordinator address: 0xdD3782915140c8f3b190B5D67eAc6dc5760C46E918 * LINK token address: 0xa36085F69e2889c224210F603D836748e7dC008819 * Key Hash: 0x6c3699283bda56ad74f6b855546325b68d482e983852a7a82979cc4807b641f420 */21 constructor()22 VRFConsumerBase(23 0xdD3782915140c8f3b190B5D67eAc6dc5760C46E9, // VRF Coordinator24 0xa36085F69e2889c224210F603D836748e7dC0088 // LINK Token25 ) public26 {27 keyHash = 0x6c3699283bda56ad74f6b855546325b68d482e983852a7a82979cc4807b641f4;28 fee = 0.1 * 10 ** 18; // 0.1 LINK (varies by network)29 }3031 /**32 * Requests randomness from a user-provided seed33 */34 function getRandomNumber(uint256 userProvidedSeed) public returns (bytes32 requestId) {35 require(LINK.balanceOf(address(this)) >= fee, "Not enough LINK - fill contract with faucet");36 return requestRandomness(keyHash, fee, userProvidedSeed);37 }3839 /**40 * Callback function used by VRF Coordinator41 */42 function fulfillRandomness(bytes32 requestId, uint256 randomness) internal override {43 randomResult = randomness;44 }45}46Tümünü göster
Chainlink Keepers
Akıllı sözleşmeler, keyfi zamanlarda veya keyfi koşullar altında kendi işlevlerini tetikleyemez veya başlatamaz. Durum değişiklikleri, yalnızca başka bir hesap bir işlem (bir kullanıcı, kâhin veya sözleşme gibi) başlattığında gerçekleşir. Chainlink Keeper Network(opens in a new tab), düzenli bakım görevlerini güvenle en aza indirilmiş ve merkeziyetsiz bir şekilde dışarıdan temin etmek için akıllı sözleşmeler için seçenekler sunar.
Chainlink Keepers'ı kullanmak için, bir akıllı sözleşme KeeperCompatibleInterface(opens in a new tab) arayüzünü sağlamalıdır, bu arayüz iki fonksiyondan oluşur:
checkUpkeep
- Sözleşmede iş yapılmasının gerekip gerekmediğini kontrol eder.performUpkeep
- checkUpkeep tarafından emir verilirse işi sözleşme üzerinde gerçekleştirir.
Aşağıdaki örnek basit bir sayaç sözleşmesidir. counter
değişkeni, performUpkeep
öğesine yapılan her çağrıda birer birer artırılır. Sıradaki kodu Remix kullanarak deneyebilirsiniz(opens in a new tab)
1// SPDX-License-Identifier: MIT2pragma solidity ^0.7.0;34// KeeperCompatible.sol imports the functions from both ./KeeperBase.sol and5// ./interfaces/KeeperCompatibleInterface.sol6import "@chainlink/contracts/src/v0.7/KeeperCompatible.sol";78contract Counter is KeeperCompatibleInterface {9 /**10 * Public counter variable11 */12 uint public counter;1314 /**15 * Use an interval in seconds and a timestamp to slow execution of Upkeep16 */17 uint public immutable interval;18 uint public lastTimeStamp;1920 constructor(uint updateInterval) {21 interval = updateInterval;22 lastTimeStamp = block.timestamp;2324 counter = 0;25 }2627 function checkUpkeep(bytes calldata /* checkData */) external override returns (bool upkeepNeeded, bytes memory /* performData */) {28 upkeepNeeded = (block.timestamp - lastTimeStamp) > interval;29 // We don't use the checkData in this example. CheckData, Upkeep kaydedildiğinde tanımlanır.30 }3132 function performUpkeep(bytes calldata /* performData */) external override {33 lastTimeStamp = block.timestamp;34 counter = counter + 1;35 // We don't use the performData in this example. PerformData, Keeper'ın checkUpkeep işlevinize yaptığı çağrıyla oluşturulur.36 }37}38Tümünü göster
Keeper uyumlu bir sözleşmeyi dağıttıktan sonra, sözleşmeyi Bakım(opens in a new tab) için kaydettirmeli ve sözleşmeniz hakkında Keeper Network'ü bilgilendirmek amacıyla LINK ile bunu finans etmelisiniz, böylece işiniz sürekli olarak yapılır.
Keepers projeleri
Chainlink API Çağrısı
Chainlink API Çağrıları(opens in a new tab), web'in geleneksel şekilde çalıştığı şekilde zincir dışı dünyadan veri almanın en kolay yoludur: API çağrıları. Bunun tek bir örneğini yapmak ve tek bir kâhine sahip olmak, bunu doğası gereği merkezileştirir. Bir akıllı sözleşme platformunun, gerçekten merkeziyetsiz şekilde kalmak için bir harici veri pazarında(opens in a new tab) bulunan çok sayıda düğümü kullanması gerekir.
Test etmek için aşağıdaki kodu kovan ağında remix'te dağıtın(opens in a new tab)
Bu aynı zamanda kâhinlerin talep ve alma döngüsünü de takip eder ve çalışması için Kovan LINK (kâhin gazı) ile finanse edilecek sözleşmeye ihtiyaç duyar.
1pragma solidity ^0.6.0;23import "@chainlink/contracts/src/v0.6/ChainlinkClient.sol";45contract APIConsumer is ChainlinkClient {67 uint256 public volume;89 address private oracle;10 bytes32 private jobId;11 uint256 private fee;1213 /**14 * Network: Kovan15 * Oracle: 0x2f90A6D021db21e1B2A077c5a37B3C7E75D15b7e16 * Job ID: 29fa9aa13bf1468788b7cc4a500a45b817 * Fee: 0.1 LINK18 */19 constructor() public {20 setPublicChainlinkToken();21 oracle = 0x2f90A6D021db21e1B2A077c5a37B3C7E75D15b7e;22 jobId = "29fa9aa13bf1468788b7cc4a500a45b8";23 fee = 0.1 * 10 ** 18; // 0.1 LINK24 }2526 /**27 * Create a Chainlink request to retrieve API response, find the target28 * data, then multiply by 1000000000000000000 (to remove decimal places from data).29 */30 function requestVolumeData() public returns (bytes32 requestId)31 {32 Chainlink.Request memory request = buildChainlinkRequest(jobId, address(this), this.fulfill.selector);3334 // Set the URL to perform the GET request on35 request.add("get", "https://min-api.cryptocompare.com/data/pricemultifull?fsyms=ETH&tsyms=USD");3637 // Set the path to find the desired data in the API response, where the response format is:38 // {"RAW":39 // {"ETH":40 // {"USD":41 // {42 // "VOLUME24HOUR": xxx.xxx,43 // }44 // }45 // }46 // }47 request.add("path", "RAW.ETH.USD.VOLUME24HOUR");4849 // Multiply the result by 1000000000000000000 to remove decimals50 int timesAmount = 10**18;51 request.addInt("times", timesAmount);5253 // Sends the request54 return sendChainlinkRequestTo(oracle, request, fee);55 }5657 /**58 * Receive the response in the form of uint25659 */60 function fulfill(bytes32 _requestId, uint256 _volume) public recordChainlinkFulfillment(_requestId)61 {62 volume = _volume;63 }64}65Tümünü göster
Chainlink geliştiricileri bloğunu(opens in a new tab) okuyarak Chainlink uygulamaları hakkında daha fazla bilgi edinebilirsiniz.
Kâhin hizmetleri
- Chainlink(opens in a new tab)
- Witnet(opens in a new tab)
- Provable(opens in a new tab)
- Paralink(opens in a new tab)
- Dos.Network(opens in a new tab)
Bir Kâhin akıllı sözleşmesi oluşturun
İşte Pedro Costa'nın örnek bir kâhin sözleşmesi. Ethereum'da Blok Zinciri Kâhin Uygulaması(opens in a new tab) makalesinde daha fazla açıklama bulabilirsiniz.
1pragma solidity >=0.4.21 <0.6.0;23contract Oracle {4 Request[] requests; //list of requests made to the contract5 uint currentId = 0; //increasing request id6 uint minQuorum = 2; //minimum number of responses to receive before declaring final result7 uint totalOracleCount = 3; // Hardcoded oracle count89 // defines a general api request10 struct Request {11 uint id; //request id12 string urlToQuery; //API url13 string attributeToFetch; //json attribute (key) to retrieve in the response14 string agreedValue; //value from key15 mapping(uint => string) anwers; //answers provided by the oracles16 mapping(address => uint) quorum; //oracles which will query the answer (1=oracle hasn't voted, 2=oracle has voted)17 }1819 //event that triggers oracle outside of the blockchain20 event NewRequest (21 uint id,22 string urlToQuery,23 string attributeToFetch24 );2526 //triggered when there's a consensus on the final result27 event UpdatedRequest (28 uint id,29 string urlToQuery,30 string attributeToFetch,31 string agreedValue32 );3334 function createRequest (35 string memory _urlToQuery,36 string memory _attributeToFetch37 )38 public39 {40 uint length = requests.push(Request(currentId, _urlToQuery, _attributeToFetch, ""));41 Request storage r = requests[length-1];4243 // Hardcoded oracles address44 r.quorum[address(0x6c2339b46F41a06f09CA0051ddAD54D1e582bA77)] = 1;45 r.quorum[address(0xb5346CF224c02186606e5f89EACC21eC25398077)] = 1;46 r.quorum[address(0xa2997F1CA363D11a0a35bB1Ac0Ff7849bc13e914)] = 1;4748 // launch an event to be detected by oracle outside of blockchain49 emit NewRequest (50 currentId,51 _urlToQuery,52 _attributeToFetch53 );5455 // increase request id56 currentId++;57 }5859 //called by the oracle to record its answer60 function updateRequest (61 uint _id,62 string memory _valueRetrieved63 ) public {6465 Request storage currRequest = requests[_id];6667 //check if oracle is in the list of trusted oracles68 //and if the oracle hasn't voted yet69 if(currRequest.quorum[address(msg.sender)] == 1){7071 //marking that this address has voted72 currRequest.quorum[msg.sender] = 2;7374 //iterate through "array" of answers until a position if free and save the retrieved value75 uint tmpI = 0;76 bool found = false;77 while(!found) {78 //find first empty slot79 if(bytes(currRequest.anwers[tmpI]).length == 0){80 found = true;81 currRequest.anwers[tmpI] = _valueRetrieved;82 }83 tmpI++;84 }8586 uint currentQuorum = 0;8788 //iterate through oracle list and check if enough oracles(minimum quorum)89 //have voted the same answer has the current one90 for(uint i = 0; i < totalOracleCount; i++){91 bytes memory a = bytes(currRequest.anwers[i]);92 bytes memory b = bytes(_valueRetrieved);9394 if(keccak256(a) == keccak256(b)){95 currentQuorum++;96 if(currentQuorum >= minQuorum){97 currRequest.agreedValue = _valueRetrieved;98 emit UpdatedRequest (99 currRequest.id,100 currRequest.urlToQuery,101 currRequest.attributeToFetch,102 currRequest.agreedValue103 );104 }105 }106 }107 }108 }109}110Tümünü gösterKopyala
Bir Kâhin akıllı sözleşmesi oluşturmaya ilişkin daha fazla belgeye sahip olmak istiyoruz. Yardım edebilecekseniz, bir PR oluşturun!
Daha fazla bilgi
Makaleler
- Bir Blok Zinciri Kâhini nedir?(opens in a new tab) - Chainlink
- Blok Zinciri Kâhini nedir?(opens in a new tab) - Patrick Collins
- Merkeziyetsiz Kâhinler: kapsamlı bir genel bakış(opens in a new tab) – Julien Thevenard
- Ethereum'da Blok Zinciri Kâhin Uygulaması(opens in a new tab) – Pedro Costa
- Akıllı sözleşmeler neden API çağrıları yapamıyor?(opens in a new tab) - StackExchange
- Neden merkeziyetsiz kâhinlere ihtiyaç duyuyoruz(opens in a new tab) - Bankless
- Demek bir fiyat kâhini kullanmak istiyorsunuz(opens in a new tab) -samczsun
Videolar
- Kâhinler ve Blok Zinciri Hizmetlerinin Genişlemesi(opens in a new tab) - Real Vision Finance
Öğreticiler