Быстрый старт с Oracle

Введение

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

Для чего это полезно?

  • Оракул, который предоставляет цены XTZ / USD, может позволить пользователям вносить средства, которые немедленно конвертируются в какой-либо актив в цепочке и представляются как указание к действию.

  • Оракул, который предоставляет данные о погоде, может позволить заключить договор страхования от цунами: пользователи покупают покрытие по контракту, которое выплачивается, когда в их районе появится достаточно сильное цунами

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

Установка

CLI

❯❯❯ lorentz-contract-oracle Oracle --help
Usage: lorentz-contract-oracle Oracle COMMAND
  Oracle contract CLI interface

Available options:
  -h,--help                Show this help text

Available commands:
  print                    Dump the Oracle contract in form of Michelson code
  print-timestamped        Dump the Timestamped Oracle contract in form of
                           Michelson code
  init                     Initial storage for the Oracle contract
  get-value                get value
  update-value             update value
  update-admin             update admin

Создание контракта

Печать контракта

Команда печати принимает единственный аргумент: valueType, тип значения, предоставленного оракулом.

Примечание. Пока проблема №6 в репозитории не будет исправлена, инструмент CLI будет выдавать ошибку, если valueType не является nat при печати контракта или в timestamped версии.

Например, если nat значения переданы:

❯❯❯ lorentz-contract-oracle Oracle print --valueType "nat"

parameter (or (pair %getValue unit
                              (contract nat))
              (or (nat %updateValue)
                  (address %updateAdmin)));
storage (pair nat
              address);
code { CAST (pair (or (pair unit (contract nat)) (or nat address)) (pair nat address));
       DUP;
       CAR;
       DIP { CDR };
       IF_LEFT { DUP;
                 CAR;
                 DIP { CDR };
                 DIP { DIP { DUP };
                       SWAP };
                 PAIR;
                 CDR;
                 CAR;
                 DIP { AMOUNT };
                 TRANSFER_TOKENS;
                 NIL operation;
                 SWAP;
                 CONS;
                 PAIR }
               { IF_LEFT { DIP { DUP;
                                 CAR;
                                 DIP { CDR } };
                           DIP { DROP;
                                 DUP;
                                 DIP { SENDER;
                                       COMPARE;
                                       EQ;
                                       IF {  }
                                          { PUSH string "only admin may update";
                                            FAILWITH } } };
                           PAIR;
                           NIL operation;
                           PAIR }
                         { DIP { DUP;
                                 CAR;
                                 DIP { CDR };
                                 DIP { SENDER;
                                       COMPARE;
                                       EQ;
                                       IF {  }
                                          { PUSH string "only admin may update";
                                            FAILWITH } } };
                           SWAP;
                           PAIR;
                           NIL operation;
                           PAIR } } };

Начальное хранение

❯❯❯ lorentz-contract-oracle Oracle init --help
Usage: lorentz-contract-oracle Oracle init --initialValueType Michelson Type
                                           --initialValue Michelson Value
                                           --admin ADDRESS
  Initial storage for the Oracle contract

Available options:
  -h,--help                Show this help text
  --initialValueType Michelson Type
                           The Michelson Type of initialValue
  --initialValue Michelson Value
                           The Michelson Value: initialValue
  --admin ADDRESS          Address of the admin.
  -h,--help                Show this help text

Поскольку мы используем nat, initialValueType имеет значение nat, а initialValue может быть 0:

❯❯❯ lorentz-contract-oracle Oracle init \
  --initialValueType "nat" \
  --initialValue 3 \
  --admin $ALICE_ADDRESS
Pair 3 "tz1R3vJ5TV8Y5pVj8dicBR23Zv8JArusDkYr"

Запуск старта контракта

ПРИМЕЧАНИЕ: чтобы использовать аннотированную (timestamped) версию, например для nat:

❯❯❯ tezos-client --wait none originate contract NatOracle \
  transferring 0 from $ALICE_ADDRESS running \
  "$(lorentz-contract-oracle Oracle print-timestamped --valueType "nat")" \
  --init "$(lorentz-contract-oracle Oracle init \
  --initialValueType "pair timestamp nat" --initialValue 'Pair "2019-12-10T17:43:53Z" 26871' \
  --admin $ALICE_ADDRESS)" --burn-cap 0.859 --force

ПРИМЕЧАНИЕ: контракт nat_oracle.tz можно найти здесь

Иначе:

