Событийная модель

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

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

Существующее решение в блокчейне Голос

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

Для того, чтобы пользователь получал актуальную информацию о голосованиях за пост, выплатах вознаграждений, трансферных операциях, для блокчейна Голос создана сервисная библиотека Призма. Данная библиотека реализует интерфейс между блокчейном и веб-сайтом приложения GolosIO. Пользователь, обращаясь к веб-сайту, получает необходимую информации о событиях, происходящих в блокчейне (рис. 1).

Рис. 1 — Структурная схема обработки транзакций в блокчейне Голос

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

  • Trx — транзакция.

  • ПУ — панель управления веб-сайта GolosIO, предоставляет интерфейс пользователю для формирования транзакций, содержит необходимые для этого клавиши и настройки.

  • БД — хранилище событий (база данных библиотеки Призма).

  • Блокчейн Golos:

    • Плагины — программные компоненты, используемые для обработки операций в транзакциях;

    • БД — внутреннее хранилище блокчейна.

  • Блок-лог — цепочка блоков с упакованными в них транзакциями.

  • Призма — сервисная библиотека, анализатор состояния блок-лога.

На схеме синим цветом выделено решение обработки событий, происходящих в блокчейне.

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

Недостатки решения обработки событий в блокчейне Голос

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

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

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

Длительная процедура в определении времени закрытия поста усложняет логику расчета выплаты вознаграждений за пост. Основной расчет выплаты вознаграждений выполняется в плагинах блокчейна сразу после закрытия поста. Поскольку Призма не получает информацию о закрытие поста, она вынуждена постоянно обращаться за информацией в БД блокчейна, чтобы определить состояние поста. При этом, если у Призмы недостаточно данных, она вынуждена выполнять свой расчет выплаты вознаграждений, то есть дублировать его. Более того, логика Призмы реализована не на языке плагинов (С++), а на языке JavaScript. Результаты расчета Призмы попадают на веб-сайт GolosIO и они могут отличаться от результатов, полученных в плагинах, которые являются действительными.

Выполнение операций по переводу средств между балансами пользователей требует постоянных обращений Призмы в БД блокчейна для получения актуальных данных о балансах пользователей.

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

Событийная модель в блокчейне CyberWay

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

Поступающие в блокчейн CyberWay транзакции обрабатываются смарт-контрактами. Результат обработки всех операций, в том числе неявно заданных, регистрируется как событие и отправляется в плагин обработчика событий (англ. event engine, далее — ЕЕ). Плагин ЕЕ на каждое полученное от смарт-контракта событие формирует соответствующее этому событию сообщение. Существует четыре вида сообщений, формируемых плагином ЕЕ, внутри которых находится информация о действиях, выполненных явным или неявным образом.

Сохранение информации о всех событиях непосредственно в блокчейне является труднореализуемой задачей из-за требуемых для этого значительных ресурсов. Поэтому для хранения информации о событиях используется сервисный компонент — брокер сообщений NATS. В качестве посредника в передачи сообщений от плагина ЕЕ в NATS используется утилита Notifier.

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

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

Рис. 2 — Структурная схема обработки транзакций в блокчейне CyberWay

Условные обозначения на структурной схеме

  • Блокчейн CyberWay:

    • События (events) — операции, выполняемые в смарт-контрактах;

    • Обработчик событий (ЕЕ) — плагин, регистрирующий события, происходящие в смарт-контрактах;

    • БД — внутреннее хранилище блокчейна (БД Состояния).

  • Утилита Notifier — прослойка, которая обеспечивает получение сообщений в формате ЕЕ и передачу их в брокер сообщений NATS.

  • Брокер NATS (от англ. NAT Streaming) — брокер сообщений.

  • Призма — сервисная библиотека.

  • Приложение (App) — приложение, разрабатываемое пользователем.

    На схеме красным цветом выделены компоненты событийной модели.

В отличие от структурной схемы, приведенной на рис.1, реализованное в CyberWay решение обеспечивает информацией библиотеку Призма о всех выполняемых действиях, в том числе виртуальных, в смарт-контрактах в полном объеме и избавляет библиотеку от постоянного обращения в БД Состояния за актуальными данными аккаунтов. Следовательно, такая событийная модель позволяет предоставить пользователю на веб-сайте приложения всю необходимую ему информацию о происходящих в блокчейне событиях.

