Оракулы

В этой главе мы обсудим оракулы - системы, которые могут предоставлять внешние источники данных для смарт-контрактов Ethereum. Термин "оракул" пришел из греческой мифологии, где он обозначал человека, общающегося с богами, который мог видеть видения будущего. В контексте блокчейн оракул - это система, которая может отвечать на вопросы, внешние по отношению к Ethereum. В идеале оракулы - это системы без доверия, то есть им не нужно доверять, поскольку они работают на децентрализованных принципах.

Зачем нужны оракулы

Ключевым компонентом платформы Ethereum является виртуальная машина Ethereum Virtual Machine, способная выполнять программы и обновлять состояние Ethereum, ограниченное правилами консенсуса, на любом узле децентрализованной сети. Для поддержания консенсуса выполнение EVM должно быть полностью детерминированным и основываться только на общем контексте состояния Ethereum и подписанных транзакций. Это имеет два особенно важных последствия: во-первых, для EVM и смарт-контрактов не может быть никакого внутреннего источника случайности; во-вторых, внешние данные могут быть введены только в качестве полезной нагрузки транзакции.

Давайте подробнее рассмотрим эти два последствия. Чтобы понять запрет на использование истинно случайной функции в EVM для обеспечения случайности смарт-контрактов, рассмотрим эффект на попытки достижения консенсуса после выполнения такой функции: узел A выполнит команду и сохранит в своем хранилище 3 от имени смарт-контракта, а узел B, выполняющий тот же смарт-контракт, вместо этого сохранит 7. Таким образом, узлы A и B придут к разным выводам о том, каким должно быть результирующее состояние, несмотря на выполнение абсолютно одинакового кода в одном и том же контексте. Действительно, может случиться так, что каждый раз при оценке смарт-контракта будет достигаться разное результирующее состояние. Таким образом, сеть с ее множеством узлов, работающих независимо по всему миру, никак не сможет прийти к децентрализованному консенсусу относительно того, каким должно быть результирующее состояние. На практике ситуация очень быстро станет намного хуже, чем в данном примере, поскольку побочные эффекты, включая переводы эфира, будут нарастать экспоненциально.

Обратите внимание, что псевдослучайных функций, таких как криптографически защищенные хэш-функции (которые являются детерминированными и поэтому могут быть и даже являются частью EVM), недостаточно для многих приложений. Возьмем, к примеру, азартную игру, имитирующую подбрасывание монет для определения выплат по ставкам, в которой необходимо случайное определение голов или решек - майнер может получить преимущество, играя в эту игру и включая свои транзакции только в те блоки, в которых он выиграет. Как обойти эту проблему? Поскольку все узлы могут договориться о содержании подписанных транзакций, посторонняя информация, включая источники случайности, информацию о ценах, прогнозы погоды и т.д., может быть представлена в качестве части данных транзакций, отправляемых в сеть. Однако таким данным просто нельзя доверять, поскольку они поступают из непроверяемых источников. Таким образом, мы просто отложили решение этой проблемы. Для решения этих проблем мы используем оракулы, которые мы подробно обсудим в оставшейся части этой главы.

Примеры и примеры использования Oracle

Оракулы, в идеале, обеспечивают беспричинный (или, по крайней мере, почти беспричинный) способ получения внешней (то есть "реальной" или внецепочечной) информации, такой как результаты футбольных матчей, цена золота или действительно случайные числа, на платформу Ethereum для использования смарт-контрактами. Они также могут использоваться для безопасной передачи данных непосредственно фронтендам DApp. Поэтому оракулы можно рассматривать как механизм для преодоления разрыва между внецепочечным миром и смарт-контрактами. Позволяя смарт-контрактам обеспечивать соблюдение договорных отношений на основе событий и данных реального мира, они значительно расширяют сферу применения. Однако это также может привнести внешние риски в модель безопасности Ethereum. Рассмотрим контракт "умного завещания", который распределяет активы после смерти человека. Этот вопрос часто обсуждается в сфере смарт-контрактов и подчеркивает риски, связанные с доверенным оракулом. Если сумма наследства, контролируемая таким контрактом, достаточно велика, то стимул взломать оракул и инициировать распределение активов до смерти владельца очень высок.