❯❯❯ tezos-client --wait none originate contract NatOracle \
  transferring 0 from $ALICE_ADDRESS running \
  "$(lorentz-contract-oracle Oracle print --valueType "nat")" \
  --init "$(lorentz-contract-oracle Oracle init \
  --initialValueType "nat" --initialValue 3 \
  --admin $ALICE_ADDRESS)" --burn-cap 0.612

Waiting for the node to be bootstrapped before injection...
Current head: BLE8kx6VhXbk (timestamp: 2020-04-03T15:28:43-00:00, validation: 2020-04-03T15:29:02-00:00)
Node is bootstrapped, ready for injecting operations.
Estimated gas: 20483 units (will add 100 for safety)
Estimated storage: 683 bytes added (will add 20 for safety)
Operation successfully injected in the node.
Operation hash is 'onsEwbbm71wpzgnk6baBGacDzsnKceypEL841STJ6B5V9cA4swr'
NOT waiting for the operation to be included.
Use command
  tezos-client wait for onsEwbbm71wpzgnk6baBGacDzsnKceypEL841STJ6B5V9cA4swr to be included --confirmations 30 --branch BLE8kx6VhXbka6FGjXmKxnH56iypJLYZ9pM5mM3HLKvoVDBiMeS
and/or an external block explorer to make sure that it has been included.
This sequence of operations was run:
  Manager signed operations:
    From: tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHm
    Fee to the baker: ꜩ0.002729
    Expected counter: 623928
    Gas limit: 20583
    Storage limit: 703 bytes
    Balance updates:
      tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHm ............. -ꜩ0.002729
      fees(tz1Ke2h7sDdakHJQh8WX4Z372du1KChsksyU,154) ... +ꜩ0.002729
    Origination:
      From: tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHm
      Credit: ꜩ0
      Script:
        {...}
        Initial storage: (Pair 3 "tz1R3vJ5TV8Y5pVj8dicBR23Zv8JArusDkYr")
        No delegate for this contract
        This origination was successfully applied
        Originated contracts:
          KT1LVLUsC1WCo4yHzeoDEE8FxxoC7EW6bSyp
        Storage size: 426 bytes
        Paid storage size diff: 426 bytes
        Consumed gas: 20483
        Balance updates:
          tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHm ... -ꜩ0.426
          tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHm ... -ꜩ0.257

New contract KT1LVLUsC1WCo4yHzeoDEE8FxxoC7EW6bSyp originated.
Contract memorized as NatOracle.

Создайте псевдоним для полученного адреса:

❯❯❯ ORACLE_ADDRESS="KT1LVLUsC1WCo4yHzeoDEE8FxxoC7EW6bSyp"

Получение значения

Подготовка к просмотру контракта

Старт контракта:

❯❯❯ tezos-client --wait none originate contract nat_storage transferring 0 \
  from $ALICE_ADDRESS running "$(lorentz-contract print --name NatStorageContract)" \
  --init 0 --burn-cap 0.295

Создайте псевдоним для полученного адреса:

❯❯❯ NAT_STORAGE_ADDRESS="KT1ShW17HERZgjUTxSxSc4W3tuWrfLCqBmEi"

См. FA1.2 для получения дополнительной информации.

Создание параметра

❯❯❯ lorentz-contract-oracle Oracle get-value --help
Usage: lorentz-contract-oracle Oracle get-value --callbackContract ADDRESS
  get value

Available options:
  -h,--help                Show this help text
  --callbackContract ADDRESS
                           Address of the callbackContract.
  -h,--help                Show this help text
❯❯❯ lorentz-contract-oracle Oracle get-value --callbackContract $NAT_STORAGE_ADDRESS
Left (Pair Unit "KT1ShW17HERZgjUTxSxSc4W3tuWrfLCqBmEi")

Получение значения

❯❯❯ tezos-client --wait none transfer 0 from $ALICE_ADDRESS to $ORACLE_ADDRESS \
  --arg "$(lorentz-contract-oracle Oracle get-value \
  --callbackContract $NAT_STORAGE_ADDRESS)" --burn-cap 0.000001