Обработчик событий

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

В настройках плагина указывается перечень смарт-контрактов, от которых могут приниматься события. Целью такой фильтрации является сокращение ресурсов процессора. Из всего перечня смарт-контрактов указываются только интересующие (например, для выполнения операции по переводу средств необходимо указать смарт-контракт cyber.token).

В зависимости от внутренних настроек плагин ЕЕ может находиться на узлах (нодах) блокчейна в одном из двух состояний — включенном или выключенном.

Рекомендации

Во включенном состоянии ЕЕ потребляет значительные ресурсы процессора, расходуемые на декодирование. Поэтому на узлах (нодах) валидаторов ЕЕ должен находиться в выключенном состоянии.

На дублирующих узлах (нодах) валидаторов ЕЕ может находиться во включенном состоянии. Все сообщения, о том, что происходит в системе, будут фиксироваться в передаваемом ему файле, указанном в настройках параметров.

Сообщения, формируемые обработчиком событий

На каждое событие, поступающее от смарт-контрактов, ЕЕ формирует одно из четырех сообщений:

  • AcceptTrx. Сообщение формируется на каждую принятую блокчейном транзакцию и содержит информацию о созданной транзакции.

  • ApplyTrx. Сообщение формируется после выполненной операции из транзакции и содержит информацию о действиях (actions) и событиях (events), произошедших при выполнении операции.

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

  • CommitBlock. Сообщение информирует, что блок принят большинством валидаторов, составляющим не менее «2/3+1» от общего их количества. Блок отправлен в блок-лог и является невозвратным (англ. last irreversible block). Его история не может быть изменена. На каждый такой созданный блок появляется сообщение CommitBlock.

Все действия, которые запрашивает пользователь при формировании транзакции, автоматически попадают в ЕЕ. При этом автоматически создается сообщение AcceptTrx и фиксируются все действия, которые выполняются в смарт-контракте, в том числе неявно заданные и выполненные неявным образом. В случае необходимости смарт-контракт может дополнительно создать событие event с соответствующими аргументами и записать его в результирующую структуру. Поля структуры содержат действия, которые переданы в ЕЕ. Отправляемые события из поля events, должны быть описаны в ABI-файле этого смарт-контракта. В описаниях events указывается набор аргументов.

Пример с типом сообщения AcceptTrx

{
"msg_type": "AcceptTrx",
"id": "ce41f90 … a8a62", // идентификатор транзакции
"accepted": true, // транзакция принята в блокчейн
"implicit": false, // «true» — неявная (скрытая) транзакция
"scheduled": false // «true» — отложенная транзакция
}

Сообщение информирует, что блокчейн принял на обработку транзакцию с указанным идентификационным номером. Наличие «false» в полях «implicit» и «scheduled» указывает, что принятая транзакция является явно заданной и не относится к отложенным.

Пример с типом сообщения ApplyTrx

{
"msg_type": "ApplyTrx",
"id": "56c93f … 3c285", // идентификатор транзакции
"block_num": 8, // номер блока в цепочке блоков
"block_time": "2019-04-25T10:01:48.000", // время создания блока
"actions": [ // произошедшие действия
{
"receiver": "cyber.token",
"code": "cyber.token",
"action": "transfer", // действие: трансферная операция
"data": "",
"args": { // аргументы действия
"from": "cyber", // отправитель средств
"to": "cyber.stake", // получатель средств
"quantity": {
"amount": 50000000000000, // перечисляемая сумма
"decs": 4,
"sym": "SYS"
},
"memo": ""
},
"events": [ // произошедшие события
{
"code": "cyber.token", // код события
"event": "balance", // событие: изменение баланса аккаунта "cyber"
"data": "",
"args": {
"account": "cyber", // имя аккаунта отправителя средств
"balance": {
"amount": 10000192666580, // остаток на балансе отправителя
"decs": 4,
"sym": "SYS"
}
}
},
{
"code": "cyber.token",
"event": "balance", // событие: изменение баланса аккаунта "cyber.stake"
"data": "",
"args": {
"account": "cyber.stake", // аккаунт получателя
"balance": {
"amount": 50000000000000, // сумма на балансе получателя
"decs": 4,
"sym": "SYS"
}
}
}
]
}
]
}

