ZYCORD docs
Русский
ZycordДокументацияТехническое описание

Zycord: одноранговая сеть самосертифицирующихся переходов состояния

Это непроверенный перевод

Эта страница переведена машиной и не проходила проверку. Там, где она расходится с английским текстом, протокол определяется английским текстом. Авторитетная архивная версия для ссылок — doi:10.5281/zenodo.22167490, а английский текст находится по адресу zycord.com/docs/whitepaper/.

Zycord: одноранговая сеть самосертифицирующихся переходов состояния. Автор — Simstoshi, v1.0, 2026. Каждая транзакция несёт состояние, которое она прочитала, и состояние, которое она записала, поэтому её проверка — чистая функция от её байтов — без диска, без истории, без доверия и без границы параллелизма.

Аннотация

Все крупные блокчейны масштабируются за счёт того, что каждый узел заново исполняет каждую транзакцию поверх общего глобального состояния. С ростом пропускной способности растут и требования к узлу, а сеть централизуется. Мы предлагаем реестр, построенный из самосертифицирующихся переходов состояния. Каждая транзакция несёт состояние, которое она прочитала, и состояние, которое она записала, поэтому её проверка — чистая функция от её байтов: без диска, без истории, без доверия, без границы параллелизма. Сама цепочка никогда ничего не исполняет. Она упорядочивает сертификаты и фиксирует их детерминированной свёрткой (fold), которая применяет каждый сертификат, чьи объявленные входы всё ещё верны, и пропускает остальные. Пропуск — это не сбой, а событие с ценой. За каждым сертификатом стоит поручитель, который страхует его от устаревания, поэтому у конфликтов есть владельцы, двусмысленное поведение объективно наказуемо, а спам дорог по построению. Контракты объявляют, по каждому слоту хранилища, является ли доступ точным, охраняемым или коммутативным; поэтому платежи, чаевые и эмиссии никогда не конкурируют. Комиссии разделяются на два рынка: один — за последовательное изменение состояния, которое дефицитно, другой — за параллельную проверку, которая нет; поэтому тяжёлая криптография дёшева по замыслу. Это свойство делает возможными конфиденциальные платежи — скрытые суммы и одноразовые адреса получателей поверх публичного графа транзакций, — криптографическая стоимость которых целиком приходится на параллельный рынок, а риск инфляции по которым правило свёртки ограничивает балансом экранированного пула, а не просто проверяет постфактум. Последовательна только фиксация, а фиксация — это цикл по памяти. Каждый узел проверяет всё на старте, дёшево и параллельно; как только проверка станет выборочной, а не повторяемой, стоимость на узел будет падать по мере роста сети.

Ссылка на этот документ. Архивная версионированная запись для ссылок — doi:10.5281/zenodo.22167490. PDF раздаётся с этого сайта вместе с отделённой подписью, сделанной ключом проекта E724 39CE DD85 11F9 D607 550B 87FD 60D5 EB4A 0B29. Текст ниже — это тот самый документ, без сокращений.

Чем этот документ не является

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

1. Введение#

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

Существующие архитектуры сплетают все три воедино. В господствующей модели узел не может проверить транзакцию, не располагая глобальным состоянием, поэтому проверка наследует пределы масштабирования состояния; а поскольку единый рынок gas оценивает все три ресурса вместе, проверка подписи конкурирует на том же аукционе, что и запись в хранилище. Недавние высокопроизводительные цепочки распараллеливают исполнение внутри узла, но каждый узел по-прежнему заново исполняет всё, и связывающим ограничением становится ввод-вывод состояния. Ответом были всё более крупные машины, что означает всё меньшее число узлов.

Эта работа идёт противоположным путём. Мы не распараллеливаем исполнение поверх общего состояния; мы полностью убираем состояние с параллельного пути. Транзакция становится сертификатом, который несёт собственные входы и выходы. Его проверка — чистая функция от его байтов. Работа цепочки сжимается до упорядочивания сертификатов и прогона по ним детерминированной свёртки (fold) — цикла сравнений и сложений, который обращается к состоянию ровно один раз на сертификат. Конфликты не делают блоки недействительными; они приводят к тому, что отдельные сертификаты пропускаются, и каждый пропуск выставляется в счёт поручителю, внёсшему залог. Параллелизм не обнаруживается во время исполнения; он объявляется, слот за слотом, автором контракта.

Дальнейшие разделы определяют сертификат (§2), свёртку (fold) (§3), типизированный доступ к состоянию (§4), экономику страхования (§5), прикладные секвенсоры (§6), устойчивость к цензуре (§7), двойной рынок комиссий (§8), доказательства мошенничества и путь к выборочной проверке (§9), виртуальную машину (§10), нативные активы без машины (§11), конфиденциальные платежи (§12), сетевое взаимодействие (§13), запуск в три эры и его казну (§14) и измерения на эталонной реализации (§15).

2. Сертификаты перехода состояния#

Сертификат — единственный тип транзакции в Zycord:

Certificate {
    reads:   [(slot, access, operand)]   // declared inputs
    writes:  [(slot, op, value)]         // declared outputs
    program: bytes                       // code or native-op reference
    sigs:    [signature]                 // spending authority
    underwriter: (id, sig, seq)          // who insures it (§5)
    ttl:     height                      // valid if committed by this height
    fee:     (seq_gas_bid, par_gas_bid)  // two markets (§8)
}

Слот — это (address, word). Сертификат является действительным, если проходят три проверки, ни одна из которых не требует состояния:

  1. каждая sig авторизует те ячейки, которые она расходует;
  2. подпись поручителя корректно сформирована над (certificate, ttl);
  3. повторное исполнение program поверх объявленных reads даёт в точности объявленные writes. Подписи должны быть каноническими, и это правило консенсуса, а не хороший тон библиотеки. Идентификатор сертификата — это хеш его авторизующих полей: reads, writes, program, underwriter, ttl и заявок на комиссию. Подписи в их число не входят, и следующий абзац объясняет почему. Множество виденных, ключом в котором служит этот идентификатор, и есть вся защита от повтора. Комиссия — авторизующее поле, а не предпочтение для ретрансляции, и различие здесь денежное: заявка есть согласие подписавшего на издержки, поэтому заявка вне идентификатора была бы заявкой, которую любой на пути мог бы переписать — раздуть, чтобы сжечь баланс отправителя через базовую комиссию, или обнулить, чтобы сертификат не попал ни в один блок. То, что платит сертификат, есть часть того, что авторизовал его подписавший, и идентификатор говорит об этом. Каноничность покупает нечто более узкое, чем идентификатор, и всё же является правилом консенсуса: схема, допускающая две кодировки одной подписи, допускает два экземпляра одного сертификата, и две реализации, расходящиеся в том, какая из них проходит проверку, разошлись в форк на сертификате, который ни одна из них не может назвать недействительным. Правило, закрывающее это, укладывается в одно предложение: неканоническая кодировка подписи недействительна, а реализация, чей верификатор принимает такую кодировку, не является реализацией этого протокола. Надёжные схемы отвергают такие кодировки и без того; записать это стоит потому, что схемы, которые их не отвергают, тоже популярны, и независимая реализация, потянувшаяся к одной из них, разошлась бы так, что никакой собственный тест этого не выявил бы.

Рандомизированные демонстрации — исключение, и это исключение структурное, а не вопрос кодировки. Доказательство диапазона (§12) рандомизировано: для одного утверждения доказывающий выбирает одноразовые числа, поэтому у одного утверждения есть неограниченно много действительных доказательств, все канонические, и нет неканонической кодировки, которую следовало бы отвергнуть. Два действительных доказательства одного утверждения — это не две кодировки одного доказательства; это два доказательства, и получатель платежа, у которого есть раскрытие, всегда может изготовить новое. Поэтому каноничность до них не дотягивается. Подпись — одна из таких вещей, и это легко упустить, потому что она не относится к экзотическим. Ed25519 — это доказательство знания по Шнорру: подписывающий выбирает одноразовое число, и каждое такое число даёт другую подпись над тем же сообщением, каждая действительная и каждая безупречно каноническая. Детерминированный вывод одноразового числа — правило для подписывающих, которое никакой верификатор не может проверить и никакое правило кодирования не может навязать, потому что каждая точка одноразового числа канонически кодируема, как и любая другая. Итак, у одной авторизации неограниченно много подписей, а у идентификатора, который бы их покрывал, было бы неограниченно много значений — каждое изготовимо любым одним из требуемых подписывающих сертификата, с нетронутым переносом подписей остальных, и каждое подлежит оплате в отдельном блоке. Модель угроз здесь у́же, чем у доказательства, а вывод тот же: доказательство может быть перерандомизировано получателем платежа, не владеющим ключом, тогда как для второй подписи нужен ключ, который сертификат и так требует. Идентификатор закрывает этот зазор по построению: он фиксирует то, что сертификат авторизует, и никогда то, что он лишь демонстрирует, поэтому и подписи, и доказательства путешествуют вне прообраза идентификатора. Повторное подписывание или перерандомизация дают тот же идентификатор, множество виденных ловит дубликат, а блок, несущий оба, недействителен. Это делит поля сертификата на два рода — авторизация, которую идентификатор покрывает и которую подписывают подписи, и свидетельство, которое не покрывается ни тем, ни другим. Это разделение — не забота §12, ожидающая конфиденциальных платежей; оно несуще с блока 0, где единственное свидетельство, которое несёт сертификат, — это его подписи. Верификатор проверяет свидетельство по байтам на параллельной стадии, а затем отбрасывает его; в идентификатор, множество виденных и свёртку (fold) переходит только авторизация.

Это разделение создаёт обязательство, которое идентификатор больше не несёт, и оно названо здесь, а не обнаружено в эксплуатации. Свидетельство вне прообраза идентификатора — это свидетельство, которое любой на пути может подменить: возьмите сертификат, замените его доказательство мусором и распространите — тот же идентификатор, теперь недействительный экземпляр. Две открывающиеся при этом дыры закрываются двумя правилами. Во-первых, блок фиксирует то свидетельство, которое несёт. Список сертификатов блока — это список хешей экземпляров: по одному листу на сертификат, над всей его кодировкой, включая свидетельство, — так что «этот блок действителен» остаётся утверждением о байтах, которые блок сам закрепляет. Идентификатор отвечает на вопрос оплачена ли эта авторизация, хеш экземпляра — на вопрос доказывают ли это данные байты, и у этих двух вопросов никогда не бывает общего ключа. Одного листа достаточно, пока свидетельство неотделимо от кодировки, как это и есть, пока свидетельство — это подписи; когда доказательства из §12 сделают его отдельным полем, лист станет парой (идентификатор, хеш свидетельства), и фиксация останется той же фиксацией. Чем он никогда не должен стать, так это списком идентификаторов: тогда он не фиксировал бы вообще никакого конкретного свидетельства, а поскольку корень списка сертификатов — поле заголовка, а заголовок является прообразом для proof of work, подмена свидетельства не стоила бы тогда ничего и оставляла бы работу в силе. Это прецедент транзакций с фиксацией свидетеля, и ему следуют по той же причине, по которой он был изобретён: идентификатор, покрывающий свидетельство, был податлив, а идентификатор, игнорирующий незафиксированное свидетельство, слеп. Во-вторых, ретрансляция имеет дело с экземплярами, а не с идентификаторами: узел, получивший экземпляр, свидетельство которого не проходит проверку, отбрасывает этот экземпляр без ущерба для идентификатора — идентификатор не помечается, не кэшируется как недействительный, и более поздний экземпляр, проходящий проверку, ретранслируется как обычно. Изуродованная копия стоит изуродовавшему её пропускной способности на её отправку и не стоит сертификату ничего. Слепота предлагающего остаётся нетронутой: он включает экземпляры, принятые его собственной проверкой без состояния, поэтому его не легче склонить к включению изуродованного доказательства, чем к включению плохой подписи, и утверждение §3 сохраняет прежний смысл.

