TapyrusのCOLOR識別子について
Tapyrus の COLOR 識別子について
就活モチベが吹き飛んだので趣味に走ります。
Tapyrus の COLOR 識別子について、軽くまとめる記事。
COLOR 識別子とは
Tapyrus で発行される Token などに対し、識別子として付与される。OP_COLOR 以後に記載され、この opcode が出現することでスタック最上位の要素が COLOR 識別子として解釈される。また、その UTXO は任意のトークンを示すこととなる。
tapyrus-cli にて、トークンを発行すると
{
"color": "c3fe867030bbc10029a2d11a7ef4719a4b6ef11e5bdbe0d023bd5a57732c48cf99",
"txid": "28618a610078b4460b8302e3cc4a1e822b600024b399ede7815de9b830a4a83a"
}
のような形で出力が返るが、このcolor
要素が COLOR 識別子である。
端的に Token の ID と解釈できる。
COLOR 識別子の構造
COLOR 識別子は 1 バイトの「タイプ(TYPE)」と 32 バイトの「ペイロード(PAYLOAD)」で構成される。タイプとペイロードの内容については以下の通り。
タイプ | 定義 | ペイロード |
---|---|---|
0xC1 | Reissuable Token | 発行 TX のインプットの scriptPubkey の SHA256 値 |
0xC2 | Non-Reissuable Token | 発行 TX のインプットの OutPoint の SHA256 値 |
0xC3 | Non-Fungible Token | 発行 TX のインプットの OutPoint の SHA256 値 |
発行 TX のインプットの OutPoint、つまり発行に用いる UTXO はチェーン上で一意であることから COLOR 識別子も一意なものであることがわかる。またこれにより UTXO 単体で COLOR 識別子を導出することが可能である。
COLOR 識別子を導出してみる
NFT の発行を例として導出してみる。
発行に用いる UTXO は以下とする。
UTXO-01
{
"txid": "08504c03b29073a8ad8705363c7fcb2708afac2e1f11453bd7f64d9d365f269d",
"vout": 0,
"address": "1EjNxzpqw411MfY8i2HFLHjDvUERfR9VLj",
"token": "TPC",
"amount": 0.00050000,
"label": "",
"scriptPubKey": "76a914969d7101a2c2aa9b25310785ecfa837e1220df7988ac",
"confirmations": 7660,
"spendable": true,
"solvable": true,
"safe": true
},
タイプ
タイプについて、NFT を発行するので「0xC3
(16 進数表示で c3
)」となる。
ペイロード
ペイロードの内容は「発行 TX のインプットの OutPoint の SHA256 値」である。
「発行 TX」は今から作る(tapyrus-cli issuetoken
で生成される)トランザクションのこと。
「発行 TX のインプット」は発行に用いる UTXO。つまり上記で示したUTXO-01。
UTXO-01のアウトポイントを導出する。導出には tapyrusrb を用いる。
$ irb
# tapyrusrbを導入
irb(main):001:0> require 'tapyrus'
=> true
# TXID
irb(main):002:0> txid = '08504c03b29073a8ad8705363c7fcb2708afac2e1f11453bd7f64d9d365f269d'
=> "08504c03b29073a8ad8705363c7fcb2708afac2e1f11453bd7f64d9d365f269d"
# index
irb(main):003:0> index = 0
=> 0
# TXIDからアウトポイントオブジェクトを生成
irb(main):004:0> out_point = Tapyrus::OutPoint.from_txid(txid, index)
=> #<Tapyrus::OutPoint:0x00000001045a6388 @index=0, @tx_hash="9d265f369d4df6d73b45111f2eacaf0827cb7f3c360587ada87390b2034c5008">
# アウトポイントオブジェクトのペイロードを取得
irb(main):005:0> out_point_payload = out_point.to_payload
=> "\x9D&_6\x9DM\xF6\xD7;E\x11\x1F.\xAC\xAF\b'\xCB\x7F<6\x05\x87\xAD\xA8s\x90\xB2\x03LP\b\x00\x00\x00\x00"
# アウトポイントのペイロードのSHA256値を求め、バイナリをHexに変換
irb(main):006:0> Tapyrus::sha256(out_point_payload).bth
=> "47b0042d422289833b5c74b169efcd54f16aa0de97085fb12c787222f7ded1c7"
これで COLOR 識別子の「ペイロード」が
47b0042d422289833b5c74b169efcd54f16aa0de97085fb12c787222f7ded1c7
であることが得られた。
COLOR 識別子
上記より、「タイプ」と「ペイロード」を組み合わせることで COLOR 識別子は
c347b0042d422289833b5c74b169efcd54f16aa0de97085fb12c787222f7ded1c7
であることがわかる。これで導出は完了。
確認
実際に発行し確認してみる。
$ tapyrus-cli issuetoken 3 1 08504c03b29073a8ad8705363c7fcb2708afac2e1f11453bd7f64d9d365f269d 0
{
"color": "c347b0042d422289833b5c74b169efcd54f16aa0de97085fb12c787222f7ded1c7",
"txid": "d8129bc7e3287bf38895cc203d8472d2e5888b94df189900b27f826d2f88eb4f"
}
導出した COLOR 識別子と同じものが出力された。導出は成功。
補足
ペイロードの導出を tapyrusrb に丸投げしたので使わずやってみる。SHA256 は流石にライブラリに頼る。
$ irb
# digestを導入
irb(main):001:0> require "digest"
=> true
# TXID
irb(main):002:0> txid = '08504c03b29073a8ad8705363c7fcb2708afac2e1f11453bd7f64d9d365f269d'
=> "08504c03b29073a8ad8705363c7fcb2708afac2e1f11453bd7f64d9d365f269d"
# index
irb(main):003:0> index = 0
=> 0
# OutPointの導出
irb(main):004:0> outpoint = [[txid].pack('H*').reverse, index].pack('a32V')
=> "\x9D&_6\x9DM\xF6\xD7;E\x11\x1F.\xAC\xAF\b'\xCB\x7F<6\x05\x87\xAD\xA8s\x90\xB2\x03LP\b\x00\x00\x00\x00"
# COLOR識別子の導出
irb(main):005:0> Digest::SHA256.digest(outpoint).unpack('H*').first
=> "47b0042d422289833b5c74b169efcd54f16aa0de97085fb12c787222f7ded1c7"
まとめると
OutPoint の導出は
TXID をバイナリに変換しエンディアンを反転したものとインデックスを pack する。pack テンプレート文字列の内容は「a: ASCII 文字, 32: 32 バイト, V: リトルエンディアンの 32bit 符号なし整数」
COLOR 識別子の導出は
OutPoint の SHA256 値を求め、16 進数文字列へ変換
以上
自己満のコーナーでした。理解するととても単純な構造。
参考
Discussion