NEM1 と NEM2 で変わる仕様まとめ

初のRC版として、コードネーム `Fushicho` 版が公開され、周辺ソフトウェアの仕様も追いついたものが公開され、
いよいよ `Catapult` のパブリックリリースとメインネットの稼働の足音が聴こえてきました。

`NEM1` からのマイグレーション、ブランディングなど他の問題もありますが、それはそれとして。

`NEM1` から `NEM2` へのアップグレードにおいて、様々なトランザクションの仕様が追加され、より強力なチェーンとなりました。

ここでは、変更された仕様についてざっくりですが、おさらいしてみようと思います。

なお、次で`Catapult(NEM2)`の通貨名や単位、固定手数料については、
現時点では便宜上、旧使用と同じ名前を使用していたり、現時点で設定されているもので、
今後のテストネットやメインネットで使用されるものとは変わる可能性があることをご了承ください。


# トランザクションの種類

全トランザクションを列挙してみました。
目的が同じ・近いトランザクションは隣り合わせてありますが、同じ仕様ということではありません。

|  NEM1(全９種) | NEM2(全２２種) | 説明 |
| ----- | ----- | ----- |
|  `Transfer` | `Transfer` | モザイクの転送 モザイクの転送やメッセージを記録します。 |
|  `ImportanceTransfer` | `AccountLink` | インポータンスの転送 デリゲートハーベスティングを行うためにインポータンスをリモートアカウントへ転送するためのリンクを記録します。 |
|  `MultisigAggregateModification` | `MultisigAccountModification` | マルチシグアカウントへの変換 アカウントをマルチシグアカウントに変換し、連署者を設定することを記録します。 |
|  `MultisigCosignatoryModification` | `-` | マルチシグアカウントの変更 マルチシグアカウントの連署者の追加・削除、最小署名数の変更を記録します。 |
|  `MultisigSignature` | `Cosignature` | 署名トランザクション 自身の署名が必要なトランザクションに対しての署名を記録します。 |
|  `ProvisionNamespace` | `NamespaceRegistration` | ネームスペース取得 ネームスペースの作成を記録します。 |
|  `MosaicDefinitionCreation` | `MosaicDefinition` | モザイク定義 モザイクの作成を記録します。 |
|  `MosaicSupplyChange` | `MosaicSupplyChange` | モザイク供給量変更 作成済みのモザイクの供給量を変更します。 |
|  `Multisig` | `AggregateBonded` | 連署トランザクション マルチシグアカウントからのトランザクションを記録する際に使用します。 |
|  `-` | `AggregateComplete` | 集約トランザクション 複数のトランザクションをアトミックに記録する場合に使用します。 |
|  `-` | `AccountMetadata` | アカウントのメタデータ アカウントに任意のデータを添付して記録します。 |
|  `-` | `MosaicMetadata` | モザイクのメタデータ モザイクに任意のデータを添付して記録します。 |
|  `-` | `NamespaceMetadata` | ネームスペースのメタデータ ネームスペースに任意のデータを添付して記録します。 |
|  `-` | `HashLock` | ハッシュロックの作成 `AggregateBonded` などを記録する際に、スパム防止のための担保を記録します。 |
|  `-` | `SecretLock` | シークレットロックの作成 クロスチェーンスワップに使用する場合にモザイクの預け入れを記録します。 |
|  `-` | `SecretProof` | シークレットロックの解除 シークレットロックでチェーン上にロックされたモザイクの取得を記録します。 |
|  `-` | `AddressAlias` | アドレスのエイリアス アドレスとネームスペースの紐づけを記録します。 |
|  `-` | `MosaicAlias` | モザイクのエイリアス モザイクとネームスペースの紐づけを記録します。 |
|  `-` | `MosaicGlobalRestriction` | モザイクのグローバル制約 |
|  `-` | `MosaicAddressRestriction` | モザイクのアドレス制約 |
|  `-` | `AccountAddressRestriction` | アカウントのアドレス制約 アカウントが受け入れる送信元アカウントの許可・制限を記録します。 |
|  `-` | `AccountMosaicRestriction` | アカウントのモザイク制約 アカウントが受け入れるモザイクの許可・制限を記録します。 |
|  `-` | `AccountOperationRestriction` | アカウントの操作制約 アカウントで使用できる操作の許可・制限を記録します。 |

なんとその差、前バージョン比のおよそ2.4倍！(意味のある数字ではありませんが)
メタデータや制約トランザクションは対象となる分類だけ、似たようなトランザクションがあるので、
実質は４つくらいの機能が追加されたというところでしょうか。

後述しますが、失われた機能や仕様が変わった機能があります。

- [トランザクションタイプ - トランザクション — NEM Developer Center](https://nemtech.github.io/ja/concepts/transaction.html#transaction-types)


# 変更された仕様

`NEM1`にもあった機能が`NEM2`でどのように変わるのかをまとめてみました。
なお、ここでは`NEM1`と執筆時点での`NEM2` RC版（`Fushicho2`）との仕様の差について述べます。


## 転送トランザクションが一本化

`NEM1`では転送トランザクションに`version 1`と`version 2`が存在していました。

`version 1`は基軸通貨である`nem:xem`を送信するための仕様で、モザイクは送信できません。
`version 2`はユーザー定義モザイクの送信をするための仕様ですが、`nem:xem`も送信することができます。

`NEM2`では`version 2`の仕様へ一本化され、基軸通貨もユーザー定義モザイクも同じように扱われます。
一本化というよりは、もっと単純に`version 1`が廃止されたと考えてよいです。


## トランザクション手数料の仕様変更

`NEM1`ではTx転送手数料は最小で`0.05`〜で、実はそれ以上を設定することができ、より優先的に処理される仕様でした(ちょっとうろ覚えですが)
送信する量が`10,000 xem`毎に`0.05 xem`かかり、最大で`1.25 xem`。
メッセージがある場合は`メッセージ長 / 32 + 1`につき`0.05 xem`。

モザイクの場合は過分性や供給量によっては可変したり、過分性0で供給量10,000以下は手数料が安くなるSBM(Small Business Mosaic)という仕様もありました。

`NEM2`では、送信するトランザクションのサイズ(容量)によって変化するものとなりました。
手数料の計算には３つの要素を考える必要があります。

- １つ目は、`minFeeMultiplier`という設定値
- ２つ目は、送信しようとしているトランザクションのバイトサイズ
- ３つ目は、トランザクションに対しての最大支払手数料

手数料は次の式で算出されます。

`effectiveFee = transaction::size * block::feeMultiplier`

`Catapult-service-bootstrap`では`minFeeMultiplier`は`100`と設定されています。
`1 nem.xem`を送るトランザクションを作ってみて、そのサイズを出したところ、`177 byte`でした。
このトランザクションには最大支払い手数料を`２００００`と設定しました。

このとき、`effectiveFee = 177 * 100 = 17700`となり、`17700`が最小手数料となります。
最大支払い手数料は`20000`なので、`17700`を上回っているので、トランザクションは承認されます。
最大支払い手数料を`17699`以下を設定した場合は承認されません。

内訳をスプレッドシートで表現してみました。参考にどうぞ。

https://docs.google.com/spreadsheets/d/13lChbSsJM6vzSKN_-7apTpOBvxnj2y1AKCCVIA95c3A/edit#gid=0

`minFeeMultiplier`(最小手数料乗数)なので、`100`より大きくなる場合はその限りではありません。
トランザクションが混み合ってきた場合に可変し、より多くの最大支払い手数料を積んでいるトランザクションほど、
優先して取り込まれ、最小に戻ったときのブロックで取り込まれるような挙動をするものかとおもわれます。

上記の場合、`block::feeMultiplier`が`113`まで上昇すると、実行手数料が`20001`となり、そのブロックには取り込まれないことになります。

どのようなトランザクションを記録するかにも寄りますが、個別にトランザクションを送信する場合とアグリゲートトランザクションでまとめた場合とでは手数料が異なってくるケースもあります。

- [手数料 — NEM Developer Center](https://nemtech.github.io/ja/concepts/fees.html)


### ネームスペース

ルートネームスペースの作成は`0.000001 nem.xem / per 1 block`とブロック数に応じた手数料となり、延長する場合も同様です。
サブネームスペースの作成には固定で`0.0001 nem.xem`です。

これに加えてトランザクション手数料が必要です。

- [ネームスペース — NEM Developer Center](https://nemtech.github.io/ja/concepts/namespace.html#rental-fee)


### モザイク

作成手数料として`0.0005 nem.xem`ですが、手数料が動的に可変する仕様も盛り込まれています。
チェーンが積み重なるにつれ変化していく可能性があります。

これに加えてトランザクション手数料が必要です。

- [モザイク — NEM Developer Center](https://nemtech.github.io/ja/concepts/mosaic.html#rental-fee)



## ネームスペースとモザイクが分離した

`NEM1`では、`{ネームスペース1}:{モザイク}`や`{ネームスペース1}:{サブネームスペース2}:{モザイク}`のように、
「ネームスペース」が存在し、その配下に「モザイク」を定義する仕様でした。

ルートネームスペースの存在が前提なので、モザイクの有効な期限は、ネームスペースの有効期限(1年間)に依存していました。

```
# NEM1 モザイクのフルネーム
organization.division.currency:coin
```

`NEM2`では、ネームスペースとモザイクは独立して存在するようになります。
ネームスペースの取得とモザイクの作成は互いに無関係なものとなります。

### ネームスペース

ネームスペースの取得は`NEM1`と同様に`3`階層までの子ネームスペースを取得できます。
文字列での表現も同様に`organization.division.currency`のようになります。

ネームスペースの有効期限をブロック単位で任意に設定できるようになりました。
(パブリックネットワークでは最大1年間とみられますが、正式な情報ではありません)


### モザイク

作成したモザイクにはネットワーク上で一意な数字の羅列の内部的な`ID`が与えられます。
この`ID`によってモザイクを特定することになります。
モザイク名というのは無くなり、モザイクに直接文字列で名前をつけることはできません。
また、モザイク自身にブロック単位の有効期限を定義(無期限も可能)できるようになりました。


### ネームスペースの用途

ここまで読むと、ネームスペースは何のためなのか？という話になりますが、ここで新機能であるエイリアス機能を使うことになります。
エイリアスによってネームスペースをモザイクに紐付けるという形でネームスペースは利用されます。

また、これらは互いに依存していないため、モザイクを作成してから、ネームスペースを取得するということも可能です。
ネームスペースの期限が切れた場合でも、モザイクはモザイクの期限に従います。

- [モザイク — NEM Developer Center](https://nemtech.github.io/ja/concepts/mosaic.html)
- [ネームスペース — NEM Developer Center](https://nemtech.github.io/ja/concepts/namespace.html)


## ネームスペースはモザイクまたはアカウントにリンクして使用する

ネームスペースとモザイクは分離され、独立して定義することなりました。
そして、ネームスペースはモザイクまたはアカウントに紐づく形で利用される仕様となりました。

モザイクに紐付けた場合の`NEM1`との違いは、モザイク自体が名前を持つわけではないので名前の深さが１段階少なくなります。

```
# 例) NEM1
organization.division.currency:coin

# 例) NEM2
organization.division.currency_coin -> mosaic(0x12345678)
```

`NEM2`ではネームスペースの3階層目にモザイク名を含めてみました。
`NEM1`ではモザイク自体の名前を決められたため、こうしてみると１段階少なくなってしまっています。

ネームスペース+モザイク名に依存したシステムはこの影響を受けてしまうので、
何らかの仕様変更が求められるかもしれません。

新機能として、ネームスペースをアカウントに紐付けることもできます。

```
# 例) NEM2
organization.admin -> NBZTP7-HUPHVB-3CQK6L-SS2M5Z-YTX6JS-YJ6E27-76BO
organization.division.manager -> NDGULD-G56U7H-OZSXGR-LRN2XY-3FEYFP-IBYFAK-XDFT
```

この紐付けが行われると、ネームスペースからアドレスを特定することができるようになります。
アドレスをIPアドレス、ネームスペースをドメイン名と置き換えれば、ほぼ同じ関係だと考えられます。

この仕様のため、あるネームスペースはモザイクまたはアカウントに紐づくことになるので、
取得してみるまではどちらを指すのかはわからないことになります。

- [エイリアス - ネームスペース — NEM Developer Center](https://nemtech.github.io/ja/concepts/namespace.html#alias)


## モザイクLevyは廃止(?)された

ユニークな機能で、応用次第ではなかなかおもしろいことができそうと期待されていたLevy(モザイク徴収機能)でしたが、
`NEM2`には実装されず、廃止となってしまったようです。
少なくとも現時点では実装されていません。
同じ機能をアグリゲートトランザクションで実装を代替してくれ、とのことですが、なかなか難しいと思われます。

しかし、有用性が見いだされたとき、いつかのハード・ソフトフォークなのか、
そういったタイミングで復活・復刻することに期待してみてはいかがでしょう。

- [NIS1 から Catapult へのマイグレーション — NEM Developer Center](https://nemtech.github.io/ja/guides/migration/migrating-from-nis1-to-catapult.html#mosaics-namespaces)


## モザイクのdescriptionフィールドの廃止

`NEM1`のモザイクには説明用の文字列を記録できるフィールドがありました。
`NEM2`では廃止となりました。

これはメタデータによって任意の値を添付することで`NEM1`と同じような情報を添付できると思います。
メタデータは複数の情報を添付できるため、従来の`description`よりもたくさんの情報を添付できます。

また、メタデータはアカウントとネームスペースにも添付することができるので、
NEM上の資産(アカウント、ネームスペース、モザイク)により多くの意味をもたせることができるようになります。

- [メタデータ — NEM Developer Center](https://nemtech.github.io/ja/concepts/metadata.html)


## APIの非同期レスポンス

`NEM1`にトランザクションをアナウンス(送信)すると、同期的に結果レスポンスを得ることができました。
成功して`unconfirmed`な状態になれば、そのハッシュなどが返却され、
エラーがあれば、エラーメッセージなどが返却されました。

`NEM2`では`HTTP`リクエストを受信したらその応答として`OK`応答をすぐに返却します。
そのレスポンスからはトランザクションにエラーが有ったのかどうかはわかりません。

トランザクションが受理されたかどうかは`WebSocket`のステータスチャネルを購読するか、トランザクションの`transaction/{HASH}/status`エンドポイントからその状態を取得することで確認できます。

トランザクションが残高や期限超えのエラー無く受理されたかどうかを問い合わせて確認する必要があるということです。

従来のように同期的なレスポンスを返す`NEM2-camel`という中間サーバソフトウェアもあるので、
状況に応じて利用してみてはいかがでしょうか。
(ただし現時点でのCatapultに対応していない可能性があります)

- [nemtech/nem2\-camel: A component to turn the asynchronous transaction announcement into synchronous\.](https://github.com/nemtech/nem2-camel)


## マルチシグ連署者追加時のオプトイン要求

マルチシグアカウントの連署者に参加する際に、その要求に署名(オプトイン)が必要になりました。
`NEM1`では管理下に無い、他人のアカウントを誤って登録してしまったりした場合に、
そのアカウントにお願いをして連署者を降りてもらわなければならないケースが発生しました。
間違ったアカウントを追加しようとしても、相手が身に覚えのない署名要求であれば無視して、期限切れを待つことで回避できます。
(しかし、トランザクションを取り消せるわけではないので、オプトインされてしまった場合はまた別に問題がありそうです)

- [マルチシグアカウントの変更 — NEM Developer Center](https://nemtech.github.io/ja/guides/multisig/modifying-a-multisig-account.html#guide-modify-a-multisig-account-add-new-cosignatory)


## マルチシグの最小削除承認者数の追加

`NEM1`ではマルチシグ連署者の増減
`NEM2`では連署者の削除に対して何名が賛同すれば承認とするのかを設定する値が追加されました。

- [マルチシグアカウントの変更 — NEM Developer Center](https://nemtech.github.io/ja/guides/multisig/modifying-a-multisig-account.html#guide-modify-a-multisig-account-removing-a-cosignatory)


## 他アカウントの署名を求める場合にデポジットが必要

自分のアカウント以外に署名が必要となるトランザクション(主にアグリゲートボンデッド)は、
その送信前に`HashLockTransaction`を送信し、`10 nem.xem` (単位は仮) をネットワーク上に預け入れなければなりません。

このトランザクションが承認され、`10 nem.xem`がネットワーク上でロックされてから、
アグリゲートボンデッドトランザクションを送れるようになります。

これは、スパムのような動作抑制のためとされ、事実、NEM1では勝手にアカウントを連署者にして、
大量の署名要求を送ることで、相手のアカウントの受信トランザクションを埋め尽くすことができました。
そういった問題への対策と思われます。


# まとめ

上記の仕様に加え、APIレスポンスの型も大幅に変更され、追加された項目がたくさんあります。
同じ機能でも、レスポンスをプログラムで処理するにあたっては、ほとんど別物と思ったほうがいいでしょう。

特にネームスペース・モザイク周りの仕様変更が大きいですが、
新しい仕様でどんなことができるのか、考えられる幅はひろくなったのではないでしょうか。

トランザクションの種類が増えたということは、それだけトランザクションが発生する機会が増えるとも考えられます。
(といっても主なトランザクションは`Transfer`であると思いますが)
つまり、よりハーベスティングできる機会が増えるということでもあります。

テストネットが公開されたら、ハーベスティングの素振りだけでもしてみてはどうでしょうか？

ここでは触れませんでしたが、メタデータや制約など、追加機能も盛りだくさんです。
これらについては別途誰かが書いてくれることに期待したり、後ほど追って記事にしたいと思ってます。