Действительность — чистая функция от байтов сертификата. Проверить её может любая машина: в пуле потоков, на другом компьютере, на GPU, без базы данных, без истории и без синхронизации. Проверки подписей группируются в пакеты по сертификатам; сертификаты от одной программы группируются в нагрузки типа «одна инструкция, много потоков» (§6); доказательства диапазона (§12) группируются с логарифмической предельной стоимостью. Это то свойство, на котором построено всё остальное в этой работе.

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

3. Реестр как свёртка (fold)#

Блок содержит заголовок, упорядоченный список хешей сертификатов и сами тела сертификатов. Тела — это данные цепочки: блок действителен только тогда, когда его тела доступны (§13). Предлагающий блок не исполняет ничего и не держит прикладного состояния; он упорядочивает байты, действительность которых может проверить по самим байтам. Он не вполне без состояния, и это исключение стоит назвать, а не округлить: он должен хранить множество идентификаторов сертификатов, виденных в пределах окна TTL, потому что включение одного и того же дважды делает блок недействительным, и никого нельзя склонить к этому случайно. Это множество ограничено TTL и допускает обрезку, поэтому TTL — параметр консенсуса, а не предпочтение для ретрансляции. Предложение блока намеренно дёшево и глупо, но не намеренно слепо.

Состояние цепочки определяется как свёртка (fold) по упорядоченным сертификатам:

apply_block(S, B):
    assert bodies_available(B)
    assert ∀c: height ≤ c.ttl ∧ ¬seen(c.id)     // an expired or replayed certificate
                                                 // makes the BLOCK invalid: a signature
                                                 // is billable at most once, and never at
                                                 // a position its signer could not avoid
    C ← sort(B.certs, key = (underwriter.id, underwriter.seq, c.id))
    for c in C:
        if leased(S, c):     bill(c, LEASED); mark_seen(c.id, c.ttl); continue  // §7; Era 1 only
        ok ← true
        for (slot, access, x) in c.reads:
            EXACT:  ok ← ok ∧ (S[slot] = x)
            GUARD:  ok ← ok ∧ pred_x(S[slot])
        if ¬ok:              bill(c, STALE);  mark_seen(c.id, c.ttl); continue
        w ← stage(S, c.writes)   // a target whose address is spent, or a delta that would
                                 // over- or underflow, fails HERE — nothing has landed yet
        if w = ⊥:            bill(c, STALE);  mark_seen(c.id, c.ttl); continue
        commit(S, w); settle_fees(c); mark_seen(c.id, c.ttl)

Записи проверяются, и проверяются до того, как хоть одна из них ляжет. В более ранних набросках этой схемы множество записей применялось безусловно, что читалось так, будто кредит может воскресить израсходованную ячейку и будто дельта может переполниться. Ни то, ни другое не верно, и оба варианта были бы фатальны, поэтому шаг подготовки теперь присутствует в схеме, а не оставлен спецификации. Арифметика проверяется везде, где появляется: дельта, которая вышла бы за 2²⁵⁶ или ниже нуля, пропускает сертификат вместо того, чтобы переполниться, — и поэтому же пределы предложения из §11 держатся при неограниченном числе одновременных эмиссий. Запись по адресу, чьи полномочия сожжены, отказывает громко, а не исчезает бесследно — именно для этого и нужен постоянный реестр израсходованных адресов, и он же является источником единственного исключения в теореме об атрибуции из §5.

**leased — механизм Эры 1, и в генезис-блоке его нет.** Он показан здесь потому, что этот раздел задаёт свёртку (fold) всего протокола, но в эре запуска нет ни аренд, ни принудительной очереди, ни со-подписантов, которых ими защищали бы, поэтому в бинарнике генезис-блока эта ветвь недостижима, — а недостижимый код консенсуса есть неаудируемый код консенсуса, поэтому он не поставляется. Один открытый вопрос отмечается, а не заминается: в нынешней записи LEASED выставляет счёт по сертификату в позиции, которую его подписавший не мог предвидеть, а это ровно то, что запрещает утверждение четырьмя строками выше. Либо этот исход не должен выставлять счёт, либо он должен делать блок недействительным. Выбор принадлежит той эре, которая вводит аренды, и он записан здесь, чтобы та эра не унаследовала это противоречие втихую.

Свойства, которые стоит указать явно:

Пропуск — это семантика, а не сбой. Сертификат, чьи чтения больше не верны, пропускается, комиссия за пропуск выставляется его поручителю (§5), а блок остаётся действительным. Включение и применение — разные события. Именно это позволяет предлагающему быть слепым: он никогда не сможет произвести недействительный блок, включив устаревший сертификат.

Детерминированность. Каждый узел выводит одинаковое состояние из одинаковой последовательности блоков. Ключ сортировки (underwriter, seq, certificate id) задаёт полный порядок на содержимом блока, поэтому свёртка (fold) нечувствительна к тому, как предлагающий чередует сертификаты разных поручителей, — и не оставляет предлагающему вообще никакой свободы, даже между двумя сертификатами, которые один поручитель подписал с одним и тем же seq. Собственный конвейер поручителя (seq по возрастанию) фиксируется в том порядке, в каком был подписан, в каком бы порядке предлагающий его ни отправил.

Ровно одно обращение к состоянию на сертификат. Свёртка (fold) выполняет сравнения, сложения и записи на горячем рабочем множестве «ключ-значение»: без исполнения кода, без проверки подписей, без повторного исполнения. Всё это уже произошло, параллельно, во время проверки действительности.

И никакой арифметики на эллиптических кривых. Конфиденциальные платежи (§12) помещают обязательства Педерсена в значения слотов, а обязательство — это точка кривой. Схема гомоморфна, и сумма двух обязательств осмысленна, что подталкивает свёртку (fold) их складывать. Свёртка отказывается. Сложение точек стоит сотни наносекунд против ~1 нс на сложение u256, и одна операция на кривой в единственной последовательной стадии израсходовала бы тот бюджет, который эта архитектура защищает. Свёртка только сохраняет байты обязательства в новые ячейки и сравнивает их на равенство — обе операции с памятью; вся арифметика на кривых происходит на параллельной стадии или в кошельке владельца (§12). Та же дисциплина управляет хешированием, о чём ниже.

Одна часть криптографии не убрана, и утверждать обратное было бы слишком удобно: идентификатор сертификата — это хеш его авторизующих полей (§2), а ключом множества виденных служит этот идентификатор, поэтому кто-то должен его вычислить. Важно где, и ответ таков: не обязательно здесь. Идентификатор зависит от байтов сертификата и ни от чего больше — ни от состояния, ни от порядка, ни от позиции, — поэтому он вычисляется рядом с проверками подписей на параллельной стадии и переносится в свёртку (fold) ровно так же, как и сам сертификат. Реализация, которая вместо этого пересчитывает его в последовательном цикле, обнаружит, что хеширование доминирует на стадии, которая должна быть про память, и эту ошибку стоит назвать, потому что её легко совершить. Мы хотим быть точны в том, что здесь убрано, а что нет. Свёртка по-прежнему выполняет произвольный доступ по всему состоянию, по одному обращению на объявленный слот, и фиксирующий узел по-прежнему держит это состояние. С последовательного пути уходит всё, что окружает доступ на обычной цепочке, — интерпретация, проверки подписей, хеширование, аутентификация меркелизованного хранилища на каждую операцию, — так что состояние может жить в плоской таблице, а единственная последовательная стадия системы становится плотным циклом по памяти. Эталонная свёртка выдерживает 883 000 операций со слотами в секунду на ядро на десятиядерном настольном x86 (§15), и это единственная стадия, которая не распараллеливается.

Равенство значений, а не версии. Применимость сравнивает объявленные значения чтений, а не счётчики версий. Поскольку исполнение — чистая функция от множества чтений, слот, который изменился и вернулся к прежнему значению (случай ABA), по-прежнему применим: применить сертификат сейчас семантически тождественно тому, как если бы он был исполнен тогда. Поэтому система пропускает строго реже, чем управление конкурентностью на версиях. Для слотов со значениями-обязательствами сравнение есть побайтовое равенство обязательства: непрозрачное, точное и столь же дешёвое — при условии, что соблюдаются условия каноничности из §4.

Повтор и однократное выставление счёта. Идентификатор сертификата — это хеш того, что он авторизует, и никогда — подписей, которые эту авторизацию демонстрируют (§2), а как применённые, так и оплаченно-пропущенные сертификаты помечаются как виденные. Именно это различие делает правило правилом: подписывающий, который переподписывает одно и то же тело с новым одноразовым числом, получает тот же идентификатор, поэтому множество виденных ловит копию вместо того, чтобы выставлять за неё счёт. Включение виденного или истёкшего сертификата делает блок недействительным — а значит, подпись оплачивается не более одного раза и только в той позиции, которую её подписавший принял, поставив подпись. Без этого правила производитель блоков мог бы повторно включать или намеренно задерживать чужие сертификаты, чтобы сжигать средства их поручителей. Значения TTL ограничены консенсусом, поэтому множество виденных остаётся обрезаемым.

4. Типизированный доступ к состоянию#

Свёртка (fold), поддерживающая только точные чтения, сериализовала бы каждый популярный контракт: тысяча сертификатов, обращающихся к одному пулу AMM, дала бы одно применение и 999 пропусков. Ответ Zycord состоит в том, что параллелизм объявляется автором контракта, по каждому слоту, в самом формате сертификата. Дисциплин доступа три:

Точное чтение. В стиле SLOAD: чтение возвращает значение слота в вычисление и привязывает к нему сертификат. Произвольная логика; конфликты на горячих слотах; вотчина прикладных секвенсоров (§6).

Охраняемая дельта. Сертификат утверждает предикат на слоте — balance ≥ 10 — не читая значение в вычисление — и записывает знаковую дельту — balance += −10. Свёртка (fold) проверяет предикат против текущего состояния и применяет дельту. Любое количество охраняемых списаний и зачислений в один и тот же слот коммутирует: они применяются в любом порядке, а пропуск случается лишь тогда, когда охрана действительно не проходит (настоящий овердрафт), а не тогда, когда баланс просто изменился. Одна эта дисциплина покрывает переводы, эмиссии с потолком предложения, разрешения и доли хранилищ — то есть подавляющее большинство записей в цепочке.

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

Правило, которое сохраняет модель непротиворечивой: охраняемые значения не должны попадать в вычисление. Утверждение не возвращает ничего; дельта не читает ничего. Поэтому повторное исполнение остаётся чистой функцией от объявленных чтений, а действительность без состояния (§2) сохраняется. Родословная этой идеи стара и надёжна: escrow-транзакции в базах данных, transactional boosting, CRDT [9][10][11]. Но существующие цепочки в лучшем случае используют коммутативность внутри планировщика одного узла; Zycord делает её контрактом о параллелизме между узлами, обеспечиваемым форматом сертификата и оцениваемым экономикой страхования.

Второе правило того же ранга, вынужденное §12: ни один слот, хранящий скрытое значение, не допускает охраны от третьей стороны. Охрана, исход которой публично наблюдаем — применено или пропущено, — на балансе, который предполагается тайным, есть оракул баланса: отправьте balance ≥ x, понаблюдайте за свёрткой (fold), делите пополам — и log₂(баланс) попыток прочитают число, ни разу не раскрыв обязательство. Исправление структурное, а не статистическое. Скрытое значение живёт только в одноразовых ячейках, расходуемых подписью их владельца; дисциплина охраняемой дельты, весь смысл которой в том, что посторонние могут безопасно обращаться к слоту, зарезервирована для слотов с публичными значениями. Поэтому платежи по модели «списания» — разрешения, подписки, выборки из хранилищ — существуют только на прозрачном пути (§12).

Соблюдение этого правила требует, чтобы свёртка (fold) была способна отличить скрытый слот от публичного, а в плоской таблице она не может сделать это осмотром: сжатое обязательство и баланс u256 — оба по 32 байта. Поэтому ячейка со скрытым значением — не обычная ячейка, в которой случайно оказалось обязательство; это отдельный вид ячеек, создаваемый только нативной экранированной операцией (§12) и живущий в зарезервированной, выводимой области адресного пространства, так что дисциплина слота есть функция его адреса и проверяема по байтам, как и всё остальное. Без этого охраняемая дельта, направленная — по ошибке или по злому умыслу — в слот с обязательством, заставила бы свёртку прибавить u256 к кодировке точки кривой: арифметические проверки проходят, результат не является обязательством, и ячейка становится нерасходуемой. Ценность, уничтоженная в тишине, при том что в свёртке ничего не отказывает, — это ровно то, что призван предотвращать шаг подготовки из §3, а вид ячейки — это то, что позволяет ему предотвратить и данный случай.

