Vai al contenuto principale

Aiuta ad aggiornare questa pagina

🌏

C'Γ¨ una nuova versione di questa pagina, ma al momento Γ¨ solo in inglese. Aiutaci a tradurre l'ultima versione.

Traduci la pagina
Visualizza in inglese

Nessun bug qui!πŸ›

Questa pagina non Γ¨ stata tradotta. Per il momento, Γ¨ stata intenzionalmente lasciata in inglese.

Questa pagina Γ¨ incompleta e ci piacerebbe avere il tuo aiuto. Modifica questa pagina e aggiungi tutto ciΓ² che pensi possa essere utile agli altri.

Oracoli

Ultima modifica: , Invalid DateTime
Modifica la pagina

Gli oracoli sono feed di dati che collegano Ethereum a informazioni del mondo reale esternamente alla catena, in modo da poter interrogare i dati negli Smart Contract. Ad esempio, le dapp dei mercati predittivi utilizzano gli oracoli per effettuare i pagamenti in base a eventi. Un mercato predittivo potrebbe chiedere di puntare ETH sul prossimo presidente degli Stati Uniti. UserΓ  un oracolo per confermare l'esito e pagare i vincitori.

Prerequisiti

È necessario avere familiarità con nodi, meccanismi di consenso e anatomia degli Smart Contract, in particolare eventi.

Cos'Γ¨ un oracolo

Un oracolo Γ¨ un ponte tra la blockchain e il mondo reale. Agisce come API sulla catena, che Γ¨ possibile interrogare per ottenere informazioni da inserire negli Smart Contract. Si puΓ² trattare di qualsiasi cosa, da informazioni sui prezzi a previsioni meteo. Gli oracoli possono anche essere bidirezionali ed essere usati per "inviare" i dati al mondo reale.

Guarda Patrick spiegare gli oracoli:

PerchΓ© sono necessari?

Con una blockchain come Ethereum, necessiti di ogni nodo nella rete per riprodurre ogni transazione e terminare con lo stesso risultato, garantito. Le API introducono dati potenzialmente variabili. Se stavi inviando ETH in base a un valore stabilito in $USD usando un'API per i prezzi, la query restituirΓ  un risultato diverso da un giorno all'altro. Per non parlare del fatto che l'API potrebbe essere oggetto di attacchi o diventare obsoleta. In tal caso, i nodi della rete non sarebbero in grado di combaciare con lo stato corrente di Ethereum e, di fatto, verrebbe meno il consenso.

Gli oracoli risolvono questo problema pubblicando i dati sulla blockchain. Quindi ogni nodo che riproduce la transazione utilizzerΓ  gli stessi dati immutabili che vengono pubblicati affinchΓ© siano visibili a tutti. A questo scopo, un oracolo in genere Γ¨ costituito da uno smart contract e da alcuni componenti esterni alla catena che possono interrogare le API e poi inviare periodicamente transazioni per aggiornare i dati dello smart contract.

Il problema dell'oracolo

Come menzionato, le transazioni di Ethereum non possono accedere direttamente ai dati esterni alla catena. Allo stesso tempo, basarsi su una singola fonte di veritΓ  per fornire i dati Γ¨ insicuro e invalida la decentralizzazione di uno smart contract. Questo Γ¨ noto come il problema dell'oracolo.

Possiamo evitarlo usando un oracolo decentralizzato che attinge da piΓΉ fonti di dati; se una fonte di dati viene hackerata o non funziona, lo smart contract funzionerΓ  comunque come previsto.

Sicurezza

La sicurezza di un oracolo Γ¨ pari a quella della sua o delle sue fonti di dati. Se una dApp usa Uniswap come oracolo per il suo feed del prezzo di ETH/DAI, un malintenzionato puΓ² spostare il prezzo su Uniswap per manipolare la comprensione della dApp del prezzo corrente. Un esempio di come combattere ciΓ² Γ¨ un sistema di feed come quello usato da MakerDAO, che raccoglie i dati sui prezzi da molti feed di prezzo esterni anzichΓ© basarsi soltanto su una singola fonte.

Architettura

Questo Γ¨ un esempio di un'architettura semplice di un oracolo, ma esistono altri modi per innescare il calcolo esterno alla catena.

  1. Emetti un registro con il tuo evento di smart contract
  2. Un servizio esterno alla catena si Γ¨ iscritto (solitamente usando qualcosa come il comando eth_subscribe di JSON-RPC) a questi registri specifici.
  3. Il servizio esterno alla catena procede con l'esecuzione di alcune attivitΓ  come definito dal registro.
  4. Il servizio esterno alla catena risponde coi dati richiesti in una transazione secondaria allo smart contract.

