すべての記事

約12分で読めます

数千ファイルを 1 レコードで:Merkle バッチ処理

Merkle ルートを使えば、1 つの Label 309 レコードで数千〜数百万のファイルハッシュをコミットでき、後から任意の 1 件を小さな包含証明で証明できます。すべての項目をチェーン上に載せる必要はありません。

1 つの Label 309 レコードで、数千〜数百万のファイルがある時点に存在していたことを証明できます。

ファイルごとに 1 つのブロックチェーントランザクションを公開するのではなく、すべてのファイルをハッシュ化し、それらのハッシュを Merkle ツリーに畳み込み、単一の 32 バイトの Merkle ルートを公開します。後から、任意の 1 ファイルがそのバッチに含まれていたことを小さな包含証明で証明できます。残りを明かす必要はなく、すべての項目をチェーン上に載せる必要もありません。

このようにして、存在証明(Proof of Existence)は 1 つの文書から任意に大きな集合へとスケールします。

Merkle バッチ処理はどんな問題を解決するのか

ブロックチェーンは長いリストを保存する場所としては不向きです。1 バイトごとに手数料がかかり、Cardano のトランザクションにはサイズの上限があります。

ログ、モデル出力、リリースビルド、請求書、レポート、証拠エントリといった成果物がシステムから絶えず生み出される場合、それぞれのハッシュを個別のオンチェーンレコードとして公開していくと、たちまち高コストでノイズの多いものになります。

Merkle バッチ処理は、順序付けされたハッシュのリストを 1 つのルートコミットメントに圧縮します。ルートは固定サイズ(32 バイト)で、バッチには上限がなく、任意の 1 件に対する証明は小さいままです。証明のサイズはバッチサイズの対数でしか増えません。これにより、大量処理のワークフローでも定期的なコミットメントが現実的になります。

Merkle ルートとは何か

Merkle ルートとは、順序付けされたリスト全体をコミットする単一のハッシュです。

まずリーフのリストから始めます。存在証明のワークフローでは、各リーフは通常、ファイル、イベント、またはマニフェストエントリのハッシュです。リーフは二分木の上に向かって 2 つずつ組み合わされ、最上部のハッシュが Merkle ルートになります。

このコミットメントは、3 つの意味で厳密です。

  • いずれかのリーフが変われば、ルートが変わります。
  • リーフの順序が変われば、ルートが変わります。
  • コミットメントはリーフの個数も記録するため、サイズの異なるリストが同じバッチとして通用することはありません。

ルートを公開することは、順序付けされたリスト全体の指紋を公開するようなものです。

実際にチェーン上へ載るものは何か

ルートだけです。リーフの完全なリストはチェーン外にとどまります。