Модель довершают ещё два примитива:

Ячейки однократной записи. Адрес, никогда не появлявшийся в цепочке, находится в состоянии ∅; первая запись переводит его в состояние хранит; подпись его ключом переводит его в состояние израсходован, навсегда. Запись в новую ячейку бесконфликтна по определению, поэтому платёж на свежевыведенный адрес — быстрый путь без конкуренции. Таково химерическое наследие этой сети [8]: постоянные ячейки в стиле счетов для контрактов, одноразовые ячейки в стиле UTXO для платежей — в одном реестре. Значения под израсходованной ячейкой могут быть уплотнены, как только блок, израсходовавший её, окажется глубже горизонта реорганизации, — глубина в подтверждениях, а не механизм финальности, поскольку в эре запуска нет финальности, которой можно было бы дождаться. Запись реестра, отмечающая адрес как израсходованный, не уплотняется никогда: именно она не даёт адресу воскреснуть, и она же — честная открытая проблема протокола, общая для всех конструкций с множеством нуллификаторов. Стелс-выходы из §12 едут по этому же пути без изменений и наращивают реестр ровно с той же скоростью, с какой это уже делают прозрачные платежи: одна запись на расходование, скрытое оно или нет.

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

Это накладывает ограничение на §12, с одним острым краем. Обязательство Педерсена vG + rH, вообще говоря, не является нулевой строкой, поэтому скрытый баланс не становится отсутствующим по арифметике, и никто, кроме владельца, не может сказать, что он пуст; постоянные скрытые слоты были бы неуплотняемы вечно, и это ещё одна причина, по которой экранированный путь состоит только из одноразовых ячеек, умирающих от расходования, — переход, который «ноль есть отсутствие» и не требовалось обеспечивать. Острый край в том, что v = 0, r = 0 — нейтральный элемент группы, а в кодировке Ristretto нейтральный элемент есть тридцать два нулевых байта — та самая строка, которая означает отсутствие. Обязательство никогда не должно совпадать с удалением, поэтому нейтральный элемент не является действительным обязательством: экранированная операция отвергает его на входе, наряду с проверками канонической кодировки, которые точке кривой и так необходимы (неканонические элементы поля, компоненты кручения), а эталонное H — это NUMS-точка с опубликованным выводом. Утверждение «побайтовое равенство точно» (§3) есть утверждение о точках лишь при выполнении этих условий.

Маяк эпохи. Программы не должны читать окружающие значения (метку времени, высоту) напрямую; это сделало бы исполнение функцией чего-то помимо объявленных чтений. Вместо этого протокол один раз за эпоху записывает маяк эпохи в зарезервированный слот, и программы читают его как любой другой слот, в идеале с охраной по диапазону (epoch ∈ [e, e+2]), что даёт осведомлённость о времени без устаревания на каждом блоке.

5. Застрахованные сертификаты: у каждого конфликта есть владелец#

Пропуск не должен быть бесплатным, иначе мемпул захлебнётся: атакующий мог бы опубликовать тысячи действительных сертификатов против одного и того же входа, заполнить блоки и заплатить за один. Но пропущенные сертификаты так и не тронули баланс отправителя, поэтому взыскивать с отправителя нечего; слотом для комиссии оказывается ровно устаревший вход. Ответ Zycord: сертификата не существует без поручителя — стороны, чьи внесённые в залог средства за него отвечают.

Быть обеспеченным поручительством можно тремя способами — один механизм в трёх обличьях:

  1. Самострахование. Отправитель прикладывает небольшой депозит из необременённой ячейки. Заранее ничего не арендуется: свёртка (fold) резервирует депозит в позиции сертификата внутри блока (схема из §3 опускает эту обвязку), а сертификат, доходящий до применения с уже израсходованным депозитом, отбрасывается — без выставления счёта, без пометки как виденный, с правом переотправки против нового депозита, — поэтому честные пользователи ничего не теряют на гонках за собственную депозитную ячейку. Пропуск при целом депозите сжигает его часть. Публикация же не стоит ничего, поэтому мемпул ограничивается политикой ретрансляции, а не консенсусом: узлы ставят предел тому, сколько они готовы держать на одного поручителя, — то же разделение труда, что и в любом мемпуле со времён Bitcoin. Это разрешительный минимум: любой всегда может совершать транзакции без контрагента. Это же единственный режим в эре запуска (§14), что сохраняет генезис-блок минимальным. Депозитная ячейка публична и принадлежит отправителю, а значит, самострахование — постоянный идентификатор, пришпиленный к каждому подписанному сертификату. Для прозрачных платежей это не раскрывает ничего, чего платёж не раскрывает и так; для экранированного платежа (§12) оно сводит на нет тот стелс-выход, за который платит, и §12 обращается к со-подписанию именно по этой причине.
  2. Со-подписанный. Поручитель с залогом проверяет сертификат против свежего состояния, со-подписывает (certificate, ttl, seq) и принимает на себя ответственность за пропуск. Взамен он может взять плату с отправителя вне цепочки, а его со-подпись и есть продукт: предподтверждение, за которым стоит собственный капитал поручителя. Ничто в этой роли не требует видеть, что́ сертификат перемещает: устаревание — свойство ячеек (живы они или израсходованы), а не сумм, поэтому поручитель оценивает экранированный сертификат так же, как прозрачный, не получая доверия к его сумме.

Две вещи, которым это обещание не должно давать смешаться, — потому что в этой работе они уже смешивались. Реакция протокола на пропуск — сжечь комиссию за пропуск из депозита поручителя: это штраф, не выплачиваемый никому, и именно он не даёт никому наживаться, вызывая пропуски. Возмещение отправителю — другая сделка: это коммерческое обещание поручителя, и данная конструкция пока не задаёт его как механизм консенсуса. Сделать его таковым — не вопрос формулировок: для этого нужны величина покрытия, объявленная в со-подписи, названный выгодоприобретатель, который не является отправителем (иначе продукт превращается в приглашение к страховому мошенничеству), и совокупная подверженность риску, отслеживаемая в цепочке, чтобы залог нельзя было продать дважды. Пока этого нет, «мой залог платит» — это заявление, которое делает поручитель и оценивает рынок, а не правило, которое обеспечивает свёртка (fold), и данная работа говорит об этом прямо, вместо того чтобы позволить неоднозначности продавать продукт.

  1. Принудительный. Путь устойчивости к цензуре (§7), обеспеченный депозитом пользователя и, в отличие от прочих, гарантированно применяемый. Экономика асимметрична для двух родов недобросовестного поведения, и в этой асимметрии всё дело:

Объективные нарушения наказываются. Если один поручитель со-подписывает два сертификата, чьи точные чтения конфликтуют (тот же слот, то же объявленное значение, пересекающиеся TTL), эти две подписи представляют собой самодостаточное доказательство двусмысленного поведения в цепочке; предъявить их может кто угодно, и залог урезается. Точно так же поручитель, со-подписавший сертификат, не проходящий проверку действительности без состояния (плохая подпись, неверное исполнение), наказывается чистым повторным исполнением: сертификат и есть доказательство мошенничества (§9).

Субъективные нарушения не наказываются никогда. Два разных поручителя, соревнующихся за один слот, не совершили доказуемого нарушения; тот, кто оказался позже в порядке свёртки (fold), платит небольшую комиссию за пропуск — и только. Медленные, отключившиеся или ненадёжные поручители теряют право участия и репутацию, а не средства. Сети умирают, когда задержка становится конфискацией; Zycord конфискует только то, что доказуемо из байтов.

И счёт приходит стороне, которую сертификат называет. Заголовок этого раздела — теорема, а не лозунг, и его стоит изложить вместе с его краями. Оплаченный пропуск всегда есть ровно одно из трёх: не прошедшее чтение или запись находится под адресом, чей ключ подписал сертификат; или это эмиссия, соревнующаяся с другой эмиссией того же объявленного эмитента актива, который тоже подписывал; или это зачисление на одноразовый адрес, чей собственный держатель вывел его из обращения (RETIRE, §11) уже после подписания сертификата. Ни одна сторона, которую сертификат не называет, не может вызвать выставление счёта. Только третий случай отделяет счёт от причины, и он ограничен по построению: вывести из обращения можно лишь одноразовые ячейки, поэтому получатель, публикующий постоянный адрес, не представляет никакой поверхности вовсе; сертификат может вывести из обращения не более фиксированного числа адресов (§13), что ограничивает, скольких платежей в полёте может коснуться один залп выводов; а комиссия за пропуск сжигается, а не выплачивается, поэтому никто не наживается, вызывая её.

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

6. Прикладные секвенсоры#

Охраняемые дельты растворяют конкуренцию за платежи. Остаётся логика точного чтения на горячем состоянии — книга заявок, пул AMM, — где двое честных поручителей в гонке всё равно произведут пропуски. Ответ протокола — позволить контракту выбрать себе сериализатор: контракт может зарегистрировать в цепочке ключ секвенсора с залогом, после чего путь точного чтения этого контракта открыт только сертификатам, со-подписанным этим секвенсором.

Секвенсор — это обычный сервер, который держит команда приложения: вебсокеты, очереди, автомасштабирование, любая веб-2 машинерия, — и ему доверяют только живучесть, но никогда не безопасность. Он не может подделать состояние: если он солгал о входах при построении, сертификат просто пропускается против канонической свёртки (fold), и ложь стоит его залога. Что он даёт:

Сериализацию. Он сдаёт слоты в аренду сертификатам в полёте с короткими TTL и сцепляет каждый сертификат с объявленными выходами предыдущего (он нумерует свои со-подписи полем seq; полный порядок свёртки (fold) гарантирует, что его конвейер фиксируется по порядку независимо от перетасовки предлагающим). Конкуренция за горячие слоты становится задачей планирования вне цепочки, невидимой для цепочки.

Пакетные сертификаты. N транзакций через один и тот же путь исполнения сворачиваются в один сертификат с агрегированными чтениями и записями, внутренние промежуточные записи схлопываются, а N подысполнений проверяются как единая SIMT-нагрузка. Именно здесь тезис о GPU становится осязаемым: сущность, которая сериализует, — это же и сущность, которая упаковывает работу в форму, нужную параллельному железу, и ей за это платят через рынок параллельного gas (§8).

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

Честное раскрытие: секвенсор первым видит поток заявок своего приложения и потому является естественной площадкой для MEV этого приложения. Zycord делает этот размен явным: приложение забирает собственный MEV вместо того, чтобы утечь его предлагающим блоки, а §7 ограничивает вытекающую отсюда власть. Тот же принудительный путь, который гарантирует выход, дисциплинирует и извлечение: пользователь, которому не нравится обхождение секвенсора, может обойти его целиком, заплатив лишь задержкой.

7. Принудительное включение с гарантированным применением#

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

Пользователь (или любой ретранслятор) восстанавливает состояние из публичной свёртки (fold), строит сертификат, прикладывает депозит и отправляет его в принудительную очередь. Предлагающие обязаны включить сертификаты из очереди в пределах F блоков (§13). В позиции включения свёртка проверяет его чтения против текущего состояния; если они верны, свёртка выдаёт детерминированную аренду на его слоты и назначает применение через D блоков. Пока действует аренда, со-подписанные сертификаты, затрагивающие эти слоты, упорядочиваются после него. Поэтому принудительный сертификат не может быть пропущен: допуск влечёт применение.

Льготный период D нужен для конвейера честного секвенсора, находящегося в полёте, — той его части, которая не затрагивает арендованные слоты. Всё, что их затрагивает, упорядочивается после принудительного сертификата — как со-подписанное, так и самозастрахованное, — и именно это делает «не может быть пропущен» истиной, а не пожеланием: сертификат, чьи чтения защищены на весь льготный период, не может устареть за этот период. Поскольку записи объявлены, состояние после применения предсказуемо, поэтому секвенсор сцепляется поверх ещё не применённого принудительного сертификата с уверенностью.