È così che si ottengono dati in un rapporto 1 a 1, tuttavia, per migliorare la sicurezza è possibile decentralizzare la raccolta dei dati esterni alla catena.

Il prossimo passaggio potrebbe consistere nel far sì che una rete di questi nodi effettuino le chiamate ad API e fonti diverse e aggreghino i dati nella catena.

Il Chainlink Off-Chain Reporting (Chainlink OCR) ha migliorato questo metodo facendo comunicare tra loro le reti dell'oracolo esterne alla catena, firmando crittograficamente le loro risposte, aggregandole all'esterno della catena e inviando solo una transazione con il risultato sulla catena. In questo modo si consuma meno carburante ma si ottiene comunque la garanzia di dati decentralizzati, poichΓ© ogni nodo ha firmato la propria parte della transazione, redendola immutabile dal nodo che invia la transazione. La politica di escalation subentra se il nodo non effettua la transazione e quello successivo la invia.

Utilizzo

Usando servizi come Chainlink, è possibile fare riferimento ai dati decentralizzati sulla catena che sono già stati prelevati dal mondo reale e aggregati. Una sorta di bene comune e pubblico, ma per i dati decentralizzati. È possibile anche creare le proprie reti dell'oracolo modulari per ottenere tutti i dati personalizzati desiderati. Inoltre, si può anche effettuare calcoli esterni alla catena e inviare le informazioni al mondo reale. Chainlink dispone dell'infrastruttura per:

Ecco un esempio di come ottenere l'ultimo prezzo di ETH nel proprio smart contract usando il feed del prezzo di Chainlink:

1pragma solidity ^0.6.7;
2
3import "@chainlink/contracts/src/v0.6/interfaces/AggregatorV3Interface.sol";
4
5contract PriceConsumerV3 {
6
7 AggregatorV3Interface internal priceFeed;
8
9 /**
10 * Network: Kovan
11 * Aggregator: ETH/USD
12 * Address: 0x9326BFA02ADD2366b30bacB125260Af641031331
13 */
14 constructor() public {
15 priceFeed = AggregatorV3Interface(0x9326BFA02ADD2366b30bacB125260Af641031331);
16 }
17
18 /**
19 * Returns the latest price
20 */
21 function getLatestPrice() public view returns (int) {
22 (
23 uint80 roundID,
24 int price,
25 uint startedAt,
26 uint timeStamp,
27 uint80 answeredInRound
28 ) = priceFeed.latestRoundData();
29 return price;
30 }
31}
32
Mostra tutto
πŸ“‹ Copia

Puoi testarlo nel remix con questo link

Consulta la documentazione

Chainlink VRF (Funzione Casuale Verificabile) Γ¨ una fonte di casualitΓ  provatamente equa e verificabile, progettata per gli smart contract. Gli sviluppatori degli smart contract possono usare Chainlink VRF come generazione di numeri casuali a prova di manomissione (RNG) per creare contratti intelligenti affidabili basati su risultati imprevedibili:

  • Giochi e NFT della blockchain
  • Assegnazione casuale di doveri e risorse (es. assegnazione casuale di giudici ai casi)
  • Scelta di un campione rappresentativo per il meccanismo del consenso

I numeri casuali sono difficili perchΓ© le blockchain sono deterministiche.

Lavorare con gli oracoli di Chainlink al di fuori dei feed di dati segue il ciclo di richiesta e ricezione di lavoro con Chainlink. Viene utilizzato il token LINK per inviare carburante dell'oracolo ai suoi fornitori per restituire le risposte. Il token LINK Γ¨ progettato specificamente per funzionare con gli oracoli e si basa sul token ERC-677 aggiornato, retrocompatibile con l'ERC-20. Il seguente codice, se sviluppato sulla testnet di Kovan recupererΓ  un numero casuale provato crittograficamente. Per effettuare la richiesta, finanzia il contratto con token LINK della testnet che puoi ottenere da Kovan LINK Faucet.