Waiting for the node to be bootstrapped before injection...
Current head: BL7fbZE3Gs2V (timestamp: 2020-04-03T15:33:25-00:00, validation: 2020-04-03T15:33:45-00:00)
Node is bootstrapped, ready for injecting operations.
Estimated gas: 31566 units (will add 100 for safety)
Estimated storage: no bytes added
Operation successfully injected in the node.
Operation hash is 'opWqWvkJczWzq5m99svSDzW7HmWY5nCUB1rerDn6utLLH5NJ1dS'
NOT waiting for the operation to be included.
Use command
  tezos-client wait for opWqWvkJczWzq5m99svSDzW7HmWY5nCUB1rerDn6utLLH5NJ1dS to be included --confirmations 30 --branch BL7fbZE3Gs2VkmziY11S4biX9cfuLVnQmLr8r7ALbJukxD4tRSY
and/or an external block explorer to make sure that it has been included.
This sequence of operations was run:
  Manager signed operations:
    From: tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHm
    Fee to the baker: ꜩ0.00347
    Expected counter: 623930
    Gas limit: 31666
    Storage limit: 0 bytes
    Balance updates:
      tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHm ............. -ꜩ0.00347
      fees(tz1Ke2h7sDdakHJQh8WX4Z372du1KChsksyU,154) ... +ꜩ0.00347
    Transaction:
      Amount: ꜩ0
      From: tz1bDCu64RmcpWahdn9bWrDMi6cu7mXZynHm
      To: KT1LVLUsC1WCo4yHzeoDEE8FxxoC7EW6bSyp
      Parameter: (Left (Pair Unit "KT1ShW17HERZgjUTxSxSc4W3tuWrfLCqBmEi"))
      This transaction was successfully applied
      Updated storage:
        (Pair 3 0x00003b5d4596c032347b72fb51f688c45200d0cb50db)
      Storage size: 426 bytes
      Consumed gas: 20242
    Internal operations:
      Transaction:
        Amount: ꜩ0
        From: KT1LVLUsC1WCo4yHzeoDEE8FxxoC7EW6bSyp
        To: KT1ShW17HERZgjUTxSxSc4W3tuWrfLCqBmEi
        Parameter: 3
        This transaction was successfully applied
        Updated storage: 3
        Storage size: 38 bytes
        Consumed gas: 11324

Изменение значения

Создание параметра

❯❯❯ lorentz-contract-oracle Oracle update-value --help
Usage: lorentz-contract-oracle Oracle update-value --newValueType Michelson Type
                                                   --newValue Michelson Value
  update value

Available options:
  -h,--help                Show this help text
  --newValueType Michelson Type
                           The Michelson Type of newValue
  --newValue Michelson Value
                           The Michelson Value: newValue
  -h,--help                Show this help text

Изменение значения

Чтобы изменить значение на 4:

Waiting for the node to be bootstrapped before injection...
Current head: BMLjQ5pgcmxd (timestamp: 2020-04-03T15:35:39-00:00, validation: 2020-04-03T15:35:44-00:00)
Node is bootstrapped, ready for injecting operations.
Estimated gas: 19463 units (will add 100 for safety)
Estimated storage: no bytes added
Operation successfully injected in the node.
Operation hash is 'ooEf7sgpvhMcUBcn66iMLaWNzs4TEAxb4icjXKF27xM2QPMTGQP'
NOT waiting for the operation to be included.
Use command
  tezos-client wait for ooEf7sgpvhMcUBcn66iMLaWNzs4TEAxb4icjXKF27xM2QPMTGQP to be included --confirmations 30 --branch BMLjQ5pgcmxdN11kfhA2NS4igfSdJeL5HbopDn8LyAckBroWZhi