Аренда может покрывать только те слоты, над которыми у сертификата есть полномочия. Это ограничение механизм не даёт даром, а остальная конструкция без него не выжила бы. Объявление чтения не требует подписи — авторизацию выводят только записи, — поэтому без этого правила любой мог бы поставить в очередь принудительный сертификат, объявляющий чтения по чужим слотам, и заморозить их на D блоков ценой депозита. Квота на контракт этого тоже не ограничивает, поскольку нативные платежи не принадлежат никакому контракту. Поэтому аренда допустима лишь над теми слотами, в которые сертификат вправе записывать, — это та же проверка полномочий, которую свёртка (fold) уже применяет, только выполненная на шаг раньше.

Дальнейшие пределы против злоупотреблений: квота на контракт и на эпоху; депозит, покрывающий навязанные издержки; арендованные слоты отвергают дальнейшие принудительные записи до освобождения.

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

8. Два рынка: последовательный и параллельный gas#

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

Последовательный gas оценивает операции свёртки (fold): проверки чтений, записи, аренды. Это дефицитный ресурс, тот единственный цикл, который каждый узел прогоняет по порядку, и оценивается он соответственно.

Параллельный gas оценивает проверку: проверки подписей, единицы повторного исполнения, байты и тяжёлые предкомпиляции (проверка доказательств, агрегация подписей, постквантовые схемы). Он в изобилии, его предложение растёт с каждым ядром и каждым GPU, добавленными к сети, а его потолок на блок установлен высоко и дёшево.

Оба рынка имеют форму EIP-1559 [15], каждый в собственной единице: базовая комиссия сжигается, а приоритетная достаётся производителю блока — по сертификатам, которые применяются, и только по ним. Комиссия пропущенного сертификата сжигается целиком и не достаётся никому, и это не подробность тарифной сетки, а несущее правило всей экономической модели. Если бы пропуск давал чаевые, сторона, выбирающая содержимое блока, получала бы плату за устройство чужих неудач, и самым дешёвым способом заработка стало бы разведение пропусков, а не включение работы. Сжигание выворачивает это: пропуск съедает место под потолком и не даёт ничего, поэтому производитель, максимизирующий выручку, максимизирует применение и не просто безразличен к порождению пропусков, а активно против него. Сжигание последовательной базовой комиссии делает перегрузку единственного дефицитного цикла дефляционной (§14.2). Сжигание параллельной базовой комиссии оставляет предлагающего безразличным к тому, какие именно тяжёлые сертификаты заполняют дешёвую полосу, поэтому приоритет в полосе проверки нельзя продать в обход книги. Это разделение продолжает направление многомерных схем комиссий [18], доведённое до полностью раздельных рынков. Чего не решает ни один из рынков, так это того, сколько дефицитного ресурса должно быть; это потолок, и §8.1 даёт правило, которое его сдвигает.

Следствие — цель конструкции, изложенная как инвариант: тяжёлая криптография не нагружает сеть, по экономическому построению. Сертификат, который проверяет большое доказательство, но записывает два слота, платит почти всё на дешёвом рынке. Тем самым Zycord позиционируется как слой расчётов, где криптографические протоколы, слишком тяжёлые для цепочек с одним рынком, экономически оправданы. Тот же рынок платит секвенсорам за придание работе формы: секвенсор агрегирует N транзакций в один пакетный сертификат, платит за него одну параллельную заявку, а со своих пользователей берёт за N — маржа и есть плата за приведение работы к SIMT-форме (§6).

8.1 Эластичный последовательный потолок#

Рынок комиссий оценивает дефицит; он не решает, сколько дефицита должно быть. Два прежних ответа на этот вопрос провалились оба, в противоположных направлениях. Фиксированный потолок превращает распространение в аукцион, который пользователи проигрывают: когда блоки Bitcoin заполнились, комиссии перевалили за 50 долларов, и обычные платежи попросту были вытеснены с цепочки ценой — к единственной выгоде того, кто продавал место. Открытый потолок без спроса проваливается иначе: его форки с большими блоками купили ёмкость, которой никто не пользовался, и заплатили за неё безопасностью, потому что комиссии берутся из объёма, а не из простора. Поэтому потолок Zycord не фиксирован и не голосуется: сеть, чей автор не будет рядом, чтобы её форкнуть, не может считать рутинный рост событием управления, а голосование — это рукоятка: майнеры выигрывают от ограничения предложения, крупные операторы — от его расширения за пределы того, за чем могут поспевать малые узлы. Потолок есть функция консенсуса от измеренного спроса, присутствующая в генезис-блоке с блока 0 и не двигаемая никем.

Правило состоит из трёх частей, по одной на каждый масштаб времени. Внутри блока у каждого рынка есть цель T и жёсткая эластичная граница 2T; базовая комиссия шагает к равновесию на ограниченную долю за блок, в форме EIP-1559 из §8 — ограниченную потому, что неограниченная подстройка, как известно, колеблется, а не сходится. Через эпохи последовательная цель следует за спросом: T ← clamp(2·median_applied(e), T − T/Δ, T + T/Γ), с нижней границей на её генезисном значении, — где median_applied считает последовательный gas только по применённым сертификатам. Пропущенные сертификаты сжигают свои комиссии и не регистрируют ничего, поэтому единственный способ поднять потолок — добиться применения: устойчивое, бесконфликтное использование, сжигающее базовую комиссию. Форсирование роста стоит атакующему ровно столько же, сколько органичное распространение стоит всем остальным, — то есть механизм не может их различить, и ему это не нужно. Рост дополнительно поставлен в зависимость от сигнала здоровья эпохи: наблюдаемая частота конкурирующих заголовков остаётся ниже порога (Эра 0), контрольные точки финализируются по расписанию (с Эры 1), — так что ёмкость никогда не обгоняет то, что распространение доказуемо выдерживает. Устаревший блок — это ровно то событие, которого цепочка не записывает, поэтому сигнал импортируется единственным честным способом: заголовки могут ссылаться на недавние конкурирующие заголовки, без оплаты; ссылка требует настоящего доказательства работы, тогда как подавление сигнала требует, чтобы почти каждый предлагающий опускал ссылки, которые восстановит любой единственный честный. Эта асимметрия склоняет ограничитель к осторожности — в ту сторону, в какую ограничителю и следует склоняться. На каждый блок — клапан всплеска: предлагающий может превысить 2T вплоть до 4T, теряя квадратично то, что блок ему начисляет, — свою долю субсидии плюс комиссии блока, относительно расписания из §14.2, как безвозвратный недобор, не перенаправляемый никому, — причём штраф начисляется на суммарный последовательный gas, применённый и пропущенный без различия, чтобы превышение нельзя было со скидкой набить искусственным конфликтом. Базой служит выручка производителя, а не одна лишь субсидия, потому что эти две величины убывают не вместе: субсидия падает примерно до 1,6 % от своего значения в генезис-блоке по кривой из §14.2, тогда как выручка от комиссий, ради которой покупается всплеск, не падает вовсе, — поэтому сдерживание, выраженное в одной лишь субсидии, перестаёт сдерживать ровно там, где возможность наибольшая. Постоянное свойство должно оцениваться в чём-то, что следует за выгодой, — это тот же довод, которым EIP-1559 обосновывает привязку сбора к той ценности, которую приносит манипуляция. В генезис-блоке это почти ничего не меняет, поскольку комиссии близки к нулю. Доля казны из §14.1 берётся из несокращённой субсидии и не теряется никогда, потому что всплеск — выбор производителя, а казна ему не сторона. Настоящие всплески покупают проход немедленно и информируют контроллер эпохи; спам покупает штраф. Прецедент — механизм штрафной медианы Monero [19], с его задокументированным затором (рост замирает, когда типичная единица работы приближается к медиане), которого здесь удаётся избежать по построению, поскольку пакетные сертификаты (§6) держат типичную единицу малой относительно цели, а границы скорости следуют линии адаптивных пределов [20]. Параллельному потолку вся эта осторожность не нужна: он закреплён как фиксированное большое кратное последовательной цели и наследует её рост, что есть инвариант §8, пересказанный в терминах ёмкости.

Перетягивание каната здесь можно прочесть прямо по механизму. Комиссия пользователя тяготеет к нижней границе, потому что устойчивая перегрузка по определению есть тот самый сигнал, который поднимает потолок и опускает её обратно, — биткойновое равновесие вечного аукциона недостижимо. Производителю платит субсидия, пока сеть молода, и объём в зрелости, но никогда не дефицит; сжигание делает так, что каждый эпизод перегрузки накапливается в пользу монеты, которую производитель держит, а §8 уже сделала применение, а не исключение, стратегией максимизации выручки. Одна честная оговорка, дважды: эластичность гарантирует лишь то, что ёмкость никогда не станет причиной, по которой распространение застопорится, — она не производит спроса, как показали форки с большими блоками, — а растущий потолок позволяет расти состоянию, и поэтому записи в новые слоты стоят в последовательном gas дороже дельт: плоская таблица, в которой живёт свёртка (fold), расширяется не быстрее, чем питающий её потолок. Отсюда следует одно правило калибровки, и оно излагается потому, что его нарушение происходит бесшумно: отношение в генезис-блоке последовательной цели к байтовому потолку должно лежать ниже плотности того трафика, ради которого сеть построена, чтобы блок, полный обычных платежей, поднимал базовую комиссию, а не опускал её. Рынок, откликающийся наоборот на собственную расчётную нагрузку, не оценивает ничего, и это отношение задаётся по измеренному трафику до заморозки.

Ёмкость через эры. Потолки по числу сертификатов и по байтам масштабируются вместе с последовательной целью, а не стоят рядом с ней неподвижно: в генезис-блоке все три связывают в пределах двукратной разницы друг от друга, поэтому фиксированный становится настоящим пределом уже после одного удвоения и превращает эластичный в украшение. За ними стоят статические ёмкости: ширина списка сертификатов, задающая глубину дерева Меркла блока, и байтовая ёмкость, которой блок может достичь, вместе с лежащими под ней транспортными константами — блок путешествует кусками, поэтому ни одно сетевое сообщение не ограничивает блок. Ширина списка задана в генезис-блоке на всю кривую (2²⁵ сертификатов; повторное закрепление позже поместило бы в одну цепочку две ширины дерева Меркла, а виртуальное дополнение делает этот запас бесплатным). Байтовая ёмкость задаётся под сеть запуска и перезакрепляется на границах эр — которые и так являются жёсткими форками (§14) — против распространения, измеренного ограничителем здоровья; никогда внутри эры, никогда голосованием. Кривая, которой служит эта лестница, вытекает из Γ: цель нарастает не более чем в 2 раза за год полных здоровых блоков, поэтому потолок генезис-блока в ~90 применённых сертификатов в секунду (блок из §15 на 30-секундный интервал) достигает ~11 000 в секунду за семь лет устойчивого спроса, ~90 000 за десять, а менее чем за четырнадцать — тех ~1,1 миллиона в секунду, которые задаёт ширина списка 2²⁵: единственная стена, которую не двигает ни одна эра, и потому конец лестницы, а не её ступень. Единица здесь — сертификаты, а не платежи: сертификат несёт один платёж или те N, что секвенсор упаковал в него (§6), поэтому каждая цифра является нижней границей по транзакциям, а не утверждением о них. Условий ровно три, и каждое уже разобрано выше как механизм: спрос должен поддерживать полные блоки, потому что применённый gas — единственный вход, поднимающий T; распространение должно держать ограничитель здоровья открытым, потому что в ту эпоху, когда он закрывается, рост удерживается; и перезакрепления должны приходиться на эры, потому что между ними стеной является байтовая ёмкость. Вычисления условием не являются — свёртка (fold) проходит дальний конец кривой на одном измеренном ядре (§15), а проверка масштабируется железом, которым сеть не владеет (§2). Пропускная способность является: тела — это данные цепочки (§13), а выборочная проверка (§9) делит проверку, но никогда данные, поэтому каждый узел несёт каждый байт, и производитель на вершине кривой относится к классу дата-центров по одной лишь пропускной способности — принимаемое конечное состояние для производителей и ни для кого больше, поскольку стоимость проверки на узел движется в другую сторону (§9). Раньше пропускной способности связывает состояние: реестр израсходованных адресов (§4) растёт на одну запись на каждое одноразовое расходование, порядка 10² терабайт в год при 10⁵ сертификатов в секунду, что превращает объявленную в §4 открытую проблему из бессрочного пункта в работу, которую кривая ставит в расписание.

