Oracles
Nazadnje urejeno: @zajko(opens in a new tab), 25. julij 2024
Oraklji so viri podatkov, ki povezujejo Ethereum s podatki izven verige iz resničnega sveta, da lahko poizvedujete o teh podatkih v svoji pametni pogodbi. Na primer, dappi napovednih trgov uporabljajo oraklje za poravnavo plačil, ki temeljijo na dogodkih. Napovedni trg lahko od vas zahteva, da stavite svoj ETH na to, kdo bo postal naslednji predsednik Združenih držav Amerike. Oraklje bodo uporabili za potrditev izida in izplačilo zmagovalcem.
Predpogoji
Prepričajte se, da ste seznanjeni z vozlišči, mehanizmi za soglasje in anatomijo pametnih pogodb, specifično za dogodke.
Kaj je orakelj
Orakelj je most med blokovno verigo in resničnim svetom. Delujejo kot API-ji na verigi, od katerih lahko poizvedujete, da prejmete informacije v svoje pametne pogodbe. To je lahko karkoli od informacij o ceni do vremenskih poročil. Oraklji so lahko tudi dvosmerni in se uporabljajo za "pošiljanje" podatkov v resnični svet.
Oglejte si Patricka, ki pojasnjuje oraklje:
Zakaj so potrebni?
Pri blokovni verigi, kot je Ethereum, je potrebno, da vsako vozlišče v omrežju vrne vsako transakcijo in ima na koncu zagotovo enak rezultat. API-ji predstavijo potencialno variabilne podatke. Če bi pošiljali ETH na podlagi dogovorjene vrednosti $USD z uporabo cenovnega API-ja, bi poizvedba vsak dan vrnila različen rezultat. Da ne omenjamo, da je lahko API napaden ali zastarel. V tem primeru se vozlišča v omrežju ne bi mogla strinjati o Ethereumovem trenutnem stanju, kar bi efektivno prelomilo soglasje.
Oraklji rešijo ta problem z objavo podatkov na blokovni verigi. Tako lahko katerokoli vozlišče uporablja iste nespremenljive podatke, ki so objavljeni na očeh vseh. Za to je orakelj po navadi sestavljen iz pametne pogodbe in nekaj komponent izven verige, ki lahko poizvedujejo prek API-jev ter nato periodično pošiljajo transakcije za posodobitev podatkov pametne pogodbe.
Problem oraklja
Kot smo omenili, transakcije Ethereum ne morejo neposredno dostopati do podatkov izven verige. Obenem je zanašanje na le en vir resnice za zagotavljanje podatkov nevarno in izpodbija decentralizacijo pametne pogodbe. To poznamo kot problem oraklja.
Problemu oraklja se lahko izognemo z decentraliziranim orakljem, ki podatke vleče iz različnih virov; če je en podatkovni vir napaden ali mu spodleti, bo pametna pogodba še vedno delovala tako, kot je bil njen namen.
Varnost
Orakelj je varen le toliko, kot so varni njegovi podatkovni viri. Če dapp kot orakelj za svoj vir cene ETH/DAI uporablja Uniswap, lahko napadalec premakne ceno na Uniswapu, da manipulira z dappovim razumevanjem trenutne cene. Primer, kako se boriti proti temu, je sistem virov(opens in a new tab), kot je tisti, ki ga uporablja MakerDAO, ki podatke o cenah zbira od več zunanjih cenovnih virov, namesto da bi se zanašal le na en vir.
Arhitektura
To je primer preproste arhitekture oraklja, ampak obstaja še več drugih načinov za sprožitev računanja izven verige.
- Oddajte dnevnik s svojim dogodkom pametne pogodbe
- Storitev izven verige se je naročila (navadno z uporabo nečesa, kot je ukaz JSON-RPC
eth_subscribe
) na te specifične dnevnike. - Storitev izven verige nadaljuje z izvedbo nalog, kot so opredeljene v dnevniku.
- Storitev izven verige se odzove s podatki, zahtevanimi v sekundarni transakciji, na pametno pogodbo.
To je način za pridobitev podatkov po načelu 1 na 1, čeprav bi za izboljšanje varnosti morda želeli decentralizirati način zbiranja svojih podatkov izven verige.
Naslednji korak bi lahko bil, da omrežje teh vozlišč izvede te klice na različne API-je in vire ter zbere podatke na verigi.
Poročanje Chainlink izven verige(opens in a new tab) (Chainlink OCR) se je na podlagi te metodologije izboljšalo s tem, da oraklji v omrežju izven verige med seboj komunicirajo, kriptografsko podpišejo svoje odzive, združijo svoje odzive izven verige in na verigo pošljejo le eno transakcijo z rezultatom. Na ta način se porabi manj goriva, ampak še vedno lahko dobite zagotovilo decentraliziranih podatkov, saj je vsako vozlišče podpisalo svoj del transakcije, kar jo je za vozlišča, ki jo pošiljajo, naredilo nespremenljivo. Politika stopnjevanja se uveljavi, če vozlišče ne opravi transakcije in transakcijo pošlje naslednje vozlišče.
Uporaba
Z uporabo storitev, kot je Chainlink, se lahko sklicujete na decentralizirane podatke na verigi, ki so že bili povlečeni in združeni iz resničnega sveta. Nekako tako kot javna skupna dobrina, vendar za decentralizirane podatke. Prav tako lahko za pridobitev katerihkoli podatkov po meri, ki jih iščete, razvijete svoja lastna modularna omrežja orakljev. Dodatno lahko izvedete računanje izven verige in prav tako pošljete informacije v resnični svet. Chainlink ima vzpostavljeno infrastrukturo za:
- Pridobitev kripto cenovnih virov v vašo pogodbo(opens in a new tab)
- Generiranje potrdljivih naključnih številk (uporabno za igričarstvo)(opens in a new tab)
- Pokličete zunanje API-je(opens in a new tab) – ena nova uporaba tega je Preverjanje zalog wBTC(opens in a new tab)
Tukaj je primer pridobivanja aktualne cene ETH v vaši pametni pogodbi z uporabo cenovnega vira Chainlink:
Viri podatkov Chainlink
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}Prikaži vseKopiraj
To lahko testirate v remiksu prek te povezave(opens in a new tab)
Oglejte si dokumentacijo(opens in a new tab)
Chainlink VRF
Chainlink VRF (potrdljiva naključna funkcija) je dokazano pravičen in potrdljiv vir naključnosti, oblikovan za pametne pogodbe. Razvijalci pametnih pogodb lahko uporabijo Chainlink VRF za naključno generiranje številk (RNG), odporno na posege, da razvijejo zanesljive pametne pogodbe za katerekoli aplikacije, ki se zanašajo na nepredvidljive izide:
- Igre na blokovnih verigah in NFT-je
- Naključno dodeljevanje zadolžitev in virov (recimo naključno dodeljevanje sodnikov primerom)
- Izbiro reprezentativnega vzorca za mehanizme za soglasje
Naključne številke so težke, saj so blokovne verige deterministične.
Delo z oraklji Chainlink zunaj podatkovnih virov sledi ciklu zahtevaj in prejmi(opens in a new tab) dela s Chainlinkom. Za pošiljanje goriva ponudnikom orakljev za vračanje odzivov uporabljajo žeton LINK. Žeton LINK je specifično oblikovan za delo z oraklji in temelji na nadgrajenem žetonu ERC-677, ki je vzvratno kompatibilen z ERC-20. Naslednja koda, če je uveljavljena na testnem omrežju Kovan, bo pridobila kriptografsko dokazano naključno številko. Za izvršitev zahteve na pogodbo nakažite nekaj žetonov LINK testnega omrežja, ki jih lahko dobite iz pipe Kovan LINK(opens in a new tab).
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}Prikaži vse
Chainlink Keepers
Pametne pogodbe ne morejo sprožiti ali iniciirati svojih lastnih funkcij v arbitrarnem času ali pod arbitrarnimi pogoji. Spremembe stanja se bodo pojavile, ko nek drug račun iniciira transakcijo (recimo uporabnik, orakelj ali pogodba). Omrežje Chainlink Keeper(opens in a new tab) zagotavlja možnosti, da pametne pogodbe sprotno vzdrževanje predajo zunanjim izvajalcem na način minimiziranega zaupanja in decentralizacije.
Za uporabo Chainlink Keeperjev mora pametna pogodba implementirati KeeperCompatibleInterface(opens in a new tab), ki je sestavljena iz dveh funkcij:
checkUpkeep
– preveri, če pogodba zahteva delo, ki ga je treba opraviti.performUpkeep
– izvede delo na pogodbi, če tako naroči checkUpkeep.
Spodnji primer je preprosta kontra pogodba. Kontra
spremenljivka je povečana za ena z vsakim klicem performUpkeep
. Lahko si ogledate naslednjo kodo z uporabo Remixa(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. Funkcija checkData je definirana, ko je bil registriran Upkeep.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. Funkcija performData je ustvarjena s strani Keeper klica na vašo funkcijo checkUpkeep36 }37}Prikaži vse
Po uveljavitvi pogodbe, kompatibilne s Keeper, morate pogodbo registrirati za Upkeep(opens in a new tab) in nanjo položiti LINK, da omrežje Keeper obvestite o svoji pogodbi in da je vaše delo izvedeno neprekinjeno.
Projekti Keepers
Klic Chainlink API
Klici Chainlink API(opens in a new tab) so najenostavnejši način za pridobivanje podatkov iz sveta izven verige na tradicionalen način, po katerem deluje splet: klici API. Enkratna izvedba in razpolaganje le z enim orakljem sta po naravi centralizirana. Da bi jo ohranili resnično decentralizirano, bi morala platforma pametnih pogodb uporabljati številna vozlišča, najdena na zunanjem podatkovnem trgu(opens in a new tab).
Za testiranje uveljavite naslednjo kodo v remiksu na omrežju Kovan(opens in a new tab)
To prav tako sledi zahtevi in prejme cikel orakljev ter za to potrebuje pogodbo, da se lahko za delovanje financira s Kovan LINK (gorivom oraklja).
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}Prikaži vse
Več o aplikacijah Chainlink lahko izveste z branjem razvijalskega bloga Chainlink(opens in a new tab).
Storitve orakljev
- 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)
Razvijte orakeljsko pametno pogodbo
Tukaj najdete primer orakeljske pogodbe Pedra Coste. Nadaljnje opombe lahko najdete v njegovem članku: Implementacija oraklja blokovne verige na Ethereumu(opens in a new tab).
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}Prikaži vseKopiraj
Želeli bi si več dokumentacije o ustvarjanju orakeljskih pametnih pogodb. Če lahko pomagate, ustvarite PR!
Nadaljnje branje
Članki
- Kaj je orakelj blokovne verige?(opens in a new tab) – Chainlink
- Kaj je orakelj blokovne verige?(opens in a new tab) – Patrick Collins
- Decentralizirani oraklji: podroben pregled(opens in a new tab) – Julien Thevenard
- Implementacija oraklja blokovne verige na Ethereumu(opens in a new tab) – Pedro Costa
- Zakaj pametne pogodbe ne morejo izvrševati klicev API?(opens in a new tab) – StackExchange
- Zakaj potrebujemo decentralizirane oraklje(opens in a new tab) – Bankless
- Torej, želite uporabljati cenovni orakelj(opens in a new tab) – samczsun
Videoposnetki
- Oraklji in razširitev uporabnosti blokovne verige(opens in a new tab) – Real Vision Finance
Vadnice