Обратите внимание, что некоторые оракулы предоставляют данные, которые относятся к определенному частному источнику данных, например, академические сертификаты или государственные удостоверения личности. Источник таких данных, например, университет или правительственный департамент, пользуется полным доверием, а истинность данных субъективна (истина определяется только путем обращения к авторитету источника). Поэтому такие данные нельзя предоставлять без доверия - то есть без доверия к источнику, так как не существует объективной истины, которую можно проверить независимо. Таким образом, мы включаем эти источники данных в наше определение того, что считается "оракулами", поскольку они также обеспечивают мост данных для смарт-контрактов. Данные, которые они предоставляют, обычно принимают форму аттестатов, таких как паспорта или записи о достижениях. Аттестаты станут важной составляющей успеха блокчейн-платформ в будущем, особенно в связи с сопутствующими вопросами проверки личности или репутации, поэтому важно изучить, как они могут быть использованы блокчейн-платформами. Некоторые другие примеры данных, которые могут быть предоставлены оракулами, включают:

  • Случайные числа/энтропия из физических источников, таких как квантовые/тепловые процессы: например, для справедливого выбора победителя в лотерее смарт-контракта
  • Параметрические триггеры, индексированные на стихийные бедствия: например, триггеры смарт-контрактов по облигациям на случай катастроф, такие как измерения по шкале Рихтера для облигаций на случай землетрясения
  • Данные об обменных курсах: например, для точной привязки криптовалют к фиатной валюте
  • Данные рынков капитала: например, ценовые корзины токенизированных активов/ценных бумаг
  • Эталонные справочные данные: например, включение процентных ставок в интеллектуальные финансовые деривативы
  • Статические/псевдостатические данные: идентификаторы безопасности, коды стран, коды валют и т.д.
  • Временные и интервальные данные: для триггеров событий, основанных на точных измерениях времени
  • Погодные данные: например, расчеты страховых премий на основе прогнозов погоды
  • Политические события: для разрешения рынка предсказаний
  • Спортивные события: для разрешения рынка прогнозов и контрактов на фэнтези-спорт
  • Геолокационные данные: например, используемые для отслеживания цепочки поставок
  • Проверка ущерба: для договоров страхования
  • События, происходящие на других блокчейнах: функции совместимости
  • Рыночная цена эфира: например, для оракулов цены фиатного газа
  • Статистика полетов: например, используется группами и клубами для объединения билетов на рейсы

В следующих разделах мы рассмотрим некоторые способы реализации оракулов, включая основные шаблоны оракулов, вычислительные оракулы, децентрализованные оракулы и реализацию клиента оракула в Solidity.

Паттерны проектирования Oracle

Все оракулы по определению обеспечивают несколько ключевых функций. К ним относятся:

  • Сбор данных из источника вне цепи.
  • Передача данных по цепочке с помощью подписанного сообщения.
  • Сделайте данные доступными, поместив их в хранилище смарт-контракта.

Как только данные оказываются в хранилище смарт-контракта, доступ к ним могут получить другие смарт-контракты через вызовы сообщений, которые вызывают функцию "извлечь" смарт-контракта оракула; доступ к ним также могут получить узлы Ethereum или клиенты с поддержкой сети напрямую, "заглянув" в хранилище оракула.

Три основных способа создания оракула можно разделить на три категории: запрос-ответ, публикация-подписка и немедленное чтение.