Константы (генезис-блок, иллюстративные, как в §13): делитель роста Γ = 512 на эпоху (потолок может самое большее удвоиться за год полных блоков); делитель убывания Δ = 1024 (простаивающая ёмкость уменьшается вдвое примерно за 2 года, никогда ниже генезиса); граница всплеска 4T, с потерей на границе доли субсидии производителя и комиссий блока (доля казны из §14.1 берётся из несокращённой субсидии и не теряется никогда, потому что всплеск — выбор производителя, а казна ему не сторона); ограничитель здоровья: процитированные конкурирующие заголовки ≤ 2 % блоков за эпоху; ёмкость списка сертификатов 2²⁵ (структурная, см. выше); байтовый потолок 2,5 МБ в генезисе, растущий вместе с целью до структурной байтовой ёмкости 8 МБ (перезакрепляется на эрах); потолок подписей на блок 6000 в генезисе, растущий вместе с целью, проверяемый до того, как будет проверена хоть одна подпись, — это граница объёма проверки, держащаяся отдельно от цены параллельного gas, потому что один параметр не может одновременно ограничивать работу и оценивать рынок.

9. Мгновенные доказательства мошенничества и путь к выборочной проверке#

Поскольку действительность есть чистая функция от байтов сертификата, недействительный сертификат сам является доказательством мошенничества. Любой, кто исполнит его повторно, может опровергнуть его одним сообщением, немедленно, без состояния и без интерактивной игры в деление пополам. В конфигурации запуска этот вопрос снят наилучшим образом: каждый узел проверяет каждый сертификат до принятия блока, поэтому недействительный сертификат никогда не доживает до того, чтобы понадобился вызов. Окно обретает смысл, как только проверка станет выборочной, и там оно является параметром распространения, а не протоколом разрешения споров: несколько блоков на то, чтобы одно сообщение пересекло сеть, за счёт поручителя, который засвидетельствовал сертификат (§5). Сравните с альтернативами: оптимистичные роллапы нуждаются в недельных интерактивных спорах, потому что для спора требуется состояние на спорном шаге; системы на доказательствах избегают споров, но платят за доказывающих, стоимость которых на порядки выше, чем у исполнения. Доказательства мошенничества в Zycord стоят столько, сколько стоит проверка: ~1× повторного исполнения.

Это открывает путь масштабирования, на который цепочкам с повторным исполнением не встать. Сети в принципе не нужно, чтобы каждый узел проверял каждый сертификат вечно. При наличии залогов поручителей проверка может стать выборочной: комитет на сертификат, отбираемый по VRF, такого размера, чтобы вероятность непроверенного недействительного сертификата была пренебрежимой, — причём любой полный узел волен проверить что угодно, а одного сообщения достаточно для урезания залога. В генезис-блоке все проверяют всё; это дёшево и параллельно. Выборочная проверка — дорожная карта, а не запуск. Но это дорожная карта, которая переворачивает отраслевую кривую: стоимость на узел падает по мере роста сети, тогда как в парадигме повторного исполнения стоимость на узел растёт вместе с пропускной способностью, пока не остаются одни дата-центры.

10. Машина: cEVM#

Zycord запускает одну виртуальную машину: cEVM, диалект EVM Ethereum [2], приспособленный к сертификатам. Выбор сделан намеренно. Бюджет новизны проекта потрачен на модель состояния, параллелизма и экономики; машина должна быть самой привычной вещью в системе. Solidity, его компиляторы, аудиторы и инструментарий переносятся без изменений.

Отличия от стандартной EVM:

  • SLOAD компилируется в точное чтение (объявленное в сертификате); SSTORE — в запись SET.
  • Новые опкоды SASSERT(slot, pred) и SDELTA(slot, ±v) дают доступ к охраняемым и чистым дельтам. SASSERT не кладёт на стек ничего — охраны не возвращают значений (§4).
  • TIMESTAMP и NUMBER читают слот маяка эпохи; никакого другого окружающего входа нет.
  • Учёт gas двойной (§8): опкоды хранилища расходуют последовательный gas; вычисления, calldata и предкомпиляции расходуют параллельный gas.
  • Формат транзакции — сертификат. Контракты Ethereum переносятся на уровне исходного кода; совместимость с кошельками на уровне сырых транзакций не заявляется, и мы не делаем вид, будто это не так. Перенесённый контракт работает в режиме сплошных точных чтений: корректно с первого дня, с сериализацией через секвенсор, если он горячий. Параллелизм включается по выбору, слот за слотом, и обычно это небольшая правка (карта балансов токена переезжает с SLOAD/SSTORE на SASSERT/SDELTA примерно за 30 строк). Чтобы флагманская возможность была видна с первого же блока эры виртуальной машины, а не ждала переносов, машина активируется вместе с нативной стандартной библиотекой — токен, копилка чаевых, эскроу, вестинг и эталонная гибридная книга заявок/AMM, — написанной в первую очередь на дельтах и заранее развёрнутой по известным адресам.

11. Активы без машины#

Эре запуска экономика нужна раньше, чем компьютер. Поэтому Zycord поставляет нативные активы как операции сертификата начиная с блока 0, без участия виртуальной машины: ISSUE (создать идентификатор актива с потолком предложения в ячейке однократной записи), MINT (охраняемая: minted + Δ ≤ cap), TRANSFER (охрана balance ≥ Δ, парные дельты; зачисление, нацеленное на чистую дельту или на новую одноразовую ячейку, и есть чаевые, поэтому чаевые не тратят собственного опкода) и RETIRE (сжечь адрес, не расходуя его: без чтений, без перемещения ценности, чистая запись, помечающая ячейку израсходованной, — собственно расходование происходит автоматически внутри TRANSFER). RETIRE оправдывает своё место дважды. Это примитив уплотнения и приватности, позволяющий получателю стереть одноразовый адрес, как только тот отслужил; и это же операция, стоящая за единственным исключением в теореме об атрибуции из §5, — третий случай существует потому что существует вывод из обращения, и поэтому формат сертификата ограничивает число выводимых адресов на сертификат (§13), и поэтому теорема излагается вместе с этим краем, а не в обход него. Набор замкнут: эти четыре операции и составляют весь набор инструкций генезис-блока, всякая иная операция — включая внесение залога — приходит с набором правил более поздней эры (§14), а теорема об атрибуции из §5 доказывается ровно против этой поверхности.

Стример, получающий десять тысяч чаевых в одном блоке, стоит свёртке (fold) десяти тысяч коммутативных сложений: ноль конфликтов, ноль пропусков, ни секвенсора, ни машины. Культуры чаевых на прежних цепочках жили милостью платформенных API и умерли вместе с ними; здесь чаевые — примитив протокола. Заодно, и не случайно, это непрерывное нагрузочное испытание центрального утверждения системы. Потолки предложения нативной монеты живут здесь, на прозрачном пути, обеспечиваемые проверяемой арифметикой из §3, и §12 их не затрагивает.

12. Конфиденциальные платежи#

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

Что скрыто, а что нет. Экранированный платёж скрывает свою сумму и откладывает связь со своим получателем. Будем точны насчёт «откладывает»: свежий стелс-выход не связываем в момент получения, но при отсутствии кольца его последующее расходование называет расходуемый выход, а называние выхода раскрывает, какой прежний платёж его пополнил. Несвязываемость держится до первого расходования и там заканчивается; это отсрочка, а не стирание. Не скрывает конструкция и положения отправителя в графе: сертификаты подписаны, обеспечены поручительством и упорядочены публично, поэтому наблюдатель видит, что платёж состоялся и кто за него поручился, — но не сумму и не то, какой именно из выходов получателя куда ушёл, пока это не раскроет расходование. Честное описание таково: конфиденциальные транзакции с одноразовыми адресами получателей поверх публичного графа, причём граф деанонимизируется задним числом по мере расходования выходов. Неоднозначность на стороне отправителя — кольцевые подписи, доказательства принадлежности над историческими выходами — вне области рассмотрения: кольцо ссылается на чужие выходы, что делает действительность функцией истории, а отсутствие состояния из §2 — то свойство, от которого протокол не отказывается. Модель угроз Monero требует другого протокола.

Экранированный выход. Экранированный платёж записывает новую ячейку однократной записи (§4), адрес которой является стелс-адресом: отправитель выводит из опубликованного ключа просмотра получателя и собственного эфемерного ключа одноразовый адрес, который может распознать только получатель и подписать за который может только ключ расходования получателя. Значение ячейки — обязательство Педерсена C = vG + rH; рядом с ним едут доказательство диапазона, что v ∈ [0, 2⁶⁴), и пара (v, r), зашифрованная на ключ просмотра получателя, плюс однобайтовая метка просмотра, позволяющая сканирующему кошельку рано отбрасывать большинство чужих выходов. Примитивы здесь — конфиденциальные транзакции со стелс-адресацией: та половина RingCT, что скрывает суммы, без кольца, и каждая из них имеет проверенное боевое внедрение.

Действительность остаётся функцией байтов. Проверка баланса экранированного сертификата — это уравнение обязательств: объявленные входные обязательства минус объявленные выходные обязательства равны fee·G, при публичной комиссии (см. о пуле ниже). Уравнение, доказательства диапазона и подписи — всё это проверяется только по байтам сертификата, на параллельной стадии, пакетами: проверка Bulletproof амортизируется логарифмически по пакету, и ничто из этого не касается состояния. Поддельный инфляционный сертификат — тот, чьи обязательства не сходятся при сломанном предположении или сломанном верификаторе, — всё равно действителен или недействителен исключительно по своим байтам, и свёртка (fold) никогда его не перепроверяет; это разделение на действительный/применимый из §2, работающее как задумано, а не исключение из него, а правило пула ниже — это то, что не даёт слому стойкости стать безграничным. Здесь же двойной рынок комиссий (§8) перестаёт быть доводом об эффективности и становится доводом о возможности: на цепочке с одним рынком gas конфиденциальные транзакции дороги, потому что миллисекунда проверки доказательства конкурирует на том же аукционе, что и запись в хранилище, тогда как здесь проверка целиком приходится на par_gas — дёшево по замыслу, — а последовательный рынок её вовсе не видит.

Свёртка (fold) хранит байты. При применении экранированный платёж — самый дешёвый сертификат из тех, что видит свёртка: его выходная ячейка новая, поэтому конфликтовать она не может (быстрый путь без конкуренции из §4); его входные ячейки либо живы, либо израсходованы — это поиск в реестре; а запись сохраняет 32 байта обязательства. Никакой арифметики на кривых в последовательную стадию не попадает (§3). Альтернатива, которую это правило отсекает, — постоянный «накопительный слот», гомоморфно пополняемый посторонними; она проваливается по трём фронтам: она помещает сложение на эллиптической кривой в последовательный цикл (§3); она создаёт переиспользуемый публичный идентификатор — ровно ту эвристику общего владения, которой стелс-адрес и призван избегать; а скрытый постоянный баланс приглашает те самые сторонние охраны, которые запрещает §4. Накопление происходит в кошельке: получатель держит множество одноразовых выходов, все распознаваемые через один ключ просмотра, и объединяет их, расходуя несколько собственных ячеек в одну новую — обычным экранированным сертификатом, с той частотой, какая ему угодна, пользуясь маяком эпохи (§4) как часами. Сумму, которую постоянный слот поддерживал бы в цепочке, владелец поддерживает вне цепочки, — и объединение не бесследно: объявление нескольких входов в одном сертификате есть публичное событие общего владения, более слабое, чем переиспользуемый идентификатор, но реальное, поэтому политика кошелька — сводить его к минимуму и никогда не смешивать несвязанные источники в одном объединении.