Label 309 レコードは、このコミットメントを専用の merkle フィールドに保持します。これは通常のファイルごとのハッシュとは分かれています。各コミットメントは、小さく固定された構造です。

  • コミットメントアルゴリズム(Label 309 v1 は rfc9162-sha256 を登録しています。これは RFC 9162 の Merkle Tree Hash を SHA-256 で構成したものです)。
  • 32 バイトのルート。
  • リーフ数。これがルートをチェーン外リストのサイズに結び付けます。
  • リーフリストのファイルを指す、任意のコンテンツアドレス指定 URI(ar:// または ipfs://)。

オンチェーンのレコードは小さいままです。単一のルートが、上限のないリストを 32 バイトという固定コストでコミットします。詳細はチェーン外、順序付けされたリーフリストの中にあります。(レコードの残りの部分がどこにあるかについては、ブロックチェーンに載るものを参照してください。)

後から 1 ファイルを証明するにはどうするのか

包含証明を生成します。

包含証明とは、1 つのリーフからルートまでの経路に沿った兄弟ハッシュの短いリストです。検証ツールはリーフとそれらの兄弟をツリーの上へと畳み込み、再計算したルートが公開されたルートと完全に一致した場合にのみ証明を受け入れます。

実際には、このチェックには 4 つの入力があります。

  1. 証明したいファイルまたは項目のハッシュ。
  2. 包含証明(兄弟の経路)。
  3. Label 309 レコード内の Merkle ルート。
  4. それを運んだトランザクションの Cardano ブロック時刻。

畳み込みが公開されたルートを再現すれば、その項目はコミットされたリストに含まれていたことになります。そしてブロック時刻が、そのリストがいつ存在したかを証言します。検証ツールに必要なのは 1 件の項目とその証明だけで、バッチ内の他のファイルは一切必要ありません。

押さえておきたい細かい点が 2 つあります。1 つ目は、この構成が順序に依存するため、リーフは公開したときと同じ並びで保持しなければならないことです。2 つ目は、リーフが 1 つだけの「ツリー」は有用なタイムスタンプにならないことです。1 リーフのツリーのルートはリーフそのものではないため、単一ファイルを証明したい場合は、1 項目の Merkle コミットメントではなく、素のコンテンツハッシュを公開します。

構築と検証を完全にオフラインで行えることがなぜ強みなのか

サーバーに触れる唯一の手順が、ルートを公開することだけだからです。

ツリーの構築、包含証明の導出、そしてその検証は、いずれも純粋な計算です。順序付けされたリーフリストを持っている人なら誰でも、ルートを再計算し、任意の証明を再導出できます。アカウントも、ゲートウェイも、ネットワークも、もともと公開した人の協力も不要です。検証時に公開者が関与することは一切ありません。

これは、ツールやベンダーよりも長く残らなければならない証拠にとって重要です。公開された Cardano のエクスプローラーに対してオフラインでチェックできる証明は、特定のサービスが姿を消したずっと後でも機能し続けます。バッチコミットメントは、Label 309 レコードを検証するのと同じ方法で検証できます。また、オープンソースの cardanowall コマンドラインツールを使えば、包含チェックをそのまま CI に組み込めます(merkle-build でフォルダをルートに畳み込み、merkle-verify で項目がそこに属することを確認します)。

なぜこれが大量処理のワークフローで役立つのか

実世界の証明の多くは、単一ファイル型ではなくバッチ型だからです。チームは次のようなことを示す必要が出てきます。

これらはいずれも、1 ファイル 1 トランザクションのモデルにはうまく当てはまりません。Merkle バッチ処理を使えば、バッチごとに単一のコミットメントを公開できます。すべての非公開項目をさらすこともなく、バッチサイズに比例して増えていくオンチェーンメタデータも不要です。

リーフリストを非公開のままにできるか

できます。公開されたルートは、それがコミットするリーフについて何も明かしません。

リーフリストは、ご自分の証拠システム、リリースアーカイブ、データルーム、またはコンプライアンスストアの中に保持しておき、後から必要なものだけを明かせます。

  • 1 ファイルとその包含証明。
  • 1 行のデータセット、文書、またはリリース成果物。
  • 1 件の監査ログエントリ。
  • リストの一部。
  • あるいはリーフリスト全体。

これは、基礎となるデータを公開せずに、公開された、タイムスタンプ付きのコミットメントを得たい場合のパターンです。公開ファイルなしの機密開示Merkle ルートによる準備金証明と密接に関連しています。

トレードオフは責任です。ルートが証明するのは、既知のサイズの何らかのリストが既知の時刻に存在していたことです。ルート単体では、具体的にどの項目がそこに含まれていたかを誰かが証明できるわけではありません。リーフリストを非公開で保持するなら、それを保全しなければなりません。リーフリストと保存しておいた包含証明の両方を失えば、タイムスタンプは残るものの、特定の項目がコミットされていたことを証明する能力は失われます。

リーフは何であるべきか

リーフは、後から証明する必要が生じうるものを、過不足なく表すべきです。

ファイルの場合、リーフはファイルバイト列のハッシュです。構造化データの場合は、通常、正規化されたマニフェストエントリのハッシュです。CI/CD の場合、リーフは成果物ダイジェスト、SBOM ダイジェスト、ビルドログのダイジェスト、コミット参照、または署名されたリリースマニフェストのエントリになり得ます。AI の来歴の場合、リーフは出力ファイルのハッシュ、プロンプト/出力のマニフェストエントリ、データセット項目のコミットメント、またはコンテンツ来歴マニフェストのハッシュになり得ます。

重要なのは一貫性という規律です。実行のたびにリーフが異なる方法で生成されると、後の包含証明は信頼しづらくなります。リーフの定義と正規化を一度固定し、毎回同じ方法で適用してください。

リーフリストを公開すべきか、非公開のままにすべきか

何を証明するのか、そして誰に見せるべきかによります。

リーフリストを公開すれば、第三者による検証は容易になります。誰でもリストを取得し、ルートを再計算し、コミットされた集合を確認できます。非公開のままにすれば、機密性と選択的開示が得られます。必要なときにだけ包含証明を明かせばよいのです。多くのワークフローは両方を行います。オープンソースのリリースには公開のリーフリストを、内部のコンプライアンスログには非公開のものを、機微な証拠には封印されたものを使います。

ルートは公開されるコミットメントです。リーフリストの方針は、その上に重ねられる別個の選択です。

どのくらいの頻度でルートを公開すべきか

ワークフローに合わせて頻度を調整してください。

CI/CD システムなら、リリース、ビルド、またはデプロイ期間ごとに 1 つのルートを公開するかもしれません。コンプライアンスシステムなら、1 時間ごと、1 日ごと、または管理期間ごとに 1 つのルートを公開するかもしれません。AI プラットフォームなら、生成コンテンツのバッチごと、学習スナップショットごと、またはモデルバージョンのイベントごとにルートを公開するかもしれません。法的証拠のシステムなら、案件バンドルごと、受付期間ごと、または証拠保管の連鎖(chain of custody)のマイルストーンごとに 1 つのルートを公開するかもしれません。

適切な頻度は、コスト、運用上のシンプルさ、そして後からどれだけ正確なタイムラインを証明する必要が生じうるかのバランスで決まります。

Merkle ルートが証明しないものは何か

Merkle ルートが証明するのは、ある時点におけるリストへのコミットメントです。そのリストを取り巻くビジネス上の主張までは証明しません。あらゆる存在証明と同じく、特定のバイト列が公開された時刻までに存在していたことを示すだけです。それが真実であること、適法であること、特定の誰かによって作成されたこと、誰かに所有されていることまでは示しません(証明が証明しないものを参照してください)。

具体的には、次のとおりです。

  • ソフトウェアのビルドが安全だったことは証明しません。リリースにどの成果物やマニフェストが含まれていたかは証明できます。
  • データセットが適法に収集されたことは証明しません。ある時刻より前にデータセットのコミットメントが存在していたことは証明できます。
  • ログエントリが真実であることは証明しません。そのエントリがコミットされたバッチの一部であったことは証明できます。
  • 作成者が誰であるかは証明しません。ただし、レコードまたはそれを取り巻くプロセスが署名やアイデンティティの管理を加える場合は別です。

Label 309 では、作成者の表明は任意であり、かつ明示的です。レコードは分離された署名を保持できますが、それが必須となることは決してなく、Merkle コミットメント単体ではリストを誰が生成したかについて何の主張もしません。ルートはタイムスタンプ付きのコミットメントを与え、それを取り巻くプロセスがビジネス上の意味を与えます。

Label 309 はどう関わるのか

Label 309 は、Cardano 上の存在証明のための、オープンでベンダー中立な標準です。Cardano の CIP プロセスに提出され、Metadata カテゴリーの提案として CIP エディターによる審査が進行中です。Merkle バッチ処理は別個の製品ではありません。標準に組み込まれたスケール層です。

バッチコミットメントは、単一ファイルの証明と同じレコードと同じ検証経路を使います。メタデータラベル 309 の下にある 1 つのレコードが Merkle ルートを保持でき、それと並んで、どのレコードもサポートする同じ任意の要素を保持できます。すなわち、通常のファイルごとのハッシュ、コンテンツアドレス指定ストレージの URI、以前のレコードへの差し替え(supersedence)ポインタ、そして作成者の署名です。こうしてバッチ証明は、単一の証明が持つすべてを受け継ぎます。

  • Cardano のブロック時刻による証言。
  • 標準化された、閉じたレコード構造。
  • 公開エクスプローラーに対する、単独で完結するオフライン検証。
  • 各言語にわたる、同じオープンソースのツール、ライブラリ、CLI。

すべての項目をハッシュ化し、順序付けされた Merkle ツリーを構築し、1 つのルートを Label 309 レコードで公開し、リーフリストと必要になりそうな証明を保管しておいてください。後から、任意の 1 件がコミットされたバッチの一部であったことを証明できます。すべての項目をチェーン上に載せる必要はありません。これこそが、CI/CD、AI の来歴、データセット、コンプライアンス、法的証拠、その他の大量処理のワークフローにとって、存在証明を実用的なものにしているのです。

さらに読む

merkleproof-of-existencelabel-309