Начиная с самых простых, оракулы немедленного чтения - это те, которые предоставляют данные, необходимые только для принятия немедленного решения, например, "Какой адрес у сайта ethereumbook.info?" или "Этому человеку больше 18 лет?". Желающие запросить такие данные, как правило, делают это на основе принципа "только во время"; поиск выполняется, когда информация нужна, и, возможно, больше никогда. Примерами таких оракулов являются оракулы, хранящие данные об организациях или выданные ими, такие как академические сертификаты, телефонные коды, членство в институтах, идентификаторы аэропортов, удостоверения личности суверена и т.п. Этот тип оракула хранит данные один раз в своем хранилище контрактов, после чего любой другой смарт-контракт может найти их, используя вызов запроса к контракту оракула. Он может быть обновлен. Данные в хранилище оракула также доступны для прямого поиска приложениями, поддерживающими блокчейн (то есть подключенными к клиенту Ethereum), без необходимости проходить через всю процедуру и нести газовые издержки, связанные с проведением транзакции. Магазин, желающий проверить возраст клиента, желающего приобрести алкоголь, может использовать оракул таким образом. Этот тип оракула привлекателен для организации или компании, которым в противном случае пришлось бы запускать и обслуживать серверы для ответа на такие запросы данных. Обратите внимание, что данные, хранящиеся в оракуле, скорее всего, не будут исходными данными, которые оракул обслуживает, например, по соображениям эффективности или конфиденциальности. Университет может создать оракул для хранения свидетельств об успеваемости студентов прошлых лет. Однако хранение полной информации о сертификатах (которая может состоять из страниц с указанием пройденных курсов и полученных оценок) было бы чрезмерным. Вместо этого достаточно хэша сертификата. Аналогичным образом, правительство может захотеть разместить идентификаторы граждан на платформе Ethereum, где, очевидно, необходимо сохранить конфиденциальность включенных в них данных. Опять же, хэширование данных (более тщательно, в деревьях Меркла с солями) и хранение только корневого хэша в хранилище смарт-контракта было бы эффективным способом организации такой услуги.

Следующая схема - публикация-подписка, когда оракул, эффективно предоставляющий широковещательный сервис для данных, которые, как ожидается, будут меняться (возможно, регулярно и часто), либо опрашивается смарт-контрактом на цепочке, либо отслеживается демоном вне цепочки на предмет обновлений. Эта категория имеет схему, подобную RSS-каналам, WebSub и т.п., где оракул обновляется новой информацией, а флаг сигнализирует, что новые данные доступны тем, кто считает себя "подписанным". Заинтересованные стороны должны либо опрашивать оракул, чтобы проверить, изменилась ли последняя информация, либо слушать обновления контрактов оракула и действовать, когда они происходят. В качестве примера можно привести информацию о ценах, погоде, экономическую или социальную статистику, данные о дорожном движении и т.д. Опрос очень неэффективен в мире веб-серверов, но не так в одноранговом контексте блокчейн-платформ: Клиенты Ethereum должны следить за всеми изменениями состояния, включая изменения в хранилище контрактов, поэтому опрос об изменении данных - это локальный вызов синхронизированного клиента. Журналы событий Ethereum позволяют приложениям особенно легко следить за обновлениями оракула, поэтому данный паттерн в некотором смысле можно даже считать "push" сервисом. Однако если опрос выполняется из смарт-контракта, что может потребоваться для некоторых децентрализованных приложений (например, где невозможна активация стимулов), то могут возникнуть значительные затраты газа.

Категория "запрос-ответ" является наиболее сложной: в этом случае объем данных слишком велик для хранения в смарт-контракте, и предполагается, что пользователям одновременно нужна лишь небольшая часть общего набора данных. Эта модель также применима для предприятий, предоставляющих данные. На практике такой оракул может быть реализован как система смарт-контрактов на цепочке и внецепочечной инфраструктуры, используемой для отслеживания запросов, получения и возврата данных. Запрос данных из децентрализованного приложения обычно представляет собой асинхронный процесс, состоящий из нескольких этапов. В этой схеме, во-первых, EOA совершает транзакцию с децентрализованным приложением, в результате чего происходит взаимодействие с функцией, определенной в смарт-контракте oracle. Эта функция инициирует запрос к оракулу, с соответствующими аргументами, детализирующими запрашиваемые данные в дополнение к дополнительной информации, которая может включать функции обратного вызова и параметры планирования. После подтверждения этой транзакции запрос оракула может наблюдаться как событие EVM, испускаемое контрактом оракула, или как изменение состояния; аргументы могут быть извлечены и использованы для выполнения фактического запроса к внецепочечному источнику данных. Оракул также может потребовать оплату за обработку запроса, оплату газа за обратный звонок и разрешения на доступ к запрошенным данным. Наконец, полученные данные подписываются владельцем оракула, подтверждающим достоверность данных на определенный момент времени, и передаются в транзакции децентрализованному приложению, сделавшему запрос - либо напрямую, либо через контракт с оракулом. В зависимости от параметров планирования оракул может транслировать дальнейшие транзакции, обновляющие данные через регулярные промежутки времени (например, информацию о ценах на конец дня).