Расходование только владельцем — и что это запрещает. Скрытое значение расходуемо только подписью его владельца над его собственной ячейкой. Сторонних охран против скрытых балансов нет (§4), а потому нет и платежей по модели списания на экранированном пути: ни разрешений, ни подписок, ни хранилища, вычерпывающего экранированные средства пользователя. Эти схемы остаются на прозрачном пути, а граница между путями шириной в один сертификат. Ограничение устраняет оракул баланса: раз посторонний не может отправить догадку против баланса и прочитать пропуск, у оракула нет оператора.

Экранированный пул — публичное целое число, за которым следит свёртка (fold). Комиссии публичны. Coinbase публичен. Платежи в слоты контрактов публичны. Всякий переход между прозрачным и экранированным путями перемещает публично видимое v: экранирующий сертификат раскрывает v на входе, разэкранирующий раскрывает v на выходе. Поэтому общая сумма пула живёт в зарезервированном слоте, открытым текстом, и движется только охраняемой дельтой (§4): экранирование зачисляет в него, pool += v; разэкранирование охраняет pool ≥ v и списывает, pool += −v; комиссия экранированного сертификата списывает точно так же. Слот в точности равен Σ вход − Σ выход, а дисциплина охраняемой дельты позволяет неограниченному числу переходов коммутировать без конкуренции.

Это делает пул забором, а не сигнализацией. Сокрытие сумм меняет проверяемую арифметику u256 из §3 на вычислительную стойкость предположения о дискретном логарифме, и слом — предположения или, куда вероятнее, верификатора — подделывает обязательства внутри пула. Но поддельное обязательство не несёт открытого текста, а ценность покидает пул только через разэкранирование, которое списывает публичный слот под его охраной. Слот рос только на настоящем экранировании, поэтому разэкранирование, которое увело бы его ниже нуля, пропускается: поддельная ценность не может пройти охрану. Инфляция не осушает пул; она не может из него выйти. Радиус поражения криптографического отказа ограничен — правилом свёртки, а не бдительностью аудитора — настоящим содержимым пула, и режим отказа здесь не тихая утечка, а видимая гонка в реальном времени, в которой последние честные держатели не могут разэкранироваться: плохо, ограниченно и наблюдаемо, — то самое сдерживание, которое система без команды экстренного реагирования обязана иметь по построению. Прецедент конкретен: ошибка с подделкой в Zcash Sprout оказалась переживаемой потому, что её экранированный пул был ограниченной, поддающейся аудиту величиной; здесь эта величина не просто поддаётся аудиту, но несуща внутри свёртки. Потолки предложения нативных активов из §11 живут на прозрачном пути и по-прежнему обеспечиваются проверяемой арифметикой, оставаясь нетронутыми.

У пула есть цена в приватности, и ей место в протоколе: пересечения границы обнажают точные публичные суммы, а характерные суммы коррелируют. Наблюдатель, который видит, как v покидает пул вскоре после того, как v + fee в него вошло, узнал нечто, чего не скрыло ни одно обязательство. Стандартные номиналы на границе притупляют это, и кошельки используют их по умолчанию; протокол их не предписывает, потому что правило консенсуса не может отличить характерную сумму от законной. Связываемость при анализе трафика здесь констатируется, вместе с мерами смягчения, а не отрицается.

Поручитель — это метаданные, и приватность с устойчивостью к цензуре не уживаются в одном сертификате. Самозастрахованный экранированный сертификат называет публичную депозитную ячейку отправителя, что заново связывает то, что стелс-адрес развязал (§5); поэтому экранированный трафик едет на со-подписанном поручительстве, где идентификатор поручителя агрегирует множество отправителей, и прикрытием служит толпа. Поручитель оценивает живучесть ячеек, а не значения (§5), поэтому суммы он не узнаёт, — но он узнаёт всё остальное, чем является сертификат: отправителя, которому он должен выставить счёт вне цепочки и, значит, установить его личность; расходуемые ячейки; создаваемые стелс-выходы; и время. Это ровно то, чего хочет судебный запрос, и с ретроактивной деанонимизацией, описанной выше, оно складывается дальше по публичному графу. Это ещё и структурная точка KYC, потому что у единственного приватного режима есть устанавливаемый оператор. Здесь обнажается ограничение, о котором работа говорит прямо, а не заминает: два режима поручительства — это со-подписание (приватное, но разрешительное: поручитель вправе вам отказать) и самострахование либо принудительный путь (без разрешений, но с самоидентификацией). Принудительный путь из §7 гарантирует, что подвергнутый цензуре пользователь всегда сможет совершить транзакцию; он не гарантирует, что тот сможет совершить её приватно. Пользователь, которому отказали все поручители, сохраняет право тратить и теряет приватность одним и тем же движением — а это ровно тот пользователь, для которого приватность и была важна. Экранированный путь наследует устойчивость к цензуре из §7 лишь ценой собственной приватности; эти два свойства не держатся в одном сертификате.

Эра, а не генезис. Расписание закрепляют два независимых довода. На практике экранированные сертификаты пользуются со-подписанными поручителями, которые существуют с Эры 1. По принципу из §3 недостижимый код консенсуса есть неаудируемый код консенсуса и не поставляется: в бинарнике генезис-блока нет ни обязательств, ни верификатора доказательств диапазона, ни слота пула — ничего, чей единственный вызывающий находится в будущей эре. Экранированная эра не является чисто дополняющей, и работа говорит об этом: типизация скрытой ячейки и запрет сторонних охран из §4 затрагивают путь охраны в свёртке (fold), а это критичная для генезиса поверхность, — значит, эра не только добавляет, но и изменяет, и её активация есть жёсткий форк, аудируемый как то критичное для консенсуса изменение, которым он и является. Эра, которая не докажет, что стоит своей сложности, попросту никогда не будет запущена, и цепочка генезиса ничего не потеряет от того, что её не содержала.

Издержки, изложенные прямо. Экранированный сертификат в 3–5 раз больше прозрачного — от одного до двух килобайт, с доминированием доказательства диапазона даже после пакетной агрегации, — что динамический блок (§8) поглощает экономически, а распространение из §13 оплачивает пропускной способностью. Получатели обнаруживают платежи сканированием: каждый новый экранированный выход пробно проверяется на ключ просмотра кошелька, что стоит O(n) от сетевого объёма, и метки просмотра уменьшают эту стоимость ранним отказом по одному байту — постоянный множитель, ограниченный предшествующим выводом общего секрета. Сканирование — главная нагрузка на удобство использования экранированного пути; вынесенное сканирование, не отдающее ключ просмотра, — открытая проблема, которую эта конструкция наследует, а не решает. Политика ретрансляции на этом пути тоже должна измениться, и не факультативно: публикация сертификата бесплатна (§5, §13), а проверка Bulletproof — нет, поэтому ретранслятор, запускающий верификатор до того, как на публикующего лягут какие-либо издержки, есть усилитель отказа в обслуживании; экранированный путь требует ретрансляции по принципу «сначала дешёвая проверка, потом дорогая» (сначала подпись и объявленная живучесть, доказательство последним, квота на поручителя), что превращает «мемпул ограничен политикой ретрансляции» из умолчания в требование.

Открытые вопросы, которые этот раздел оставляет более поздней редакции, — отмеченные, а не похороненные. Несёт ли экранированный путь только нативную монету или также активы из §11: единственный генератор H делает vG + rH обязательством относительно скаляра, а не пары (актив, значение), поэтому мультиактивный экранированный путь требует генераторов на каждый актив (Confidential Assets), что меняет размер доказательства и приведённую выше цифру «3–5×»; до принятия решения путь ограничен нативной монетой по правилу, а не по недосмотру. Действует ли RETIRE (§11) на экранированные ячейки: если действует, ценность может покинуть пул без публичного разэкранирования, и тогда слот пула становится верхней границей (Σ вход − Σ выход ≥ содержимое), а направление обнаружения инфляции придётся переформулировать как неравенство; если не действует, экранированный путь лишается сборщика мусора, и нераскрываемые выходы (см. ниже) накапливаются. Живёт ли зашифрованная пара (v, r) в теле сертификата (дёшево сейчас, но невосстановимо при обрезке тел, что рушит восстановление кошелька по одной лишь seed-фразе) или в значении ячейки (стоит состояния на каждый выход, исчезает при расходовании ячейки и согласуется с «накопление происходит в кошельке»). И может ли поручитель обеспечить третью сторону, беря плату внутри сертификата публичным значением, — что сняло бы требование идентификации, изложенное выше, и является самым многообещающим путём в обход ограничения «приватность против цензуры». Это вопросы конструкции, а не формулировок, и они названы здесь, чтобы следующая редакция не унаследовала их втихую.

13. Сеть#

Тела — это данные цепочки. Тела сертификатов блока должны быть извлекаемы, чтобы блок был действительным; поэтому состояние всегда восстановимо из одной лишь цепочки, и ни один оператор — включая секвенсор — никогда не является хранителем данных. Сертификаты больше классических транзакций (они несут чтения и записи), и меры смягчения структурны: пакетные сертификаты схлопывают внутренние записи (§6), а израсходованные одноразовые ячейки уплотняются, как только оказываются глубже горизонта реорганизации (§4).

Третья мера — перспективная, и она названа именно так, а не принята как данность: чтение могло бы ссылаться на запись предыдущего сертификата парой (cert_id, index) вместо повторения значения — приём из UTXO. Он не входит в описываемый здесь протокол и не войдёт, пока не будет ответа на один вопрос, потому что этот вопрос — про консенсус, а не про кодировку: во что разрешается ссылка, когда названный ею сертификат был пропущен или вообще не был включён. Ссылка, которая бесшумно разрешается в текущее значение, больше не является объявленным чтением, и вместе с ней умирает действительность без состояния; ссылка, которая отказывает, роняет сертификаты, чья собственная авторизация никогда не вызывала сомнений. Сжатие ценой того самого свойства, на котором держится вся конструкция, — это сжатие, которого не стоит иметь, поэтому такого поля нет, пока семантика не улажена.

Ретрансляция начинается с хешей. Сертификаты расходятся по сети независимо и проверяются на действительность (без состояния, параллельно) по прибытии; блоки ретранслируются как заголовки плюс списки хешей относительно мемпула, в стиле compact block [13], поэтому задержка распространения не масштабируется с содержимым блока. Ретранслирующему узлу не нужно вообще никакого состояния, чтобы полностью отфильтровать спам: действительность без состояния плюс подпись поручителя проверяются по байтам, что делает содержание ретрансляционной инфраструктуры почти бесплатным на прозрачном пути. Экранированный путь (§12) — платное исключение: его проверка без состояния включает проверку доказательства диапазона, которая стоит на три порядка больше подписи, поэтому там бесплатность публикации по умолчанию становится усилителем, и ретрансляция связана дисциплиной «сначала дешёвое, потом дорогое» и квотами на поручителя, которые §12 делает требованием, а не предпочтением. Ретрансляция на одном пути почти бесплатна; на другом она дёшева только потому, что её политика обязательна.

Параметры (генезис-блок, иллюстративные). Блоки по 30 секунд; TTL сертификата по умолчанию 240 блоков (~2 ч); выведенных из обращения адресов на сертификат ≤ 64; эпоха 2880 блоков (~1 день); задержка принудительного применения D = 4 блока; предел принудительного включения F = 16 блоков; окно доли для запуска эры K = 14 эпох (~2 недели); доля казны 300 базисных пунктов (3 %) от субсидии блока с блока 0, ячейка запечатана до Эры 2, затем 3 из 5 по набору ключей, закреплённому жёстким форком, задержка ротации ключей R = 20 160 блоков (~7 дней) (§14.1); константы эмиссии — в §14.2.

14. Запуск: три эры, ноль премайна#

Zycord запускается без премайна, без выделения доли основателю, без инвесторского раунда и без административных ключей. Генезис-блок воспроизводим из опубликованных исходников. Сначала работает testnet; только после того как он стабилен, объявляется дата запуска mainnet — открыто и заранее, чтобы блок 0 был достижим для всякого, кто этого захочет. На автора налагается отсутствие привилегий, и это проверяемо строка за строкой в генезис-блоке. Обновления происходят через общественный консенсус и жёсткий форк.

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

