Oracles
Dans ce chapitre, nous discutons des oracles, qui sont des systèmes qui peuvent fournir des sources de données externes aux contrats intelligents Ethereum. Le terme « oracle » vient de la mythologie grecque, où il faisait référence à une personne en communication avec les dieux qui pouvait avoir des visions du futur. Dans le contexte des chaînes de blocs, un oracle est un système qui peut répondre à des questions externes à Ethereum. Idéalement, les oracles sont des systèmes sans confiance, ce qui signifie qu’ils n’ont pas besoin d’être fiables car ils fonctionnent selon des principes décentralisés.
Pourquoi les oracles sont nécessaires
Un composant clé de la plate-forme Ethereum est la machine virtuelle Ethereum, avec sa capacité à exécuter des programmes et à mettre à jour l’état d’Ethereum, contraint par des règles de consensus, sur n’importe quel nœud du réseau décentralisé. Afin de maintenir le consensus, l’exécution d’EVM doit être totalement déterministe et basée uniquement sur le contexte partagé de l’état Ethereum et des transactions signées. Cela a deux conséquences particulièrement importantes : la première est qu’il ne peut y avoir de source intrinsèque d’aléatoire avec laquelle l’EVM et les contrats intelligents peuvent fonctionner ; la seconde est que les données extrinsèques ne peuvent être introduites que comme données utiles d’une transaction.
Déballons ces deux conséquences plus loin. Pour comprendre l’interdiction d’une véritable fonction aléatoire dans l’EVM pour fournir un caractère aléatoire aux contrats intelligents, considérez l’effet sur les tentatives de parvenir à un consensus après l’exécution d’une telle fonction : le nœud A exécuterait la commande et stockerait 3
au nom du contrat intelligent dans son stockage, tandis que le nœud B, exécutant le même contrat intelligent, stockerait 7
à la place. Ainsi, les nœuds A et B arriveraient à des conclusions différentes sur ce que devrait être l’état résultant, bien qu’ils aient exécuté exactement le même code dans le même contexte. En effet, il se pourrait qu’un état résultant différent soit atteint à chaque fois que le contrat intelligent est évalué. En tant que tel, il n’y aurait aucun moyen pour le réseau, avec sa multitude de nœuds fonctionnant indépendamment dans le monde, de parvenir à un consensus décentralisé sur ce que devrait être l’état résultant. En pratique, cela deviendrait bien pire que cet exemple très rapidement, car les effets d’entraînement, y compris les transferts d’ether, s’accumuleraient de façon exponentielle.
Notez que les fonctions pseudo-aléatoires, telles que les fonctions de hachage cryptographiquement sécurisées (qui sont déterministes et peuvent donc faire, et font en effet, partie de l’EVM), ne suffisent pas pour de nombreuses applications. Prenez un jeu de hasard qui simule des lancers de pièces pour résoudre les paiements de pari, qui doivent randomiser pile ou face – un mineur peut obtenir un avantage en jouant au jeu et en n’incluant ses transactions que dans les blocs pour lesquels il gagnera. Alors comment contourner ce problème ? Eh bien, tous les nœuds peuvent s’entendre sur le contenu des transactions signées, de sorte que les informations extrinsèques, y compris les sources aléatoires, les informations sur les prix, les prévisions météorologiques, etc., peuvent être introduites en tant que partie des données des transactions envoyées au réseau. Cependant, ces données ne sont tout simplement pas fiables, car elles proviennent de sources invérifiables. En tant que tel, nous venons de reporter le problème. Nous utilisons des oracles pour tenter de résoudre ces problèmes, dont nous parlerons en détail dans la suite de ce chapitre.
Cas d’utilisation Oracle et exemples
Les oracles, idéalement, fournissent un moyen sans confiance (ou du moins presque sans confiance) d’obtenir des informations extrinsèques (c’est-à-dire "du monde réel" ou hors chaîne), tels que les résultats des matchs de football, le prix de l’or ou des nombres vraiment aléatoires, sur la plate-forme Ethereum pour les contrats intelligents à utiliser. Ils peuvent également être utilisés pour relayer directement les données en toute sécurité vers les interfaces DApp. Les oracles peuvent donc être considérés comme un mécanisme permettant de combler le fossé entre le monde hors chaîne et les contrats intelligents. Permettre aux contrats intelligents d’appliquer des relations contractuelles basées sur des événements et des données du monde réel élargit considérablement leur portée. Cependant, cela peut également introduire des risques externes pour le modèle de sécurité d’Ethereum. Considérez un contrat « testamentaire intelligent » qui distribue les actifs lorsqu’une personne décède. C’est quelque chose de fréquemment discuté dans l’espace des contrats intelligents, et met en évidence les risques d’un oracle de confiance. Si le montant de l’héritage contrôlé par un tel contrat est suffisamment élevé, l’incitation à pirater l’oracle et à déclencher la distribution des actifs avant le décès du propriétaire est très élevée.
Notez que certains oracles fournissent des données propres à une source de données privée spécifique, telles que des certificats universitaires ou des identifiants gouvernementaux. La source de ces données, comme une université ou un département gouvernemental, est entièrement fiable et la vérité des données est subjective (la vérité n’est déterminée qu’en faisant appel à l’autorité de la source). De telles données ne peuvent donc pas être fournies sans confiance, c’est-à-dire sans faire confiance à une source, car il n’y a pas de vérité objective vérifiable de manière indépendante. En tant que tels, nous incluons ces sources de données dans notre définition de ce qui compte comme des "oracles", car elles fournissent également un pont de données pour les contrats intelligents. Les données qu’ils fournissent prennent généralement la forme d’attestations, telles que des passeports ou des certificats de réussite. Les attestations deviendront une grande partie du succès des plates-formes de chaîne de blocs à l’avenir, en particulier en ce qui concerne les problèmes connexes de vérification de l’identité ou de la réputation, il est donc important d’explorer comment elles peuvent être servies par les plates-formes de chaîne de blocs.
Voici d’autres exemples de données pouvant être fournies par les oracles :
-
Nombres aléatoires/entropie provenant de sources physiques telles que les processus quantiques/thermiques : par exemple, pour sélectionner équitablement un gagnant dans un contrat intelligent de loterie
-
Déclencheurs paramétriques indexés sur les aléas naturels : par exemple, déclenchement de contrats intelligents d’obligation catastrophe, tels que les mesures à l’échelle de Richter pour une obligation tremblement de terre
-
Données de taux de change : par exemple, pour un rattachement précis des cryptomonnaies à la monnaie fiduciaire
-
Données sur les marchés des capitaux : par exemple, prix des paniers d’actifs/titres symboliques
-
Données de référence de tests de performance : par exemple, intégration des taux d’intérêt dans les dérivés financiers intelligents
-
Données statiques/pseudostatiques : identifiants de sécurité, codes pays, codes devises, etc.
-
Données de temps et d’intervalle : pour les déclencheurs d’événements fondés sur des mesures de temps précises
-
Données météorologiques : par exemple, calculs de primes d’assurance basés sur les prévisions météorologiques
-
Événements politiques : pour la résolution du marché de prédiction
-
Événements sportifs : pour la résolution du marché de la prédiction et les contrats de sports fantastiques
-
Données de géolocalisation : par exemple, telles qu’elles sont utilisées dans le suivi de la chaîne d’approvisionnement
-
Vérification des dommages : pour les contrats d’assurance
-
Événements survenant sur d’autres chaînes de blocs : fonctions d’interopérabilité
-
Prix du marché de l’ether : par exemple, oracles pour le prix du gaz en fiat
-
Statistiques de vol : par exemple, telles qu’elles sont utilisées par les groupes et les clubs pour la mise en commun des billets d’avion
Dans les sections suivantes, nous examinerons certaines des façons dont les oracles peuvent être implémentés, y compris les modèles d’oracle de base, les oracles de calcul, les oracles décentralisés et les implémentations de client oracle dans Solidity.
Modèles de conception Oracle
Tous les oracles fournissent quelques fonctions clés, par définition. Ceux-ci incluent la capacité de :
-
Recueillir des données à partir d’une source hors chaîne.
-
Transférez les données en chaîne avec un message signé.
-
Rendre les données disponibles en les plaçant dans le stockage d’un contrat intelligent.
Une fois que les données sont disponibles dans le stockage d’un contrat intelligent, elles peuvent être consultées par d’autres contrats intelligents via des appels de message qui invoquent une fonction "retrieve" (récupérer) du contrat intelligent de l’oracle ; il est également accessible directement aux nœuds Ethereum ou aux clients activés par le réseau en "recherchant" le stockage de l’oracle.
Les trois principales façons de configurer un oracle peuvent être classées comme request–response (requête-réponse), publish-subscribe (publication-abonnement) et immediate-read (immédiat-lecture).
En commençant par le plus simple, les oracles à lecture immédiate sont ceux qui fournissent des données qui ne sont nécessaires que pour une décision immédiate, comme "Quelle est l’adresse de ethereumbook.info?" ou "Cette personne a-t-elle plus de 18 ans ?" Ceux qui souhaitent interroger ce type de données ont tendance à le faire sur une base « juste à temps » ; la recherche est effectuée lorsque l’information est nécessaire et peut-être plus jamais après. Des exemples de tels oracles incluent ceux qui contiennent des données sur ou émises par des organisations, telles que des certificats académiques, des codes de numérotation, des adhésions institutionnelles, des identifiants d’aéroport, des identifiants auto-souverains, etc. Ce type d’oracle stocke les données une fois dans son stockage contractuel, d’où tout un autre contrat intelligent peut le rechercher à l’aide d’un appel de demande au contrat oracle. Il peut être mis à jour. Les données dans le stockage de l’oracle sont également disponibles pour une recherche directe par des applications compatibles avec la chaîne de blocs (c’est-à-dire, Ethereum connecté au client) sans avoir à passer par la palabre et à encourir les coûts de gaz liés à l’émission d’une transaction. Un magasin voulant vérifier l’âge d’un client souhaitant acheter de l’alcool pourrait utiliser un oracle de cette manière. Ce type d’oracle est attrayant pour une organisation ou une entreprise qui pourrait autrement avoir à exécuter et à entretenir des serveurs pour répondre à de telles demandes de données. Notez que les données stockées par l’oracle ne sont probablement pas les données brutes que l’oracle sert, par exemple, pour des raisons d’efficacité ou de confidentialité. Une université peut mettre en place un oracle pour les certificats de réussite scolaire des anciens étudiants. Cependant, stocker tous les détails des certificats (qui pourraient s’étendre sur des pages de cours suivis et de notes obtenues) serait excessif. Au lieu de cela, un hachage du certificat est suffisant. De même, un gouvernement pourrait souhaiter mettre les identifiants des citoyens sur la plate-forme Ethereum, où il est clair que les détails inclus doivent rester confidentiels. Encore une fois, hacher les données (plus soigneusement, dans les arbres Merkle avec des sels) et ne stocker que le hachage racine dans le stockage du contrat intelligent serait un moyen efficace d’organiser un tel service.
La configuration suivante est publication-abonnement (publish–subscribe), où un oracle qui fournit effectivement un service de diffusion pour les données qui devraient changer de valeurs (peut-être à la fois régulièrement et fréquemment) est soit interrogé par un contrat intelligent sur la chaîne, soit surveillé par un processus hors chaîne pour les mises à jour. Cette catégorie a un modèle similaire aux flux RSS, WebSub, etc., où l’oracle est mis à jour avec de nouvelles informations et un indicateur signale que de nouvelles données sont disponibles pour ceux qui se considèrent comme "abonnés". Les parties intéressées doivent soit interroger l’oracle pour vérifier si les dernières informations ont changé, soit écouter les mises à jour des contrats oracle et agir lorsqu’elles se produisent. Les exemples incluent les flux de prix, les informations météorologiques, les statistiques économiques ou sociales, les données de trafic, etc. Le sondage est très inefficace dans le monde des serveurs Web, mais pas dans le contexte pair à pair des plateformes en chaîne de blocs : les clients Ethereum doivent suivre avec tous les changements d’état, y compris les changements de stockage de contrat, de sorte que l’interrogation des changements de données est un appel local à un client synchronisé. Les journaux d’événements Ethereum permettent aux applications de rechercher particulièrement, et ce facilement, les mises à jour d’un oracle, et donc ce modèle peut même être considéré à certains égards comme un service "push" (d’envoi). Cependant, si l’interrogation est effectuée à partir d’un contrat intelligent, ce qui peut être nécessaire pour certaines applications décentralisées (par exemple, lorsque les incitations à l’activation ne sont pas possibles), des dépenses importantes en gaz peuvent être engagées.
La catégorie request–response (requête-réponse) est la plus compliquée : c’est lorsque la quantité de données est trop grande pour être stocké dans un contrat intelligent et les utilisateurs ne devraient avoir besoin que d’une petite partie de l’ensemble de données globale à la fois. C’est également un modèle applicable pour les entreprises de fournisseurs de données. Concrètement, un tel oracle pourrait être mis en œuvre comme un système de contrats intelligents en chaîne et une infrastructure hors chaîne utilisée pour surveiller les demandes et récupérer et renvoyer des données. Une demande de données à partir d’une application décentralisée serait généralement un processus asynchrone impliquant un certain nombre d’étapes. Dans ce modèle, premièrement, un EOA traite avec une application décentralisée, ce qui entraîne une interaction avec une fonction définie dans le contrat intelligent de l’oracle. Cette fonction initie la demande à l’oracle, avec les arguments associés détaillant les données demandées en plus d’informations supplémentaires pouvant inclure des fonctions de rappel et des paramètres de planification. Une fois cette transaction validée, la requête oracle peut être observée comme un événement EVM émis par le contrat oracle, ou comme un changement d’état ; les arguments peuvent être récupérés et utilisés pour effectuer la requête réelle de la source de données hors chaîne. L’oracle peut également exiger un paiement pour le traitement de la demande, c’est à dire le paiement du gaz pour le rappel et les autorisations d’accès aux données demandées. Enfin, les données résultantes sont signées par le propriétaire de l’oracle, attestant de la validité des données à un moment donné, et livrées dans une transaction à l’application décentralisée qui a fait la demande, soit directement, soit via le contrat de l’oracle. En fonction des paramètres de planification, l’oracle peut diffuser d’autres transactions mettant à jour les données à intervalles régulières (par exemple, des informations de tarification en fin de journée).
Les étapes d’un oracle de requête-réponse peuvent être résumées comme suit :
-
Recevez une requête d’un DApp.
-
Analysez la requête.
-
Vérifiez que les autorisations de paiement et d’accès aux données sont fournies.
-
Récupérez les données pertinentes d’une source hors chaîne (et cryptez-les si nécessaire).
-
Signez la ou les transactions avec les données incluses.
-
Diffusez la ou les transactions sur le réseau.
-
Planifiez toutes les autres transactions nécessaires, telles que les notifications, etc.
Une gamme d’autres régimes sont également possibles; par exemple, les données peuvent être demandées et renvoyées directement par un EOA, supprimant ainsi le besoin d’un contrat intelligent d’oracle. De même, la demande et la réponse pourraient être faites vers et depuis un capteur matériel compatible avec l’Internet des objets. Par conséquent, les oracles peuvent être humains, logiciels ou matériels.
Le modèle requête-réponse décrit ici est couramment observé dans les architectures client-serveur. Bien qu’il s’agisse d’un modèle de messagerie utile qui permet aux applications d’avoir une conversation bidirectionnelle, il est peut-être inapproprié dans certaines conditions. Par exemple, une obligation intelligente nécessitant un taux d’intérêt auprès d’un oracle pourrait devoir demander les données quotidiennement selon un modèle demande-réponse afin de s’assurer que le taux est toujours correct. Étant donné que les taux d’intérêt changent rarement, un modèle de publication-abonnement peut être plus approprié ici, en particulier si l’on tient compte de la bande passante limitée d’Ethereum.
La publication-abonnement est un modèle dans lequel les éditeurs (dans ce contexte, les oracles) n’envoient pas de messages directement aux destinataires, mais classent plutôt les messages publiés dans des classes distinctes. Les abonnés peuvent exprimer leur intérêt pour une ou plusieurs classes et récupérer uniquement les messages qui les intéressent. Dans un tel modèle, un oracle pourrait écrire le taux d’intérêt dans sa propre mémoire interne à chaque fois qu’il change. Plusieurs DApps abonnés peuvent simplement le lire à partir du contrat oracle, réduisant ainsi l’impact sur la bande passante du réseau tout en minimisant les coûts de stockage.
Dans un modèle de diffusion ou de multidiffusion, un oracle publierait tous les messages sur un canal et les contrats d’abonnement écouteraient le canal sous une variété de modes d’abonnement. Par exemple, un oracle peut publier des messages sur un canal de taux de change de cryptomonnaie. Un contrat intelligent d’abonnement pourrait demander le contenu complet de la chaîne s’il avait besoin de la série chronologique pour, par exemple, un calcul de moyenne mobile ; un autre peut n’exiger que le dernier taux pour un calcul du prix au comptant. Un modèle de diffusion est approprié lorsque l’oracle n’a pas besoin de connaître l’identité du contrat d’abonnement.
Authentification des données
Si nous supposons que la source de les données interrogées par une DApp font à la fois autorité et sont dignes de confiance (une hypothèse non négligeable), une question reste en suspens : étant donné que l’oracle et le mécanisme de requête-réponse peuvent être exploités par des entités distinctes, comment pouvons-nous faire confiance à ce mécanisme ? Il existe une réelle possibilité que les données soient altérées en transit, il est donc essentiel que les méthodes hors chaîne soient en mesure d’attester de l’intégrité des données renvoyées. Deux approches courantes de l’authentification des données sont les preuves d’authenticité et les environnements d’exécution de confiance (TEE).
Les preuves d’authenticité sont des garanties cryptographiques que les données n’ont pas été falsifiées. Basées sur une variété de techniques d’attestation (par exemple, des preuves signées numériquement), elles transfèrent efficacement la confiance du support de données vers l’attestateur (c’est-à-dire le fournisseur de l’attestation). En vérifiant la preuve d’authenticité en chaîne, les contrats intelligents sont en mesure de vérifier l’intégrité des données avant de les exploiter. Oraclize est un exemple de service oracle exploitant une variété de preuves d’authenticité. Une de ces preuves qui est actuellement disponible pour les requêtes de données à partir du réseau principal Ethereum est la preuve TLSNotary. Les preuves TLSNotary permettent à un client de fournir la preuve à un tiers que le trafic Web HTTPS s’est produit entre le client et un serveur. Bien que HTTPS soit lui-même sécurisé, il ne prend pas en charge la signature des données. Par conséquent, les preuves TLSNotary reposent sur les signatures TLSNotary (via PageSigner). Les preuves TLSNotary s’appuient sur le protocole Transport Layer Security (TLS), permettant à la clé principale TLS, qui signe les données après leur accès, d’être répartie entre trois parties : le serveur (l’oracle), un audité (Oraclize) et un Auditeur. Oraclize utilise une instance de machine virtuelle Amazon Web Services (AWS) comme auditeur, qui peut être vérifiée comme n’ayant pas été modifiée depuis l’instanciation. Cette instance AWS stocke le secret TLSNotary, lui permettant de fournir des preuves d’honnêteté. Bien qu’elle offre des garanties plus élevées contre la falsification des données qu’un simple mécanisme de requête-réponse, cette approche nécessite l’hypothèse qu’Amazon lui-même ne falsifiera pas l’instance de VM.
Town Crier est un système oracle de flux de données authentifié basé sur l’approche TEE ; ces méthodes utilisent des enclaves sécurisées basées sur le matériel pour garantir l’intégrité des données. Town Crier utilise Intel Software Guard eXtensions (SGX) pour s’assurer que les réponses des requêtes HTTPS peuvent être vérifiées comme authentiques . SGX offre des garanties d’intégrité, garantissant que les applications s’exécutant dans une enclave sont protégées par le CPU contre toute altération par tout autre processus. Il assure également la confidentialité, garantissant que l’état d’une application est opaque pour les autres processus lors de son exécution dans l’enclave. Et enfin, SGX permet l’attestation, en générant une preuve signée numériquement qu’une application, identifiée de manière sécurisée par un hachage de sa version, s’exécute réellement dans une enclave. En vérifiant cette signature numérique, il est possible pour une application décentralisée de prouver qu’une instance Town Crier fonctionne en toute sécurité dans une enclave SGX. Ceci, à son tour, prouve que l’instance n’a pas été falsifiée et que les données émises par Town Crier sont donc authentiques. La propriété de confidentialité permet en outre à Town Crier de gérer des données privées en autorisant le chiffrement des requêtes de données à l’aide de la clé publique de l’instance Town Crier. L’utilisation du mécanisme de requête-réponse d’un oracle dans une enclave telle que SGX nous permet de penser qu’il s’exécute en toute sécurité sur du matériel tiers de confiance, garantissant que les données demandées sont renvoyées sans altération (en supposant que nous faisons confiance à Intel/SGX).
Oracles de calcul
Jusqu’à présent, nous n’avons discuté des oracles que dans le contexte de la demande et de la livraison de données. Cependant, les oracles peuvent également être utilisés pour effectuer des calculs arbitraires, une fonction qui peut être particulièrement utile compte tenu de la limite de gaz de bloc inhérente à Ethereum et des coûts de calcul relativement élevés. Plutôt que de simplement relayer les résultats d’une requête, les oracles de calcul peuvent être utilisés pour effectuer des calculs sur un ensemble d’entrées et renvoyer un résultat calculé qu’il aurait peut-être été impossible de calculer en chaîne. Par exemple, on peut utiliser un oracle pour effectuer un calcul de régression intensif afin d’estimer le rendement d’un contrat obligataire.
Si vous êtes prêt à faire confiance à un service centralisé mais auditable, vous pouvez revenir à Oraclize. Ils fournissent un service qui permet aux applications décentralisées de demander la sortie d’un calcul effectué dans une machine virtuelle AWS en bac à sable. L’instance AWS crée un conteneur exécutable à partir d’un fichier Dockerfile configuré par l’utilisateur, compressé dans une archive qui est téléchargée sur le système de fichiers décentralisé (IPFS ; voir [data_storage_sec]). Sur demande, Oraclize récupère cette archive à l’aide de son hachage, puis initialise et exécute le conteneur Docker sur AWS, en transmettant tous les arguments fournis à l’application en tant que variables d’environnement. L’application conteneurisée effectue le calcul, soumis à une contrainte de temps, et écrit le résultat sur la sortie standard, où il peut être récupéré par Oraclize et renvoyé à l’application décentralisée. Oraclize propose actuellement ce service sur une instance AWS t2.micro auditable, donc si le calcul a une valeur non triviale, il est possible de vérifier que le bon conteneur Docker a été exécuté. Néanmoins, ce n’est pas une solution véritablement décentralisée.
Le concept de "cryptlet" en tant que norme pour les vérités d’oracle vérifiables a été formalisé dans le cadre plus large de l’ESC Framework de Microsoft. Les cryptlets s’exécutent dans une capsule chiffrée qui fait abstraction de l’infrastructure, telle que les Entrées/Sorties, et auquel le CryptoDelegate est attaché afin que les messages entrants et sortants soient signés, validés et prouvés automatiquement. Les cryptlets prennent en charge les transactions distribuées afin que la logique de contrat puisse prendre en charge des transactions complexes à plusieurs étapes, à plusieurs chaînes de blocs et de systèmes externes de manière ACID. Cela permet aux développeurs de créer des résolutions portables, isolées et privées de la vérité à utiliser dans les contrats intelligents. Les cryptlets suivent le format indiqué ici :
public class SampleContractCryptlet : Cryptlet
{
public SampleContractCryptlet(Guid id, Guid bindingId, string name,
string address, IContainerServices hostContainer, bool contract)
: base(id, bindingId, name, address, hostContainer, contract)
{
MessageApi = new CryptletMessageApi(GetType().FullName,
new SampleContractConstructor())
Pour une solution plus décentralisée, nous pouvons nous tourner vers TrueBit, qui offre une solution de calcul hors chaîne évolutive et vérifiable. Ils utilisent un système de solveurs et de vérificateurs qui sont incités à effectuer des calculs et à vérifier ces calculs, respectivement. Si une solution est contestée, un processus de vérification itératif sur des sous-ensembles du calcul est effectué en chaîne, une sorte de « jeu de vérification ». Le jeu se déroule à travers une série de tours, chacun vérifiant de manière récursive un sous-ensemble de plus en plus petit du calcul. Le jeu atteint finalement un tour final, où le défi est suffisamment trivial pour que les juges - les mineurs d’Ethereum - puissent rendre une décision finale sur la question de savoir si le défi a été relevé, en chaîne. En effet, TrueBit est une implémentation d’un marché de calcul, permettant aux applications décentralisées de payer pour un calcul vérifiable à effectuer en dehors du réseau, mais s’appuyant sur Ethereum pour faire respecter les règles du jeu de vérification. En théorie, cela permet aux contrats intelligents sans confiance d’effectuer en toute sécurité n’importe quelle tâche de calcul.
Un large éventail d’applications existe pour des systèmes comme TrueBit, allant de l’apprentissage automatique à la vérification de la preuve de travail. Un exemple de ce dernier est le pont Doge-Ethereum, qui utilise TrueBit pour vérifier la preuve de travail de Dogecoin (Scrypt), qui est une fonction gourmande en mémoire et en calcul qui ne peut pas être calculée dans la limite de gaz du bloc Ethereum. En effectuant cette vérification sur TrueBit, il a été possible de vérifier en toute sécurité les transactions Dogecoin dans un contrat intelligent sur le testnet Rinkeby d’Ethereum.
Oracles décentralisés
Alors que les données centralisées ou les oracles de calcul suffisent pour de nombreuses applications, ils représentent des points de défaillance uniques dans le réseau Ethereum. Un certain nombre de schémas ont été proposés autour de l’idée d’oracles décentralisés comme moyen d’assurer la disponibilité des données et la création d’un réseau de fournisseurs de données individuels avec un système d’agrégation de données en chaîne.
ChainLink a proposé un réseau oracle décentralisé composé de trois contrats intelligents clés : un contrat de réputation, un contrat de correspondance des commandes et un contrat d’agrégation — et un registre hors chaîne des fournisseurs de données. Le contrat de réputation est utilisé pour suivre les performances des fournisseurs de données. Les scores du contrat de réputation sont utilisés pour remplir le registre hors chaîne. Le contrat d’appariement des commandes sélectionne les offres des oracles à l’aide du contrat de réputation. Il finalise ensuite un accord de niveau de service, qui inclut les paramètres de requête et le nombre d’oracles requis. Cela signifie que l’acheteur n’a pas besoin de traiter directement avec les oracles individuels. Le contrat d’agrégation collecte les réponses (soumises à l’aide d’un schéma de validation-révélation) de plusieurs oracles, calcule le résultat collectif final de la requête et réinjecte finalement les résultats dans le contrat de réputation.
L’un des principaux défis d’une telle approche décentralisée est la formulation de la fonction d’agrégation. ChainLink propose de calculer une réponse pondérée, permettant de rapporter un score de validité pour chaque réponse oracle. La détection d’un score «invalide» ici n’est pas triviale, car elle repose sur la prémisse que les points de données aberrants, mesurés par les écarts par rapport aux réponses fournies par les pairs, sont incorrects. Le calcul d’un score de validité basé sur l’emplacement d’une réponse oracle parmi une distribution de réponses risque de pénaliser les réponses correctes par rapport aux réponses moyennes. Par conséquent, ChainLink propose un ensemble standard de contrats d’agrégation, mais permet également de spécifier des contrats d’agrégation personnalisés.
Une idée connexe est le protocole SchellingCoin. Ici, plusieurs participants rapportent des valeurs et la médiane est considérée comme la « bonne » réponse. Les déclarants sont tenus de fournir un acompte qui est redistribué en faveur de valeurs plus proches de la médiane, incitant ainsi à déclarer des valeurs similaires aux autres. Une valeur commune, également connue sous le nom de point de Schelling, que les répondants pourraient considérer comme la cible naturelle et évidente autour de laquelle se coordonner devrait être proche de la valeur réelle.
Jason Teutsch de TrueBit a récemment proposé une nouvelle conception pour un oracle décentralisé de disponibilité des données hors chaîne. Cette conception s’appuie sur une chaîne de blocs de preuve de travail dédiée qui est capable de signaler correctement si les données enregistrées sont disponibles ou non à une époque donnée. Les mineurs tentent de télécharger, stocker et propager toutes les données actuellement enregistrées, garantissant ainsi que les données sont disponibles localement. Bien qu’un tel système soit coûteux dans le sens où chaque nœud de minage stocke et propage toutes les données enregistrées, le système permet de réutiliser le stockage en libérant les données après la fin de la période d’enregistrement.
Interfaces clients Oracle en Solidity
Utilisation d’Oraclize pour mettre à jour le taux de change ETH/USD à partir d’une source externe est un exemple Solidity démontrant comment Oraclize peut être utilisé pour interroger en continu le prix ETH/USD à partir d’une API et stocker le résultat de manière utilisable.
/*
Défileur de prix ETH/USD tirant parti de l'API CryptoCompare
Ce contrat garde en mémoire un prix ETH/USD mis à jour,
qui est mis à jour toutes les 10 minutes.
*/
pragma solidity ^0.4.1;
import "github.com/oraclize/ethereum-api/oraclizeAPI.sol";
/*
"oraclize_" prepended methods indicate inheritance from "usingOraclize"
*/
contract EthUsdPriceTicker is usingOraclize {
uint public ethUsd;
event newOraclizeQuery(string description);
event newCallbackResult(string result);
function EthUsdPriceTicker() payable {
// signale la génération et le stockage de la preuve TLSN sur IPFS
oraclize_setProof(proofType_TLSNotary | proofStorage_IPFS);
// demande de requête
queryTicker();
}
function __callback(bytes32 _queryId, string _result, bytes _proof) public {
if (msg.sender != oraclize_cbAddress()) throw;
newCallbackResult(_result);
/*
* Analyse la chaîne de résultat en un entier non signé pour une utilisation en chaîne.
* Utilise l'assistant "parseInt" hérité de "usingOraclize", permettant
* un résultat de chaîne tel que "123.45" à convertir en uint 12345.
*/
ethUsd = parseInt(_result, 2);
// appelé depuis le rappel puisque nous interrogeons le prix
queryTicker();
}
function queryTicker() external payable {
if (oraclize_getPrice("URL") > this.balance) {
newOraclizeQuery("Oraclize query was NOT sent, please add some ETH
to cover for the query fee");
} else {
newOraclizeQuery("Oraclize query was sent, standing by for the
answer...");
// les paramètres de la requête sont (délai en secondes, type de source de données,
// argument de source de données)
// spécifie JSONPath, pour récupérer une partie spécifique du résultat de l'API JSON
oraclize_query(60 * 10, "URL",
"json(https://min-api.cryptocompare.com/data/price?\
fsym=ETH&tsyms=USD,EUR,GBP).USD");
}
}
}
Pour s’intégrer à Oraclize, le contrat EthUsdPriceTicker doit être un enfant de usingOraclize
; le contrat usingOraclize est défini dans le fichier oraclizeAPI. La demande de données est effectuée à l’aide de la fonction oraclize_query
, qui est héritée du contrat usingOraclize
. Il s’agit d’une fonction surchargée qui attend au moins deux arguments :
-
La source de données prise en charge à utiliser, telle que URL, WolframAlpha, IPFS ou calculation
-
L’argument de la source de données donnée, qui peut inclure l’utilisation d’assistants d’analyse JSON ou XML
La requête de prix est effectuée dans la fonction queryTicker
. Afin d’effectuer la requête, Oraclize exige le paiement d’une somme modique en ether, couvrant le coût du gaz pour traiter le résultat et le transmettre à la fonction __callback et un supplément d’accompagnement pour le service. Ce montant dépend de la source de données et, le cas échéant, du type de preuve d’authenticité requis. Une fois les données récupérées, la fonction __callback est appelée par un compte contrôlé par Oraclize autorisé à effectuer le rappel ; il transmet la valeur de réponse et un argument queryId unique, qui, par exemple, peut être utilisé pour gérer et suivre plusieurs rappels en attente d’Oraclize.
Le fournisseur de données financières Thomson Reuters fournit également un service oracle pour Ethereum, appelé BlockOne IQ, permettant de demander des données de marché et de référence par des contrats intelligents exécutés sur des réseaux privés ou autorisés. Contrat faisant appel au service BlockOne IQ pour les données de marché montre l’interface pour l’oracle, et un contrat client qui fera la demande.
pragma solidity ^0.4.11;
contract Oracle {
uint256 public divisor;
function initRequest(
uint256 queryType, function(uint256) external onSuccess,
function(uint256
) external onFailure) public returns (uint256 id);
function addArgumentToRequestUint(uint256 id, bytes32 name, uint256 arg) public;
function addArgumentToRequestString(uint256 id, bytes32 name, bytes32 arg)
public;
function executeRequest(uint256 id) public;
function getResponseUint(uint256 id, bytes32 name) public constant
returns(uint256);
function getResponseString(uint256 id, bytes32 name) public constant
returns(bytes32);
function getResponseError(uint256 id) public constant returns(bytes32);
function deleteResponse(uint256 id) public constant;
}
contract OracleB1IQClient {
Oracle private oracle;
event LogError(bytes32 description);
function OracleB1IQClient(address addr) external payable {
oracle = Oracle(addr);
getIntraday("IBM", now);
}
function getIntraday(bytes32 ric, uint256 timestamp) public {
uint256 id = oracle.initRequest(0, this.handleSuccess, this.handleFailure);
oracle.addArgumentToRequestString(id, "symbol", ric);
oracle.addArgumentToRequestUint(id, "timestamp", timestamp);
oracle.executeRequest(id);
}
function handleSuccess(uint256 id) public {
assert(msg.sender == address(oracle));
bytes32 ric = oracle.getResponseString(id, "symbol");
uint256 open = oracle.getResponseUint(id, "open");
uint256 high = oracle.getResponseUint(id, "high");
uint256 low = oracle.getResponseUint(id, "low");
uint256 close = oracle.getResponseUint(id, "close");
uint256 bid = oracle.getResponseUint(id, "bid");
uint256 ask = oracle.getResponseUint(id, "ask");
uint256 timestamp = oracle.getResponseUint(id, "timestamp");
oracle.deleteResponse(id);
// Faire quelque chose avec les données de prix
}
function handleFailure(uint256 id) public {
assert(msg.sender == address(oracle));
bytes32 error = oracle.getResponseError(id);
oracle.deleteResponse(id);
emit LogError(error);
}
}
La demande de données est initiée à l’aide de la fonction initRequest
, qui permet de spécifier le type de requête (dans cet exemple, une demande de prix infrajournalier), en plus de deux fonctions de rappel.
Cela renvoie un identifiant uint256 qui peut ensuite être utilisé pour fournir des arguments supplémentaires. La fonction addArgumentToRequestString permet de spécifier le Reuters Instrument Code (RIC), ici pour le stock IBM, et addArgumentToRequestUint
permet de spécifier l’horodatage. Maintenant, passer un alias pour block.timestamp récupérera le prix actuel pour IBM. La requête est alors exécutée par la fonction executeRequest
. Une fois la requête traitée, le contrat oracle appellera la fonction callback onSuccess avec l’identifiant de la requête, permettant de récupérer les données résultantes ; en cas d’échec de la récupération, le rappel onFailure
renverra un code d’erreur à la place. Les champs disponibles qui peuvent être récupérés en cas de succès incluent les prix open
, high, low
, close (OHLC) et bid/ask.
Conclusion
Comme vous pouvez le constater, les oracles fournissent un service crucial aux contrats intelligents : ils apportent des faits externes à l’exécution du contrat. Avec cela, bien sûr, les oracles présentent également un risque important - s’ils sont des sources fiables et peuvent être compromis, ils peuvent entraîner une exécution compromise des contrats intelligents qu’ils alimentent.
Généralement, lorsque vous envisagez l’utilisation d’un oracle, faites très attention au modèle de confiance. Si vous supposez que l’oracle est digne de confiance, vous risquez de compromettre la sécurité de votre contrat intelligent en l’exposant à des entrées potentiellement fausses. Cela dit, les oracles peuvent être très utiles si les hypothèses de sécurité sont soigneusement prises en compte.
Les oracles décentralisés peuvent résoudre certains de ces problèmes et proposer des contrats intelligents Ethereum sans confiance en données externes. Choisissez avec soin et vous pourrez commencer à explorer le pont entre Ethereum et le "monde réel" qu’offrent les oracles.