Lightining Networkとの連携も含めた、「RGB」というBitcoinベースの新しいデジタルアセットプロトコルが発表された↓
RGBのプロトコル仕様は、現状以下の5つのモジュールに分かれている。
- RGB
プロトコルのコアおよび低レベルのアセットロジックを定義。 - Kaleidoscope
他のモジュールを包括しプロトコルとして相互作用するための高レベルの機能を定義。 - Bifröst
クライアントサイド検証の枠組みのプルーフの保存と公開について定義。 - Lighting Network Integration
RGBをLighting Networkに適用する(アセットに対応したルーティング、チャネルの更新、クローズなど)ために必要なBOLTの拡張などを定義。 - Proofmarshal
アセットに特化した形で、スケーラビリティとプライバシーを向上させる、Lightning Networkを補完・代替するレイヤー2ソリューションの定義。
まだ完成という訳ではないっぽく、現時点で使用が少しでも記載されてるのはRGBと、Bifröst、Lighting Network Integration。いずれもまだ作成途中っぽい。Lighting Networkで任意のアセットをオフチェーンで取引するための拡張仕様が定義されてたり、LNとは別のスケーラビリティソリューションの提案とか特徴的。
まずは、RGBモジュールみながらコア機能についてまとめた。
アセットの検証
一般的に、カラードコインはOP_RETURN
を利用してBitcoinのトランザクションレイヤーを拡張しているが、Bitconのプロトコル上、OP_RETURNにあるデータは何の意味ももたず、その上に構成されるアセットの取引もコンセンサスレベルで関与することはない。そのため、こういった拡張プロトコルでは、そのプロトコルに対応したウォレットやノードなどのクライアントが、アセットの振る舞いの検証をするClient Side Validationモデルを採用する。RGBも他のカラードコインのプロトコルと同様このClient Side Validationを採用している。
コントラクト
アセットがどのようなもので、アセットの発行方法、転送のルールなどを定義したものをコントラクトと呼んでいる。このコントラクトのデータは以下の2つのデータで構成される。
headerのデータ項目は以下の通り。
フィールド | 内容 |
---|---|
title | アセットコントラクトのタイトル |
description | アセットコントラクトの定義 |
contract_url | コントラクトとlight-anchorの発行に関する一意のURL |
issuance_utxo | このコントラクトをデプロイするためのコミットメントを持つトランザクションで使用されるUTXO |
network | 使用中のネットワーク(mainnet, testnet) |
total_supply | 総供給量(単位はsatoshi) |
min_amount | dust limitのように転送する際のトークンの最小量 |
max_hops | 再発行前の最大ホップ数(この機能を無効にする場合は0xFFFFFFFF を設定する) |
reissuance_enabled | 再発行機能を有効にするかどうか |
reissuance_utxo | (オプション)トークンを再発行する際に使用するUTXO |
burn_address | トークンを償却する際の送信先アドレス |
commitment_scheme | このコントラクトで使用するコミットメント方式 |
version | 使用されたブループリントのバージョンを表す16 bitの数値 |
Open Assets ProtocolなんかだとAsset Definition Fileに近いけどあれはメタデータ的な位置付けで、↑ではアセットの種類による振る舞いやルールも定義するようになっている。
アセット識別子:asste_id
各アセットはasset_id
で識別される。このasset_id
はコントラクトのいくつかのデータ項目のハッシュから計算されるようだが、現時点では算出方法については書かれてない。
Proof-of-burn
アセットを焼却する際は、コントラクトのheader内のburn_address
で指定されたアドレスにアセットを送る。
ブループリント
コントラクトには種類があって、この種類によってアセットがどのように管理されるかであったりその振る舞いが決まる。これをブループリントと呼んでいる。
現状定義されているブループリントは以下の3つ。
Simple issuance: 0x01
, version: 0x0008
シンプルなアセット発行のコントラクトで、headerのtotal_supply
で指定された量のアセットを発行し、owner_utxo
宛に送る。
このタイプのコントラクトのbodyのデータ項目は、以下の通り。
フィールド | 内容 |
---|---|
owner_utxo | 全てのトークンを受け取るUTXO |
この場合コントラクトは以下のようになる。
{ "kind": 0x01 // 作成するコントラクトの種類で、これは一般的な発行 "version": 0x0008 // このコントラクトの種類で使われるバージョン "title": <String>, // アセットコントラクトのタイトル "description": <String>, // 償還可能なアクションと非スクリプトによる条件の定義 "issuance_utxo": <String>, // このコントラクトへのコミットメントに使われるUTXO "contract_url": <String>, // コントラクトおよびlight-anchorを公開するための一意のURL "total_supply": <Integer>, // 総供給量(satoshi) "max_hops": <Integer>, // 再発行前にアセットに対して実行可能なオンチェーン転送の最大量 "min_amount": <Integer>, //一緒に転送可能なカラーリングされたsatoshiの最小量 "network": "BITCOIN", // 使用するネットワーク "reissuance_enabled": 0, // 再発行の無効化 "burn_address": <Address>, // トークンを焼却するのに使用するアドレス "commitment_scheme": "OP_RETURN", // このアセットで使用するコミットメント方式 "owner_utxo": <String>, // 全ての発行トークンを受信するUTXOで、コントラクト指定のフィールド。 }
Crowdsale: 0x02
, version: 0x0008
クラウドセール用のブループリント。total_supply
まで指定した価格でトークンを販売する。コントラクトには異なるasset_id
をもつ2つのアセットが作られる。1つは通常のトークン用のアセットでもう1つは払い戻し用のトークン。払い戻し用のトークンはクラウドセールの期間前や後に送金してセールを逃したユーザー向けのもの。
このタイプのコントラクトのbodyのデータ項目は、以下の通り。
フィールド | 内容 |
---|---|
deposit_address | トークンを購入する際のBitcoinの送金先アドレス |
price_sat | 1トークンあたりの価格(satoshi) |
from_block | クラウドセールを開始するブロック |
to_block | クラウドセール終了のブロック |
Re-issuance: 0x03
, version: 0x0008
アセットの発行者が、供給量を増やすことでアセットの再発行を可能にするブループリント。このコントラクトを使用する際は、オリジナルのコントラクトのreissuance_enabled
が0でないこと。またオリジナルコントラクトのreissuance_utxo
で指定されているUTXOを使ってデプロイする必要がある。
このコントラクトの場合、header内のtitle
,description
,network
,min_amount
,max_hops
,burn_address
,commitment_scheme
はオリジナルから変わらないので全て0をセットする。
またbodyのデータ項目はない。
プルーフ
コントラクトは上記のように種類によってルールが異なるが、各コントラクトに設定された全ての条件を満たすことでアセットの所有権を証明し、そのアセットの送付が可能になる。このコントラクトに設定された全ての条件を満たしたことを証明するのがプルーフになる。
プルーフもコントラクトと同様header
とbody
を持つとされているが、具体的な項目についてはまだ定義されていないっぽい。
アセット送付時のプルーフ
アセットを送付する際は、以下のデータがプルーフになる。
- アセットの発行から今までの全てのプルーフのチェーン
- 以下3つの項目からなるリスト
- (オプション)meta-dataに関連するmeta-script
これらのプルーフは以下のdark-tag
を使ってAES256で暗号化され、Publisher Server
に送られる。
dark-tag
アセットの受取人が生成する30バイトのエントロピーを持つ共通鍵で、アセットを送ってもらう際に、アドレスおよびPublisher Serverの情報と一緒に、アセットの送信元に送る。
受取人がdark-tagを生成する際は、受信用のアドレスを生成するのに使用しているBIP32ベースの導出鍵を使って導出する。
※ プルーフの情報はこのdark-tagで暗号化されているため、取引されているカラーや量に関してはこのdark-tagを知っているユーザーのみが把握でき、第三者がブロックチェーン上のトランザクションを確認してもこれらの情報は確認できないと思われる。
dark-tagが漏洩すると、発行トランザクションからそのトランザクションまでのアセットの流通経路は分かるが、途中で分岐していた場合などはそっちのアセットの流通経路までは分からない。
Publisher Server
Publisher Serverは、各アセットの取引で生成された暗号化されたプルーフを保存し、そのクエリに対応するサーバー。アセットの発行者によってメンテナンスされる場合もあるし、個々の受信者がメンテナンスしたり、第三者によって提供されることも考えられる。
※ BitTorrentやIPFSなどの分散ストレージの利用も挙げられているが、RGB自体はPublisher Serverについてシンプルさのため集中型の管理もありとしてる。
コミットメント方式
アセットを新規発行する際は↑のコントラクトのデータを、アセットを送付する際はその条件を満たしていることを証明する↑のプルーフをそれぞれブロックチェーンにコミットする必要がある。Open Assets Protocolでは、これらは基本的にOP_RETURN
のアウトプットにMakerOutput
と呼ばれるOA用のペイロードをプッシュする形態をとっていたけど、RGBの場合は以下の2種類の方法が用意されている。
OP_RETURN
他のカラードコイン同様OP_RETURN
を使う方法で、OP_RETURN
の後に↑のコントラクトやプルーフのエンティティ情報をプッシュする。OP_RETURN
を使ったRGBの有効なコミットメントを含むトランザクションのルールは以下の通り。
- トランザクションに
OP_RETURN
のアウトプットが少なくとも1つある。 - 最初の
OP_RETURN
アウトプットにトランザクションがコミットするエンティティをdouble-SHA-256したハッシュ値が入っている。
pay-to-contract
pay-to-contractは直訳するとコントラクトへの支払い。コントラクトの内容を元に鍵およびアドレスを生成するプロトコルで、昔Blockstreamが発表したSidechainのホワイトペーパーなどで紹介されている。
RGBのエンティティにコミットするpay-to-contractアドレスは以下のように計算する。
- ランダムに128 bitのnonceを生成する。
weak = hmac_sha256(key=original_pubkey, data=(nonce||double_sha256(RGBのエンティティ)))
を計算する。new_pubkey = original_pubkey + G * tweak
を計算する。- 計算した
new_pubkey
を公開鍵として、P2WPKH or P2PKHアドレスを生成する。
この公開鍵に対応する秘密鍵は、元の秘密鍵に対して同じ計算を適用することで計算できる。
後は計算したアドレス宛に送金するトランザクションを作るだけで、トランザクションの構成は通常の支払いと何ら変わらない。
アセットの送付方法
RGBで実際にアセットを送付する際、送信者は以下の2つの方法でアセットの所有権を移転できる。
アドレスベース
アセットの受信者がアセットのUTXO自体を受け取りたい場合に使用する。この場合、プルーフには、トランザクション内の受信者の送信先アドレス宛のアウトプットのインデックスをセットする。
※ アセットを受信者のアドレスに送るという直観的に分かりやすい方法で、他のカラードコインなどでも一般的によく使われている方法。
UTXOベース
受信者が既に持っているUTXOに、トークンをバインドしたい場合に使用する。このためこの送付トランザクションには受信者向けのアウトプットは含まれず、プルーフには、送信先のUTXOのハッシュをセットする。
※ この場合ブロックチェーンのトランザクションを見ただけでは、誰から誰にアセットが送付されているのか推測できない。
この場合、複数のアセットが同じUTXOを指定していた場合、そのUTXOは両方のアセットを持つということになるのかな?
RgbOutPoint
上記のようにアドレスベースの場合は送信トランザクションのアウトプットインデックスを、UTXOベースの場合は受信者の既存のUTXOのOutPointを指定することになるが、それぞれをエンコードしたオブジェクトをRgbOutPoint
と呼んでいる。
RgbOutPoint
をシリアライズする際は、どちらか分かるようUTXOベースの場合は0x01
、アドレスベースの場合は0x02
がプレフィックスとして付与される。(長さで分かりそうな気がするけど)
所感
Open Assets Protocolとかだと、取引するアセットの量や宛先は全てトランザクション内のMarkerOutput(OP_RETURNにOpen Assets Payloadをプッシュしたもの)で管理されていて、OAのトランザクションを解釈できれば、ブロックチェーン上でどのアドレスからどのアドレスにいくつのアセットが送られているか確認できるプロトコルだったけど、RGBの場合取引するアセットやその量は全てプルーフに記載され、受信者が生成した共通鍵dark-tagで暗号化されPublisher Serverと呼ばれる外部ストレージに保存されるようになっている。ブロックチェーン単体ではアセットの動きは追えず、外部にあるプルーフが必要になる。UTXOベースのトランザクションであれば、プルーフのみがブロックチェーンアンカリングされているといっても良い。
ノードはトランザクション内のコミットメントとプルーフから受信したアセットの情報を判断するので、フルノードでなくSPVノードのような軽量ウォレットでもアセットの管理ができるだろう。
まだ不明点も多いので具体的な実装を含めてプロトコルの完成までまだ時間かかりそうだけど、他にもLNとの連携や、LNとは別のスケーラビリティソリューションなど面白そうな機能はあるので、今後が楽しみ。
不明点
↓のようにドキュメントの中に出てくるけど、内容や仕組みについてまだ書かれてないことが多い。