«Без правок» — это обещание о находках, и стоит указать точно, что именно оно покрывает, поскольку запись переиздаётся в виде файлов, а не как живой архив. Каждая находка, каждое измерение, каждый довод и каждая отвергнутая альтернатива сохраняются в том виде, в каком были написаны, включая ошибочные и включая инструменты, рапортовавшие об успехе, ничего при этом не измеряя; ничто не прореживается, не смягчается, не сливается и не выбрасывается. Изменения вносятся двух родов, и только двух. Первый — редактирование идентифицирующих данных: имён, псевдонимов, адресов, названий машин и локальных путей, которые ничего не говорят о конструкции. Второй — самодостаточность: ссылка в трекер или в историю коммитов, которых опубликованное дерево не содержит, заменяется тем рассуждением, за которое она стояла, изложенным на месте. Читатель, у которого есть только эти файлы, может поэтому проследить каждое утверждение — ради чего обещание и давалось; ссылка, ведущая в никуда, сохранила бы букву «без правок» и утратила бы весь её смысл.

Proof of stake не может обеспечить честный запуск: начальная доля должна откуда-то взяться, а всякий классический путь (продажа, премайн, распределение) либо концентрирует сеть, либо устанавливает личность её автора. Поэтому доказательство работы (proof of work) используется как механизм распределения со сроком годности, а не как постоянный консенсус:

ЭраЗапускКонсенсусЧто существует
0 — Майнинг & чаевыеблок 0 (публичная дата mainnet, объявляемая после стабильного testnet)PoW (RandomX [14]), правила Накамото [1]Нативные активы (§11); каждый сертификат самозастрахован; ни аренд, ни принудительной очереди — и то и другое является механизмом Эры 1 (§3, §7); казна накапливается, запечатана (§14.1)
1 — Платеживысота H₁ (набор инструкций); наложение финальности, как только заложенная доля ≥ 1 % предложения продержится K эпохPoW предлагает; с момента активации наложения валидаторы с залогом финализируют контрольные точки каждые 32 блока (наложение FFG [12]), а субсидия делится 77/20/3 — производитель / аттестующие контрольных точек / казнаBOND, поручители & секвенсоры (§5–6); cEVM + стандартная библиотека (§10); рынок предподтверждений созревает вместе с финальностью (проектные заметки)
2 — Платформавысота H₂ и доля ≥ 10 %, удерживаемая 30 эпохПредлагает комитет PoS; вознаграждение PoW сходит к нулю примерно за 90 дней, приостанавливаясь, пока контрольные точки не финализируются; источник случайности переходит с хешей PoW на VRFПолный протокол; ячейка казны открывается по схеме 3 из 5 (§14.1); начинаются исследования выборочной проверки (§9)
S — Экранированная (активируется поверх той эры, которая текущая; требует набора инструкций Эры 1)жёсткий форк, принятый операторами узлов, предлагаемый только после выполнения всего перечисленного: со-подписанное поручительство работает (§5); верификатор и его пакетный путь опубликованы вместе с не менее чем двумя независимыми аудитами, находки и исправления публичны; полный экранированный путь отработал в публичном testnet при враждебном участии ≥ K эпох; эталонные векторы для верификатора включены в артефакт протоколабез изменений — эра не добавляет роли в консенсусе и не меняет ни одного правила упорядочиванияКонфиденциальные платежи (§12): экранированные операции, вид скрытой ячейки и запрет охран (§4), слот пула и его правило в свёртке (fold), верификатор доказательств диапазона как критичный для консенсуса код

Проектные заметки о переходе. Эра 0 намеренно крошечная. Без административных ключей нет и кнопки паузы, поэтому каждая строка генезис-блока — строка, способная убить сеть без средств помощи; свёртка (fold) (§3) плюс нативные операции (§11) составляют всю критичную для безопасности поверхность (настолько малую, что эта работа содержит их полную спецификацию), и они поставляются проаудированными и прогнанными во враждебном моделировании. Майнинг на CPU (RandomX) соответствует аудитории: майните на том ноутбуке, который у вас уже есть. Он же приглашает ботнеты; с ними боролась каждая монета, добываемая на CPU, и мы не рассчитываем стать исключением. Мы идём на этот размен с открытыми глазами: распределение, перекошенное ботнетами, всё равно шире того, что решается продажей, а сохранение конкурентоспособности честного массового железа — весь смысл проектного задания RandomX [14]. Со-подписание работает с того момента, как поручители могут регистрироваться; финальность по контрольным точкам — нет, пока не удержится доля, и мы называем этот зазор, а не прячем его: залог оценивает пропуски, но никогда реорганизации, поэтому никакое правило протокола не мешает поручителю продавать предподтверждения в этот зазор — чего никакое правило не может, так это сделать такую продажу честной. «Применится за секунды или мой залог платит» становится обеспечиваемым только тогда, когда глубокие реорганизации сняты со стола, поэтому продукт застрахованного предподтверждения следует за финальностью как рыночная честность, а не как закон протокола. Аттестующим платят из эмиссии с момента активации наложения — так делали оба предшествующих гибридных перехода (Decred платит голосующим PoS долю от каждого вознаграждения за блок [17]; валидаторы beacon-цепочки Ethereum получали эмиссию два года, прежде чем начали предлагать блоки mainnet), — а разделение 77/20/3 с перевесом в пользу производителя ограничено фазой распределения, поскольку тот же прецедент показывает, что перевес в пользу майнеров — неверное постоянное состояние: сход на нет его упраздняет. У Эры 1 запуск раздвоен, и это раздвоение несуще: набор инструкций активируется по высоте — сначала BOND, затем регистрация поручителей и секвенсоров и cEVM, две высоты, которые параметры генезиса держат раздельными и упорядоченными, — тогда как наложение финальности активируется только после того, как заложенная доля ≥ 1 % предложения продержалась K эпох, поскольку долю нельзя измерить раньше, чем появится операция, её создающая. У Эры 2 запуск двойной (высота и удержанная доля), поэтому сеть не переходит ни на ничтожной доле, ни позволяет действующим майнерам застопорить переход навсегда; высоты — это пороги, а не даты, и никакого календаря не обещается. Одну оговорку мы излагаем, а не хороним: на пороге активации в 1 % застопорить финальность стоит трети от этого (0,33 % предложения), поэтому финальность, на которой держатся первые застрахованные предподтверждения, сама молода. Требование удержания в K эпох со временем поднимает планку, утечка за бездействие делает удержание затора дорогим, а от поручителей ожидается, что молодую финальность они заложат в цену молодых полисов; более глубокая безопасность приходит с более глубокой долей, а не по объявлению. Эра 1 — это теневая цепочка: набор валидаторов финализирует в боевом режиме всю эру — настоящие залоги, настоящие урезания — прежде чем предложить хоть один блок; именно это свойство сделало безопасным единственный успешный переход PoW→PoS в масштабе. Это ещё и состояние покоя, а не коридор: если доля так и не удержит порог Эры 2, сеть останется работающим гибридом сколь угодно долго. Сход вознаграждения на нет, а не обрыв, лишает майнерский форк момента для сплочения, и этот сход можно прервать: если контрольные точки не финализируются две эпохи подряд, он приостанавливается на текущем уровне, пока финальность не возобновится. Купить паузу майнеры не могут: застопорить финальность стоит трети заложенной доли, которую утечка за бездействие обескровливает, пока финальность не вернётся, поэтому атака стоит больше, чем платит приостановленное вознаграждение. Майнеры Эры 0, заложившие свой coinbase, получают приоритет — а не дополнительные монеты — в первых ротациях секвенсоров, что превращает сообщество майнеров в сообщество операторов, а не отбрасывает его.

Запуск экранированной эры намеренно устроен иначе, чем остальные. Высоты и пороги долей — это факты, которые узел измеряет; готовность криптографического верификатора — нет, поэтому запуском здесь служит контрольный список, на который жёсткий форк должен быть способен сослаться: аудиты опубликованы, эпохи в testnet отработаны, векторы в артефакте. Форма здесь важнее пунктов. У этой сети нет команды экстренного реагирования — ошибка с подделкой в Zcash оказалась переживаемой отчасти потому, что укомплектованная организация выпустила исправление за считаные дни, а здесь этого обещать нечем, — поэтому активация эры устроена так, чтобы создавать своих сопровождающих, а не предполагать их наличие: сообщество, не способное произвести два независимых аудита и укомплектовать враждебный testnet, есть сообщество, не способное сопровождать верификатор консенсуса, и контрольный список делает вторую неспособность видимой как проявление первой — до активации, а не после слома. Правило свёртки (fold) из §12 ограничивает то, во что может обойтись уцелевшая ошибка; контрольный список ограничивает то, насколько неисследованным может быть верификатор в момент, когда он начнёт во что-то обходиться. Одно не заменяет другого, и эра поставляется с обоими или не поставляется вовсе.

Сход на нет — это передел, а не сокращение: какую бы долю ни уступило доказательство работы, её забирают предлагающие на proof of stake, поэтому расписание субсидии из §14.2 не зависит от того, где сеть находится в своём переходе. Именно это позволяет расписанию оставаться чистой функцией от высоты, вычислимой любым узлом из четырёх констант без обращения к реестру.

Переход осуществим по архитектурной причине, которую стоит назвать: свёртке (fold) безразлично, кто упорядочивает. Майнер PoW уже является тем слепым предлагающим, который нужен этой конструкции; Эра 2 меняет то, чья подпись стоит на заголовке, и не меняет ни одного правила семантики состояния. Нет никакого движка исполнения, который пришлось бы переносить через эту границу.

Граница эры — это ещё и то место, где сдвигается ёмкость: байтовая ёмкость из §8.1 и лежащие под ней транспортные константы перезакрепляются именно там, против распространения, измеренного на работающей сети, — так что рутинный рост едет на тех обновлениях, которые это расписание и так содержит, вместо того чтобы становиться отдельным событием управления.

14.1 Казна#

Три процента каждой субсидии блока зачисляются в ячейку казны; девяносто семь процентов оплачивают консенсус — производителя блока и, начиная с Эры 1, аттестующих контрольные точки (§14). Доля закреплена в генезис-блоке, действует с блока 0 и действует одинаково для каждого блока. Комиссии не затрагиваются никогда (у казны нет притязаний на рынки из §8), поэтому издержки ложатся на эмиссию и распределяются между всеми держателями пропорционально их долям.

Ячейка запечатана до Эры 2. Она накапливает с блока 0, и до тех пор её не открывает никакой ключ: ни кворума в генезисе, ни адреса, ни авторского ключа, ни аварийного пути. На блоке 0 нет зрелого сообщества, которое держало бы ключи. Если оно так и не появится, ячейка никогда не откроется и монеты никогда не будут выпущены. Правило накопления присутствует в генезис-блоке с первого блока именно для того, чтобы оно никогда не было изменением; на Эре 2 не происходит ничего нового, кроме того, что согласованное правило вступает в действие.

Ничто из этого не является премайном, и разница здесь проверяема, а не риторична. Премайн — это распределение: монеты, адрес и ключ, которые существуют в генезисе и кому-то принадлежат. Генезис-блок здесь не содержит ни одного из трёх. Ни одна монета казны не расходуема, ни один адрес не назначен, ни один ключ не существует и ни одна сторона не названа; генезис-блок содержит правило, применяемое одинаково к каждому когда-либо добытому блоку, плюс второе правило о том, как однажды может быть закреплён кворум над накопленным результатом. Придёт ли этот день, решает не автор. Поскольку набор ключей закрепляется жёстким форком, механизм отбора — тот же, что и у всякого изменения консенсуса: кто-то предлагает пятерых публично установленных держателей, операторы узлов принимают закрепляющий их форк или отказываются его запускать, а кворум-кандидат, не способный убедить сеть запустить его форк, держит ключи ни от чего. Здесь нет голосования, которое можно было бы захватить, нет реестра участников, которым можно было бы манипулировать, и нет момента, в который голос автора весил бы больше голоса любого другого оператора узла.

