Главная

Полные и селективные индексеры Tezos

Команды экосистемы Tezos разработали около десятка блокчейн-индексеров. Условно их можно разделить на две категории:

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

Мы связались с MadFish Solutions, Kukai Wallet, Plenty DeFi, youves и разработчиками других проектов на Tezos, чтобы узнать, какими индексерами они пользуются. Чаще всего они используют TzIndex, TzKT и Que Pasa, а также фреймворк DipDup для создания собственных селективных индексеров.

Сейчас расскажем об этих индексерах, а в следующих уроках рассмотрим использование в проектах публичного TzKT API, а также селективных индексеров: простого Que Pasa, продвинутого DipDup и нового интересного индексера Dappetizer.

Какой индексер для чего подходит

С помощью TzKT и TzStats (TzIndex, если говорить про self-hosted вариант) можно получить любые ончейн-данные Tezos: от версии Octez, которую использует конкретный бейкер, до содержимого big_map смарт-контракта. При этом у них есть различия:

  • TzKT API поддерживает различные фильтры и сортировку ответов по значениям в выбранном столбце. Например, можно отсортировать балансы держателей конкретного токена по их размеру;
  • TzStats API не поддерживает продвинутую сортировку — ее нужно реализовать на стороне клиента. Зато у него есть своя уникальная фича: Time Series API позволяет разработчикам получить исторические данные по балансам, статистике сети Tezos и токену tez с агрегацией по указанному временному отрезку. Это полезно для аналитики.

С помощью Que Pasa и DipDup можно получить только данные по смарт-контрактам, а Dappetizer кроме того поддерживает индексацию других данных из блоков.

1

Терминология и немного технических деталей

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

  • поле (field) — ячейка в базе данных. Пример: сумма одной транзакции, адрес одного пользователя;
  • строка или ряд (row) — горизонтальная совокупность полей, которые относятся к одному ключу. Например, в строке об одной транзакции будут ячейки с хешем, адресами отправителя и получателя, суммой, комиссиями и другими данными об операции;
  • колонка или столбец (column) — вертикальная совокупность полей одного типа. Пример: столбец «Сумма транзакции» будет содержать только ячейки с суммами транзакций;
  • схема базы данных или модель данных — описание структуры таблиц и связей между ними.

Задача блокчейн-индексера — не просто вносить данные из блоков в таблицу и создавать индексы, но создать такую схему, чтобы оптимизировать производительность базы данных, объем индексов и количество возможных запросов. Например, вряд ли кто-то будет искать операцию по сумме транзакционных комиссий, поэтому публичные индексеры не используют такой индекс.

Публичные и self-hosted индексеры

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

Публичные API можно использовать для экспериментов и тестирования, но для запуска приложения лучше клонировать индексер и запустить его у себя — self-hosted.

Во-первых, при использовании self-hosted-индексера разработчик сможет быстрее получать данные и не ждать в очереди, если публичный API будет перегружен. TzStats и TzKT в соглашении на использование API предупреждают, что могут ограничивать приложения, которые слишком часто отправляют запросы.

Во-вторых, self-hosted индексер можно доработать под задачи проекта. Селективные индексеры Que Pasa, DipDup и Dappetizer будут сохранять в базу данных и индексировать только те данные, которые укажет разработчик, а работу полных индексеров TzKT и TzIndex можно настроить через систему управления базой данных вроде PostgreSQL.

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

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

Как работает TzKT

Индексер TzKT разработала команда Baking Bad. Его использует одноименный обозреватель TzKT.io.

Схема работы TzKT выглядит так:

  1. TzKT проверяет последний блок в своей базе данных PostgreSQL и сверяет его с последним блоком в Tezos.
  2. Если последнего блока в Tezos еще нет в базе данных, TzKT проверяет его валидность.
  3. Если блок валидный, индексер распознает данные в блоке по заранее описанным моделям данных, а затем последовательно добавляет их в базу данных в отдельных операциях. Если в блокчейне происходит реорганизация, индексер автоматически откатывает операции и не нарушает структуру базы данных.
  4. PostgreSQL принимает коммиты и обновляет индексы общей базы данных.
  5. API-модуль TzKT выполняет запросы к базе данных.

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

  • присваивание токенам идентификаторов, которое упрощает их поиск;
  • обновления в реальном времени — TzKT поддерживает WebSocket API и может получать информацию о новых транзакциях, вызовах смарт-контрактов и других операциях в сети Tezos в реальном времени;
  • автоматическая валидация полученных блоков через сравнение блока с «эталоном». Так индексер убеждается, что обработал данные правильно и не получил никаких неожиданных данных;
  • возможность скачать снапшот базы данных и использовать его для быстрого запуска индексера вместо того, чтобы индексировать блокчейн с нуля;
  • индексирование токенов и офчейн-метаданных из IPFS. TzKT распознает смарт-контракты токенов по big_map со структурой реестра (ledger), описанной в TZIP-12.

