Wyrocznie
Wyrocznie to źródła danych łączące Ethereum z informacjami spoza łańcucha, ze świata rzeczywistego, umożliwiające zapytania o dane w inteligentnych kontraktach. Na przykład aplikacje dapp rynków prognostycznych używają wyroczni do rozliczania płatności na podstawie zdarzeń. Rynek prognostyczny może poprosić Cię o postawienie ETH na następnego prezydenta Stanów Zjednoczonych. Użyje wyroczni, aby potwierdzić wynik i wypłacić nagrodę zwycięzcom.
Warunki wstępne
Upewnij się, że wiesz wystarczająco dużo na temat węzłów, mechanizmów konsensusu i anatomii kontraktów inteligentnych, w szczególności zdarzeń.
Co to jest wyrocznia
Wyrocznia jest pomostem między blockchainem a światem rzeczywistym. Wyrocznie działają jako interfejsy API w łańcuchu, do których można wysyłać zapytania, aby uzyskać informacje do inteligentnych kontraktów. Może to być wszystko, od informacji o cenach po prognozy pogody.
Dlaczego są potrzebne?
Z blockchainem takim jak Ethereum potrzebujesz każdego węzła w sieci, aby móc odtworzyć każdą transakcję i uzyskać ten sam wynik, gwarantowany. API wprowadzają potencjalnie zmienne dane. Jeśli wysyłasz komuś kwotę ETH na podstawie uzgodnionej wartości $USD za pomocą interfejsu API ceny, zapytanie zwróci inny wynik każdego dnia. Nie wspominając o tym, że API może zostać zhakowany lub być przestarzały. Jeśli tak się stanie, węzły w sieci nie będą w stanie uzgodnić aktualnego stanu Ethereum, skutecznie łamiąc konsensus.
Wyrocznie rozwiązują ten problem, publikując dane w blockchainie. Tak więc każdy węzeł odtwarzający transakcję wykorzysta te same niezmienne dane, które zostały opublikowane dla wszystkich. W tym celu wyrocznia składa się zazwyczaj z inteligentnego kontraktu i niektórych elementów nieobjętych łańcuchem, które mogą odpytywać API, następnie okresowo wysyłać transakcje, aby zaktualizować dane inteligentnego kontraktu.
Ochrona
Wyrocznia jest tak bezpieczna, jak jej źródła danych. Jeśli aplikacja dapp używa Uniswap jako wyroczni dla swojego kanału cenowego ETH/DAI, atakujący może zmienić cenę na Uniswap w celu manipulowania wiedzą aplikacji na temat bieżącej ceny. Można z tym walczyć, wykorzystując na przykład system kanałów podobny do używanego przez MakerDAO, który porównuje dane cenowe z wielu zewnętrznych źródeł cen, zamiast polegać tylko na jednym.
Wykorzystanie
Wyrocznie jako usługa
Usługi takie jak Chainlink oferują wyrocznie jako usługę, z której możesz korzystać. Dysponują infrastrukturą umożliwiającą użytkownikom podjęcie następujących działań:
- pobieranie źródeł cen kryptowalut do swojego kontraktu
- generowanie weryfikowalnych liczb losowych (przydatne do gry)
- wywoływanie zewnętrznych interfejsów API – jednym z nowatorskich zastosowań jest sprawdzanie rezerw wBTC
Oto przykład możliwości uzyskania ostatniej ceny ETH w inteligentnym kontrakcie za pomocą kanału cenowego Chainlink:
1pragma solidity ^0.6.7;23import "@chainlink/contracts/src/v0.6/interfaces/AggregatorV3Interface.sol";45contract PriceConsumerV3 {67 AggregatorV3Interface internal priceFeed;89 /**10 * Sieć: Kovan11 * Agregator: ETH/USD12 * Adress: 0x9326BFA02ADD2366b30bacB125260Af64103133113 */14 constructor() public {15 priceFeed = AggregatorV3Interface(0x9326BFA02ADD2366b30bacB125260Af641031331);16 }1718 /**19 * Zwraca ostatnią cenę20 */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}32Pokaż wszystkoKopiuj
Usługi wyroczni
Tworzenie kontraktu inteligentnego z wykorzystaniem wyroczni
Oto przykład kontraktu z wykorzystaniem wyroczni autorstwa Pedro Costa. W artykule znajdziesz kolejną adnotację: Wprowadzanie wyroczni blockchainu w Ethereum.
1pragma solidity >=0.4.21 <0.6.0;23contract Oracle {4 Request[] requests; //lista żądań wprowadzonych do kontraktu5 uint currentId = 0; //rosnący id żądania6 uint minQuorum = 2; //minimalna liczba otrzymanych odpowiedzi przed zadeklarowaniem ostatecznego wyniku7 uint totalOracleCount = 3; // liczba wyroczni osadzonych w kodzie źródłowym8 // defines a general api request9 struct Request {10 uint id; // id żądania11 string urlToQuery; //url API12 string attributeToFetch; //atrybut json (klucz) do pobrania w odpowiedzi13 string agreedValue; //wartość z klucza14 mapping(uint => string) anwers; //odpowiedzi dostarczone przez wyrocznie15 mapping(address => uint) quorum; //wyrocznie, które będą odpytywać odpowiedź (1=wyrocznia nie głosowała, 2=wyrocznia głosowała)16 }1718 //zdarzenie wyzwalające wyrocznię poza blockchainem19 event NewRequest (20 uint id,21 string urlToQuery,22 string attributeToFetch23 );2425 //wyzwalane, jeśli jest konsensus co do końcowego wyniku26 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 lenght = requests.push(Request(currentId, _urlToQuery, _attributeToFetch, ""));40 Request storage r = requests[lenght-1];4142 // osadzony adres wyroczni43 r.quorum[address(0x6c2339b46F41a06f09CA0051ddAD54D1e582bA77)] = 1;44 r.quorum[address(0xb5346CF224c02186606e5f89EACC21eC25398077)] = 1;45 r.quorum[address(0xa2997F1CA363D11a0a35bB1Ac0Ff7849bc13e914)] = 1;4647 // uruchomienie zdarzenia do wykrycia poza blockchainem48 emit NewRequest (49 currentId,50 _urlToQuery,51 _attributeToFetch52 );5354 // zwiększanie id żądania55 currentId++;56 }5758 //wywołane przez wyrocznię, aby zarejestrować jej odpowiedź59 function updateRequest (60 uint _id,61 string memory _valueRetrieved62 ) public {6364 Request storage currRequest = requests[_id];6566 //sprawdzenie, czy wyrocznia jest na liście zaufanych wyroczni67 //i czy wyrocznia jeszcze nie głosowała68 if(currRequest.quorum[address(msg.sender)] == 1){6970 //oznaczenie, że ten adres głosował71 currRequest.quorum[msg.sender] = 2;7273 //iteracyjne przejście przez "tablicę" odpowiedzi do czasu uzyskania wolnej pozycji i zapisanie pobranej wartości74 uint tmpI = 0;75 bool found = false;76 while(!found) {77 //find first empty slot78 if(bytes(currRequest.anwers[tmpI]).length == 0){79 found = true;80 currRequest.anwers[tmpI] = _valueRetrieved;81 }82 tmpI++;83 }8485 uint currentQuorum = 0;8687 //iteracyjne przejście przez listę wyroczni i sprawdzenie, czy ich liczba jest wystarczająca(minimalne kworum)88 //głosowały na tę samą odpowiedź jak bieżąca89 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}109Pokaż wszystkoKopiuj
Ucieszyłaby nas większa ilość dokumentacji dotyczącej tworzenia inteligentnych kontraktów z wykorzystaniem wyroczni. Jeśli możesz pomóc, utwórz PR!
Dalsza lektura
- Zdecentralizowane wyrocznie: kompleksowy przegląd – Julien Thevenard
- Wdrażanie wyroczni blockchainu w Ethereum – Pedro Costa
- Wyrocznie – EthHub
Pomóż nam zaktualizować tę stronę
Jeśli jesteś ekspertem w temacie i chcesz podzielić się wiedzą, edytuj tę stronę i wzbogać ją swoją mądrością.
Zyskasz uznanie i pomożesz społeczności Ethereum!
Użyj tego elastycznego szablonu dokumentacji
Pytania? Zadaj je na kanale #content na naszym serwerze Discord
Edytuj stronę