Швидкий старт з 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