Oráculos
Última edición: , Invalid DateTime
Los oráculos son feeds de datos que conectan Ethereum a información del mundo real, externa a la blockchain (off-chain) para que puedas consultar datos en tus contratos inteligentes. Por ejemplo, las dapps de mercados de predicciones utilizan oráculos para establecer pagos basados en eventos. Un mercado de predicción podría pedirte que apostases tu ETH sobre el próximo presidente de los Estados Unidos. Utilizarán un oráculo para confirmar el resultado y pagar a los ganadores.
Pre requisitos
Asegúrate de estar familiarizado con los nodos, los mecanismos de consenso y la anatomía de los contratos inteligentes, especialmente con los eventos.
¿Qué es un oráculo?
Un oráculo es un puente entre la blockchain y el mundo real. Los oráculos actúan como API internas a la cadena de bloques (on-chain), que puedes consultar a fin de aportar información a los contratos inteligentes. Esta información podría ser muy variada: desde datos de precios hasta informes climáticos. Los oráculos pueden también ser bidireccionales y usarse para "enviar" datos al mundo real.
Ver explicación de Patrick sobre los oráculos:
¿Por qué son necesarios?
En una cadena de bloques como Ethereum, es necesario que cada nodo de la red sea capaz de replicar cada transacción y obtener el mismo resultado de manera garantizada. Las API introducen información potencialmente variable. Si le enviara una cierta cantidad de ETH a alguien según un valor de $USD acordado y para ello utilizara una API, la consulta arrojaría un resultado diferente de un día para otro. Esto sin mencionar que la API podría ser hackeada o tornarse obsoleta. Si esto ocurriera, los nodos de la red no podr án lograr un acuerdo sobre el estado actual de Ethereum, lo que llevaría a una ruptura del consenso.
Los oráculos resuelven este problema publicando la información en la cadena de bloques. Así, cualquier nodo que replique la transacción usará los mismos datos inmutables que se publicaron en la red. Para ello, un oráculo típicamente constará de un contrato inteligente y algunos componentes externos a la cadena que consultan diversas API y posteriormente envían transacciones para actualizar los datos de los contratos inteligentes.
El problema de los oráculos
Como hemos mencionado, las transacciones de Ethereum no pueden acceder a información fuera de la cadena directamente. Al mismo tiempo, confiar en una sola fuente de confianza para proporcionar la información es inseguro e invalida la descentralización de un contrato inteligente. Esto es conocido como el problema de los oráculos.
Podemos evitar este problema usando un oráculo descentralizado que extraiga información de diferentes fuentes; si una fuente de información es hackeada o falla, el contrato inteligente continuará funcionando según lo previsto.
Seguridad
Un oráculo es tan seguro como las fuentes de datos que utiliza. Si una dapp usa Uniswap como oráculo para el feed de precio ETH/DAI, un atacante podría modificar dicho precio en Uniswap para manipular la comprensión de precio actual de la dapp. Un ejemplo de cómo combatir esto es un sistema de feed(opens in a new tab) como el utilizado por MakerDAO, el cual coteja precios desde muchos feeds de datos externos en vez de confiar solo en una fuente de datos.
Arquitectura
Este es un ejemplo de una arquitectura simple de un oráculo, pero hay más formas de activar el cálculo fuera de la cadena.
- Emite un registro con su evento de contrato inteligente.
- Un servicio fuera de cadena se suscribió (generalmente usando algo como el comando JSON-RPC
eth_subscribe
) a estos registros específicos. - El servicio fuera de cadena realiza algunas tareas según se define en el registro.
- El servicio fuera de cadena responde con los datos solicitados en una transacción secundaria al contrato inteligente.
Esta es la forma de obtener datos de una manera de 1 a 1. Sin embargo, para mejorar la seguridad, es posible que desee descentralizar la forma en que recopila sus datos fuera de cadena.
El siguiente paso podría ser tener una red de estos nodos haciendo estas llamadas a diferentes API y fuentes, y agregando los datos en cadena.
Off-Chain Reporting de Chainlink(opens in a new tab) (Chainlink OCR) ha mejorado esta metodología haciendo que la red de oráculos fuera de cadena se comunique entre sí. firmen criptográficamente sus respuestas, agreguen sus respuestas fuera de cadena y envíen solo una transacción en cadena con el resultado. De esta manera, se consume menos gas, pero aún obtiene la garantía de datos descentralizados, ya que cada nodo ha firmado su parte de la transacción, lo que hace que el nodo que envía la transacción no pueda modificarla. La política de escalamiento entra en acción si el nodo no realiza transacciones y lo hace el siguiente nodo.
Uso
Usando servicios como Chainlink, puede referenciar datos descentralizados en cadena que se hayan sacado del mundo real y agregado. Algo así como un patrimonio público, pero para datos descentralizados. También puede crear sus propias redes de oráculos modulares para obtener cualquier dato personalizado que esté buscando. Además, puede hacer cómputo fuera de la cadena y enviar información al mundo real también. Chainlink tiene infraestructura para:
- Obtener feeds de precios de criptomonedas en su contrato(opens in a new tab)
- Generar números aleatorios verificables (útiles para gaming)(opens in a new tab)
- Hacer llamadas a API externas(opens in a new tab): un caso de uso novedoso de esto es revisar reservas de wBTC(opens in a new tab)
Este es un ejemplo de cómo obtener el precio más reciente de ETH en su contrato inteligente usando un feed de precios de Chainlink:
Feeds de datos de 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}32Mostrar todoCopiar
Puede probar esto en remix con este enlace(opens in a new tab)
Ver la documentación(opens in a new tab)
Chainlink FAV
Chainlink FAV (del acrónimo en inglés de función aleatoria verificable) es una fuente justa y verificable de aleatoriedad diseñada para contratos inteligentes. Los desarrolladores de contratos inteligentes pueden utilizar Chainlink VRF como un generador de números aleatorios (GNA) a prueba de manipulaciones para crear contratos inteligentes confiables para cualquier aplicación que esté basada en resultados impredecibles:
- NFT y juegos de cadena de bloques
- Asignación aleatoria de tareas y recursos (por ejemplo, asignación aleatoria de jueces a casos)
- Elección de una muestra representativa para mecanismos de consenso
Los números aleatorios son difíciles de lograr porque las cadenas de bloques son deterministas.
El trabajo con oráculos de Chainlink fuera de los feeds de datos sigue el ciclo de solicitud y recepción(opens in a new tab) de trabajar con Chainlink. Utilizan el token LINK para enviar gas de oráculo a los proveedores de oráculos para mostrar respuestas. El token LINK está diseñado específicamente para funcionar con oráculos y se basa en el token ERC-677 actualizado, el cual ofrece compatibilidad con versiones anteriores de ERC-20. El siguiente código, si se implementa en la red de prueba de Kovan, recuperará un número aleatorio comprobado de forma criptográfica. Para hacer la solicitud, financie el contrato con algún token LINK de la red de prueba, que puede obtener del Faucet de LINK de Kovan(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}46Mostrar todo
Chainlink Keepers
Los contratos inteligentes no pueden activar o iniciar sus propias funciones en momentos arbitrarios o bajo condiciones arbitrarias. Los cambios de estado solo pueden ocurrir cuando otra cuenta inicia una transacción (como un usuario, un oráculo o un contrato). La Red Chainlink Keepers(opens in a new tab) proporciona opciones para contratos inteligentes a fin de externalizar tareas de mantenimiento regular de manera minimalizada y descentralizada.
Para usar Ckainlink Keepers, un contrato inteligente debe implementar KeeperCompatibleInterface(opens in a new tab), que consta de dos funciones:
checkUpkeep
: verifica si el contrato requiere trabajo.performUpkeep
: realiza el trabajo en el contrato, si se lo indica checkUpkeep.
El siguiente ejemplo es un contrato de contador simple. La variable counter
se incrementa en uno por cada llamada a performUpkeep
. Puede revisar el siguiente código usando 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. Los datos de verificación se definen cuando se registró el 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. Los datos de rendimiento son generados por la llamada de Keeper a su función checkUpkeep36 }37}38Mostrar todo
Después de implementar un contrato compatible con Keeper, debe registrar el contrato para Upkeep(opens in a new tab) y depositar fondos con LINK para notificar a la Red de Keepers sobre su contrato, de modo que su trabajo se realice continuamente.
Proyectos de Keepers
Llamada a la API de Chainlink
Las llamadas a la API de Chainlink(opens in a new tab) son la forma más fácil de obtener datos del mundo fuera de la cadena en la forma tradicional en que funciona la Web: llamadas a la API. Una sola instancia de esto y teniendo un solo oráculo hacen que el proceso sea centralizado por naturaleza. Para mantener una verdadera descentralización, una plataforma de contratos inteligentes necesitaría usar numerosos nodos encontrados en un mercado externo de datos(opens in a new tab).
Implementar el siguiente código en remix en la red kovan para probar(opens in a new tab)
Esto también sigue el ciclo de solicitud y recepción de los oráculos y necesita que el contrato reciba fondos de Kovan LINK (el gas de los oráculos) para funcionar.
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}65Mostrar todo
Puede obtener más información acerca de las aplicaciones de Chainlink leyendo el blog para desarrolladores de Chainlink(opens in a new tab).
Servicios de oráculos
- 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)
Creación de un contrato inteligente de oráculo
Este es un ejemplo de un contrato inteligente de oráculo diseñado por Pedro Costa. Puede encontrar anotaciones adicionales en su artículo: Implementación de un oráculo de cadena de bloques en Ethereum(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}110Mostrar todoCopiar
Nos encantaría tener más documentación sobre la creación de un contrato inteligente de oráculo. Si puede colaborar, cree una PR.
Para profundizar sobre el tema
Artículos
- ¿Qué es un oráculo de cadena de bloques?(opens in a new tab) - Chainlink
- ¿Qué es un oráculo de cadena de bloques?(opens in a new tab) - Patrick Collins
- Oráculos descentralizados: descripción completa(opens in a new tab) – Julien Thevenard
- Implementación de un oráculo de cadena de bloques en Ethereum(opens in a new tab) – Pedro Costa
- ¿Por qué los contratos inteligentes no pueden hacer llamadas a API?(opens in a new tab) - StackExchange
- ¿Por qué necesitamos oráculos descentralizados(opens in a new tab) - Bankless
- Así que quiere usar un oráculo de precios(opens in a new tab) - samczsun
Videos
- Oráculos y la expansión de la utilidad de la cadena de bloques(opens in a new tab) -Real Vision Finance
Tutoriales