waves_logo Docs
  • Почему Waves
    Почему Waves
  • Основные понятия
    Основные понятия
  • Аккаунт
    • Создание аккаунта
      Создание аккаунта
    • Адрес
      Адрес
    • Баланс аккаунта
      Баланс аккаунта
    • Хранилище данных аккаунта
      Хранилище данных аккаунта
    • Псевдоним
      Псевдоним
    • dApp и смарт-аккаунт
      dApp и смарт-аккаунт
    Аккаунт
  • Токен (ассет)
    • NFT: невзаимозаменяемый токен
      NFT: невзаимозаменяемый токен
    • Смарт-ассет
      Смарт-ассет
    • ID токена
      ID токена
    • WAVES
      WAVES
    Токен (ассет)
  • Транзакция
    • Комиссия за транзакцию
      • Спонсирование комиссии
        Спонсирование комиссии
      Комиссия за транзакцию
    • Подпись и подтверждения
      Подпись и подтверждения
    • Типы транзакций
      • Вызов скрипта
        Вызов скрипта
      • Выпуск
        Выпуск
      • Генезис
        Генезис
      • Данные
        Данные
      • Довыпуск
        Довыпуск
      • Закрытие лизинга
        Закрытие лизинга
      • Лизинг
        Лизинг
      • Массовый перевод
        Массовый перевод
      • Обмен
        • Ордер
          Ордер
        Обмен
      • Обновление информации ассета
        Обновление информации ассета
      • Перевод
        Перевод
      • Сжигание токена
        Сжигание токена
      • Cоздание псевдонима
        Cоздание псевдонима
      • Спонсирование
        Спонсирование
      • Установка скрипта
        Установка скрипта
      • Установка скрипта ассета
        Установка скрипта ассета
      • Ethereum-like транзакция
        Ethereum-like транзакция
      Типы транзакций
    • Валидация транзакции
      Валидация транзакции
    Транзакция
  • Блок
    • Корневой хеш транзакций
      Корневой хеш транзакций
    • Блок генезиса
      Блок генезиса
    Блок
  • Нода
    • Лизинг
      Лизинг
    • Доход генератора блока
      Доход генератора блока
    • Монетарная политика
      Монетарная политика
    Нода
  • Mainnet, Testnet, Stagenet
    Mainnet, Testnet, Stagenet
  • Unit Zero
    Unit Zero
  • Оракул
    Оракул
  • Протоколы и форматы данных
    • [en] Cryptographic practical details
      [en] Cryptographic practical details
    • Leased Proof of Stake
      Leased Proof of Stake
    • [en] Waves-NG solution
      [en] Waves-NG solution
    • Протокол Waves-NG
      Протокол Waves-NG
    • Waves 1.5
      Waves 1.5
    • Типы данных блокчейна
      Типы данных блокчейна
    • Бинарные форматы
      • Бинарный формат адреса
        Бинарный формат адреса
      • Бинарный формат псевдонима
        Бинарный формат псевдонима
      • Бинарный формат блока
        Бинарный формат блока
      • [en] Network message binary format
        • [en] Block message binary format
          [en] Block message binary format
        • [en] Checkpoint message binary format
          [en] Checkpoint message binary format
        • [en] Get block message binary format
          [en] Get block message binary format
        • [en] Get peers message binary format
          [en] Get peers message binary format
        • [en] Get signatures message binary format
          [en] Get signatures message binary format
        • [en] Handshake message binary format
          [en] Handshake message binary format
        • [en] Peers message binary format
          [en] Peers message binary format
        • [en] Score message binary format
          [en] Score message binary format
        • [en] Signatures message binary format
          [en] Signatures message binary format
        • [en] Transaction message binary format
          [en] Transaction message binary format
        [en] Network message binary format
      • Бинарный формат ордера
        Бинарный формат ордера
      • Бинарный формат транзакции
        • Вызов скрипта
          Вызов скрипта
        • Выпуск
          Выпуск
        • Генезис
          Генезис
        • Данные
          Данные
        • Довыпуск
          Довыпуск
        • Лизинг
          Лизинг
        • Массовый перевод
          Массовый перевод
        • Обмен
          Обмен
        • Обновление информации ассета
          Обновление информации ассета
        • Отмена лизинга
          Отмена лизинга
        • Сжигание токена
          Сжигание токена
        • Cоздание псевдонима
          Cоздание псевдонима
        • Спонсирование
          Спонсирование
        • Перевод
          Перевод
        • Установка скрипта
          Установка скрипта
        • Установка скрипта ассета
          Установка скрипта ассета
        • Ethereum-like
          Ethereum-like
        Бинарный формат транзакции
      • Бинарный формат подтверждений
        Бинарный формат подтверждений
      Бинарные форматы
    • [en] Validation rules
      [en] Validation rules
    Протоколы и форматы данных
  • Термины
    Термины
      • English
      • Русский
      On this page
        • Обзор
        • Снапшот состояния для транзакции
        • Хеш состояния для блока
        • Оспаривание
        • Противодействие недобросовестным оспариваниям
        • Пропущенные транзакции
        • VRF
        • Изменения схемы
        • Активация
      waves_logo Docs

          # Waves 1.5: легкая нода

          # Обзор

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

          # Снапшот состояния для транзакции

          Состояние блокчейна можно описать как набор соответствий key => value, который необходим для проверки последующих транзакций, включая конечный баланс WAVES, ассетов и лизингов для аккаунта, записи данных, статусы исполнения ордеров и т. д. Каждая транзакция, в свою очередь, каким-то образом изменяет состояние, создавая, изменяя или удаляя некоторые значения из состояния. Снапшот состояния для транзакции (transaction state snapshot, TSS) — это набор всех пар (key, value), затронутых транзакцией. На сетевом уровне TSS кодируются как protobuf-сообщение TransactionStateSnapshot.

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

          # Хеш состояния для блока

          Генератор вычисляет хеш снапшота состояния для транзакции (transaction hash, TH) путем построения списка бинарных строк si, представляющих изменения состояния. Эти бинарные строки сортируются в лексикографическом порядке и подаются на вход хеш-функции Blake2b. Для целей сортировки байты считаются беззнаковыми. Полученный хеш и является хешем состояния для транзакции.

          Для снапшота формируются следующие бинарные строки (|| — оператор конкатенации строк):

          • Балансы WAVES: address || balance
          • Балансы ассетов: address || asset_id || balance
          • Записи данных: address || key || data_entry
          • Скрипт аккаунта: sender_public_key || script || verifier_complexity). В случае удаления скрипта хешируется только sender_public_key.
          • Скрипт ассета: asset_id || script
          • Баланс лизинга: address || lease_in || lease_out
          • Параметры лизинга: lease_id || amount || sender_public_key || recipient
          • Статус лизинга: lease_id || is_active
          • Спонсорство: asset_id || min_sponsored_fee
          • Псевдоним: address || alias
          • Выполненное количество и комиссия ордера: order_id || filled_volume || filled_fee
          • Статические данные ассета: asset_id || issuer_public_key || decimals || is_nft. decimals занимает 1 байт.
          • Возможность довыпуска ассета: asset_id || is_reissuable || total_quantity
          • Название и описание ассета: asset_id || name || description || change_height
          • Статус выполнения неуспешной транзакции: tx_id || application_status. Статус выполнения представляет собой 1 байт: либо 0x01 (неудачное выполнение скрипта), либо 0x02 (транзакция пропущена; см. ниже).

          Логические флаги (is_active, is_nft, is_reissuable) кодируются как один байт, где 0x01 означает true, а 0x00 — false. Все числовые поля представляют собой 8-байтовые значения с прямым порядком байтов (big-endian), если не указано иное.

          Определим H0 как хеш пустой строки, а Hi — как хеш предыдущего хеша Hi-1, объединенного с THi. Hi — это хеш состояния после применения i-й транзакции:

          • TH = Blake2b(s1||s2||...||sm),
          • H0 = Blake2b('')
          • Hn = Blake2b(Hn–1 || THn)

          Генератор не включает снапшоты состояния в блок. Чтобы удостоверить подлинность TSS, генератор включает в заголовок блока финальный хеш Hn, где n — порядковый номер последней транзакции в блоке. Hn называется хешем состояния для блока.

          Этот алгоритм хорошо работает для Waves-NG: при добавлении нового микроблока к состоянию не требуется пересчитывать хеши. Как и другие изменяемые поля «жидкого» блока (например, корневой хеш транзакций — merkle root), хеш состояния блока изменяется при добавлении новых микроблоков.

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

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

          # Оспаривание

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

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

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

          Когда какая-либо нода получает блок с оспариванием, она валидирует как оспариваемый блок, так и консенсус по оспариванию. Если оспаривание валидно, эффективный баланс вредоносного генератора (и, следовательно, его генерирующий баланс для следующих 1000 блоков) считается равным 0. Нода, успешно оспорившая блок, получает вознаграждение вместо первоначального генератора.

          Уменьшение генерирующего баланса вредоносного генератора помогает предотвратить повторную попытку атаки. Сброс эффективного баланса до 0 в основной цепочке приведет к эффективному отключению майнера на следующие 1000 блоков.

          # Противодействие недобросовестным оспариваниям

          Недобросовестные генераторы могут распространять в сети невалидные оспаривающие блоки несколькими способами: транслируя альтернативный блок наверху блокчейна с намерением заменить валидный «жидкий» блок или предоставляя блок в ответ на запрос GetBlock во время синхронизации. В обоих случаях такие невалидные блоки не будут оспариваться генератором и вместо этого будут отброшены. Оспорить можно только исходный блок (не являющийся оспаривающим).

          # Пропущенные транзакции

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

          • Предположим, что регулярный баланс аккаунта генератора исходного блока равен 0 (то есть вся генерирующая мощность получена за счет входящего лизинга). Первая транзакция исходного блока переводит вознаграждение за блок со счета генератора в «сейф». Поскольку генератор оспаривающего блока меняется, эта транзакция больше не будет валидной.
          • Временная метка блока и адрес генератора доступны из скриптов Ride. Изменения в этих полях могут изменить результаты выполнения скрипта и либо сделать неуспешной транзакцию вызова скрипта, либо сделать транзакцию невалидной из-за того, что верификатор аккаунта-отправителя вернет false.

          Чтобы проверить корневой хеш транзакций (merkle root) исходного блока, оспаривающий блок должен включать все транзакции из исходного блока, поэтому никакие транзакции не могут быть отброшены, даже если они стали невалидными в оспаривающем блоке. Такие транзакции становятся пропущенными (elided): они остаются в блоке, но порождают пустое изменение состояния. Пропущенные транзакции обладают следующими свойствами:

          • могут появиться только в оспаривающем блоке (транзакции в обычных блоках никогда не могут быть пропущенными),
          • уникальность идентификатора транзакции по-прежнему требуется,
          • поле applicationStatus содержит значение elided,
          • метод /transactions/merkleProof API ноды предоставляет доказательства присутствия в блоке для пропущенных транзакций,
          • встроенные функции Ride transactionHeightById(), transferTransactionById() и transactionById() возвращают unit для пропущенных транзакций.

          # VRF

          VRF играет ключевую роль как на уровне консенсуса, так и на прикладном уровне. Поскольку VRF пересчитывается в оспаривающем блоке, важно убедиться, что оспаривающий генератор не сможет злоупотреблять механизмом оспаривания. Как упоминалось выше, только аккаунту с генерирующим балансом не менее 1000 WAVES разрешается оспаривать недопустимые хеши состояний. Это требование делает невозможным «добыть» конкретное значение VRF, чтобы переиграть dApp.

          # Изменения схемы

          В схему заголовка блока добавлены два новых поля:

          bytes state_hash = 11;
          ChallengedHeader challenged_header = 12;
          

          Поле state_hash содержит хеш состояния для текущего блока.

          Сообщение ChallengedHeader содержит поля заголовка блока, который был оспорен:

          message ChallengedHeader {
                  int64 base_target = 1;
                  bytes generation_signature = 2;
                  repeated uint32 feature_votes = 3;
                  int64 timestamp = 4;
                  int32 version = 5;
                  bytes generator = 6;
                  int64 reward_vote = 7;
                  bytes header_signature = 8;
          }
          

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

          # Активация

          После активации фичи № 22 “Light Node” схема блоков изменилась. Старые ноды не могут проверить подписи новых блоков, содержащих хеши состояния, поэтому не могут их добавить к своей цепочке. Ноды версии 1.4 проверяют активацию функции после того, как блок был добавлен. Поскольку новые блоки не добавлены, ноды не знают, что фича уже была активирована, и не могут отключиться из-за активации неподдерживаемой функции. Эта очевидная проблема привела бы к тихому отсоединению нод 1.4 от основной цепочки.

          Чтобы гарантировать, что ноды 1.4 остановятся после активации фичи, изменение структуры блоков было отложено на 1000 блоков: генераторы начали добавлять в блок хеши состояний на высоте активации + 1000. 1000 превышает максимальную глубина отката (100), поэтому ноды, работающие в режиме синхронизации, могут добавить все блоки и увидеть, что была активирована неподдерживаемая фича.

          Протокол Waves-NG
          Типы данных блокчейна
          Протокол Waves-NG
          Типы данных блокчейна