Сообщение информирует, что выполнена операция transfer, при выполнении которой произошли два события — изменились балансы аккаунтов отправителя и получателя средств.

Пример с типом сообщения AcceptBlock

{
"msg_type": "AcceptBlock",
"id": "00000005 … 78e7c", // идентификатор блока
"block_num": 5, // номер блока в цепочке блоков
"block_time": "2019-04-30T16:01:12.000",
"validated": true,
"in_current_chain": true,
"trxs": [ // перечень транзакций, содержащихся в блоке
{
"id": "db85... 19af9e5", // идентификатор транзакции
"status": "executed", // транзакция выполнена
"cpu_usage_us": 12322, // ресурс CPU, затраченный на выполнение транзакции
"net_usage_words": 25 // ресурс NET, затраченный на выполнение транзакции
},
....
{
"id": "cb6cf8b9a5da039dceb913d9713f3d56b6a9da403d2c44135fc55349c0176df9",
"status": "executed",
"cpu_usage_us": 54623,
"net_usage_words": 2664
},
{
"id": "384afa3778456b8b61ba43622f79b33b4b53fab020e2849aa36255ec7c7cadcc",
"status": "executed",
"cpu_usage_us": 45484,
"net_usage_words": 1099
},
{
"id": "ce41f9032b12ce3e5dbb4bf40c2d3ccb34f0a167f21d65391182f997aa3a8a62",
"status": "executed",
"cpu_usage_us": 479120,
"net_usage_words": 16
}
],
}

Сообщение информирует, что сформирован блок и помещен в цепочку блоков под номером 5. В блоке содержатся транзакции с указанными идентификационными номерами. Для каждой из транзакции приведены значения ресурсов bandwidth, затраченных на ее выполнение.

Пример с типом сообщения CommitBlock

{
"msg_type": "CommitBlock",
"id": "000000034044... ac178e7c", // идентификатор блока
"block_num": 3,
"block_time": "2019-04-30T16:01:12.000",
"validated": true,
"in_current_chain": true
}

Сообщение информирует, что сформированный блок принят валидаторами и помещен в цепочку блоков под номером 3.

Утилита Notifier

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

В зависимости от настроек формируемые плагином ЕЕ сообщения о событиях записываются либо в файловый дескриптор, либо передаются в конвейер (англ. pipeline).

Для передачи сообщений о событиях в брокер сообщений NATS создана утилита Notifier. Notifier открывает линию pipeline, получает событие и отправляет его в NATS. Затем запускается узел (нода), которая передает в линию всю информацию о событии.

Брокер сообщений

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

Задача воспроизведения ранее произошедших событий не входит в рамки функций EE. Для поддержки данной функциональности в событийную модель подключен отдельный сервис — брокер сообщения NATS. Этот сервис имеет настройки и обеспечивает сохранение полученной информации о событиях на жесткий диск с возможностью доступа к этой информации.

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

Библиотека Призма

Библиотека Призма является продуктом разработки команды ГолосИО. Библиотека предоставляет пользователю информацию о событиях, произошедших в блокчейне, в удобной для него форме. Пользователь может также разработать собственное приложение App (на рис. 2 выделено зеленым цветом) для получения информации о событиях. Приложение App будет легко реализуемо с остальными компонентами системы.

Информация по реализации библиотеки Призма будет предоставлена позже.

Достоинства решения

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

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

    • перечисление с баланса пользователя определенной суммы на баланс смарт-контракта вестинг;

    • информирование пользователя смарт-контрактом вестинг об изменении его (пользователя) баланса.

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

Решение позволяет исключить обращения событийной модели в БД Состояния (например, за получением данных о балансах пользователей).

  • Пример 2. Выполнение операции по переводу части средств с баланса одного пользователя на баланс другого приводит к изменению данных сразу двух балансов. Смарт-контракт cyber.token дополняет действие transfer событиями event со значениями измененных балансов. В сформированном результирующем событии будет находиться вся актуальная информация о выполненной трансферной операции. Исчезает необходимость обращения в БД Состояния, благодаря чему работа блокчейна не прерывается.