1
2pragma solidity 0.6.6;
3
4import "@chainlink/contracts/src/v0.6/VRFConsumerBase.sol";
5
6contract RandomNumberConsumer is VRFConsumerBase {
7
8 bytes32 internal keyHash;
9 uint256 internal fee;
10
11 uint256 public randomResult;
12
13 /**
14 * Constructor inherits VRFConsumerBase
15 *
16 * Network: Kovan
17 * Chainlink VRF Coordinator address: 0xdD3782915140c8f3b190B5D67eAc6dc5760C46E9
18 * LINK token address: 0xa36085F69e2889c224210F603D836748e7dC0088
19 * Key Hash: 0x6c3699283bda56ad74f6b855546325b68d482e983852a7a82979cc4807b641f4
20 */
21 constructor()
22 VRFConsumerBase(
23 0xdD3782915140c8f3b190B5D67eAc6dc5760C46E9, // VRF Coordinator
24 0xa36085F69e2889c224210F603D836748e7dC0088 // LINK Token
25 ) public
26 {
27 keyHash = 0x6c3699283bda56ad74f6b855546325b68d482e983852a7a82979cc4807b641f4;
28 fee = 0.1 * 10 ** 18; // 0.1 LINK (varies by network)
29 }
30
31 /**
32 * Requests randomness from a user-provided seed
33 */
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 }
38
39 /**
40 * Callback function used by VRF Coordinator
41 */
42 function fulfillRandomness(bytes32 requestId, uint256 randomness) internal override {
43 randomResult = randomness;
44 }
45}
46
Mostra tutto

Gli smart contract non possono attivare o avviare le proprie funzioni in momenti arbitrari o in condizioni arbitrarie. I cambiamenti di stato avvengono solo quando un altro account inizia una transazione (come un utente, un oracolo o un contratto). La Rete di Chainlink Keeper fornisce opzioni per gli smart contract per esternalizzare le regolari attivitΓ  di manutenzione in modo minimizzato e decentralizzato.

Per usare i Chainlink Keeper, uno smart contract deve implementare KeeperCompatibleInterface, che consiste di due funzioni:

  • checkUpkeep - Controlla se il contratto richiede l'esecuzione di un lavoro.
  • performUpkeep - Esegue il lavoro sul contratto, se indicato da checkUpkeep.

L'esempio seguente Γ¨ un semplice contratto Counter. La variabile counter Γ¨ incrementata di uno a ogni chiamata a performUpkeep. controllare il seguente codice usando Remix

1// SPDX-License-Identifier: MIT
2pragma solidity ^0.7.0;
3
4// KeeperCompatible.sol imports the functions from both ./KeeperBase.sol and
5// ./interfaces/KeeperCompatibleInterface.sol
6import "@chainlink/contracts/src/v0.7/KeeperCompatible.sol";
7
8contract Counter is KeeperCompatibleInterface {
9 /**
10 * Public counter variable
11 */
12 uint public counter;
13
14 /**
15 * Use an interval in seconds and a timestamp to slow execution of Upkeep
16 */
17 uint public immutable interval;
18 uint public lastTimeStamp;
19
20 constructor(uint updateInterval) {
21 interval = updateInterval;
22 lastTimeStamp = block.timestamp;
23
24 counter = 0;
25 }
26
27 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. Il checkData Γ¨ definito quando l'Upkeep Γ¨ stato registrato.
30 }
31
32 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. Il performData Γ¨ generato dalla chiamata del Keeper alla propria funzione checkUpkeep
36 }
37}
38
Mostra tutto

Dopo aver distribuito un contratto compatibile con Keeper, è necessario registrarlo per Upkeep e finanziarlo con LINK, per informare la Rete di Keeper del proprio contratto, così che il tuo lavoro sia eseguito continuamente.

Progetti dei Keeper

Le Chiamate all'API di Chainlink sono il metodo piΓΉ facile per ottenere dati dal mondo esterno alla catena con il metodo tradizionale in cui funziona il web: le chiamate API. Eseguire una sola istanza e utilizzare un solo oracolo lo rende centralizzato per natura. Per mantenerlo veramente decentralizzato, una piattaforma di smart contract dovrebbe usare numerosi nodi trovati in un mercato di dati esterni.

Distribuisci il seguente codice nel remix sulla rete di kovan per testarlo

