Oracole
Ultima modificare: @nicklcanada(opens in a new tab), 25 iulie 2024
Oracolele sunt fluxuri de date care conectează Ethereum la informații din lumea reală, în afara lanțului, astfel încât să puteţi interoga datele în contractele dvs. inteligente. De exemplu, aplicațiile dapp de predicție de piață utilizează oracole pentru a efectua plăți pe baza evenimentelor. O piață de predicție vă poate cere săpariaţi ETH pe următorul președinte al Statelor Unite. Va folosi un oracol pentru a confirma rezultatul și pentru a plăti câștigătorilor.
Condiții prealabile
Aveţi grijă să vă familiarizaţi cu nodurile, mecanismele de consens și anatomia contractelor inteligente, în special cu evenimentele.
Ce este un oracol
Un oracol este o punte între blockchain și lumea reală. Acestea acționează ca API-uri pe lanț pe care le puteţi interoga pentru a obține informații în contractele inteligente. Acest lucru ar putea fi orice, de la informații de preț la rapoarte meteorologice. Oracolele pot fi şi bidirecționale, adică folosite pentru a „trimite” date în lumea reală.
Urmăriți-l pe Patrick explicând Oracolele:
De ce este nevoie de oracole?
Cu un blockchain precum Ethereum, aveți nevoie de fiecare nod din rețea ca să repete fiecare tranzacție și să ajungă la același rezultat, garantat. API-urile introduc date potențial variabile. Dacă ați trimite ETH pe baza unei valori $USD convenite folosind un API de prețuri, interogarea ar răspunde printr-un rezultat diferit de la o zi la alta. Ca să nu mai spunem că API-ul ar putea fi piratat sau perimat. Dacă se întâmplă acest lucru, nodurile din rețea nu ar fi în măsură să se pună de acord asupra stării actuale a lui Ethereum, încălcând în mod efectiv consensul.
Oracolele rezolvă această problemă postând datele pe blockchain. De aceea, orice nod care redă tranzacția va utiliza aceleași date imuabile care sunt postate pentru ca toți să le vadă. Pentru a face acest lucru, un oracol este format de obicei dintr-un contract inteligent și unele componente din lanț care pot interoga API-urile, iar apoi trimit periodic tranzacții pentru a actualiza datele contractului inteligent.
Problema oracolului
După cum am menționat, tranzacțiile Ethereum nu pot accesa direct datele din afara lanțului. Totodată, dacă ne bizuim pe o singură sursă a adevărului pentru a furniza date, acest lucru este nesigur și invalidează descentralizarea unui contract inteligent. Aceasta este cunoscută sub numele de problema oracolului.
Putem evita problema oracolului prin utilizarea unui oracol descentralizat care preia date din mai multe surse; dacă una dintre sursele de date este piratată sau eșuează, contractul inteligent va funcționa în continuare așa cum a fost stabilit.
Securitate
Un oracol este la fel de securizat ca sursele sale de date. Dacă o aplicație dapp utilizează Uniswap ca oracol pentru alimentarea cu prețul ETH/DAI, un atacator poate muta prețul pe Uniswap pentru a manipula înțelegerea prețului curent de către aplicația dapp. Un exemplu de modalitate de combatere a acestui lucru este un sistem de alimentare(opens in a new tab) precum cel utilizat de MakerDAO, care colaționează datele despre prețuri din mai multe surse externe în loc să se bazeze doar pe una singură.
Arhitectură
Acesta este un exemplu de arhitectură Oracle simplă, însă există mai multe moduri de a declanșa calculul off-chain.
- Emiteți un jurnal cu evenimentul contractului dvs. inteligent
- Un serviciu off-chain s-a abonat (de regulă folosind ceva de genul comenzii JSON-RPC
eth_subscribe
) la aceste jurnale specifice. - Serviciul off-chain trece la efectuarea unor sarcini definite de jurnal.
- Serviciul off-chain răspunde contractului inteligent prin datele solicitate într-o tranzacție secundară.
Aceasta este modalitatea de obținere a datelor într-o manieră 1 la 1, dar, pentru a îmbunătăți securitatea, poate doriți să descentralizați modul în care colectați datele off-chain.
Următoarea etapă ar putea fi aceea de a avea o rețea a acestor noduri care să efectueze acele apeluri către diferite API-uri și surse și să agrege datele pe lanț.
Chainlink Off-Chain Reporting(opens in a new tab) (Chainlink OCR) a îmbunătățit această metodologie prin faptul că rețelele de oracole off-chain comunică între ele, își semnează criptografic răspunsurile, agregă răspunsurile off-chain și trimit doar o singură tranzacție on-chain cu rezultatul. În acest mod se cheltuiește mai puțin gaz, dar se menține garanția datelor descentralizate, întrucât fiecare nod a semnat partea sa de tranzacție, prin aceasta nemaiputând fi modificată de către nodul care trimite tranzacția. Politica de escaladare intră în vigoare dacă nodul nu efectuează tranzacția, ci următorul nod trimite tranzacția.
Utilizare
Utilizând servicii precum Chainlink, puteți face referire la datele descentralizate on-chain care au fost deja extrase din lumea reală și agregate. Un fel de bunuri comune publice, dar pentru date descentralizate. De asemenea, vă puteți construi propriile rețele de oracole modulare pentru a obține datele personalizate pe care le căutați. În plus, puteți efectua calcule off-chain și de asemenea trimite informații în lumea reală. Chainlink dispune de infrastructura necesară pentru:
- obținerea de fluxuri de preț cripto în contractul dvs.(opens in a new tab)
- generarea de numere aleatorii verificabile (utile pentru jocuri)(opens in a new tab)
- apelarea de API-uri externe(opens in a new tab) – o utilizare inedită a acestui lucru este Verificarea rezervelor wBTC(opens in a new tab)
Iată un exemplu al modului de a obţine cel mai recent preț ETH în contractul dvs. inteligent folosind un flux de prețuri Chainlink:
Fluxuri de date 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}Afișează totCopiați
Puteți testa acest lucru în remix cu acest link(opens in a new tab)
Vedeţi documentația(opens in a new tab)
Chainlink VRF
Chainlink VRF (Funcția aleatorie verificabilă) este o sursă de randomizare verificabilă și verificabilă, cu o corectitudine dovedită, concepută pentru contractele inteligente. Dezvoltatorii de contracte inteligente pot folosi Chainlink VRF ca generator de numere aleatorii (RNG) inviolabil ca să construiască contracte inteligente fiabile pentru orice aplicații care se bazează pe rezultate imprevizibile:
- Jocuri blockchain și NFT-uri
- Alocarea aleatorie de sarcini și resurse (de exemplu, alocarea aleatorie a judecătorilor la procese)
- Alegerea unui eșantion reprezentativ pentru mecanismele de consens
Numerele aleatorii sunt dificile, deoarece blockchain-urile sunt deterministe.
Modul de lucru cu oracolele Chainlink în afara fluxurilor de date urmează ciclul de solicitare și primire(opens in a new tab) al modului de lucru cu Chainlink. Acesta foloseşte tokenul LINK pentru a trimite furnizorilor de oracole gazul oracolelor ca să dea răspunsuri. Tokenul LINK este conceput special pentru a lucra cu oracolele și se bazează pe tokenul ERC-677 actualizat, care este compatibil cu ERC-20. Dacă următorul cod este implementat pe testnet-ul Kovan, acesta va prelua un număr aleatoriu dovedit criptografic. Pentru a face cererea, finanțați contractul cu câteva tokenuri de testnet LINK, pe care le puteți obține de la faucet-ul 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}Afișează tot
Chainlink Keepers
Contractele inteligente nu își pot declanșa sau iniția propriile funcții în momente sau în condiții arbitrare. Starea contractelor se va modifica doar când un alt cont inițiază o tranzacție (cum ar fi un utilizator, un oracol sau un contract). Rețeaua Chainlink Keeper(opens in a new tab) oferă contractelor inteligente opțiuni de externalizare a sarcinilor regulate de întreținere, în mod descentralizat și necesitând încredere minimă.
Pentru a utiliza Chainlink Keepers, un contract inteligent trebuie să implementeze o interfață KeeperCompatibleInterface(opens in a new tab), care constă din două funcții:
checkUpkeep
- Verifică dacă sunt prevăzute în contract lucrări de efectuat.performUpkeep
- Execută lucrările prevăzute în contract, dacă este instruit de checkUpkeep.
Exemplul de mai jos este un simplu contract counter. Variabila counter
este incrementată cu unu la fiecare apel lcătre performUpkeep
. Puteți examina codul următor folosind Remix(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 este definită în momentul înregistrării Upkeep-ului.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 este generată de apelul Keeeper-ului la funcția checkUpkeep.36 }37}Afișează tot
După implementarea unui contract compatibil Keeper, trebuie să înregistrați contractul pentru Upkeep(opens in a new tab) (întreținere) și să îl finanțați cu LINK, pentru a anunţa rețeaua Keeper despre contract, astfel încât munca dvs. să fie efectuată în mod continuu.
Proiecte Keepers
Apelul API Chainlink
Apelurile API Chainlink(opens in a new tab) sunt cea mai simplă modalitate de a obține date off-chain în modul tradițional în care funcționează web-ul: apelurile API. Realizarea unei singure astfel de instanțe și existența unui singur oracol îl face să devină centralizat prin natura sa. Pentru a-l menține cu adevărat descentralizat, o platformă de contracte inteligente ar trebui să utilizeze numeroase noduri găsite pe o piață de date externă(opens in a new tab).
Implementați următorul cod în remix pe rețeaua kovan pentru a testa(opens in a new tab)
Acesta urmează tot ciclul de solicitare și primire a oracolelor și are nevoie să fie finanţat contractul cu Kovan LINK (gazul oracolului) pentru a funcționa.
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}Afișează tot
Puteți afla mai multe despre aplicațiile Chainlink consultând blogul dezvoltatorilor Chainlink(opens in a new tab).
Servicii Oracle
- 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)
Construiește un contract inteligent oracol
Iată un exemplu de contract oracol al lui Pedro Costa. Puteţi găsi şi alte adnotări în articolul său: Implementarea unui blockchain oracol pe Ethereum(opens in a new tab).
1pragma solidity >=0.4.21 <0.6.0;23contract Oracle {4 Request[] requests; //lista cererilor adresate contractului5 uint currentId = 0; //creșterea ID-ului solicitării6 uint minQuorum = 2; //numărul minim de răspunsuri de primit înainte de declararea rezultatului final7 uint totalOracleCount = 3; // Număr de oracol codificat greu89 // definește o cerere API generală10 struct Request {11 uint id; //cerere id12 string urlToQuery; //API url13 string attributeToFetch; //atribut json (cheie) pentru a prelua în răspuns string agreedValue; //valoarea din cheie14 mapping(uint => string) anwers; //răspunsuri oferite de oracole15 mapping(address => uint) quorum; //oracole care vor interoga răspunsul (1 = oracolul nu a votat, 2 = oracolul a votat)16 }1718 //eveniment care declanșează oracolul în afara blockchain-ului19 event NewRequest (20 uint id,21 string urlToQuery,22 string attributeToFetch23 );2425 //declanșat atunci când există un consens cu privire la rezultatul final26 event UpdatedRequest (27 uint id,28 string urlToQuery,29 string attributeToFetch,30 string agreedValue31 );3233 function createRequest (34 string memory _urlToQuery,35 string memory _attributeToFetch36 )37 public38 {39 uint length = requests.push(Request(currentId, _urlToQuery, _attributeToFetch, ""));40 Request storage r = requests[length-1];4142 // adresa oracole codificată greu43 r.quorum[address(0x6c2339b46F41a06f09CA0051ddAD54D1e582bA77)] = 1;44 r.quorum[address(0xb5346CF224c02186606e5f89EACC21eC25398077)] = 1;45 r.quorum[address(0xa2997F1CA363D11a0a35bB1Ac0Ff7849bc13e914)] = 1;4647 //lansează un eveniment care va fi detectat de oracol în afara blockchain-ului48 emit NewRequest (49 currentId,50 _urlToQuery,51 _attributeToFetch52 );5354 // crește cererea id55 currentId++;56 }5758 //chemat de oracol pentru a înregistra răspunsul său59 function updateRequest (60 uint _id,61 string memory _valueRetrieved62 ) public {6364 Request storage currRequest = requests[_id];6566 //verifică dacă oracolul se află în lista oracolelor de încredere67 //și dacă oracolul nu a votat încă68 if(currRequest.quorum[address(msg.sender)] == 1){6970 //marcând că această adresă a votat71 currRequest.quorum[msg.sender] = 2;7273 //iterează prin „matricea” de răspunsuri până la o poziție dacă este liberă și salvează valoarea recuperată74 uint tmpI = 0;75 bool found = false;76 while(!found) {77 //găsește primul slot gol78 if(bytes(currRequest.anwers[tmpI]).length == 0){79 found = true;80 currRequest.anwers[tmpI] = _valueRetrieved;81 }82 tmpI++;83 }8485 uint currentQuorum = 0;8687 //iterează prin lista oracolelor și verifică dacă sunt suficiente oracole (cvorum minim)88 //au votat același răspuns ca și cel actual89 for(uint i = 0; i < totalOracleCount; i++){90 bytes memory a = bytes(currRequest.anwers[i]);91 bytes memory b = bytes(_valueRetrieved);9293 if(keccak256(a) == keccak256(b)){94 currentQuorum++;95 if(currentQuorum >= minQuorum){96 currRequest.agreedValue = _valueRetrieved;97 emit UpdatedRequest (98 currRequest.id,99 currRequest.urlToQuery,100 currRequest.attributeToFetch,101 currRequest.agreedValue102 );103 }104 }105 }106 }107 }108}Afișează totCopiați
Ne-ar plăcea să mai avem documentație privind crearea unui contract inteligent oracol. Dacă puteți ajuta, creați un PR!
Referințe suplimentare
Articole
- Ce este un blockchain oracol?(opens in a new tab) – Chainlink
- Ce este un blockchain oracol?(opens in a new tab) – Patrick Collins
- Oracole descentralizate: o prezentare cuprinzătoare(opens in a new tab) – Julien Thevenard
- Implementarea unui blockchain oracol pe Ethereum(opens in a new tab) – Pedro Costa
- De ce contractele inteligente nu pot face apeluri API?(opens in a new tab) – StackExchange
- De ce avem nevoie de oracole descentralizate(opens in a new tab) – Bankless
- Deci doriți să folosiți un oracol de prețuri(opens in a new tab) – samczsun
Videoclipuri
- Oracolele și expansiunea utilității blockchain-ului(opens in a new tab) – Real Vision Finance
Tutoriale