Blockstreamが開発しているサイドチェーン実装のElementsで実装されているFederated Pegの技術的な仕組みが↓で公開されてたので見てみる。(記事自体は2016/02/29に書かれたもの)
The Federated Peg in Elements Alpha — The Elements Project
メインチェーンとサイドチェーン間の資金の移動は以下のようなイメージで行われる↓
各プロセスの具体的な仕組みを↑のドキュメントでおさえていく。
Federated Pegの仕組み
OP_WITHDRAWPROOFVERIFY (OP_WPV)
まずAlphaのgenesis blockから見てみる。Alphaのgenesis blockのcoinbase↓
{ "hex" : "01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4d04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73ffffffff00000000000000000100000000000000000000000000000000000000000000000000000775f05a074000000037206fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000149eac001049d5c38ece8996485418421f4a01e2d7b300000000", "txid" : "0377d218c36f5ee90244e660c387002296f3e4d5cac8fac8530b07e4d3241ccf", "version" : 1, "locktime" : 0, "fee" : 0.00000000, "vin" : [ { "coinbase" : "04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73", "sequence" : 4294967295 } ], "vout" : [ { "value" : 21000000.00000000, "serValue" : "00000000000000000000000000000000000000000000000000000775f05a0740000000", "n" : 0, "scriptPubKey" : { "asm" : "6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000 9eac001049d5c38ece8996485418421f4a01e2d7 OP_WITHDRAWPROOFVERIFY", "hex" : "206fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000149eac001049d5c38ece8996485418421f4a01e2d7b3", "type" : "withdraw" } } ], "blockhash" : "f7f0ca371b1003dc7346bab766b4a131f9e3a5d68820a364d70921cb15b95eaa", "confirmations" : 304446, "time" : 1296688602, "blocktime" : 1296688602 }
Bitcoinのgenesis blockとはだいぶ違って、1つの出力に2100万の値を持っており(Bitcoinの総発行量と同値)、そのscriptPubKeyも↓のように変わったスクリプトになっている(scriptPubKeyのタイプもwithdraw
)。
6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000
9eac001049d5c38ece8996485418421f4a01e2d7
OP_WITHDRAWPROOFVERIFY
この出力はwithdraw lock
と呼ばれている。OP_WITHDRAWPROOFVERIFY
(OP_WPV) は新しいopcode。
Alphaにはマイニング報酬が無いため、Alphaのコインを入手するための唯一の手段は、このwithdraw lock
を使うことになる。実際にwithdraw lock
を使用するトランザクションwithdrawal transaction
を作るケースを考えてみる。
OP_WPV
はスタック上に以下の要素があることを想定している。
- HASH160(
secondScriptPubKey
) 、secondScriptPubKey
のチェックのために使う - メインチェーンのgenesis blockのハッシュ
locking transaction
が含まれているブロックのcoinbase tx- 使用しようとしている
locking transaction
の出力のインデックス locking transaction
locking transaction
が含まれているブロックのマークルブロック構造- コインを送信しようとしているコントラクト
secondScriptPubKey
を満たすscriptSigsecondScriptPubKey
最初の2つの引数(secondScriptPubKey
のハッシュと、genesis blockのハッシュ)はscriptPubKeyによって提供されている。これらにはチェーン固有の情報が追加されており、このケースでは後述するscripthashとbitcoinのgenesis blockハッシュになる。↑の
6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000
のエンディアンを変換すると
000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f
となり、Bitcoinのgenesis blockのハッシュと同じ値になる。
その次の要素はlocking transaction
を提供している。これは、サイドチェーン上でコインを取り出すために、メインチェーン上のコインをロックするメインチェーンのトランザクションである。以下の図はこれまで出てきたトランザクションタイプの関係を表したものになる。
withdrawal transaction
は、他のチェーン上のロックを参照して、OP_WPV
でロックされたコインを使用する。メインチェーンにはOP_WPV
というopcodeは無いので、OP_WPV
を使う代わりにメインチェーンでは連合のコントロール下にあるマルチシグ出力でロックする。語彙の対称性に注意すること(メインチェーンで現在アンロックされているコインは、サイドチェーン側ではロックされている状態にある)。
スクリプトインタプリタはlocking transaction
の宛先が本当に連合のマルチシグかどうかチェックする。さらに、locking tx
とcoinbase tx
がマークルブロック構造の中に含まれているかチェックし、コインベースからブロック高を読み取る。Elements Alphaは非対称ペグを使用しているため、Alphaのフルノードは親チェーンと同様完全なバリデータであることが期待される。locking transaction
がBitcoinのブロックチェーン上に存在することを検証するために、AlphaはRPCを介してbitcoindに接続し、getblock
をコールしてトランザクションがブロックチェーンに記録され10回承認されているかチェックする。将来的にOP_WPV
は、bitcoindに依存することなくブロックが充分な承認がされているかどうかチェックするために、SPV証明を受け入れる。
次にOP_WPV
は16バイトのnonceからなるcontract
の宛先とwithdrawal transaction
の受信者を表す20バイトのscript hashを検証する。インタプリタはpay-to-contract (P2C)プロトコルを使ってlocking transaction
がコントラクトにコミットしているかどうかチェックする。P2Cを使うと、locking transaction
の送信者は透過的に宛先のscript hashを指定することができ、バリデータはサイドチェーン側でコインを取り出す受信者をチェックできる。これはコントラクトのために新しいキーペアを導出することで動作する。
x: privkey = old_privkey + H(x), pubkey = old_pubkey + H(x)*G.
要約すると、OP_WPV
でロックされた出力を使いたいユーザは、最初にサイドチェーン側でP2SHアドレスを作成し、サイドチェーンに移動する資金をメインチェーン上で連合に送るlocking transaction
を組み立てる。続いて、(contract形式の)script hashをlocking transaction
に埋め込みブロードキャストする。ブロードキャストしたトランザクションの確認期間(10ブロック)が経過したら、locking transaction
とコントラクトを使ってOP_WPV
を使うことができる。
Withdraw output
OP_WPV
は、それを使用するトランザクションの出力へのアクセス権を持つopcodeの新しいタイプである。OP_WPV
は、トランザクションがwithdraw output
という出力と、おつりを表すOP_WPV-locked output
という2つの出力を持っているかチェックする。次にインタプリタは、出力の値を比較し、withdraw output
の資金の量がメインチェーンでロックされた資金より多くないか、残りのおつりがロックされた出力に戻るようになっているか検証する。このおつりは将来また↑のようにメインチェーンからサイドチェーンへ資金を移動する際のトランザクションで使われる。
withdraw output
には↓のscriptPubKeyが設定されている。
OP_IF
<nLockHeight>
<lockTxHash>
<nLocktxOut>
<fraudBounty>
<HASH160(secondScriptPubKey)>
<genesisHash>
OP_REORGPROOFVERIFY
OP_ELSE
144
OP_CHECKSEQUENCEVERIFY
OP_DROP
OP_HASH160
<HASH160(destinationScript)>
OP_EQUAL
OP_ENDIF
まずELSEブランチを見てみる。OP_CHECKSEQUENCEVERIFYによりこのwithdraw output
がブロックに格納されてから144ブロック(24時間)経過するまで(contest period)、このブランチが実行できないようになっている。contest periodが過ぎたら、withdraw output
は通常のP2SHスクリプトになる。インタプリタはさらに、destination scriptHashがlocking transaction
内でコミットされたcontractから作られたscript hashか確認する。
最初のブランチの実行を成功させるには、2つめの新しいopcode OP_REORGPROOFVERIFY
(OP_RPV)に不正の証拠を提供する必要がある。そのため、contest periodの間、withdraw output
は任意のノードから不正の証拠を受け入れることができ、それによりこの出力をアンロックし、fraud bounty
を収集する。
OP_REORGPROOFVERIFY (OP_RPV)
OP_RPV
はメインチェーンのロックの二重使用と(チェーンが分岐し再収縮するケースなどによる)メインチェーンの再構成という2つの無効な状態を修正するためのopcodeである。同じメインチェーンのロックを参照したwithdrawal transactions
を作ることは可能で、以下の図はメインチェーン上のlocking transaction
を使ってサイドチェーン側で二重使用しようとする例。
OP_RPV
は、不正の証拠が提供された際、withdraw output
をアンロックできる(↑のscriptPubKeyの最初のブランチ)。メインチェーンのロックへの参照は既にwithdraw output
に与えられているため、インタプリタは実際に二重使用があるか、オリジナルのwithdraw transaction
と二重使用のwithdraw transaction
共にマークルブロックが有効で、二重使用のwithdraw transaction
がオリジナルのwithdraw transaction
より新しいかチェックする。Elements Alphaのブロックチェーンのコンセンサスは署名者の連合によって決定するため、インタプリタは唯一有効な署名を持つブロックを必要とする。もしAlphaのコンセンサスがPoWであれば、OP_RPV
は(OP_WPV
がブロック高の検証にSPV署名を使うのと同様)検証のためにSPV証明を必要とする。
OP_WPV
と同様、OP_RPV
もアンロックするトランザクションの出力を参照する。トランザクションはwithdraw output
の値からfraud bounty
を差し引いた値を再ロックするため、OP_WPVを使った1つの出力を持つ。fraud bounty
は不正の証明者によって請求される。
名前が示すようにOP_RPV
は二重使用があるときだけでなく、メインチェーンが再構成された際にも使われる。そのような状況では、lockin transaction
は他のブロックに含まれるか、チェーン上から完全に消えており、いずれの場合も再構成の証拠によってwithdraw output
は無効化される必要がある。これはまだAlphaでは実装されてないが、原則的に証明者が充分時間が経過した後、withdrawal transaction
が含まれていたブロックからwithdrawal transaction
が消えていること示すSPV証明を提供すると思われる。
alphadの起動オプションにtracksidechain=all
を指定していると、二重使用が発生した際に不正の証拠を提供するため全てのメインチェーンのロック出力を保存する。
最後に、OP_WPV
の9つめのsecondScriptPubKey
について見てみよう。secondScriptPubKey
は、scriptSigの実行結果やwithdrawal transaction
に関する情報を含むスタックで実行される。Elements Alphaでは、BitcoinをロックするsecondScriptPubKey
は
OP_DROP 144 OP_LESSTHANOREQUAL
で、これで効果的にcontest periodを経過したことを確認できる。secondScriptPubKey
はscriptSigの結果をチェックしないので、この場合のデフォルトのscriptSigはちょうど1バイトのプッシュになる。この仕組みは原則的にトランザクション手数料やfraud bounty
、その他の複雑なルールにチェーン特有の制限を加えることができる。
サイドチェーンからメインチェーンへの移動
サイドチェーンからメインチェーンへ資金を移動する仕組みは比較的単純。以下の図は、メインチェーンへ資金を移動する際のトランザクションのシーケンスを表している。
メインチェーン上のfederated lockはm-of-nのマルチシグの出力である。ロックを保持する職員はサイドチェーン上でメインチェーンへの払い戻しのリクエストが来ると、RPCを介してalphadと通信しロックを解除するwatchmanというプログラムを実行する。
払い戻しのリクエストはロック出力の形式をとり、サイドチェーンからメインチェーンへの転送は以下のscriptPubKeyを持つ新しいトランザクションで始まる。
<HASH160(scriptDestination)> OP_DROP <genesisBlockHash> <HASH160(secondScriptPubKey)> OP_WITHDRAWPROOFVERIFY
このスクリプトはサイドチェーンのコインをロックし、メインチェーンのアドレスを伝える。これによりロックされたコインを意図した受信者に入金するよう職員に指示する。
この仕組みの裏側では、watchman
が別のネットワークを使用してround-basedの分散プロトコルに従い、round-leaderを選ぶ。round-leaderは、払い戻しのリクエストを集めて対応するメインチェーンのwithdrawal transaction
を作成する。round-leader以外の他の職員は、そのトランザクションが払い戻しのリクエストに正しく対応しているか(宛先は正しいか、サイドチェーンのロックはn confirmされているかなど)チェックし、署名する。充分な署名が集まったらwithdrawal transaction
は有効になり、Bitcoinネットワークにブロードキャストする。
この際、連合はトランザクション手数料を支払わなければならない。そのためユーザに寄付をしてもらう仕組みがいくつかある(サイドチェーンでOP_RETURNの出力を作るか、直接連合のアドレスにコインを送ってもらうか)。
まとめ&所感
- Elements AlphaにはBitcoinと違ってマイニング報酬はなく、genesis blockのコインベースにあるコインが全てで、このコインベースにはBitcoinの発行総量と同じ2100万のコインがセットされている。
- Federated Pegを実現するため、Alphaには
OP_WITHDRAWPROOFVERIFY
とOP_REORGPROOFVERIFY
という2つの新しいopcodeが追加されている。 OP_WITHDRAWPROOFVERIFY
はメインチェーンからサイドチェーンに移動した資金を入手する際に使われるopcode。OP_REORGPROOFVERIFY
は、メインチェーンでロックした資金をサイドチェーン側で二重使用しようとした場合や、メインチェーン側のブロックチェーンが再構成されlocking transaction
が別のブロックになったり、チェーンから消えてしまった際の対応をするためのopcode。- Alphaでは
OP_WPV
を使ってメインチェーン側のロック状況を参照した上でサイドチェーン側のコインのアンロックしている。 - Bitcoinには
OP_WPV
といったopcodeは無いので、連合が管理するマルチシグで代替する。 - サイドチェーン側で資金を入手する際は
OP_WPV
による検証が行われ、ロックされたコインを入手する出力と、再度ロックされるおつり分の出力の2つの出力を持つトランザクションを作成する。 - サイドチェーン側に移動する際の二重使用や、メインチェーン側の再構成を考慮して、メインチェーンからサイドチェーンに移動したコインは、使えるようになるまでに144ブロック(24時間)かかる。
- AlphaのコンセンサスはPoWではなく、連合の署名によって決められる。
- サイドチェーンからメインチェーンへの移動は、サイドチェーンのコインを
withdraw lock
するトランザクションを作り、それが検証され、連合の職員によりメインチェーンのBitcoinのマルチシグをアンロックするトランザクションが署名&ブロードキャストされる。 - 現時点で
OP_WPV
はロッキングトランザクションのブロックのconfirmationの確認にbitcoindを使ってて将来的にSPV証明を利用する形になるってあるので、現状はOP_WPV
のスクリプトインタプリタ内でbitcoindにRPCしてるっぽい。 - SPV証明使う機能は将来的に組み込むと書かれてるけどまだ組み込まれてない?
- Pay-to-Contract(P2C)の内容がよく分かってないのでホワイトペーパー読む。
OP_REORGPROOFVERIFY
を使って不正の証拠を提供するって具体的にどういうデータを提供すればいいのか?