Bitcoin 上のアセットの仕組み

Hiroki Gondo
Nayuta エンジニアブログ
6 min readMay 15, 2023
Photo by Traxer on Unsplash

Bitcoin の上で Bitcoin 以外のアセットのトークン(例えばステーブルコイン)を表現するアセットプロトコルがいくつかある(Open Asset Protocol、Omni、Counterparty、RGB、Taproot Assets Protocol 他)。これらがどのような仕組みなのか説明する。

シンプルなアセットプロトコル

ここではとてもシンプルなアセットプロトコルを再発明する。発行者はアセットを発行する。アセットの所有者は別の人に転送できる。アセットがインフレしたり二重支払いができてはいけない。

アセットの発行

アセットの発行は Bitcoin トランザクション(以下 Bitcoin Tx) を発行することによって行われる。既存の Bitcoin UTXO TXID_A:0(トランザクション TXID_A の 0 番目の出力を表す)を消費する Bitcoin Tx TXID_B を発行する。TXID_B の新たな UTXO(TXID_B:0)には少量の Bitcoin が含まれる。これは Bitcoin Tx の有効な出力を生成するだけのためのものである。それとは別にこの UTXO にはアセットが 100 単位組み込まれている。

TXID_A  :0 (genesis point) ->
:1

TXID_B :0 asset_id=XXX, amt=100
:1

ここでは UTXO にアセットをどのように組み込むか定義しない(例:OP_RETURNTaproot)。ともかく、UTXO になにか余分なデータを追加することになる。またそのことが Bitcoin Tx の検証には影響しない(検証のルールに抵触しない)ようにする。

このシンプルなプロトコルでは UTXO にアセットの ID と 量の情報しか載せていない。それでもこのアセットの発行をグローバルに一意に識別することができる。それはグローバルで一意な TXID_A:0(アセットの genesis point)を消費することによって発行されたからである。

アセット ID は genesis point から導出するように定義するとグローバルに一意であることが保証される。

asset_id := sha256(genesis point)

アセットの転送

アセットをどこかへ転送する。

TXID_B  :0 asset_id=XXX, amt=100 ->
:1

TXID_C :0 asset_id=XXX, amt=100
:1

アセットの生成、転送は Bitcoin Tx の発行によって行われるので、UTXO の所有者とアセットの所有者は同じである。

次に、同じ種類のアセットを分割して送ったり、結合したりできるようにする。つまり Bitcoin と同じことができるようにする。

アセットの分割。

TXID_C  :0 asset_id=XXX, amt=100 ->
:1

TXID_D :0 asset_id=XXX, amt=21
:1 asset_id=XXX, amt=79
:2

そして結合。

TXID_D  :0 asset_id=XXX, amt=21 ->
:1 asset_id=XXX, amt=79 ->
:2

TXID_E :0 asset_id=XXX, amt=100
:1

アセットの検証

これでアセットの分割と結合ができるようになった。しかし、このプロトコルを実用化するためには解決しなければならない問題がある。次のケースを考えてみる。

TXID_D  :0 asset_id=XXX, amt=21 ->
:1 asset_id=XXX, amt=79 ->
:2

TXID_E2 :0 asset_id=XXX, amt=10
:1 asset_id=XXX, amt=90
:2

これは問題ない。アセットの分割と結合が正しく行われた。TXID_D と TXID_E2 それぞれに組みこまれたアセットの総量はともに 100 で変わらない。次のトランザクションは問題がある。

TXID_D  :0 asset_id=XXX, amt=21 ->
:1 asset_id=XXX, amt=79 ->
:2

TXID_E3 :0 asset_id=XXX, amt=10
:1 asset_id=XXX, amt=100
:2

総量 110 が入力を上回った。

TXID_D  :0 asset_id=XXX, amt=21 ->
:1 asset_id=XXX, amt=79 ->
:2

TXID_E4 :0 asset_id=XXX, amt=10
:1 asset_id=XXX, amt=90
:2 asset_id=XXX, amt=90

総量 190 が入力を上回った。出力 :2 にアセットが含まれていたため。

アセットの受信者、例えば TXID_E:0 の受信者は、なにをチェックする必要があるか?

  • 自身へ割り当てられた出力(TXID_E:0)に約束の量(10)が含まれている。
  • 出力のアセット総量が入力のアセット総量を超えていない(アセットがインフレしていない)。そのためには自身の管理下にない入出力に含まれるアセットの量についてもチェックできなければならない。

アセットの出自の検証

もう一つ重要なチェックが必要である。入力されたアセットの UTXO(TXID_D に含まれているもの) はそもそも正しいものなのだろうか?従って、以下をチェックする。

  • 入力されたアセットの UTXO が、目的のアセットのものであること。それは自己申告された asset_id をチェックするだけでは十分ではない。その転送履歴を遡ると目的の genesis point に行き着くことをチェックする必要がある。
  • 入力されたアセットの UTXO の転送履歴に含まれる全ての Bitcoin Tx が正しいものであること。つまり、全ての地点において上記のアセット転送前後の総量チェックをクリアしていること。

不可分トークン(硬貨、紙幣など)の場合、転送履歴は genesis point から一直線である。新しい転送が発生した場合、転送履歴にチェックしなければいけない最新の Bitcoin Tx が一つ追加される。

今回のケースのような、可分トークン(Bitcoin、ステーブルコインなど)の場合だいぶ複雑になる。転送履歴は一直線にはならず分割、結合を含んだ複雑なトランザクショングラフになる。

このようなアセットを含む Bitcoin Tx のトランザクショングラフがある場合、Tx A ではその祖先の青色のトランザクションを全てチェックする必要がある。Tx B ではそれに加えて赤色のトランザクションを全てチェックする必要がある。履歴は準指数関数的に増加する。これはアセットプロトコルのスケーラビリティについて大きな課題である。

上記のスケーラビリティの問題について、すでに提案されているいくつかの改善案を別の記事で挙げる。

--

--