> ## Documentation Index
> Fetch the complete documentation index at: https://docs.intention.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# ストレージと証明

> コミット済みの状態が3つのRocksDBストアにどう永続化され、バージョン付きMerkleツリーとアキュムレータでどう認証され、時間とともにどうプルーニングされるのかです。

コミット済みの状態は、互いに引っ張り合う2つの要求を満たさなければなりません。実行側が求めるのは、あるキーの現在値を高速に、何百万回も取り出すことです。検証側が求めるのは、ある値が特定のバージョン時点でネットワークの言うとおりだったという証明です。ひとつの構造で両方をまかなえば、両方とも中途半端になります。

そこでストレージは問題を別々のストアに分割し、それぞれを自分のアクセスパターンに合わせた形にしています。

<h2 id="three-stores">
  3つのストア
</h2>

<div className="dg" data-dg="storage-stores">
  <div className="dg-c" style={{aspectRatio:"720 / 332"}}>
    <svg className="dg-w" viewBox="0 0 720 332" aria-hidden="true">
      <path className="dg-wire dg--green dg-dash" d="M 434.00 48.00 L 459.60 48.00" />

      <path className="dg-head dg--green" d="M 466.00 48.00 L 459.60 52.40 L 459.60 43.60 Z" />

      <path className="dg-wire dg--green dg-dash" d="M 434.00 144.00 L 459.60 144.00" />

      <path className="dg-head dg--green" d="M 466.00 144.00 L 459.60 148.40 L 459.60 139.60 Z" />

      <path className="dg-wire dg--green dg-dash" d="M 434.00 240.00 L 459.60 240.00" />

      <path className="dg-head dg--green" d="M 466.00 240.00 L 459.60 244.40 L 459.60 235.60 Z" />

      <path className="dg-wire dg--blue dg-soft" d="M 135.00 144.00 L 172.54 53.91" />

      <path className="dg-head dg--blue" d="M 175.00 48.00 L 176.60 55.60 L 168.48 52.22 Z" />

      <path className="dg-wire dg--blue dg-soft" d="M 135.00 144.00 L 168.60 144.00" />

      <path className="dg-head dg--blue" d="M 175.00 144.00 L 168.60 148.40 L 168.60 139.60 Z" />

      <path className="dg-wire dg--blue dg-soft" d="M 135.00 144.00 L 172.54 234.09" />

      <path className="dg-head dg--blue" d="M 175.00 240.00 L 168.48 235.78 L 176.60 232.40 Z" />
    </svg>

    <div className="dg-b dg--blue" style={{left:"0.0000%",top:"31.3253%",width:"18.0556%",height:"24.0964%"}}><span className="dg-t">コミット済みブロック</span></div>
    <div className="dg-b dg--sky dg-left" style={{left:"25.0000%",top:"2.4096%",width:"34.7222%",height:"24.0964%"}}><span className="dg-t">レジャーストア</span><span className="dg-s">トランザクション · 出力 · イベント · ライトセット · アキュムレータ · ブロックメタデータ</span></div>
    <div className="dg-b dg--green" style={{left:"65.2778%",top:"2.4096%",width:"34.7222%",height:"24.0964%"}}><span className="dg-t">リプレイと監査</span></div>
    <div className="dg-b dg--sky dg-left" style={{left:"25.0000%",top:"31.3253%",width:"34.7222%",height:"24.0964%"}}><span className="dg-t">ステートKVストア</span><span className="dg-s">現在値と過去の値、16分割でシャーディング、ホットな状態は専用ティア</span></div>
    <div className="dg-b dg--green" style={{left:"65.2778%",top:"31.3253%",width:"34.7222%",height:"24.0964%"}}><span className="dg-t">クエリと実行</span></div>
    <div className="dg-b dg--sky dg-left" style={{left:"25.0000%",top:"60.2410%",width:"34.7222%",height:"24.0964%"}}><span className="dg-t">ステートMerkleストア</span><span className="dg-s">バージョン付きスパースMerkleツリーと、置換ノードを追跡するインデックス</span></div>
    <div className="dg-b dg--green" style={{left:"65.2778%",top:"60.2410%",width:"34.7222%",height:"24.0964%"}}><span className="dg-t">検証：証明</span></div>
    <div className="dg-free" style={{left:"0.0000%",top:"89.1566%",width:"100.0000%"}}><div className="dg-n">値だけが必要な読み取りはツリー走査のコストを払わず、証明は単一キー参照向けに最適化されたストアから組み立て直す必要がありません。</div></div>
  </div>