Questo segue anche il ciclo di richiesta e ricezione degli oracoli e necessita del finanziamento del contratto con Kovan LINK (il carburante dell'oracolo) per funzionare.

1pragma solidity ^0.6.0;
2
3import "@chainlink/contracts/src/v0.6/ChainlinkClient.sol";
4
5contract APIConsumer is ChainlinkClient {
6
7 uint256 public volume;
8
9 address private oracle;
10 bytes32 private jobId;
11 uint256 private fee;
12
13 /**
14 * Network: Kovan
15 * Oracle: 0x2f90A6D021db21e1B2A077c5a37B3C7E75D15b7e
16 * Job ID: 29fa9aa13bf1468788b7cc4a500a45b8
17 * Fee: 0.1 LINK
18 */
19 constructor() public {
20 setPublicChainlinkToken();
21 oracle = 0x2f90A6D021db21e1B2A077c5a37B3C7E75D15b7e;
22 jobId = "29fa9aa13bf1468788b7cc4a500a45b8";
23 fee = 0.1 * 10 ** 18; // 0.1 LINK
24 }
25
26 /**
27 * Create a Chainlink request to retrieve API response, find the target
28 * 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);
33
34 // Set the URL to perform the GET request on
35 request.add("get", "https://min-api.cryptocompare.com/data/pricemultifull?fsyms=ETH&tsyms=USD");
36
37 // 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");
48
49 // Multiply the result by 1000000000000000000 to remove decimals
50 int timesAmount = 10**18;
51 request.addInt("times", timesAmount);
52
53 // Sends the request
54 return sendChainlinkRequestTo(oracle, request, fee);
55 }
56
57 /**
58 * Receive the response in the form of uint256
59 */
60 function fulfill(bytes32 _requestId, uint256 _volume) public recordChainlinkFulfillment(_requestId)
61 {
62 volume = _volume;
63 }
64}
65
Mostra tutto

Puoi scoprire di piΓΉ sulle applicazioni di Chainlink leggendo il blog degli sviluppatori di Chainlink.

Servizi per oracoli

Creare uno smart contract oracolo

Ecco un esempio di contratto oracolo di Pedro Costa. Puoi trovare ulteriori commenti nel suo articolo: Implementing a Blockchain Oracle on Ethereum.

1pragma solidity >=0.4.21 <0.6.0;
2
3contract Oracle {
4 Request[] requests; //list of requests made to the contract
5 uint currentId = 0; //increasing request id
6 uint minQuorum = 2; //minimum number of responses to receive before declaring final result
7 uint totalOracleCount = 3; // Hardcoded oracle count
8
9 // defines a general api request
10 struct Request {
11 uint id; //request id
12 string urlToQuery; //API url
13 string attributeToFetch; //json attribute (key) to retrieve in the response
14 string agreedValue; //value from key
15 mapping(uint => string) anwers; //answers provided by the oracles
16 mapping(address => uint) quorum; //oracles which will query the answer (1=oracle hasn't voted, 2=oracle has voted)
17 }
18
19 //event that triggers oracle outside of the blockchain
20 event NewRequest (
21 uint id,
22 string urlToQuery,
23 string attributeToFetch
24 );
25
26 //triggered when there's a consensus on the final result
27 event UpdatedRequest (
28 uint id,
29 string urlToQuery,
30 string attributeToFetch,
31 string agreedValue
32 );
33
34 function createRequest (
35 string memory _urlToQuery,
36 string memory _attributeToFetch
37 )
38 public
39 {
40 uint lenght = requests.push(Request(currentId, _urlToQuery, _attributeToFetch, ""));
41 Request storage r = requests[lenght-1];
42
43 // Hardcoded oracles address
44 r.quorum[address(0x6c2339b46F41a06f09CA0051ddAD54D1e582bA77)] = 1;
45 r.quorum[address(0xb5346CF224c02186606e5f89EACC21eC25398077)] = 1;
46 r.quorum[address(0xa2997F1CA363D11a0a35bB1Ac0Ff7849bc13e914)] = 1;
47
48 // launch an event to be detected by oracle outside of blockchain
49 emit NewRequest (
50 currentId,
51 _urlToQuery,
52 _attributeToFetch
53 );
54
55 // increase request id
56 currentId++;
57 }
58
59 //called by the oracle to record its answer
60 function updateRequest (
61 uint _id,
62 string memory _valueRetrieved
63 ) public {
64
65 Request storage currRequest = requests[_id];
66
67 //check if oracle is in the list of trusted oracles
68 //and if the oracle hasn't voted yet
69 if(currRequest.quorum[address(msg.sender)] == 1){
70
71 //marking that this address has voted
72 currRequest.quorum[msg.sender] = 2;
73
74 //iterate through "array" of answers until a position if free and save the retrieved value
75 uint tmpI = 0;
76 bool found = false;
77 while(!found) {
78 //find first empty slot
79 if(bytes(currRequest.anwers[tmpI]).length == 0){
80 found = true;
81 currRequest.anwers[tmpI] = _valueRetrieved;
82 }
83 tmpI++;
84 }
85
86 uint currentQuorum = 0;
87
88 //iterate through oracle list and check if enough oracles(minimum quorum)
89 //have voted the same answer has the current one
90 for(uint i = 0; i < totalOracleCount; i++){
91 bytes memory a = bytes(currRequest.anwers[i]);
92 bytes memory b = bytes(_valueRetrieved);
93
94 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.agreedValue
103 );
104 }
105 }
106 }
107 }
108 }
109}
110
Mostra tutto
πŸ“‹ Copia