Лицензирование: Baking Bad разрешают бесплатно использовать TzKT в self-hosted режиме и публичный TzKT API, но с добавлением в проект дисклеймера "Powered by TzKT".

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

2

Для запуска индексера нужна машина с 4 ГБ оперативной памяти или больше. Чем больше RAM, тем больше места можно выделить под кеширование данных для ускорения поиска данных. Как и индексы, кеширование можно настроить: отключить полностью, уменьшить или увеличить их размер для конкретного типа данных.

Снапшот базы данных занимает 60 ГБ, а вместе со всеми индексами TzKT может использовать 300-400 ГБ. Так что TzKT лучше запускать на машине с жестким диском объемом 500 ГБ или 1 ТБ.

С помощью TzKT можно получить такие данные:

  • head — статус индексера: текущая сеть, последний проиндексированный блок, последний timestamp;
  • протокол — информация о всех версиях протокола Tezos: уровни первого и последнего блоков, время создания блока, лимит газа, слоты эндорсмента и другое;
  • голосования — пропозиции (proposals), адреса проголосовавших бейкеров, периоды голосований;
  • циклы Tezos — уровень начала и завершения, общий стейк, количество делегаторов;
  • делегаты — информацию о конкретном делегате: баланс, уровень активации, количество делегаторов;
  • бейкинг — награды за бейкинг и делегирование, версии ПО, на котором работают ноды;
  • аккаунты — балансы и метаданные адресов, дата последней активности, делегирование и другая информация;
  • bigmap — информация о bigmap, ключи, значения, апдейты ключей и исторические значения;
  • блоки — полное содержание блоков с разными возможностями для сортировки, например по объему транзакционных комиссий;
  • глобальные константы;
  • смарт-контракты — код, описание, состояние и схема хранилища, bigmap-ы контракта;
  • операции — транзакции, делегирование, активации аккаунтов, а также операции с роллапами, попытки двойного бейкинга, внесение предложений и другие;
  • котировки Tezos к фиатным валютам и криптовалютам;
  • вознаграждения за бейкинг и делегирование за цикл;
  • статистика сети за указанный период;

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

Самая крупная транзакция kUSD — $1,17 млн!

Запрос выглядит так:

https://api.tzkt.io/v1/tokens/transfers?token.contract=KT1K9gCRgaLRFKTErYt1wVxA3Frb9FjasjTV&limit=1&sort.desc=amount

Сначала мы запрашиваем таблицу /tokens/transfers/. Затем добавляем фильтры: token.contract с адресом контракта kUSD, limit=1 чтобы получить только одну строку, и sort.desc=amount, чтобы получить строку с наибольшим значением «amount».

3

Данные о всех протоколах Tezos: первый блок протокола, слоты эндорсмента блока, стоимость байта и другие параметры.

Это простой запрос к таблице /protocols/ — https://api.tzkt.io/v1/protocols/

4

Последние попытки двойного бейкинга.

Немного сложный запрос — https://api.tzkt.io/v1/operations/double_baking?limit=5&sort.desc=level

Запрашиваем таблицу /operations/double_baking/ и применяем два фильтра: limit для получения 5 строк и sort.desc=levels, чтобы получить самые последние операции.

5

Как работает TzIndex

TzIndex (также известен как Blockwatch) Tezos Indexer разработала аналитическая компания Blockwatch Data и использует его в обозревателе TzStats.

Главная фича TzIndex — кастомная колоночная база данных, которая хранит информацию в столбцах вместо строк. По словам разработчиков, такое решение лучше справляется со сложными аналитическими запросами и получением данных.

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

Обычные базы данных вроде PostgreSQL хранят названия полей в столбцах, а записи — в строках.

6

На жестком диске эта таблица будет выглядеть так:

[Book1, The Call of Cthulhu, Lovecraft, 1928], [Book3, The Lord of the Rings, Tolkien, 1954], [The Adventures of Tom Sawyer, Mark Twain, 1876]

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

Допустим, мы хотим получить из базы данных даты публикации всех книг, чтобы определить самый продуктивный год. Поиск будет выглядеть так: СУБД возьмет первую строку, последовательно прочтет записи в строке, запишет дату, затем перейдет на вторую строку, последовательно прочтет записи, и так далее.

7

Колоночные базы учитывают особенности физического хранения данных, и решают проблему с помощью поворота таблиц на 90°: хранят названия полей в строках, а данные — в столбцах.