</div>

**レジャーストア**はチェーンの履歴を保持します。トランザクション、その出力と補助データ、イベント、ライトセット、ブロックのメタデータ、アキュムレータです。リプレイの対象はこれです。

**ステートKVストア**は状態の値を、キーとバージョンでアドレス指定して保持します。実行とクエリが読むのはこれです。**16分割でシャーディング**されており、1ブロック分の書き込みは1つのインスタンスで競合するのではなく、独立した16のRocksDBインスタンスへ分散します。アクセス頻度の高い状態はさらに専用のティアに置かれるため、活発なマーケットのワーキングセットを、チェーンがこれまで保存してきたすべての中から探し出す必要がありません。

**ステートMerkleストア**は認証構造を保持します。値を証明可能にするツリーノードと、どのノードが置き換えられたかを追跡するインデックスです。

分割することで、値だけが必要な読み取りはツリー走査のコストを払わずに済み、証明は単一キー参照向けに最適化されたストアから組み立て直す必要がなくなります。

<h2 id="authentication">
  認証
</h2>

2つのMerkle構造が、それぞれ別の仕事をします。

<div className="dg" data-dg="storage-proofs">
  <div className="dg-c" style={{aspectRatio:"720 / 400"}}>
    <svg className="dg-w" viewBox="0 0 720 400" aria-hidden="true">
      <path className="dg-wire" d="M 173.50 98.50 L 173.50 110.10" />

      <path className="dg-head" d="M 173.50 116.50 L 169.10 110.10 L 177.90 110.10 Z" />

      <path className="dg-wire" d="M 173.50 169.00 L 173.50 180.60" />

      <path className="dg-head" d="M 173.50 187.00 L 169.10 180.60 L 177.90 180.60 Z" />

      <path className="dg-wire" d="M 173.50 239.50 L 173.50 251.10" />

      <path className="dg-head" d="M 173.50 257.50 L 169.10 251.10 L 177.90 251.10 Z" />

      <path className="dg-wire" d="M 546.50 122.00 L 546.50 133.60" />

      <path className="dg-head" d="M 546.50 140.00 L 542.10 133.60 L 550.90 133.60 Z" />

      <path className="dg-wire" d="M 546.50 216.00 L 546.50 227.60" />

      <path className="dg-head" d="M 546.50 234.00 L 542.10 227.60 L 550.90 227.60 Z" />
    </svg>

    <div className="dg-band" style={{left:"0.0000%",top:"6.5000%",width:"48.1944%",height:"72.5000%"}}><span className="dg-cap">バージョン付きスパースMerkleツリー</span></div>
    <div className="dg-band" style={{left:"51.8056%",top:"6.5000%",width:"48.1944%",height:"72.5000%"}}><span className="dg-cap">アキュムレータ</span></div>
    <div className="dg-b dg--blue" style={{left:"2.2222%",top:"12.5000%",width:"43.7500%",height:"11.1250%"}}><span className="dg-t">対象のキーとその値</span></div>
    <div className="dg-b" style={{left:"2.2222%",top:"30.1250%",width:"43.7500%",height:"11.1250%"}}><span className="dg-t">兄弟ノードのハッシュ</span></div>
    <div className="dg-b" style={{left:"2.2222%",top:"47.7500%",width:"43.7500%",height:"11.1250%"}}><span className="dg-t">兄弟ノードのハッシュ</span></div>
    <div className="dg-b dg--green" style={{left:"2.2222%",top:"65.3750%",width:"43.7500%",height:"11.1250%"}}><span className="dg-t">ステートルート、コンセンサスがコミット</span></div>
    <div className="dg-b dg--blue" style={{left:"54.0278%",top:"12.5000%",width:"43.7500%",height:"17.0000%"}}><span className="dg-t">対象のトランザクションかイベント</span></div>
    <div className="dg-b" style={{left:"54.0278%",top:"36.0000%",width:"43.7500%",height:"17.0000%"}}><span className="dg-t">トランザクション · イベントのアキュムレータ</span><span className="dg-s">含まれた全体を順序どおりコミットする</span></div>
    <div className="dg-b dg--green" style={{left:"54.0278%",top:"59.5000%",width:"43.7500%",height:"17.0000%"}}><span className="dg-t">レジャールート、コンセンサスがコミット</span></div>
    <div className="dg-b dg-dashed dg-left" style={{left:"0.0000%",top:"83.0000%",width:"100.0000%",height:"14.5000%"}}><span className="dg-s">ツリーは値が何であったかを証明し、アキュムレータは何がどの順で起きたかを証明します。両者が揃うことで、「このトランザクションはチェーンのこの位置にある」ことを、チェーンを保持せずに証明できます。</span></div>
  </div>