Начиная с Эры 2 ячейка списывается только сертификатом, несущим три подписи из пяти по набору ключей, закреплённому жёстким форком. Расходы — обычные сертификаты: публичные, окончательные и пересчитываемые из одной лишь цепочки. Кворум набирается из участников, активных на момент открытия, и публично устанавливается до вступления набора в силу; каждый ключ находится у отдельной стороны, ни один не под общим контролем. Действительный расход 3 из 5 может вместо этого назвать пять заменяющих ключей, вступающих в силу через R блоков, в течение которых ротация публична, а старый набор ещё действует: ротация несёт тот же порог и ту же видимость, что и расход.

Эры 0 и 1 финансируются пожертвованиями: предложения публикуются до оплаты, вехи и бюджет объявляются заранее, выплата производится по сданной работе, неизрасходованные суммы возвращаются в фонд. Кворум наследует эту дисциплину, когда ячейка открывается. Это норма, а не правило консенсуса; обеспечивает её то, что всякое отступление видно в реестре.

Эта доля не истекает. Это доля от эмиссии, а не количество монет, поэтому она убывает вместе с субсидией из §14.2 и сохраняется на хвосте как фиксированный номинальный поток; как доля предложения она стремится к нулю. Её отмена стоит того же, чего стоит любое изменение консенсуса: жёсткого форка. Начиная с Эры 2 схема 3 из 5 — единственный доверенный кворум протокола.

14.2 Эмиссия#

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

E(0) = E₀
E(n) = max(tail, E(n−1) − E(n−1)/Q)

где L — эпоха в блоках, Q — делитель убывания, E₀ — субсидия генезис-блока, а E(n) — субсидия на блок в течение эпохи n. Эти четыре — L, Q, E₀, tail — и есть константы; C, доэхвостовое предложение, к которому суммируется расписание, выводится из них прогоном рекуррентности и не является для неё входом. В более ранних редакциях первая строка была записана как E(0) = C / (L · Q), что читается так, будто C — константа, из которой субсидия выделяется делением; на самом деле это замкнутая форма бесконечного геометрического убывания, а конечное расписание ниже к ней не суммируется. Здесь нет ни чисел с плавающей точкой, ни таблицы, в которой можно ошибиться, ни обрывов при халвинге: шаг достаточно мал, чтобы ни один отдельный блок его не увидел, — то же рассуждение, что делает вознаграждение Эры 2 плавным сходом. Как только формула опускается ниже хвоста, субсидия становится фиксированной величиной на блок, навсегда.

Расписание — чистая функция от высоты. Оно не справляется о том, сколько было выплачено на самом деле, а значит, блок, выплативший меньше расписания (например, coinbase, причитающийся адресу, чей держатель его сжёг), есть безвозвратный недобор относительно C, а не долг, который кривая позже возвращает. Поэтому C — та величина, к которой расписание суммируется, а не потолок, достижение которого оно гарантирует.

Хвост существует потому, что безопасность есть постоянный расход: он оплачивает того, кто обеспечивает текущую эру, — майнеров, затем майнеров и аттестующих, затем валидаторов, — не призывая на службу рынки комиссий из §8. Он рассчитан так, чтобы годовая эмиссия хвоста начиналась ниже 1 % от обращающегося предложения; поскольку числитель фиксирован, а предложение растёт, этот процент может только падать. Против него работает сжигание последовательной базовой комиссии из §8, поэтому чистая эмиссия есть хвост минус сжигание и под нагрузкой может быть отрицательной. Разделение 97/3 из §14.1 применяется к каждой субсидии, включая хвостовую.

Константы (генезис, иллюстративные, как в §13): эпоха L = 2880 блоков; делитель убывания Q = 1054; субсидия генезис-блока E₀ = 21 на блок; хвост 0,33 на блок. При блоках по 30 секунд это даёт годовой множитель 0,70702, то есть скорость эмиссии уменьшается вдвое каждые два года — и притом точно, а не приблизительно: E(730) = 10.50230028 против E₀ = 21. Формула опускается ниже хвоста на эпохе 4376, высоте 12 602 880, примерно на 12-м году, поэтому убывающее плечо охватывает эпохи с 0 по 4375, а C, предложение, к которому оно суммируется, составляет 62 744 838,47. Из них фактически выпускается 62 744 817,47: разница — это 21 генезис-блока, который не выплачивает coinbase вовсе, потому что платить некому и воспроизводимый генезис не должен зачислять средства ни на какой адрес. Годовая эмиссия хвоста составляет тогда ≈347 тыс., или 0,55 % выпущенного предложения, и далее падает. **Замкнутая форма L · E₀ · Q = 63 745 920 является верхней границей для C, а не его значением**, и разрыв здесь не ошибка округления: это произведение есть сумма бесконечного геометрического убывания, тогда как расписание конечно, округляет вниз на каждом шаге и останавливается на хвосте. Оно превышает C на 1 001 081,53, то есть на 1,60 %. Ссылайтесь на сумму и никогда — на замкнутую форму. Соответствием является воспроизведение рекуррентности: ни один узел никогда не вычисляет C — как и любую другую цифру из этого абзаца — ни на какой высоте.

15. Измерения#

Конструкция, чьё центральное утверждение — асимметрия пропускной способности, должна читателю цифры. Приведённые ниже получены на эталонной реализации и могут быть выведены заново из её опубликованных исходников. Оборудование: десятиядерный настольный процессор x86. Приведены медианы по 5 прогонам.

  • Пропускная способность свёртки (fold): 883 000 операций со слотами в секунду на ядро при рабочем множестве в 100 000 слотов, то есть 294 000 применённых сертификатов в секунду при 3 слотах на сертификат.
  • Проверка без состояния: 1470 сертификатов в секунду на ядро CPU и 5220 в секунду на 10 ядрах — это отношение и есть утверждение о параллелизме, измеренное, а не заявленное.
  • Проверка подписей: 1500 в секунду, на одном ядре, с учётом проверок на малый порядок и кручение.
  • От начала до конца: блок из 2900 сертификатов проходит проверку за 1963 мс и сворачивается за 9,9 мс. Эти две величины приводятся раздельно, потому что они — две половины аргументации: первая масштабируется ядрами, которыми сеть не владеет, вторая есть тот единственный цикл, которым владеет.

Измерение свёртки (fold) получено вычитанием, и сказать об этом — часть его изложения: фиксация блока прогоняет проверки без состояния и последовательную свёртку вместе, поэтому цифра свёртки есть целое минус проверки, замеренные отдельно. Обе половины есть в артефакте.

Мы сообщаем только то, что действительно исполняет эталонная реализация, и это задаёт два предела, которые стоит назвать, а не оставлять читателю на самостоятельное обнаружение. Проверка подписей измерена по одной подписи за раз: пакетная проверка — реальный приём и очевидно уместный здесь, но это критичная для безопасности криптография, которую этот проект не писал, а цифра для несуществующего кода не является измерением. Показатели GPU и SIMT, которых ожидают §2 и §6, относятся к пакетным сертификатам секвенсора, а те приходят с Эрой 1. И то и другое — проектные ожидания. Ни то ни другое не несуще для приведённых выше цифр: утверждение о параллелизме держится на том, что сертификаты проверяемы независимо, а пакетирование могло бы сделать это быстрее и не может сделать это истинным.

Конвейер Zycord — сначала исполнить, упорядочить вслепую, проверить при фиксации — имеет предка в системах с разрешениями: схема execute-order-validate в Hyperledger Fabric [3], чьи задокументированные слабости — доля прерываний при конкуренции и опора на институциональные политики подтверждения. Вклад Zycord относительно этой линии таков: (i) применимость по равенству значений с пропуском как полноправной, устойчивой к ABA семантикой; (ii) экономическая атрибуция конфликта — поручительство с залогом, делающее двусмысленное поведение объективно наказуемым, а устаревание — оцениваемой, страхуемой услугой, чего execute-order-validate и не хватало, чтобы обойтись без разрешений; и (iii) принудительное включение с гарантированным применением, тогда как аварийные выходы роллапов гарантируют только включение. Детерминированные заранее объявленные множества чтений и записей происходят от Calvin [4] и встречаются в списках доступа Solana [16]; коммутативные escrow-методы восходят к O'Neil [9] и живут сегодня внутри планировщиков отдельных узлов, таких как агрегаторы Aptos поверх Block-STM [5], — Zycord переносит контракт о коммутативности на уровень между узлами и назначает ему цену. Системы с параллельной EVM [5] и цепочки с отложенным исполнением всё равно исполняют заново повсюду и упираются в стену ввода-вывода состояния; Narwhal [6] отделяет распространение данных от упорядочивания, как это делали наши ранние конструкции; собственные объекты Sui — параллель нашим ячейкам однократной записи; разделение pending/base из Zether [7] вдохновило дисциплину охраняемой дельты (и возвращается, вместе с приватностными корнями химерического реестра [8], в конфиденциальных платежах §12 — первом арендаторе полосы тяжёлой криптографии, где скрытые суммы и одноразовые адреса оценены в параллельном gas, а не встроены в базовый слой). Наложения сцепленной финальности следуют Casper FFG [12].

17. Заключение#

Мы предложили сеть, которая упорядочивает сертификаты, а не исполняет транзакции: действительность проверяема кем угодно, где угодно, параллельно, по одним лишь байтам; состояние продвигается свёрткой (fold), достаточно простой, чтобы уместить её спецификацию на одной странице; конфликты пропускаются, имеют цену и владельца; параллелизм объявляется, а не обнаруживается; цензура переживаема по построению; а запуск распределяет монету прежде, чем просит кого-либо довериться набору валидаторов. Проверка масштабируется вширь железом, которым сеть не владеет. Фиксация остаётся последовательной — и почти бесплатной.

Zycord не гонится за работой. Он стоит неподвижно, а работу делает сеть.

Ссылки#

[1] S. Nakamoto. Bitcoin: A Peer-to-Peer Electronic Cash System. 2008. [2] V. Buterin. Ethereum: A Next-Generation Smart Contract Platform. 2013. [3] E. Androulaki et al. Hyperledger Fabric: A Distributed Operating System for Permissioned Blockchains. EuroSys 2018. [4] A. Thomson et al. Calvin: Fast Distributed Transactions for Partitioned Database Systems. SIGMOD 2012. [5] R. Gelashvili et al. Block-STM: Scaling Blockchain Execution by Turning Ordering Curse to a Performance Blessing. 2022. [6] G. Danezis et al. Narwhal and Tusk: A DAG-based Mempool and Efficient BFT Consensus. EuroSys 2022. [7] B. Bünz, S. Agrawal, M. Zamani, D. Boneh. Zether: Towards Privacy in a Smart Contract World. Financial Cryptography 2020. [8] J. Zahnentferner. Chimeric Ledgers: Translating and Unifying UTXO-based and Account-based Cryptocurrencies. IACR ePrint 2018/262. [9] P. E. O'Neil. The Escrow Transactional Method. ACM TODS, 1986. [10] M. Herlihy, E. Koskinen. Transactional Boosting: A Methodology for Highly-Concurrent Transactional Objects. PPoPP 2008. [11] M. Shapiro et al. Conflict-free Replicated Data Types. SSS 2011. [12] V. Buterin, V. Griffith. Casper the Friendly Finality Gadget. 2017. [13] M. Corallo. BIP 152: Compact Block Relay. 2016. [14] tevador et al. RandomX: Proof-of-Work Algorithm Optimized for General-Purpose CPUs. 2019. [15] EIP-1559: Fee Market Change for the ETH 1.0 Chain. Ethereum Improvement Proposals, 2019. [16] A. Yakovenko. Solana: A New Architecture for a High Performance Blockchain. 2017. [17] Decred Documentation: Issuance. docs.decred.org — распределение вознаграждения за блок между майнерами PoW, голосующими PoS и казной. [18] EIP-4844: Shard Blob Transactions. Ethereum Improvement Proposals, 2022. [19] Monero: Dynamic Block Weight and Penalty. Документация Monero Research Lab; см. также JollyMort, Monero Dynamic Block Size and Dynamic Minimum Fee, 2017. [20] bitcoincashautist. CHIP-2023-04: Adaptive Blocksize Limit Algorithm for Bitcoin Cash. 2023.