Шаги для оракула "запрос-ответ" можно обобщить следующим образом:

  1. Получение запроса от DApp.
  2. Разберите запрос.
  3. Убедитесь, что разрешения на оплату и доступ к данным предоставлены.
  4. Получение соответствующих данных из внецепочечного источника (и при необходимости их шифрование).
  5. Подпишите транзакцию(и) с включенными данными.
  6. Транслировать транзакцию(и) в сеть.
  7. Запланируйте все дальнейшие необходимые операции, такие как уведомления и т.д.

Возможен и ряд других схем; например, данные могут быть запрошены у EOA и возвращены непосредственно им, что устраняет необходимость в смарт-контракте с оракулом. Аналогичным образом, запрос и ответ могут быть направлены к аппаратному датчику с поддержкой Интернета вещей и от него. Таким образом, оракулы могут быть человеческими, программными или аппаратными.

Описанная здесь схема "запрос-ответ" часто встречается в архитектурах клиент-сервер. Хотя это полезная схема обмена сообщениями, позволяющая приложениям вести двусторонний диалог, в определенных условиях она, возможно, неуместна. Например, интеллектуальная облигация, требующая процентную ставку от оракула, должна ежедневно запрашивать данные по схеме "запрос-ответ", чтобы гарантировать, что ставка всегда верна. Учитывая, что процентные ставки меняются нечасто, здесь может быть более уместна схема публикации-подписки - особенно если принять во внимание ограниченную пропускную способность Ethereum.

Publish-subscribe - это схема, в которой издатели (в данном контексте оракулы) не отправляют сообщения непосредственно получателям, а вместо этого распределяют опубликованные сообщения по отдельным классам. Подписчики могут проявлять интерес к одному или нескольким классам и получать только те сообщения, которые их интересуют. При такой схеме оракул может записывать процентную ставку в собственное внутреннее хранилище при каждом ее изменении. Несколько подписавшихся DApps могут просто считывать ее из контракта оракула, тем самым снижая влияние на пропускную способность сети и минимизируя затраты на хранение.

При широковещательной или многоадресной схеме оракул публикует все сообщения в канал, а контракты-подписчики прослушивают канал в различных режимах подписки. Например, оракул может публиковать сообщения в канал курса криптовалюты. Подписавшийся смарт-контракт может запросить полное содержимое канала, если ему нужен временной ряд, например, для расчета скользящего среднего; другой может запросить только последний курс для расчета спотовой цены. Широковещательный шаблон подходит в тех случаях, когда оракулу не нужно знать личность подписавшегося контракта.

Аутентификация данных

Если предположить, что источник данных, запрашиваемых DApp, является авторитетным и заслуживающим доверия (немаловажное предположение), остается нерешенный вопрос: учитывая, что оракул и механизм запроса-ответа могут управляться разными сущностями, как мы можем доверять этому механизму? Существует большая вероятность того, что данные могут быть подделаны при передаче, поэтому очень важно, чтобы внецепочечные методы могли подтвердить целостность возвращаемых данных. Двумя распространенными подходами к проверке подлинности данных являются доказательства подлинности и доверенные среды выполнения (TEE).

