Develop with pleasure!

福岡でCloudとかBlockchainとか。

Taroのアセットツリーの構造

Lightning Labsが発表したBitcoin上の新しいアセットプロトコルTaroについて、今回はTaroのアセットツリー周りのデータ構造/表現についてみていく。

Taroのアセットツリー

Taroは、Taprootを利用したアセットのオーバーレイプロトコルになる(TaprootベースのオーバーレイプロトコルはTaroがおそらく初)。なのでTaroを理解する場合、Taprootの知識があった方がいい↓

Taprootのアウトプットは32バイトの公開鍵だが、この公開鍵は、内部公開鍵(Key-Path)とスクリプトツリー(Script-Path)で構成されている。Taroのアセットは、この内、スクリプトツリー内の構造化されたデータへのコミットメントとして表される。

Taroのアセットツリーは、Merkle-Sum Sparse Merkle Treeというデータ構造のツリーになる↓

techmedia-think.hatenablog.com

Taroのアセットツリーは、以下のような2階層のMS-SMTで構成される。

Taro Asset Tree

1階層めは、アセットIDまたはアセットキーファミリーをキーとしたMS-SMT。このツリーのリーフの値は↓

taro_version || asset_id_tree_root || asset_sum

つまり、アセットIDをキーにして、対応するアセットの合計量(asset_sum)と、asset_id_tree_rootをルートとする2階層めのツリーのルートコミットメントおよびtaro_versionから構成されるリーフノードをマッピングしている。

そして2階層めが、アセット毎に作成されるMS-SMT。キーはAsset Script Keyで、リーフは、asset_leafとリーフが保持するそのアセットの量(leaf_sum)で構成される。つまり、あるキーが保持しているアセットの残高を保持するツリーになる。

asset_leaf || leaf_sum

asset_leafは、TLV形式のデータで、以下のデータが現在定義されている。

  • taro_version:使用するTaroのバージョン
  • asset_id:アセットID
  • asset_type:アセットのタイプ(0:通常のアセット、1:収集品)
  • amt:このリーフが保持するアセットの量
  • lock_time:アセットを移動可能なタイムロック
  • prev_asset_witnesses:ネストされたTLVで、対象となるアセットリーフへのマージを検証するためのアセットwitnessを含む。
  • split_commitment:通常のアセットについて、新しいアウトプットの分割の検証を許可するために使用。
  • asset_script_version:以下のTLV値の検証を方法を管理する2バイトのアセットスクリプトバージョン。
  • asset_script_key:このアセットリーフを包含するアセットスクリプトにコミット可能なBIP341方式で導出された外部公開鍵。
  • asset_family_key:BIP340で定義された32バイトの公開鍵、で、assert_idに対する64バイトのBIP340署名が続く。
  • TODO(まだ作業中っぽい)

なお、Asset Script Keyは、BIP341形式の32バイトの公開鍵。なので、2階層めも1階層めと同様に高さ256のツリーになる。

↑のようにアセットの保持状況をネストしたMS-SMTにエンコードして、そのルートハッシュをTaprootのスクリプトツリーにコミットしてるっぽい。

アセットID

↑で既に登場してるけど、オーバーレイプロトコルとしてアセットプロトコルを定義する場合、各アセットを識別するためのIDをどう導出するかを決める必要がある。Taroでは、アセットIDは以下のように計算される32バイトのデータになる。

asset_id = sha256(genesis_outpoint || asset_tag || asset_meta || output_index)

ここで、

  • genesis_outpoint: アセット発行トランザクションで使用されるインプットが参照するUTXOのOutPoint。
  • asset_tag: 特定のアセットを表現するランダムな32バイトの値。複数のアセットを1つのアセットファミリーとしてリンクする際に使用されるタグで、実際にはアセット名のハッシュ値が設定される。
  • asset_meta: 外部リンクやドキュメント、属性値、画像などのメタデータにコミットするために使われる32バイトの値。
  • output_index: ジェネシストランザクション内で一意なTaroコミットメントを含むアウトプットのインデックス

この内、genesis_outpointによってアセットIDの一意性が担保される。

参考

次は、アセットの作成や転送の仕組みについて。