Квитанции и топология сети
Блокчейн живёт тем, что его узлы передают друг другу блоки и транзакции. Proof of Participation измеряет именно эту услугу. Когда зарегистрированный узел получает данные от другого зарегистрированного узла, он отвечает квитанцией — коротким утверждением, подписанным его ключом узла. Поэтому доказательство работы исходит от пира, который её получил, а не от узла, который на неё претендует. Какие пиры засчитываются, тоже решают не узлы: каждые 40 блоков протокол перетасовывает реестр с помощью сида блока и назначает каждому узлу его приоритетных пиров.
Приоритетные пиры: топология
Реестр перетасовывается раз в период из 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 минут, группа сговорившихся узлов не может устроить так, чтобы оказаться пирами друг друга и ручаться только друг за друга. Скорость соединения роли не играет, и никто не публикует список пиров.
Что говорит квитанция
Квитанция занимает 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.