Доказательства подлинности - это криптографические гарантии того, что данные не были подделаны. Основанные на различных методах подтверждения подлинности (например, доказательства с цифровой подписью), они эффективно переносят доверие с носителя данных на подтверждающее лицо (т.е. поставщика подтверждения). Проверяя доказательство подлинности на цепи, смарт-контракты могут убедиться в целостности данных, прежде чем работать с ними. Oraclize - это пример ораклового сервиса, использующего различные доказательства подлинности. Одним из таких доказательств, которое в настоящее время доступно для запросов данных из основной сети Ethereum, является доказательство TLSNotary. Доказательства TLSNotary позволяют клиенту предоставить третьей стороне доказательства того, что между клиентом и сервером происходил веб-трафик HTTPS. Хотя HTTPS сам по себе безопасен, он не поддерживает подписание данных. В результате, доказательства TLSNotary полагаются на подписи TLSNotary (через PageSigner). Доказательства TLSNotary используют протокол Transport Layer Security (TLS), что позволяет разделить главный ключ TLS, которым подписываются данные после доступа к ним, между тремя сторонами: сервером (оракулом), проверяющим (Oraclize) и аудитором. В качестве аудитора Oraclize использует экземпляр виртуальной машины Amazon Web Services (AWS), который может быть проверен на неизменность с момента создания. Этот экземпляр AWS хранит секрет TLSNotary, что позволяет ему предоставлять доказательства честности. Хотя этот подход обеспечивает более высокие гарантии против фальсификации данных, чем механизм "запрос-ответ", он требует предположения, что Amazon сама не будет вмешиваться в работу экземпляра виртуальной машины.

Town Crier - это аутентифицированная система оракула для передачи данных, основанная на подходе TEE; в таких методах для обеспечения целостности данных используются аппаратные защищенные оболочки. Town Crier использует программные расширения Intel Software Guard eXtensions (SGX), чтобы гарантировать, что ответы на HTTPS-запросы могут быть проверены на подлинность. SGX обеспечивает гарантии целостности, гарантируя, что приложения, работающие в анклаве, защищены процессором от несанкционированного вмешательства любого другого процесса. Он также обеспечивает конфиденциальность, гарантируя, что состояние приложения непрозрачно для других процессов при работе внутри анклава. И, наконец, SGX позволяет проводить аттестацию, генерируя подписанное цифровой подписью доказательство того, что приложение - надежно идентифицированное хэшем его сборки - действительно запущено в анклаве. Проверяя эту цифровую подпись, децентрализованное приложение может доказать, что экземпляр Town Crier безопасно работает в анклаве SGX. Это, в свою очередь, доказывает, что экземпляр не был подделан и что данные, испускаемые Town Crier, являются подлинными. Свойство конфиденциальности дополнительно позволяет Town Crier работать с частными данными, позволяя шифровать запросы данных с помощью открытого ключа экземпляра Town Crier. Работа механизма запросов/ответов оракула внутри анклава, такого как SGX, позволяет нам считать, что он работает в безопасном режиме на доверенном оборудовании третьей стороны, гарантируя, что запрошенные данные будут возвращены без вмешательства (при условии, что мы доверяем Intel/SGX).

Вычислительные оракулы

До сих пор мы обсуждали оракулы только в контексте запроса и доставки данных. Однако оракулы также могут использоваться для выполнения произвольных вычислений - функция, которая может быть особенно полезной, учитывая присущий Ethereum лимит газа блоков и сравнительно дорогие затраты на вычисления. Вместо того чтобы просто передавать результаты запроса, оракулы вычислений могут использоваться для выполнения вычислений над набором входных данных и возвращать результат, который, возможно, было невозможно вычислить на цепочке. Например, можно использовать вычислительный оракул для выполнения регрессионного расчета, требующего больших вычислительных затрат, чтобы оценить доходность облигационного контракта.

