グローバルステート

“グローバルステート”は、Casper ブロックチェーンのストレージレイヤーです。全てのアカウントやコントラクト、そして関連しているどのデータもグローバルステートに格納されます。グローバルステートは、key-valueストアのセマンティックに従います(全てのユーザーが同様に全ての値にアクセスできる訳ではない追加のパーミッションのロジックを持つ)。

💡NOTE
鍵についての詳細情報は、鍵とパーミッションをご確認ください。

グローバルステートへの変更はファイナライズされたブロック内のデプロイ実行を介して行われます。これらの変更に対する正当性を効率よくジャッジするバリデータにとって、簡潔にコミュニケートされた新しい状態に関する情報が必要です。更には、ネットワークは受信した部分の正当性について認証可能な状態にて、ユーザーにグローバルステートの一部をコミュニケートしなくてはなりません。key-valueストアは、あらゆる理由においてマークルツリーとして実装されます。

マークルツリーの構造

Global State

大まかには、マークルツリーのデータ構造は(マークル・プルーフという構造を用いた)認証可能な方法にて分解可能なkey-valueストアとなっています。各ノードは、そのデータのハッシュにてラベリングされます。リーフノードは、それらのデータハッシュにてラベリングされます。

Casperが実装するトライ木は、最大256のラディックスを持っており、各ブランチノードが最大256個の子供を持つことが可能となっています。木を介するパスは、バイト配列型となっており、シリアライゼーションは鍵をその関連する値として木を介するパスに直接紐づけます。

正式には、トライノードは以下のいずれかとなります。

  • リーフ(leaf):鍵と値を含みます。
  • ブランチ(branch):最大256個のblake2b256ハッシュを持ち、最大256個のトライ内にいる他ノードに向いています(各ノードはそのハッシュによってラベリングされていることを思い出してください)。
  • 拡張ノード(extension node):(affixという)バイト配列とトライ内の他ノードに向いているblake2b256ハッシュを持っています。

拡張ノードの目的は、パスの縮小を可能とすることです。全ての鍵がトライ内の値に同じ最初の4バイトを使用した例を考えてみましょう。この場合、選択肢が1つだけである4つのブランチノードによるトラバースは非効率となる為、代わりにトライのルートノードがその最初の4バイトに同等なaffixと最初のnon-trivialブランチノードを向いているポインターを持つ拡張ノードになる得ます。

RustでのCasperトライの実装は、GitHubを参照ください。

💡NOTE
コンセプト的には、各ブロックはそのトライを持っておりますが、それは、そこに含まれるデプロイによって状態が変化するからです。理由としては、Casperの実装にはTrieStoreの概念を持っており、各トライのルートノードの検索を可能としているからです。