9 мин чтения
Одна запись для тысяч файлов: пакетирование Merkle
Корень Merkle позволяет одной записи Label 309 зафиксировать тысячи или миллионы хешей файлов, а позже доказать наличие любого из них с помощью компактного доказательства включения — не публикуя каждый элемент в блокчейне.

Одна запись Label 309 способна подтвердить, что тысячи или миллионы файлов существовали в определённый момент времени.
Вместо того чтобы публиковать отдельную транзакцию блокчейна на каждый файл, вы вычисляете хеш каждого файла, сворачиваете эти хеши в дерево Merkle и публикуете единственный 32-байтовый корень Merkle. Позже вы можете доказать, что любой отдельный файл входил в этот пакет, с помощью компактного доказательства включения — не раскрывая остальные файлы и не публикуя каждый элемент в блокчейне.
Именно так Proof of Existence масштабируется с одного документа до произвольно большого набора.
Какую проблему решает пакетирование Merkle?
Блокчейн — неудачное место для хранения длинных списков. Каждый байт стоит денег, а у транзакции Cardano есть жёсткий потолок размера.
Если система постоянно порождает поток артефактов — логи, выводы моделей, релизные сборки, счета, отчёты, записи доказательств, — публикация каждого хеша как отдельной записи в блокчейне быстро становится дорогой и шумной.
Пакетирование Merkle сжимает упорядоченный список хешей в одно корневое обязательство. Корень имеет фиксированный размер (32 байта), сам пакет может быть сколь угодно большим, а доказательство для любого отдельного элемента остаётся компактным — оно растёт лишь как логарифм от размера пакета. Это делает регулярную фиксацию практичной для высоконагруженных процессов.
Что такое корень Merkle?
Корень Merkle — это единственный хеш, фиксирующий весь упорядоченный список.
Начните со списка листьев. В процессе Proof of Existence каждый лист обычно представляет собой хеш файла, события или записи манифеста. Листья попарно объединяются вверх по двоичному дереву, и хеш на самой вершине — это корень Merkle.
Это обязательство точно сразу в трёх смыслах:
- если меняется любой лист, меняется и корень;
- если меняется порядок листьев, меняется и корень;
- обязательство также фиксирует, сколько в списке листьев, поэтому список другого размера не сможет выдать себя за тот же пакет.
Опубликовать корень — всё равно что опубликовать отпечаток всего упорядоченного списка.
Что в действительности попадает в блокчейн?
Только корень. Полный список листьев остаётся вне блокчейна.
Запись Label 309 несёт это обязательство в отдельном поле merkle, не смешивая его с обычными хешами отдельных файлов. Каждое обязательство — это небольшая структура фиксированной формы:
- алгоритм обязательства (в Label 309 v1 зарегистрирован
rfc9162-sha256: Merkle Tree Hash из RFC 9162 на основе SHA-256); - 32-байтовый корень;
- количество листьев, которое привязывает корень к размеру списка вне блокчейна;
- необязательные контентно-адресуемые URI (
ar://илиipfs://), указывающие на файл со списком листьев.
Запись в блокчейне остаётся крошечной — один корень фиксирует неограниченный список при постоянной стоимости в 32 байта. Все детали живут вне блокчейна, в упорядоченном списке листьев. (О том, где хранится остальная часть записи, см. что попадает в блокчейн.)
Как позже доказать наличие одного файла?
Вы формируете доказательство включения.
Доказательство включения — это короткий список соседних хешей вдоль пути от одного листа до корня. Верификатор сворачивает лист и эти соседние хеши обратно вверх по дереву и принимает доказательство, только если пересчитанный корень в точности совпадает с опубликованным.
На практике у проверки четыре входных данных:
- хеш файла или элемента, наличие которого вы доказываете;
- доказательство включения (путь из соседних хешей);
- корень Merkle из записи Label 309;
- время блока Cardano для транзакции, которая его несла.
Если свёртка воспроизводит опубликованный корень, элемент входил в зафиксированный список — а время блока свидетельствует, когда этот список существовал. Верификатору нужны только сам элемент и его доказательство; остальные файлы пакета ему никогда не требуются.
Две детали, которые стоит держать в голове. Конструкция чувствительна к порядку, поэтому листья нужно хранить в той же последовательности, в которой они были опубликованы. И «дерево» из одного листа не даёт полезной метки времени: корень дерева с одним листом не равен самому листу, поэтому для доказательства одного файла вы публикуете обычный хеш содержимого, а не обязательство Merkle с единственным элементом.
Почему полностью офлайновое построение и проверка — это сила?
Потому что единственный шаг, который обращается к серверу, — это публикация корня.
Построение дерева, вывод доказательств включения и их проверка — это чистые вычисления. Любой, у кого есть упорядоченный список листьев, может пересчитать корень и заново вывести любое доказательство — без учётной записи, без шлюза, без сети и без участия того, кто изначально опубликовал запись. Публикатор никогда не нужен в момент проверки.
Это важно для доказательств, которым предстоит пережить инструменты и поставщиков. Доказательство, которое можно проверить офлайн по публичному обозревателю блокчейна Cardano, продолжает работать ещё долго после того, как конкретный сервис исчезнет. Проверить обязательство пакета можно так же, как и любую запись Label 309, а проверку включения можно встроить прямо в CI с помощью открытого инструмента командной строки cardanowall (merkle-build сворачивает папку в корень, merkle-verify подтверждает, что элемент входит в него).
Чем это полезно для высоконагруженных процессов?
Потому что многие реальные доказательства по своей природе пакетные, а не однофайловые. Команде может понадобиться показать:
- что собрал конвейер CI/CD и какие артефакты вошли в релиз;
- какой состав программного обеспечения (SBOM) существовал до раскрытия уязвимости;
- какие выводы ИИ были получены в конкретный день;
- какой снимок набора данных существовал до запуска обучения;
- какие логи комплаенса существовали до аудита;
- какие файлы юридических доказательств были сохранены до наложения запрета на их удаление;
- какие резервы зафиксировал баланс в определённый момент времени.
Ни один из этих случаев толком не укладывается в модель «один файл — одна транзакция». Пакетирование Merkle позволяет публиковать одно обязательство на пакет — не раскрывая каждый приватный элемент и без метаданных в блокчейне, которые растут линейно с размером пакета.
Может ли список листьев оставаться приватным?
Да. Опубликованный корень не раскрывает ничего о листьях, которые он фиксирует.
Вы можете держать список листьев внутри собственной системы доказательств, релизного архива, дата-рума или хранилища комплаенса, а позже раскрывать только то, что нужно:
- один файл и его доказательство включения;
- одну строку набора данных, документ или релизный артефакт;
- одну запись журнала аудита;
- подмножество списка;
- или весь список листьев.
Это подходящий приём, когда вам нужно публичное обязательство с меткой времени, но без раскрытия исходных данных, — он тесно связан с конфиденциальным раскрытием без публичных файлов и доказательством резервов с корнями Merkle.
Плата за это — ответственность. Корень доказывает, что некоторый список известного размера существовал в известное время; сам по себе он не позволяет никому доказать, какие именно элементы в нём были. Если вы держите список листьев приватным, его нужно сохранять. Потеряете и список листьев, и все сохранённые доказательства включения — метка времени останется, но возможность доказать, что конкретный элемент был зафиксирован, исчезнет.
Чем должен быть лист?
Лист должен представлять ровно ту сущность, наличие которой вам, возможно, придётся доказывать позже.
Для файлов листом служит хеш байтов файла. Для структурированных данных это обычно хеш канонической записи манифеста. Для CI/CD листом может быть дайджест артефакта, дайджест SBOM, дайджест журнала сборки, ссылка на коммит или запись подписанного релизного манифеста. Для установления происхождения данных ИИ листом может быть хеш файла-вывода, запись манифеста промпта/вывода, обязательство элемента набора данных или хеш манифеста происхождения содержимого.
Главное здесь — дисциплина согласованности. Если листья формируются по-разному от запуска к запуску, поздним доказательствам включения становится трудно доверять. Зафиксируйте определение листа и канонизацию один раз и применяйте их одинаково каждый раз.
Публиковать список листьев или держать его приватным?
Это зависит от того, что вы доказываете и кто должен это видеть.
Публикация списка листьев делает стороннюю проверку тривиальной: любой может получить список, пересчитать корень и изучить зафиксированный набор. Хранение его приватным даёт конфиденциальность и избирательное раскрытие — вы предъявляете доказательства включения только тогда, когда это нужно. Многие процессы делают и то и другое: публичный список листьев для открытых релизов, приватный — для внутренних логов комплаенса, запечатанный — для чувствительных доказательств.
Корень — это публичное обязательство. Политика в отношении списка листьев — это отдельное решение, выстроенное поверх него.
Как часто стоит публиковать корни?
Подбирайте ритм под процесс.
Система CI/CD может публиковать один корень на релиз, сборку или окно развёртывания. Система комплаенса — один корень в час, в день или за контрольный период. Платформа ИИ может публиковать корни на каждый пакет сгенерированного содержимого, на каждый снимок обучения или на каждое событие смены версии модели. Система юридических доказательств может публиковать корень на каждый пакет по делу, окно приёма материалов или контрольную точку цепочки ответственного хранения.
Правильный ритм балансирует между стоимостью, операционной простотой и тем, насколько точную хронологию вам, возможно, придётся доказывать позже.
Чего корень Merkle не доказывает?
Корень Merkle доказывает обязательство по списку в определённый момент времени. Он не доказывает деловых утверждений, выстроенных вокруг этого списка. Как и любой Proof of Existence, он показывает, что конкретные байты существовали к публичному моменту времени, — но не то, что они истинны, законны, кем-то конкретным созданы или кому-то принадлежат (см. что подтверждение не доказывает).
Конкретно:
- Он не доказывает, что сборка ПО была безопасной. Он может подтвердить, какие артефакты или манифесты вошли в релиз.
- Он не доказывает, что набор данных был собран законно. Он может подтвердить, что обязательство по набору данных существовало до определённого момента.
- Он не доказывает, что запись журнала истинна. Он может подтвердить, что запись входила в зафиксированный пакет.
- Он не доказывает авторства — если только сама запись или окружающий процесс не добавляют подписи и средства контроля идентичности.
В Label 309 авторство необязательно и явно: запись может нести отделённые подписи, но они никогда не требуются, и обязательство Merkle само по себе ничего не утверждает о том, кто создал список. Корень даёт обязательство с меткой времени; процесс вокруг него придаёт деловой смысл.
Как сюда вписывается Label 309?
Label 309 — это открытый, независимый от поставщика стандарт Proof of Existence на Cardano; он подан в процесс Cardano CIP и сейчас рассматривается редакторами CIP как предложение категории Metadata. Пакетирование Merkle — не отдельный продукт, а слой масштабирования, встроенный в сам стандарт.
Обязательство по пакету использует ту же запись и тот же путь проверки, что и доказательство для одного файла. Одна запись под меткой метаданных 309 может нести корень Merkle, а вместе с ним и те же необязательные части, которые поддерживает любая запись: обычные хеши отдельных файлов, контентно-адресуемые URI хранилища, указатель замещения на более раннюю запись и подписи авторства. Поэтому пакетное доказательство наследует всё то же, что и одиночное:
- свидетельство времени блока Cardano;
- стандартную, закрытую структуру записи;
- автономную офлайновую проверку по публичному обозревателю;
- те же открытые инструменты, библиотеки и CLI на разных языках.
Вычислите хеш каждого элемента, постройте упорядоченное дерево Merkle, опубликуйте один корень в записи Label 309 и сохраните список листьев и все доказательства, которые могут понадобиться. Позже докажите, что любой отдельный элемент входил в зафиксированный пакет, — не публикуя каждый элемент в блокчейне. Именно это делает Proof of Existence практичным для CI/CD, установления происхождения данных ИИ, наборов данных, комплаенса, юридических доказательств и других высоконагруженных процессов.
Что почитать дальше
- Как работает Label 309 — структура записи, в которую встраивается обязательство по пакету.
- Доказать обучающие данные, не раскрывая их — избирательное раскрытие из приватного списка листьев, от начала и до конца.
- Чем Label 309 отличается от OpenTimestamps — ещё один протокол, который агрегирует множество хешей в одну точку фиксации.
- Стандарт, открытые SDK и CLI, а также текст спецификации: label309.org и github.com/cardanowall.
- RFC 9162 — конструкция Merkle Tree Hash, которую Label 309 использует для обязательств по пакетам.