Если вы готовы довериться централизованной, но проверяемой службе, вы можете снова обратиться к Oraclize. Они предоставляют услугу, которая позволяет децентрализованным приложениям запрашивать результаты вычислений, выполняемых на виртуальной машине AWS в песочнице. Экземпляр AWS создает исполняемый контейнер из настроенного пользователем файла Docker, упакованного в архив, который загружается в Межпланетную файловую систему (IPFS; см. [data_storage_sec]). По запросу Oraclize извлекает этот архив, используя его хэш, а затем инициализирует и выполняет Docker-контейнер на AWS, передавая любые аргументы, которые предоставляются приложению в качестве переменных окружения. Контейнерное приложение выполняет вычисления с учетом ограничения по времени и записывает результат на стандартный вывод, откуда он может быть извлечен Oraclize и возвращен децентрализованному приложению. В настоящее время Oraclize предлагает эту услугу на проверяемом экземпляре t2.micro AWS, поэтому, если вычисления имеют какую-то нетривиальную ценность, можно проверить, что был выполнен правильный контейнер Docker. Тем не менее, это не является по-настоящему децентрализованным решением.

Концепция "криплета" как стандарта для проверяемых истин оракула была формализована как часть более широкого ESC Framework от Microsoft. Криплеты выполняются в зашифрованной капсуле, которая абстрагируется от инфраструктуры, такой как ввод-вывод, и имеет подключенный CryptoDelegate, чтобы входящие и исходящие сообщения подписывались, проверялись и подтверждались автоматически. Криплеты поддерживают распределенные транзакции, так что логика контрактов может принимать сложные многоэтапные, многоблочные и внешние системные транзакции в ACID-манере. Это позволяет разработчикам создавать переносимые, изолированные и приватные резолюции истины для использования в смарт-контрактах. Криплеты имеют формат, показанный здесь:

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())

Для более децентрализованного решения мы можем обратиться к компании TrueBit, которая предлагает решение для масштабируемых и проверяемых вычислений вне цепочки. Они используют систему решателей и проверяющих, которые стимулируются для выполнения вычислений и проверки этих вычислений, соответственно. Если решение оспаривается, итерационный процесс проверки подмножеств вычислений выполняется на цепи - своего рода "игра в верификацию". Игра проходит через серию раундов, каждый из которых рекурсивно проверяет все меньшее и меньшее подмножество вычислений. В конечном итоге игра доходит до финального раунда, где задача становится достаточно тривиальной, чтобы судьи - майнеры Ethereum - могли вынести окончательное решение о том, была ли задача решена, на цепочке. По сути, TrueBit - это реализация рынка вычислений, позволяющая децентрализованным приложениям платить за верифицируемые вычисления, выполняемые вне сети, но полагающаяся на Ethereum для обеспечения соблюдения правил верификационной игры. Теоретически это позволяет смарт-контрактам без доверия безопасно выполнять любые вычислительные задачи.

Для систем, подобных TrueBit, существует широкий спектр приложений, начиная от машинного обучения и заканчивая проверкой доказательств работы. Примером последнего является мост Doge-Ethereum, который использует TrueBit для проверки доказательства работы Dogecoin (Scrypt), которая является функцией, занимающей много памяти и требующей больших вычислительных затрат, и которую невозможно вычислить в пределах лимита газа блока Ethereum. Выполняя эту проверку на TrueBit, стало возможным безопасно проверять транзакции Dogecoin в рамках смарт-контракта в тестовой сети Ethereum Rinkeby.

Децентрализованные оракулы

Хотя централизованные оракулы данных или вычислений достаточны для многих приложений, они представляют собой единые точки отказа в сети Ethereum. Был предложен ряд схем, основанных на идее децентрализованных оракулов как средства обеспечения доступности данных и создания сети индивидуальных поставщиков данных с системой агрегации данных на цепочке.

ChainLink предложила децентрализованную оракловую сеть, состоящую из трех ключевых смарт-контрактов - репутационного контракта, контракта на согласование заказов и агрегационного контракта - и внецепочечного реестра поставщиков данных. Репутационный контракт используется для отслеживания эффективности работы поставщиков данных. Оценки в репутационном контракте используются для пополнения внецепочечного реестра. Контракт по подбору заказов выбирает предложения от оракулов, используя репутационный контракт. Затем он заключает соглашение об уровне обслуживания, которое включает параметры запроса и количество необходимых оракулов. Это означает, что покупателю не нужно напрямую взаимодействовать с отдельными оракулами. Контракт агрегации собирает ответы (представленные с использованием схемы фиксации-раскрытия) от нескольких оракулов, вычисляет окончательный коллективный результат запроса и, наконец, передает результаты обратно в контракт репутации.

