3つのストア
コミット済みブロック
レジャーストアトランザクション · 出力 · イベント · ライトセット · アキュムレータ · ブロックメタデータ
リプレイと監査
ステートKVストア現在値と過去の値、16分割でシャーディング、ホットな状態は専用ティア
クエリと実行
ステートMerkleストアバージョン付きスパースMerkleツリーと、置換ノードを追跡するインデックス
検証:証明
値だけが必要な読み取りはツリー走査のコストを払わず、証明は単一キー参照向けに最適化されたストアから組み立て直す必要がありません。
認証
2つのMerkle構造が、それぞれ別の仕事をします。バージョン付きスパースMerkleツリー
アキュムレータ
対象のキーとその値
兄弟ノードのハッシュ
兄弟ノードのハッシュ
ステートルート、コンセンサスがコミット
対象のトランザクションかイベント
トランザクション · イベントのアキュムレータ含まれた全体を順序どおりコミットする
レジャールート、コンセンサスがコミット
ツリーは値が何であったかを証明し、アキュムレータは何がどの順で起きたかを証明します。両者が揃うことで、「このトランザクションはチェーンのこの位置にある」ことを、チェーンを保持せずに証明できます。
投機的状態
ブロックの結果は、コミットされる前から存在します。永続的なツリーへ書き込んでおいて、ブロックがコミットされなければ取り消す、という作りではありません。未コミットの状態は、最後にコミットされたバージョンの上に重ねたメモリ上のスパースMerkleオーバーレイに保持されます。 実行はこのオーバーレイ越しに読み、一貫したビューを見ます。ブロックがコミットされればオーバーレイは実体化されます。コミットされなければオーバーレイは破棄され、永続領域には一切手が付いていません。投機的実行がストレージに残骸を残さないのは、この仕組みによります。キャッシュ
ツリーノードは2層でキャッシュされます。直近のバージョンをアドレス指定可能に保つバージョン対応キャッシュと、その下にあるLRUキャッシュです。取引チェーンのアクセスパターン(毎ブロック触られる少数のホットキーと、めったに触られないロングテール)は、まさにこの構成が想定している形です。プルーニング
すべてのバージョンを永久に保持することは、要件ではなく選択です。3つのストアそれぞれに独立したプルーナが走り、いずれも固有の保持ポリシーを持ちます。レジャー用、状態の値用、Merkleノード用です。 Merkle用と状態の値用のプルーナを駆動するのは、データと同時に書き込まれる陳腐化インデックス(stale index)です。あるバージョンがノードや値を置き換えると、置き換えられた側はそのバージョンで陳腐化したものとして記録されます。そのためプルーニングは、ゴミを探し回る処理ではなくインデックスに対するレンジスキャンになります。何がいつ回収可能になるかは、書き手がすでに言い残しているからです。保持期間は運用者の判断であり、現実に結果が伴います。積極的にプルーニングしたノードは現在の状態を効率よく提供しますが、過去に関するクエリには答えられず、より古い地点から始めるノードへのステートシンクも提供できません。アーカイブノードはすべてを保持し、その分のコストを払います。ノードを運用するを参照してください。
バックアップとリストア
各ストアは、稼働中のノードとは独立にバックアップおよびリストアできます。これによって、ジェネシスからリプレイするのではなく、スナップショットからノードを立ち上げられます。リストアしたノードの状態は、バックアップを信用するのではなく、コミット済みのルートに照らして検証できます。次に読む
ステートシンク
ノードが履歴のすべてをリプレイせずにチェーンへ追いつく方法です。
ステートモデル
何が保存されているのか、どの表現が権威を持つのかです。
インデクサー
コミット済みの記録から履歴を再構成します。
ノードを運用する
ノードの役割と、運用について問い合わせる方法です。