Ci piacerebbe avere piΓΉ documentazione sulla creazione di uno smart contract oracolo. Se vuoi contribuire, crea una PR!

Letture consigliate

Articoli

Video

Tutorial

β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–„β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–„β–‘β–‘β–‘β–‘ β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–Œβ–’β–ˆβ–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–„β–€β–’β–Œβ–‘β–‘β–‘ β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–Œβ–’β–’β–ˆβ–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–„β–€β–’β–’β–’β–β–‘β–‘β–‘ ░░░░░░░▐▄▀▒▒▀▀▀▀▄▄▄▀▒▒▒▒▒▐░░░ β–‘β–‘β–‘β–‘β–‘β–„β–„β–€β–’β–‘β–’β–’β–’β–’β–’β–’β–’β–’β–’β–ˆβ–’β–’β–„β–ˆβ–’β–β–‘β–‘β–‘ β–‘β–‘β–‘β–„β–€β–’β–’β–’β–‘β–‘β–‘β–’β–’β–’β–‘β–‘β–‘β–’β–’β–’β–€β–ˆβ–ˆβ–€β–’β–Œβ–‘β–‘β–‘ β–‘β–‘β–β–’β–’β–’β–„β–„β–’β–’β–’β–’β–‘β–‘β–‘β–’β–’β–’β–’β–’β–’β–’β–€β–„β–’β–’β–Œβ–‘β–‘ β–‘β–‘β–Œβ–‘β–‘β–Œβ–ˆβ–€β–’β–’β–’β–’β–’β–„β–€β–ˆβ–„β–’β–’β–’β–’β–’β–’β–’β–ˆβ–’β–β–‘β–‘ β–‘β–β–‘β–‘β–‘β–’β–’β–’β–’β–’β–’β–’β–’β–Œβ–ˆβ–ˆβ–€β–’β–’β–‘β–‘β–‘β–’β–’β–’β–€β–„β–Œβ–‘ β–‘β–Œβ–‘β–’β–„β–ˆβ–ˆβ–„β–’β–’β–’β–’β–’β–’β–’β–’β–’β–‘β–‘β–‘β–‘β–‘β–‘β–’β–’β–’β–’β–Œβ–‘ β–€β–’β–€β–β–„β–ˆβ–„β–ˆβ–Œβ–„β–‘β–€β–’β–’β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–’β–’β–’β–β–‘ β–β–’β–’β–β–€β–β–€β–’β–‘β–„β–„β–’β–„β–’β–’β–’β–’β–’β–’β–‘β–’β–‘β–’β–‘β–’β–’β–’β–’β–Œ ▐▒▒▒▀▀▄▄▒▒▒▄▒▒▒▒▒▒▒▒░▒░▒░▒▒▐░ β–‘β–Œβ–’β–’β–’β–’β–’β–’β–€β–€β–€β–’β–’β–’β–’β–’β–’β–‘β–’β–‘β–’β–‘β–’β–‘β–’β–’β–’β–Œβ–‘ ░▐▒▒▒▒▒▒▒▒▒▒▒▒▒▒░▒░▒░▒▒▄▒▒▐░░ β–‘β–‘β–€β–„β–’β–’β–’β–’β–’β–’β–’β–’β–’β–’β–’β–‘β–’β–‘β–’β–‘β–’β–„β–’β–’β–’β–’β–Œβ–‘β–‘ β–‘β–‘β–‘β–‘β–€β–„β–’β–’β–’β–’β–’β–’β–’β–’β–’β–’β–„β–„β–„β–€β–’β–’β–’β–’β–„β–€β–‘β–‘β–‘ β–‘β–‘β–‘β–‘β–‘β–‘β–€β–„β–„β–„β–„β–„β–„β–€β–€β–€β–’β–’β–’β–’β–’β–„β–„β–€β–‘β–‘β–‘β–‘β–‘ β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–’β–’β–’β–’β–’β–’β–’β–’β–’β–’β–€β–€β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘

Aiutaci con questa pagina

Se conosci l'argomento e vuoi contribuire, modifica questa pagina e condividi un po' del tuo sapere.

Il tuo nome verrΓ  aggiunto ai crediti e aiuterai la community di Ethereum!

Usa questo flessibile modello di documentazione

Domande? Chiedicelo nel canale #content sul nostro server Discord

Modifica pagina

Questo articolo Γ¨ stato utile?

πŸ‘ˆ

Indietro

Valore estraibile massimo (MEV)

Avanti

Ampliamento
πŸ‘‰