Оракул Tradisys

Оракул Centaur

Смарт-контаркты в блокчейне Waves успешно активированы на блоке 1190000. Это означает, что теперь мы можем делать с помощью блокчейна всякие интересные штуки. Конечно же, мы смотрим и работаем в сторону игр. На митапе Waves Platform в Санкт-Петербурге мы презентовали первую игру на блокчейне, работающую полностью на смарт-контракте. Но вот незадача - чтобы решить, кто будет делать первый ход, нам пришлось бросать монетку. Ну что же, мы разработали более технологичное решение для этой проблемы.

На том же митапе мы презентовали сразу двух оракулов.

Что такое оракул?

Оракул - это машина, которая поставляет данные из реального мира в блокчейн. Задача при этом решается крайне важная: сгенерировать случайное число. Это число не должно быть известно заранее, и у всех должна быть возможность проверить надёжность этого числа. Никто, включая оракула, не должен иметь возможности повлиять на это случайное число. Оно должно быть максимально непредвзятым.

Как работает оракул Tradisys?

Мы презентовали сразу двух оракулов на митапе: Cyclops и Centaur. Оракул Centaur успешно запущен и работает по этому адресу. Чем же он занимается?

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

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

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

В итоге, до тех пор, пока оракул работает по адресу, на котором был размещён публичный RSA-ключ, все его записи можно проверить.

Зачем это нужно

Надеюсь, вы помните, что перед тем, как сыграть в крестики-нолики на митапе, мы с Иналом бросали монетку, чтобы определить, за кем первый ход. А теперь давайте попробуем решить эту задачу с помощью оракула :)

Предположим, что партию в крестики-нолики мы хотим начать в 17:10 по Московскому времени. Крестики-нолики - это игра, но в нашем случае, это ещё и смарт-контракт. Мы можем добавить в смарт-контракт инструкцию, которая даcт право на первый ход одному из игроков в зависимости от определённого условия. Этим условием может быть число оракула, которое ни я, ни Инал, заранее знать не можем.

  1. В 17:09:55 оракул Tradisys прочитал высоту блокчейна и определил, что текущая высота блокчейна - #1191337. Брать подпись блока текущей высоты смысла нет, так как этот блок продолжает пополняться транзакциями, каждая из которых меняет его финальную подпись. Поэтому оракул берёт подпись последнего полностью сгенерированного блока - #1191336. Подпись этого блока выглядит так:

  1. Оракул взял подпись этого блока и перед отправкой подписал приватным ключом RSA, который неизвестен никому, кроме оракула. И майнеру нет смысла перебирать подписи блока, который он генерирует, так как ему неизвестно, какое получится итоговое случайное число после подписания хэша блока оракулом.
  2. Подписав хэш блока, оракул отправляет дата-транзакцию в сеть. Выглядит это вот так:

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

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

  1. basedOnBlockHeight. Высота блока, хэш которого был использован. Перезаписываемая ячейка.
  2. basedOnBlockSignature. Подпись блока для генерирования случайного числа. Перезаписываемая ячейка.
  3. oraclePublicKey. Публичный RSA-ключ, с помощью которого валидируется корректность подписи оракула. Эту ячейку перезаписать невозможно, за это отвечает смарт-контракт.
  4. randomNumber. Само рандомное число. Перезаписываемая ячейка.

Итак, мы получили случайное число, в данном случае это:

PBfWlrG2sZhw7axnsBHj6XlKSPparV5LEW3a/b2FBztxgtAeA3iIwsXD1Zji+EX/z9xJuGAlqcWa1JW2cbQVciMZKCTYUDyhEd9rko6yIcFOp9uMvTsk7jz7Pp+Go61Jn/5TzQJ3TiLd0BoQcVSPZujHP6pw/krXbKBNufLAhPZIXJxS1NRLZSiT/E3BUuTglkqWFeEvMEP5/EqLqzZWnkk9iY41L9V5z8mtp0Of7XVjbPxKEpMWQi9XykKPXWQaV+M2jX4cvQTB0An1HfUrNYNaP0CTwNyGV9BYtBSYw1J/BfrWlveer8CGCft9HKFmHjKZPvXCFzx+LZ1ACvzQtA==

Не совсем число, вы правы :) Но давайте удалим из него всё, кроме цифр, получаем:

27653231912996153061359419580792401091891

Как видите, цифр тут довольно много. И в каждой записи оракула это будет разный набор цифр, их число будет тоже отличаться.

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

  1. Прочитать ячейку со случайным числом оракула.
  2. Удалить всё, кроме цифр.
  3. Взять пятую слева цифру в полученном списке.
  4. Если полученная цифра от 0 до 4, то первыми ходят крестики.
  5. Если полученная цифра от 5 до 9, то первыми ходят нолики.

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

И это лишь один из тысяч примеров использования случайных чисел от оракула.

Ситема-без-доверия

А что если оракул Tradisys вступит в сговор с какой-нибудь нодой, например, нодой Tradisys? :) Ведь тогда нода Tradisys сможет договориться с оракулом Tradisys и получить доступ к приватному RSA-ключу оракула. И это будет означать, что нода сможет манипулировать подписью блока, проверяя результат случайного числа полученным приватным RSA-ключом. И если нода Tradisys играет в крестики-нолики с Иналом, то она, с высокой долей вероятности, всегда будет ходить первой :)

Именно поэтому исходный код оракула Tradisys Centaur будет выложен в открытый доступ. Мы очень надеемся, что в самое ближайшее время появится ещё несколько оракулов, которые обладают достаточным уровнем доверия. Это позволит внести корректировку в смарт-контракт таким образом, что смарт-контракт будет брать случайные числа нескольких разных оракулов и, например, складывать их.

А поскольку у всех оракулов будут уникальные приватные RSA-ключи, то несмотря на то, что подпись блока у всех будет взята одинаковая (при условии, что эти оракулы делают транзакции с одинаковой частотой), итоговые случайные числа будут отличаться.

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

Послесловие

Сейчас оракул работает стабильно и записывает случайное число каждые 30 блоков. В будущем мы увеличим частоту записи случайных чисел. В опенсорс все данные попадут в ближайшие дни (немного причешем код).

Адрес оракула:

http://wavesexplorer.com/address/3P4xYCRQtXKkLV4gKVPEjE8ckwRKRjhdahk

Ну и, собственно, код смарт-контракта:

let contractPK = base58'BYvio3cJctKKydTMQkfZEnPLEvm9nEnPodCbhz8SuZda'

match (tx) {
case t:DataTransaction =>

   let sig =  sigVerify(t.bodyBytes,t.proofs[0],t.senderPublicKey)

   t.data[0].key == "randomNumber" && t.data[1].key == "basedOnBlockHeight" && t.data[2].key == "basedOnBlockSignature"  
   && size(t.data) == 3 && sig

case _ => false
}

Да, мы немного спешили, поэтому идеальным смарт-контракт не получился. Его логика выстроена безупречно, но есть одна лишняя деталь :) Кто найдёт - пишите в наш чат, подарим несколько волн. Косяк несущественный, нет смысла деплоить контракт на другой адрес, угрозы безопасности нет. Но это ещё раз подтверждает, что в спешке можно допустить ошибку. Оракул полностью рабочий, безопасный, генерирует случайное число каждые 30 блоков, можете пользоваться.

Всем удачных рандомов!

Next PostPrevious Post