8

На жестком диске эта таблица выглядит так:

[Book Name, The Call of Cthulhu, The Lord of the Rings, The Adventures of Tom Sawyer], [Book Author, Lovecraft, Tolkien, Mark Twain], [Publication Year, 1928, 1954, 1876].

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

9

В результате колоночная база данных будет выполнять комплексные запросы в 2-10 раз быстрее, чем обычная строчная база. Разработчики TzIndex в блоге приводят точную скорость выполнения запросов в своей кастомной колоночной базе данных:

10

Разработчики могут запустить TzIndex на своей машине или пользоваться индексами через TzStats API. Для работы TzIndex, помимо быстрого жесткого диска, нужно минимум 8 ГБ оперативной памяти и двухъядерный процессор. Однако, чем больше памяти и ядер, тем быстрее будет работать индексер.

TzIndex может работать в трех режимах:

  • Light — индексирует все ончейн-операции, кроме тех, что связаны с бейкингом: эндорсментами, раскрытием nonce, пропозициями, голосованиями и другими. Подходит для бэкенда большинства децентрализованных приложений. На момент написания база данных занимает 32 ГБ;
  • Full — индексирует все операции включительно с бейкингом. Подходит для всех блокчейн-приложений, особенно тех, которые работают с данными о бейкинге. База данных занимает 38-40 ГБ;
  • Validate — при индексации каждого блока он сверяет обновленные балансы пользователей и состояния смарт-контрактов с данными archive-ноды перед тем, как добавить их в базу данных. Также в конце цикла Tezos индексер сверяет все балансы в базе данных. Режим нужен, чтобы удостовериться в безошибочности данных.

Лицензирование: Light-режим и TzStats API — бесплатные для некоммерческих проектов. Чтобы использовать их для заработка или запустить self-hosted TzIndex в Full- и Validate-режиме нужно купить подписку.

TzIndex поддерживает несколько конечных точек API-запросов:

explorer — детальная информация про объект с описаниями. Например, при запросе значений конкретной big_map TzIndex вернет информацию в читаемом JSON. Подходит для получения конкретных значений по запросу, например для отображения балансов пользователя в приложении.

Например, запросим балансы нескольких держателей токена hDAO, но напрямую из big_map "Ledger" с id "515". Фильтры limit=1 и sort=desc означают, что мы получим только одну строку с наибольшим значением row_id (помните про сортировку только по row_id?)

https://api.tzstats.com/explorer/bigmap/515/values?limit=1&sort=desc

11

Table — информация из таблицы индексера. Ответ менее читабельный, потому что не включает названия полей, но лучше подходит для запроса большого количества однотипных данных, так как объем ответа будет меньше.

Запросим ту же big_map "Ledger" смарт-контракта hDAO с теми же параметрами: limit=1, order=asc.

https://api.tzstats.com/tables/bigmap_values?bigmap_id=515&limit=1&order=asc

12

Time-series — исторические данные балансов, операций, эмиссии tez и других значений. Подходит для составления графиков и аналитики. Для примера запросим time-series баланса случайного адреса.

Нам нужно указать стартовую дату, затем — временной интервал агрегации в аргументе collapse, и наконец адрес. Запрос примера следующий:

  • start_date — 2021, по сути 1 января 00:01;
  • collapse — 1d, то есть каждая строка будет показывать баланс за один день;
  • address — просто адрес.

https://api.tzstats.com/series/balance?start_date=2021&collapse=1d&address=tz2TSvNTh2epDMhZHrw73nV9piBX7kLZ9K9m

В ответе получим набор чисел. Первое число в строке — это timestamp в миллисекундах, второе, с точкой, — баланс в tez.

13

С помощью TzIndex можно получить такие данные:

  • head — статус индексера: текущая сеть, последний проиндексированный блок, последний timestamp;
  • протокол — информация о всех версиях протокола Tezos: уровни первого и последнего блоков, время создания блока, лимит газа, слоты эндорсмента и другое;
  • голосования — пропозиции (proposals), адреса проголосовавших бейкеров, периоды голосований;
  • циклы Tezos — уровень начала и завершения, общий стейк, количество делегаторов;
  • делегаты — информацию о конкретном делегате: баланс, уровень активации, количество делегаторов;
  • бейкинг — награды за бейкинг и делегирование, версии ПО, на котором работают ноды;
  • аккаунты — балансы и метаданные адресов, дата последней активности, делегирование и другая информация;
  • bigmap — информация о bigmap, ключи, значения, апдейты ключей и исторические значения;
  • блоки — полное содержание блоков с разными возможностями для сортировки, например по объему транзакционных комиссий;
  • глобальные константы;
  • смарт-контракты — код, описание, состояние и схема хранилища, bigmap-ы контракта;
  • операции — транзакции, делегирование, активации аккаунтов, а также операции с роллапами, попытки двойного бейкинга, внесение предложений и другие;
  • вознаграждения за бейкинг и делегирование за цикл;
  • статистика сети за указанный период;
  • котировки Tezos к фиатным валютам и криптовалютам от бирж Binance, Kraken, HitBTC и других.

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

  1. Получаем баланс USDT конкретного адреса, для этого запрашиваем значение big_map Ledger контракта USDT (id 198031) по ключу адреса и id 0.

