少し前にStarkWareが、Bitcoinのsignet上でOP_CATを利用したSTARKベースのゼロ知識証明の実証をしてたので、どんな内容なのか見てる中で、トランザクションチェーンで状態を遷移させる手法が興味深かった↓
The path to general computation on Bitcoin | StarkWare
まず、前提としてOP_CATがあれば、SchnorrやECDSAのトリックを使ってコベナンツを実装することができる↓
- Schnorr署名とOP_CATを使ったCovenants - Develop with pleasure!
- ECDSAとOP_CATを使ったコベナンツ - Develop with pleasure!
(コベナンツの構成方法についてはこっちの記事の方が少し詳しいかも)
これをさらに拡張することで、トランザクションが参照する前のトランザクションのデータを間接的に参照できるようになる。
State Caboose
StarkWareが行っているのは、既存のBitcoinのScript機能に限定されることなく任意の計算をオフチェーンで実行し、その結果の検証をBitcoinのScriptでできるようにし、有効な状態遷移をさせるというもの。
これを実現する基本的なトランザクションは2つのアウトプット持つ:
- 最初のアウトプットは、コントラクトのロジックとそこにロックされた資金を管理する。
- 2つめのアウトプットは、コントラクトの現在の状態を保持する。このアウトプットは状態を保持するだけで使用されない。
block-beta
block:first
columns 2
space
A1["Logic"]
Tx0(["Tx 0"])
A2["State 0"]
end
block: second
columns 3
B1[" "]
space
B2["Logic"]
Tx1(["Tx 1"])
space
B4["State 1"]
end
block: third
columns 3
C1[" "]
space
C2["Logic"]
Tx2(["Tx 2"])
space
C4["State 2"]
end
space
A1 --> B1
B1-->A2
B1 ---> B2
B1 ---> B4
B2 --> C1
C1-->B4
C1-->C2
C1-->C4
style Tx0 stroke:transparent;
style Tx1 stroke:transparent;
style Tx2 stroke:transparent;
そして、コベナンツにより最初のアウトプットには同じロックスクリプトが設定されていることが強制され、2つめのアウトプットには有効な状態が設定され、前の状態から新しい状態への遷移が有効であることをスクリプトで証明させる(この状態遷移が正しいか検証するのがSTARK verifier。今回の記事ではこれ自体には触れない)。
このような構成のトランザクションをState Cabooseと呼んでいる。Cabooseというのは、貨物列車の最後尾に連結される乗務員の作業ペースとなる車両のことで、状態を運搬する最後のアウトプットという意味でこの名前を提案してるみたい。
OP_CATを利用した状態の取得
状態遷移に伴い前の状態を取得(上記の例だと、Tx1がTx0のState 0を参照)する必要がある場合に、スクリプト内でどうやって前のトランザクションの情報にアクセスするかという点について。
まず、前提としてOP_CATベースのコベナンツでは、コベナンツUTXOを使用する際のトランザクションのwitnessで、コベナンツUTXOのOutPoint(TXID + Index)の情報が提供される。このTXIDとは、コベナンツUTXOを持つトランザクションのデータ*1をdouble-SHA256したハッシュ値である。
そのため、
- 同じくwitnessで、その前のトランザクション情報を提供させ
- それらの要素をOP_CATで連結し
- そのハッシュ値が提供されたTXIDと一致するか検証し
- 一致すれば前のトランザクション情報をスクリプト内で処理することができる。
つまり、前のトランザクションが持つ状態の値を入手することができるということ。さらにスクリプトの制限が許せば、前の前のトランザクションの状態と遡ることも理論的には可能だ。
OP_CATが再導入されると本当にいろんなことが可能になるなー。
*1:witnessを除く