and/or an external block explorer to make sure that it has been included.
This sequence of operations was run:
  Manager signed operations:
    From: tz1R3vJ5TV8Y5pVj8dicBR23Zv8JArusDkYr
    Fee to the baker: ꜩ0.001259
    Expected counter: 632294
    Gas limit: 10000
    Storage limit: 0 bytes
    Balance updates:
      tz1R3vJ5TV8Y5pVj8dicBR23Zv8JArusDkYr ............. -ꜩ0.001259
      fees(tz1Ke2h7sDdakHJQh8WX4Z372du1KChsksyU,154) ... +ꜩ0.001259
    Revelation of manager public key:
      Contract: tz1R3vJ5TV8Y5pVj8dicBR23Zv8JArusDkYr
      Key: edpkvCHgVArnZo9RTP4P6euLTyhE89u73CYjBgsP4wEJbj4quao9oR
      This revelation was successfully applied
      Consumed gas: 10000
  Manager signed operations:
    From: tz1R3vJ5TV8Y5pVj8dicBR23Zv8JArusDkYr
    Fee to the baker: ꜩ0.002123
    Expected counter: 632295
    Gas limit: 19563
    Storage limit: 0 bytes
    Balance updates:
      tz1R3vJ5TV8Y5pVj8dicBR23Zv8JArusDkYr ............. -ꜩ0.002123
      fees(tz1Ke2h7sDdakHJQh8WX4Z372du1KChsksyU,154) ... +ꜩ0.002123
    Transaction:
      Amount: ꜩ0
      From: tz1R3vJ5TV8Y5pVj8dicBR23Zv8JArusDkYr
      To: KT1LVLUsC1WCo4yHzeoDEE8FxxoC7EW6bSyp
      Parameter: (Right (Left 4))
      This transaction was successfully applied
      Updated storage:
        (Pair 4 0x00003b5d4596c032347b72fb51f688c45200d0cb50db)
      Storage size: 426 bytes
      Consumed gas: 19463

Настройка сервера

Хотя у нас есть все необходимое для создания и администрирования контракта оракула, мы хотели бы автоматически отправлять обновления в контракт.

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

Минимальный сервер на Bash

Минимальный сервер, написанный на Bash, может состоять из:

  • Bash скрипта update_value.sh который получает NEW_VALUE и вызывает точку входа

    update-value:

##!/bin/bash
## update_value.sh

NEW_VALUE="$(my_get_new_value_script)

tezos-client --wait none transfer 0 from $ALICE_ADDRESS to $ORACLE_ADDRESS \
  --arg "$(lorentz-contract-oracle Oracle update-value \
  --newValueType "nat" --newValue $NEW_VALUE)" --burn-cap 0.000001
  • crontab настройку update_value.sh запускающуюся периодически

    (в примере: ежедневно в 5:03 pm):

03 05 * * * update_value.sh

Сервер Docker Flask

Существует реализация указанного выше сервера Bash на Python, упакованная как образ Docker, которая:

  • Получает последнюю информацию о ценах на акции от Alpha Vantage

  • Запускает "задание cron", чтобы отправить обновление в контракт оракула с pytezos каждые 30 секунд

  • Обслуживает веб-страницу для отладки

Он делает то же самое, что и скрипт Bash, где my_get_new_value_script извлекает последнюю цену из Alpha Vantage.

Вы можете найти проект на Github здесь или просмотреть однофайловый код Python здесь.

Чтобы получить изображение из репозитория DockerHub, запустите:

❯❯❯ docker pull tqtezos/oracle-stock-ticker:2.1

Сервер настраивается с использованием переменных среды:

  • Чтобы сгенерировать TEZOS_USER_KEY, выполните: echo "$(base64 MY_KEY_FILE.json | tr -d '\n')",

    где MY_KEY_FILE.json это ваш файл Tezos вилки (см. здесь, чтобы получить файл).

  • Вы можете получить бесплатный ALPHA_VANTAGE_API_KEY от Alpha Vantage

  • Search Endpoint от Alpha Vantage можно использовать, чтобы найти значения ALPHA_VANTAGE_TICKER_SYMBOL

TEZOS_USER_KEY=".."
ORACLE_ADDRESS="KT1CUTjTqf4UMf6c9A8ZA4e1ntWbLVTnvrKG"
ALPHA_VANTAGE_API_KEY=".."
ALPHA_VANTAGE_TICKER_SYMBOL="AAPL"
FLASK_APP="tq/oracles/ticker.py"

Чтобы запустить контейнер Docker:

❯❯❯ docker run -d -p 5000:5000 \
  --env TEZOS_USER_KEY=".."
  --env ORACLE_ADDRESS="KT1.." \
  --env ALPHA_VANTAGE_API_KEY=".." \
  --env ALPHA_VANTAGE_TICKER_SYMBOL="AAPL" \
  --env FLASK_APP="tq/oracles/ticker.py" \
  oracle-stock-ticker

Как только он будет запущен, он будет обслуживать страницу отладки и обновлять контракт оракула примерно каждые 30 секунд.

Теперь вы должны иметь возможность просматривать экран отладки по адресу localhost:5000, получать последние значения с помощью get-value и использовать проводник блоков для проверки контракта.

Вы можете найти действующий пример контракта на Carthage.

Материалы разработаны TQ Tezos переведены на русский язык Tezos Ukraine

Last updated