Одной из основных проблем такого децентрализованного подхода является формулировка агрегирующей функции. ChainLink предлагает вычислять взвешенный ответ, позволяющий получить оценку достоверности для каждого ответа оракула. Определение "недействительного" балла здесь нетривиально, поскольку оно основывается на предпосылке, что отклоняющиеся точки данных, измеряемые отклонениями от ответов, предоставленных коллегами, являются неправильными. Вычисление оценки достоверности на основе расположения оракульного ответа среди распределения ответов рискует наказать правильные ответы по сравнению со средними. Поэтому ChainLink предлагает стандартный набор контрактов агрегации, но также позволяет задавать индивидуальные контракты агрегации. Родственной идеей является протокол SchellingCoin. Здесь несколько участников сообщают значения, а в качестве "правильного" ответа принимается медиана. От респондентов требуется внести депозит, который перераспределяется в пользу значений, которые ближе к медиане, таким образом стимулируя сообщение значений, которые похожи на другие. Ожидается, что общее значение, также известное как точка Шеллинга, которое респонденты могут рассматривать как естественную и очевидную цель, вокруг которой следует координировать свои действия, будет близко к фактическому значению.

Джейсон Тутш из TrueBit недавно предложил новый дизайн децентрализованного оракула доступности данных вне цепочки. Эта конструкция использует специальный блокчейн с доказательством работы, который способен правильно сообщать о том, доступны ли зарегистрированные данные в определенную эпоху. Майнеры пытаются загрузить, сохранить и распространить все зарегистрированные на данный момент данные, гарантируя тем самым их локальную доступность. Хотя такая система является дорогостоящей в том смысле, что каждый майнинговый узел хранит и распространяет все зарегистрированные данные, система позволяет повторно использовать хранилище, освобождая данные после окончания периода регистрации.

Клиентские интерфейсы Oracle в Solidity

Использование Oraclize для обновления курса ETH/USD из внешнего источника - это пример Solidity, демонстрирующий, как Oraclize можно использовать для постоянного опроса цены ETH/USD из API и хранения результата в удобном для использования виде.

Пример 1. Использование Oraclize для обновления курса ETH/USD из внешнего источника

/*
   Тикер цен ETH/USD, использующий API CryptoCompare

   Этот контракт хранит в памяти обновленную цену ETH/USD,
   который обновляется каждые 10 минут.
 */

pragma solidity ^0.4.1;
import "github.com/oraclize/ethereum-api/oraclizeAPI.sol";

/*
   Методы с префиксом "oraclize_" указывают на наследование от "usingOraclize"
 */
