Вики ZooBC
Proof of Participation

Квитанции и топология сети

Блокчейн живёт тем, что его узлы передают друг другу блоки и транзакции. Proof of Participation измеряет именно эту услугу. Когда зарегистрированный узел получает данные от другого зарегистрированного узла, он отвечает квитанцией — коротким утверждением, подписанным его ключом узла. Поэтому доказательство работы исходит от пира, который её получил, а не от узла, который на неё претендует. Какие пиры засчитываются, тоже решают не узлы: каждые 40 блоков протокол перетасовывает реестр с помощью сида блока и назначает каждому узлу его приоритетных пиров.

Узел A ретранслирует блок узлу B; B возвращает квитанцию, подписанную B; следующий блок A несёт эту квитанцию, которая двигает оценку участия A, а с ней и его долю новых ZBC.
Узел A ретранслирует блок узлу B; B возвращает квитанцию, подписанную B; следующий блок A несёт эту квитанцию, которая двигает оценку участия A, а с ней и его долю новых ZBC.

Приоритетные пиры: топология

Реестр перетасовывается раз в период из 40 блоков (topology_period_blocks), примерно раз в 10 минут. На первом блоке периода каждый зарегистрированный узел получает ключ сортировки:

key = SHA3-256(seed of the period's first block (64 bytes)
               ‖ node id (8 bytes, little-endian)
               ‖ period height (8 bytes, little-endian)
               ‖ "zbc-topology-v2")

Сортировка реестра по этим ключам даёт перемешанный список. Каждому узлу назначается окно из P идущих подряд узлов этого списка в качестве приоритетных пиров, где P — это max_assigned_peers: 12 в mainnet и 8 в devnet. Окно узла на позиции i начинается с позиции (i × P) mod L, где L — длина списка; окно всегда содержит ровно P узлов, а его начала разносятся, когда у P и L есть общий делитель. Отношение действует в одну сторону: если A — приоритетный пир B, то B от этого не становится приоритетным пиром A.

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

Реестр в порядке идентификаторов узлов сортируется по ключу SHA3-256 от сида, идентификатора узла, периода и метки; в перемешанном списке отмечено окно из 12 приоритетных пиров одного узла, которое перетасовывается каждые 40 блоков.
Реестр в порядке идентификаторов узлов сортируется по ключу SHA3-256 от сида, идентификатора узла, периода и метки; в перемешанном списке отмечено окно из 12 приоритетных пиров одного узла, которое перетасовывается каждые 40 блоков.

Что говорит квитанция

Квитанция занимает 232 байта:

ПолеБайт
ключ узла отправителя (узла, который передал данные)32
ключ узла получателя (узла, который подписывает)32
опорный блок: последний блок получателя, высота4
опорный блок: хеш32
тип данных: 1 для блока, 2 для транзакции4
хеш данных: какой блок или какая транзакция получены32
корень последнего пакета квитанций получателя32
подпись Ed25519 получателя над 168 байтами выше64

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

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

Пакеты и публикация

Отправитель хранит заработанные им квитанции. Для каждой высоты он собирает их в пакет не более чем из 1 000 квитанций, отсортированных по подписи, под корнем Меркла. Когда он создаёт собственный блок, он публикует в нём выборку своих квитанций двух видов: несвязанные квитанции, показанные как есть, и связанные квитанции, показанные с доказательством Меркла относительно корня более раннего пакета. Эталонная программа выбирает квитанции примерно 40-блочной давности; это её поведение, а не правило действительности.

Что проверяют валидаторы

Для каждой квитанции, опубликованной в блоке, каждый узел проверяет следующее (здесь n — число зарегистрированных узлов):

  • подпись получателя;
  • что хеш опорного блока — это блок этой цепочки на той высоте;
  • её возраст: квитанция истекает через max(max(100, 2 × n) + 1, receipt_lifecycle) блоков, что в mainnet составляет 518 400 блоков (около 90 дней);
  • начиная с высоты 40 — что подписант несвязанной квитанции был приоритетным пиром производителя блока в том периоде, из которого квитанция;
  • начиная с высоты 80 — доказательство Меркла каждой связанной квитанции;
  • количество: не более 2 × min(n − 1, P) квитанций и никогда больше 200.

Некоторые вещи правилами действительности не являются, и вычитывать их в них не следует: валидаторы не проверяют, что отправитель квитанции — производитель блока, что квитанция новая, что её данным около 40 блоков или что связанный корень раньше появлялся в цепочке.

От квитанций к оценке

Ретрансляция приносит квитанции, а не оценку. Оценка меняется, только когда узел публикует свои квитанции в собственном блоке: если он показывает больше опорного значения, примерно половины того, что он мог бы показать, его оценка растёт, если меньше — падает. До высоты 40 никакая оценка не меняется. Подробности — в статье оценка участия, а как оценка превращается в доход — в статье лотерея coinbase.

См. также