14

  1. Получаем информацию о котировках tez к BTC на Binance.

15

  1. Получаем данные о текущей эмиссии tez за указанный период: количество токенов в обращении, созданные tez для вознаграждения бейкеров, сжигание для оплаты хранилища и другие цифры.

16

Que Pasa

Que Pasa — селективный индексер смарт-контрактов на Rust. Его разработали Рик Кломп и Джон Ньюбай из TzConnect.

В отличие от TzIndex и TzKT Que Pasa работает только в self-hosted режиме. Главная фича — низкие требования к процессору и оперативной памяти, можно использовать старый ноутбук или Raspberry Pi.

Que Pasa записывает все состояние указанного смарт-контракта в базу данных PostgreSQL: список и детали операций с каждой точкой входа, все записи в хранилище, содержание big_map и другое. Пользователю не нужно писать обработчики блокчейн-данных — Que Pasa делает это автоматически.

Для экономии времени при первом индексировании контракта разработчики добавили опцию с использованием Better Call Dev, специального блокчейн-обозревателя для получения детальной информации про смарт-контракты и операции с ними. Если она включена, Que Pasa будет запрашивать у Better Call Dev уровни блоков, в которых менялось состояние указанного контракта, и индексировать только их.

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

Лицензирование: код Que Pasa опубликован под лицензией MIT, и его можно бесплатно использовать в коммерческих проектах.

Индексер DipDup

DipDup — фреймворк для создания селективных индексеров с использованием Python, которые будут получать данные о вызовах смарт-контракта и их параметрах, а также состояние контракта. Его разработала команда Baking Bad.

17

DipDup работает только в режиме self-hosted на локальной машине или в Docker. По умолчанию индексер получает ончейн-данные от TzKT, но пользователь может подключить другие источники данных: сторонние API, RPC-ноды, ресурсы на IPFS и другие.

В отличие от Que Pasa, в котором нужно лишь указать адрес RPC-ноды и контракта для индексирования, в DipDup нужно самостоятельно написать логику индексирования, обработки и записи полученных данных в базу данных. DipDup поддерживает Hasura GraphQL для создания API эндпоинтов.

Лицензирование: Baking Bad опубликовала DipDup под лицензией MIT. Его можно использовать бесплатно в коммерческих проектах.

Индексер Dappetizer

Dappetizer — фреймворк для создания селективных индексеров с использованием JavaScript или TypeScript. Как и в DipDup, пользователь должен сам написать логику индексирования данных и записи в базу данных. Но в отличие от DipDup Dappetizer может индексировать не только смарт-контракты, но и операции в блоках вроде обновления балансов tez.

Dappetizer нужно запускать в self-hosted режиме на локальной машине или в Docker. Индексер получает данные только от RPC-нод, так что индексирование популярного контракта может занять несколько часов.

Dappetizer поддерживает Hasura GraphQL для передачи данных по API.

Лицензирование: Dappetizer опубликован под лицензией MIT, и его можно бесплатно использовать в любых проектах.

Домашнее задание

Посмотрите документацию индексеров:

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

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

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

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

  • простой блокчейн-эксплорер для отображения балансов tez и токенов пользователя;
  • сложный блокчейн-эксплорер со встроенной аналитикой бейкинга и смарт-контрактов;
  • кошелек Tezos с отображением токенов, NFT и истории операций пользователя;
  • роутер ликвидности, который выбирает лучшие маршруты обмена токенов в пулах ликвидности;
  • NFT-витрина, которая показывает последние сминченные NFT на выбранном NFT-маркетплейсе.

Решение

Чтобы сделать простой обозреватель с балансами, можно использовать любой индексер Tezos кроме Que Pasa — он работает со смарт-контрактами, но не с tez. При небольшом предполагаемом количестве пользователей можно использовать публичный индексер, так как понадобиться делать мало запросов.

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

Для простого кошелька можно использовать публичные API, чтобы запрашивать баланс tez, токенов и NFT и операции по адресу. Но чтобы сделать кошелек более безопасным, лучше захостить собственный полный индексер.

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

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

Поделиться в соцсетях: