NEM で NFT を作ってみた。ついでにモザイクに画像を保存してみた。

NEM でも NFT を作ってみたいんですが、実装はできるだけシンプルにしたい！何か良い方法はないものでしょうか。

## TL;DR
トークン名はサブネームスペースに定義して、固有パラメータはモザイク名に定義すればいいよ！

## NFT とは
NFT とは Non-Fungible Token の頭字語です。NFT はトークン毎に固有のパラメータを定義することで、同種のトークンでありながらそれぞれに別の価値を持たせる事ができるトークンです。価値が違うので Non-Fungible （代替可能性がない）という事だそうです。

NFT がどう使われるかの実例は Ethereum の dApps 「CryptoKitties」を見ると解りやすいです。
[CryptoKitties | Collect and breed digital cats!](https://www.cryptokitties.co)

NEM はスマートコントラクトを書かずとも、ビルトインの機能でモザイクというトークンを作ることができます。しかしモザイクには固有のパラメータを設定することはできないので、そのままでは NFT としては使用できません。

## 固有パラメータを設定するアプローチ色々
そこで各開発者の皆様は様々なアプローチで NFT 的な機能を実現しています。

例えば…
<dl>
<dt>マルチシグアカウント型</dt>
<dd>署名参加者が一人だけのマルチシグアカウントを NFT とみなし、モザイクの付与により固有パラメータを設定する方法。NFT の譲渡は署名参加者の付け替えで行う。</dd>
</dl>

<dl>
<dt>description 型</dt>
<dd>モザイク定義トランザクションの説明欄（description）を固有パラメータの保持用に使う方法。</dd>
</dl>

そのほかにも、トランザクションにトークンの状態を記録していく方法なども議論されていたはず…なんですがどこで議論されていたのか失念してしまいました。（ご存知の方いらっしゃいましたらコメントください）

## モザイクだけで完結したい
上記の通り、すでに NFT を実現する方法はあるものの、使用するのに若干の手間がかかります。もっとシンプルに実装することはできないでしょうか。通常のモザイクの送受信だけで NFT 取り扱うことはできないでしょうか。

## NEM にはネームスペースがあるじゃないか！
NEM のトークンであるモザイクを作成するためにはネームスペースを取得して紐づける必要があります。ネームスペースにはルートネームスペースの下層にサブネームスペースを作る事ができ、モザイクはサブネームスペースにも紐づける事ができます。[^0]

```
{root-namespace}.{sub-namespace}:{mosaic-name}
```

こんな感じの階層構造ですね。

このネームスペースの仕組みを使い、トークン名はサブネームスペース名で定義してしまい、トークンの固有のパラメータはモザイク名に定義することで NFT を表現することにします。

同一のサブネームスペースに紐づいているモザイクを同種のトークンとみなすことで NFT 的に扱う事ができる、という寸法です。

[^0]: ネームスペースについてはトレストさんが解りやすくまとめてくださっています。[NEMのネームスペースとモザイクって何なのか？ - クリプトストリーム](https://www.cryptostream.jp/nem-namespace-mosaic-3551/)

## モザイク名に値を保持する
モザイク名は最大 32 文字設定できます。 ここに固有のパラメータを設定しましょう。

<img width="532" alt="モザイク名は最大 32 文字設定できます" src="https://qiita-image-store.s3.amazonaws.com/0/215722/303095d8-52db-332e-496d-518c7eea113c.png">


パラメータを文字列でそのまま保持しても良いし、 Base32[^1]を使えば 20 byte の値が保持できます。

これでモザイクに固有のパラメータを保持することができます！NFT！

[^1]: モザイク名には a から z までのアルファベットと 0 から 9 までの数字が使えるので、Base32エンコードした文字列が保持できます。Base32 については Yu Kimura さんが解りやすくまとめてくださっています。[Base32とは](https://yu-kimura.jp/2018/03/21/base32/)

## さらに発展させてみる
さて、文字情報を保持するだけだと物足りないので、少し工夫して白黒2値のドット絵の XBM データ[^3] を Base32 エンコードしてモザイク名に保持してみます。保持するのは下記のビットマップデータです。

#### イメージ
<img width="395" alt="NEM bitmap" src="https://qiita-image-store.s3.amazonaws.com/0/215722/663b7c16-d319-20cd-7fd3-610a687226c4.png">

#### XBM データ

```
#define pict_width 16
#define pict_height 8
static char pict_bits[] = { 0x00,0x7e,0x04,0x08,0x7e,0x00,0x7e,0x4a,0x4a,0x00,0x7e,0x04,0x08,0x04,0x7e,0x00 };
```

この XBM の配列の値を Base32 エンコードすると

``` 
01z0823y01z4mjg0fr20g13y00
```

という値になるので、これをモザイク名にして Mosaic definition transaction を発行します。ルートネームスペースは reward、サブネームスペースは pixelart としました。

<img width="761" alt="Mosaic definition transaction" src="https://qiita-image-store.s3.amazonaws.com/0/215722/61aa8a94-881f-9eaf-242c-2a9fd1ab27ff.png">

これでモザイク自体に画像データを保持することができました。モザイクの名前を参照するだけで画像データを取得する事ができます。

今回使用した XBM という形式はデータ圧縮をしない画像形式なので、zip 圧縮したり圧縮効率の良い画像形式にすれば、もっとデータサイズの大きな画像を保持できそうですね。

[^3]: X Bitmap。モノクロのビットマップ画像をC言語の配列として表した画像データです。ここでは define 行などを除いた配列の値のみをモザイク名に保持しています。

## モザイク名だとアップデートできないのでは？
モザイク名はアップデートできません。なので…バーンしましょう。アップデートが必要な時は、バーンしてパラメータをアップデートしたモザイクを新規に作成しましょう。Burn ‘em all!

## まとめ
今回は NEM で NFT を表現するために、トークン名はサブネームスペースで定義し、固有のパラメータはモザイク名に保持してみました。

実際には今回のやり方よりも、アカウント型の NFT が優れていると思います。モザイクの送付のみでパラメータの付与ができるため低コストですし、効率的です。

モザイク名に固有のパラメータを保持する方法では、パラメータ違いのトークンを作るたびにモザイクが増えていくため、いずれ収拾がつかなくなる事が予想できます。

とはいえ、モザイク自体にパラメータを保持することにもメリットはあります。通常のモザイクの機能を使って送受信ができることや、外部の情報を参照することなくパラメータを取得できる面はメリットと言えるでしょう。

また、 description 型では所有者の許可を得ずモザイクの作成者がパラメータを変更できますが、モザイク名であれば後から変更はできません。アップデートができないというデメリットでもありますが、改竄されない保証でもあります。

この方法を面白いと思った方は是非、モザイク名にパラメータを保持してみてください。サブネームスペースは2階層まで設定できるので、2階層目のサブネームスペース名（最大64文字）とモザイク名（最大32文字）を使用すれば Base32 エンコードで 60 byte のパラメータが保持できます。無茶な使い方だとは思いますが、チャレンジしてみてはいかがでしょうか。