</div>

**バージョン付きスパースMerkleツリー**が状態を認証します。すべてのキーはハッシュで決まる位置を持ち、ツリーの各バージョンは変化しなかったノードを共有します。そのため、1ブロックで1つのキーを書いても増えるのは経路1本であって、ツリー1本ではありません。あるバージョンにおけるキーの証明とは、そのキーの葉からネットワークがコミットしたルートまでの経路のことです。

**アキュムレータ**は順序を認証します。トランザクション用とイベント用の2つがあり、それぞれ、そこまでに含めたすべてを順序どおりにコミットするルートを生成します。「このトランザクションはチェーンのこの位置にある」ことを、チェーンを保持せずに証明できるのはこのおかげです。

両者の役割分担はこうです。ステートツリーは*値が何であったか*を証明し、アキュムレータは*何が、どの順で起きたか*を証明します。

<h3 id="speculative-state">
  投機的状態
</h3>

ブロックの結果は、コミットされる前から存在します。永続的なツリーへ書き込んでおいて、ブロックがコミットされなければ取り消す、という作りではありません。未コミットの状態は、最後にコミットされたバージョンの上に重ねた**メモリ上のスパースMerkleオーバーレイ**に保持されます。

実行はこのオーバーレイ越しに読み、一貫したビューを見ます。ブロックがコミットされればオーバーレイは実体化されます。コミットされなければオーバーレイは破棄され、永続領域には一切手が付いていません。投機的実行がストレージに残骸を残さないのは、この仕組みによります。

<h3 id="caching">
  キャッシュ
</h3>

ツリーノードは2層でキャッシュされます。直近のバージョンをアドレス指定可能に保つバージョン対応キャッシュと、その下にあるLRUキャッシュです。取引チェーンのアクセスパターン（毎ブロック触られる少数のホットキーと、めったに触られないロングテール）は、まさにこの構成が想定している形です。

<h2 id="pruning">
  プルーニング
</h2>

すべてのバージョンを永久に保持することは、要件ではなく選択です。3つのストアそれぞれに独立したプルーナが走り、いずれも固有の保持ポリシーを持ちます。レジャー用、状態の値用、Merkleノード用です。

Merkle用と状態の値用のプルーナを駆動するのは、データと同時に書き込まれる**陳腐化インデックス**（stale index）です。あるバージョンがノードや値を置き換えると、置き換えられた側はそのバージョンで陳腐化したものとして記録されます。そのためプルーニングは、ゴミを探し回る処理ではなくインデックスに対するレンジスキャンになります。何がいつ回収可能になるかは、書き手がすでに言い残しているからです。

<Note>
  保持期間は運用者の判断であり、現実に結果が伴います。積極的にプルーニングしたノードは現在の状態を効率よく提供しますが、過去に関するクエリには答えられず、より古い地点から始めるノードへのステートシンクも提供できません。アーカイブノードはすべてを保持し、その分のコストを払います。[ノードを運用する](/ja/developers/run-a-node)を参照してください。
</Note>

<h2 id="backup-and-restore">
  バックアップとリストア
</h2>

各ストアは、稼働中のノードとは独立にバックアップおよびリストアできます。これによって、ジェネシスからリプレイするのではなく、スナップショットからノードを立ち上げられます。リストアしたノードの状態は、バックアップを信用するのではなく、コミット済みのルートに照らして検証できます。

<h2 id="where-to-go-next">
  次に読む
</h2>

<CardGroup cols={2}>
  <Card title="ステートシンク" href="/ja/protocol/architecture/state/sync">
    ノードが履歴のすべてをリプレイせずにチェーンへ追いつく方法です。
  </Card>

  <Card title="ステートモデル" href="/ja/protocol/architecture/state/model">
    何が保存されているのか、どの表現が権威を持つのかです。
  </Card>

  <Card title="インデクサー" href="/ja/protocol/architecture/indexer">
    コミット済みの記録から履歴を再構成します。
  </Card>

  <Card title="ノードを運用する" href="/ja/developers/run-a-node">
    ノードの役割と、運用について問い合わせる方法です。
  </Card>
</CardGroup>
