先日RBG 1.0のイエローペーパーが公開されてたので見てみる↓
2018年に記事を書いた頃からだいぶ様変わりしてる。
SONICアーキテクチャ
ペーパーでは、現代のコンピューターの基本的なアーキテクチャの一つであるノイマン型アーキテクチャと対比してSONIC(State machine with Ownership Notation Involving Capabilities)アーキテクチャというものを提案している。ノイマン型アーキテクチャは、以下のようにプログラムとデータを同じ主記憶装置に格納し、CPUとバス接続し、入力に対してプログラムを実行し出力を行うアーキテクチャ。
(図はWikipediaより)
主記憶装置のRAMは、
- CPUから自由に何度でも読み書きが可能で
- アドレスを知っていれば誰でもアクセス可能
- データの上書きが可能
という特性があり柔軟性がある一方、自由にアクセスできるメモリというのはバグやセキュリティ侵害の要因になることもあり、RGBはこれに対して以下の要素で構成されるSONICアーキテクチャを提案している。
flowchart subgraph SONICアーキテクチャ CPU3["CPU"] <--ケイパビリティ--> R1M Operation --ケイパビリティ--> CPU3 CPU3 <--> W1M Program2["プログラム"] --> CPU3 end
- zk-AluVM:CPU部分に相当するゼロ知識証明に対応したVM
- R1M(Read-once memory):一度読み込んだら消滅する(破壊的な読み取り)メモリ。
- W1M(Write-once memory):一度書き込んだら変更不可(不変書き込み)なメモリで、誰でもアクセスでき、グローバルなコントラクトの状態を定義するのに使われる。
- ケイパビリティシステム(アクセス制御):認証トークンを用いたアクセス制御を行うシステムで、このケイパビリティチェックをパスしないとR1Mへのアクセスはできない。
RAMについては、制約のある2つのタイプのメモリ(R1MとW1M)に置き換えられる。このようなメモリの仕組みは、以下のような状態遷移を保証するのに役立つ。
R1M: コインA(アリス所有) ↓ ケイパビリティチェック & 読み取り 消滅 ↓ R1M: コインA(ボブ所有)新規作成
一度読み込んだ状態は自動的に消滅するため二重使用が不可能になる。また、各状態は一度しか使われず、循環参照や複雑な依存関係がないため状態遷移が単純なため、挙動を完全に予測し、証明することが簡単になる模様。
ケイパビリティアクセス
コントラクトの状態に対する適切やアクセス権を持っているか(トークンの正しい所有者かどうか)をチェックするケイパビリティアクセスで使用される仕組みがシングルユースシール。シングルユースシールはPeter Toddが提案したプリミティブ。コンテナを封印するのに使うタグのようなもので、一度だけロックされることを保証し、偽造が困難という特性を持つもので、そんな特性を持つのがBitcoinのUTXO。
シングルーユースシールの定義はLNPBP-8として定義されている。仕様で定義されている操作は以下の2つ:
- Close(l, m)→w:メッセージ
m
に対してシールl
を閉じwitnessw
を生成する。 - Verify(l, w, m)→bool:メッセージ
m
に対してシールl
が閉じられていることを検証する。
この2つの操作が実際にRGBでどう使われるかを、アリスが100トークン持っていて、50トークンをボブに受け取る場合で説明する。まず受信者のボブは新たにシール定義を作成する。このシール定義は、L1としてBitcoinのチェーンを使用する場合は、
- ボブが持っている任意のUTXOのOutPointの情報
- ノイズデータ*1
で構成され、このシール定義から生成したハッシュ値が認証トークンになる。
作成したシール定義をアリスに送ると、アリスは自分が持っているトークンの状態を更新し、
- 50トークンをボブの認証トークン宛に
- 残り50トークンをアリスの認証トークン宛に
割り当てる新しい状態を作成する。その際、アリスの100トークンを受け取った時の認証トークンを使ってR1Mを読み取り、その旧状態はそこで破棄される。この時、アリスは、
- 旧状態に割り当てられていた認証トークンのシール定義内のUTXOを使用するトランザクションをBitcoinネットワークでブロードキャストすることで、旧状態のシールを閉じる。
- 1のトランザクション内(OP_RETURNかTaprootのwitnessとして)にRGBのオペレーションID(オペレーションについては後述)を埋め込むことで、RGBの操作にコミットする。
1をシールクローズドウィットネストランザクションと呼び、アリスはこれに加えて、以下をボブに送る。
- アンカー:Bitcoin側のトランザクションとRGBのオペレーションを紐付ける証明データで、以下で構成される。
- MMB(Multi-Message Bundle)証明:トランザクションのインプットが単一のRGBオペレーションでのみ使用されることの証明
- コントラクトIDとMPC証明:オペレーションが特定のコントラクトに属していることの証明
- DBC証明:(Taprootでコミットする場合のみ使用)Taprootのあるリーフにコミットメントが含まれていることを証明するためのデータ
- フォールバック証明:将来のフォールバックシール用に確保されているデータ
- RGBのオペレーションデータ
公開データであるシールクローズドウィットネストランザクションとアンカーが、シールが正しく閉じられ特定のRGB操作にコミットされたことを証明するwitnessデータw
に該当する。
コントラクト
以前はスキーマで記述されていたコントラクトは廃止され、zk-AluVMのアセンブリ言語と高級言語Contractumを使って開発するようになる模様。
RGBのコントラクトは以下の要素で構成される。
- ステート:コントラクトの状態。誰がどれだけ所有しているかを管理。
- オペレーション:状態遷移を提案するデータ構造
- コーデックス:コントラクトのルールを定義したもの。状態遷移の妥当性を検証するロジック。
一般的なスマートコントラクトだと、コントラクトを実行することによって状態が更新されるけど、RGBの場合、実行するロジックの代わりに検証用ロジックをコーデックスとして定義し、オペレーション(状態遷移の内容)が正しいかを検証する仕組みになっている。
コントラクトが実行される場合は、オペレーションに対応したコーデックスを参照し、検証ロジックをzk-AluVM上で実行する。先程のトークンの例であれば、
- 入出力のバランスが正しいかを検証し、
- 正しい所有者かを検証し(ケイパビリティアクセス)、
- 数値のオーバーフロー防止
- (あれば)カスタムルールの検証
を行う。
PRiSM
RGBのコントラクトはIssue(コントラクトの発行)以降、PRiSM(Partially Replicated state machines)として動作する。PRiSMは部分的複製状態マシンを指し、これは状態が状態マシンのすべてのインスタンス全体で複製されるのではなく、各インスタンスが必要とする状態の一部のみが伝播されることを意味する。簡単に言うと、たとえば、Ethereumであれば各ノードはすべてのコントラクトの状態を保持しているけど、RGBの場合、自分が取引するアセットの状態遷移のみを確認できればいいから、検証する状態は全アセットの状態ではなく部分的でよいということ。発行されたトークンは複数のUTXOに分割されて流通していくので、自分が受け取ったUTXOまでの状態遷移を確認できれば良い。このあたりは、UTXOモデルのCSV(Client Side Validation)プロトコルだと大体似た感じになってる。
なお、Issue時のコントラクトに関する以下のデータはグローバルなデータとして、(各処理はPRiSM上で実行されるとしても)全参加者で共有される。
- RGB発行データ構造バージョン
- コントラクトのメタデータ
- テスト用かどうかを示すbool値
- コントラクトで使用するL1のID
- コントラクト発行時のタイムスタンプ
- 機能フラグ(将来の拡張用)
- コントラクトの名称
- 発行者のアイデンティティ情報
- コーデックス
- ジェネシスオペレーション
ただ、PRiSM単位で動作するようになっても、発行されたトークンが広く転々流通するようになると、その履歴の検証コストは大きくなり、極端な話、Bitcoinレベルに流通するとL1と同等の検証コストが追加されることになる。この問題を回避するために、RGBではzk-STARKベースの再帰的な履歴の圧縮をするアプローチを採るようにしたんだと思われる。
zk-AluVM
zk-AluVMは上記の状態遷移の検証を行うためのVM。AluVM(Arithmetic logic unit Virtual Machine)自体は、RISC命令セットとレジスタベースのVMを開発するためのフレームワークで、RGBが使用するzk-AluVMは、有限体の要素の算術演算をサポートするGFA256命令セットをサポートしている。命令セットについてはペーパーのAppendix Aにリストされている。
SONICプログラム(後述)を実行すると、以下の要素で構成される実行トレースが生成される。
- 命令
- 入力値(命令実行前のレジスタの値)
- 出力値(命令実行後のレジスタの新しい値)
- 外部データからアクセスされた場合の隠しパラメーター
生成された実行トレースは、有限体の要素を使ってエンコードされ、zk-STARK証明器の入力になり、STARKベースの証明を生成するみたい。予め各命令を使った計算を多項式制約として表現しやすくしzk-STARK証明用に最適化するアプローチを採っているみた。
ペーパーには
The specific details of the encoding and selection of the zk-STARK prover are beyond the scope of this document and are a subject of future work.
とあるけど、RGB v0.12コンセンサスリリースの記事だと、v0.12で初めてzk-AluVMが導入されたのかな?↓
https://rgb.tech/blog/release-v0-12-consensus/
上記のzk-AluVMにR1M/W1M、ケイパビリティシステム、状態遷移の調整もろもろを行うコンセンサスレイヤーを多項式コンピューターUltraSONICと呼んでる模様。
概要はなんとなく掴めてきたので、詳細は実際に動かしながら確認してみたい。
*1:認証トークンが漏洩した場合にユーザーが所有するUTXOとの紐付けを隠すためのデータ