контракт EthUsdPriceTicker используетсяOraclize {

    uint public ethUsd;

    событие newOraclizeQuery(string description);
    событие newCallbackResult(string result);

    function EthUsdPriceTicker() payable {
        // сигнализирует о генерации доказательств TLSN и их хранении на IPFS
        oraclize_setProof(proofType_TLSNotary | proofStorage_IPFS);

        // запрос запроса
        queryTicker();
    }

    function __callback(bytes32 _queryId, string _result, bytes _proof) public {
        if (msg.sender != oraclize_cbAddress()) throw;
        newCallbackResult(_result);

        /*
         * Разберите строку результата в целое число без знака для использования в цепи.
         * Использует унаследованный помощник "parseInt" из "usingOraclize", позволяя
         * строковый результат, такой как "123.45", должен быть преобразован в uint 12345.
         */
        ethUsd = parseInt(_result, 2);

        // вызывается из обратного вызова, поскольку мы опрашиваем цену
        queryTicker();
    }

    function queryTicker() external payable {
        if (oraclize_getPrice("URL") > this.balance) {
            newOraclizeQuery("Запрос Oraclize НЕ был отправлен, пожалуйста, добавьте немного ETH
                чтобы покрыть плату за запрос");
        } else {
            newOraclizeQuery("Запрос Oraclize был отправлен, ожидаем ответа для
                ответ...");

            // параметрами запроса являются (задержка в секундах, тип источника данных,
            // аргумент источника данных)
            // указывает JSONPath, чтобы получить определенную часть результата JSON API
            oraclize_query(60 * 10, "URL",
                "json(https://min-api.cryptocompare.com/data/price?\
                fsym=ETH&tsyms=USD,EUR,GBP).USD");
        }
    }
}

Для интеграции с Oraclize контракт EthUsdPriceTicker должен быть дочерним для usingOraclize; контракт usingOraclize определен в файле oraclizeAPI. Запрос данных выполняется с помощью функции oraclize_query, которая наследуется от контракта usingOraclize. Это перегруженная функция, которая ожидает как минимум два аргумента:

  • Поддерживаемый источник данных для использования, например URL, WolframAlpha, IPFS или вычисление
  • Аргумент для данного источника данных, который может включать использование вспомогательных средств разбора JSON или XML

Запрос цены выполняется в функции queryTicker. Для выполнения запроса Oraclize требует уплаты небольшой платы в эфире, покрывающей стоимость газа для обработки результата и передачи его в функцию __callback, а также сопутствующую наценку за услугу. Эта сумма зависит от источника данных и, если указано, от типа требуемого доказательства подлинности. После получения данных функция __callback вызывается учетной записью, контролируемой Oraclize, которой разрешено выполнять обратный вызов; она передает значение ответа и уникальный аргумент queryId, который, например, может использоваться для обработки и отслеживания нескольких ожидающих обратных вызовов от Oraclize.

Поставщик финансовых данных Thomson Reuters также предоставляет сервис оракула для Ethereum под названием BlockOne IQ, позволяющий запрашивать рыночные и справочные данные смарт-контрактами, работающими в частных или разрешенных сетях. Контракт вызова службы BlockOne IQ для получения рыночных данных показывает интерфейс для оракула и клиентский контракт, который будет выполнять запрос.

Пример 2. Контракт, вызывающий службу BlockOne IQ для получения рыночных данных

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);
        // Do something with the price data
    }

    function handleFailure(uint256 id) public {
        assert(msg.sender == address(oracle));
        bytes32 error = oracle.getResponseError(id);
        oracle.deleteResponse(id);
        emit LogError(error);
    }

}

Запрос данных инициируется с помощью функции initRequest, которая позволяет указать тип запроса (в данном примере запрос внутридневной цены), а также две функции обратного вызова. Функция возвращает идентификатор uint256, который затем может быть использован для ввода дополнительных аргументов. Функция addArgumentToRequestString используется для указания кода инструмента Reuters (RIC), здесь для акций IBM, а addArgumentToRequestUint позволяет указать временную метку. Теперь, передав псевдоним block.timestamp, вы получите текущую цену для IBM. Затем запрос выполняется функцией executeRequest. После обработки запроса контракт oracle вызывает функцию обратного вызова onSuccess с идентификатором запроса, позволяя получить результирующие данные; в случае неудачи обратный вызов onFailure возвращает код ошибки. Доступные поля, которые могут быть получены в случае успеха, включают цены открытия, максимума, минимума, закрытия (OHLC), а также цены покупки/продажи.

Выводы

Как видите, оракулы предоставляют смарт-контрактам важнейшую услугу: они привносят внешние факты в исполнение контракта. При этом, конечно, оракулы также вносят значительный риск - если они являются доверенными источниками и могут быть скомпрометированы, они могут привести к нарушению исполнения смарт-контрактов, которые они питают.

В целом, при рассмотрении вопроса об использовании оракула будьте очень внимательны к модели доверия. Если вы предполагаете, что оракулу можно доверять, вы можете подорвать безопасность вашего смарт-контракта, подвергая его потенциально ложным входным данным. Тем не менее, оракулы могут быть очень полезны, если предположения о безопасности тщательно продуманы.

Децентрализованные оракулы могут решить некоторые из этих проблем и предложить смарт-контрактам Ethereum надежные внешние данные. Выбирайте тщательно, и вы сможете начать исследовать мост между Ethereum и "реальным миром", который предлагают оракулы.