Symbolのリボーカブルモザイク

# 概要

Symbolの`1.0.3.0`で`MosaicSupplyRevocationTransaction`と`MosaicFlag.Revokable`という機能が追加されました。

https://github.com/symbol/catapult-client/releases/tag/v1.0.3.0

執筆時点ではドキュメントにはこれらの記載がなかったと思いますが、件のハードフォークから推測すると、`MosaicFlag.Revokable`がオンになったモザイクでは、revoke=取り消す、つまりモザイクの没収ができると思われます。

https://docs.symbolplatform.com

なお、モザイクフラグは作成時点で設定し、後から変更することができなかったはず。ですので、モザイク取得時にちゃんとフラグをチェックしておけば、知らぬ間に無くなっているということはなさそうです。


# やってみる


せっかくなので、これらの機能を実際に使ってみたいと思います。

1. `MosaicFlag.Revokable`を有効にしたモザイクを作成する
1. そのモザイクを誰かに送信する
1. `MosaicSupplyRevocationTransaction`を送信して没収する


![noname.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172833/0f7fae41-6d81-a945-bc53-c44334ac2190.png)


## MosaicFlag.Revokable

発行量は`1000000`です。

作成完了すると、作成者（トランザクションの署名者）に全量が付与されます。

### ソースコード

モザイク作成のソースコード。

```typescript:mosaic-revokable1.ts
const account: Account = Account.createFromPrivateKey(privateKey, nt);

const duration = UInt64.fromUint(1000);
const isSupplyMutable = true;
const isTransferable = true;
const isRestrictable = true;
const isRevokable = true;

const divisibility = 0;

const nonce = MosaicNonce.createRandom();
const txd = MosaicDefinitionTransaction.create(
	Deadline.create(ea),
	nonce,
	MosaicId.createFromNonce(nonce, account.address),
	MosaicFlags.create(isSupplyMutable, isTransferable, isRestrictable, isRevokable),
	divisibility,
	duration,
	nt,
);

const delta = 1000000;

const txs = MosaicSupplyChangeTransaction.create(
	Deadline.create(ea),
	txd.mosaicId,
	MosaicSupplyChangeAction.Increase,
	UInt64.fromUint(delta * Math.pow(10, divisibility)),
	nt,
);

const txa = AggregateTransaction.createComplete(
	Deadline.create(ea),
	[
		txd.toAggregate(account.publicAccount),
		txs.toAggregate(account.publicAccount),
	],
	nt,
	[],
	UInt64.fromUint(2000000),
);
```

`MosaicFlags.Revokable`が設定できない場合は、sdkが古い可能性があります。`symbol-sdk@1.0.3`以上かを確認するとよいと思います。

### 送信した


#### 承認待ち…

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172833/242c0afc-ee13-8b24-7784-182e1b07e363.png)

#### 承認された！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172833/e2696676-ed4d-c2c2-7533-a58f771dfffe.png)

#### トランザクション情報

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172833/a5e2d990-efd9-aa28-db01-9ecaaeb17252.png)

#### モザイク情報

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172833/862cafab-fe82-5cbf-3880-564352f96d0d.png)

モザイクIDは`29D21D29DE83A9BC`、フラグは`15`になっていて、`1 + 2 + 4 + 8`であることがわかります。

フラグの計算式はこのあたりが参考になります。

https://github.com/symbol/symbol-sdk-typescript-javascript/blob/v1.0.3/src/model/mosaic/MosaicFlags.ts#L115

#### アカウント情報

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172833/d49383e1-d4cb-b459-1a1b-2b8e830eeafe.png)

`29D21D29DE83A9BC`が`1000000`あることがわかります。

### 古いノードは受け入れない

ところで、`1.0.3.0`以前の古いノードは、この新しいモザイクフラグをどう処理するのでしょうか。

トランザクションが承認されたブロックである、`564849`のブロック情報を見ていきます。

`1.0.3.0`のノード

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172833/92f5eddf-c045-aef8-08e6-4d7e064676a7.png)

`1.0.2.0`のノード

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172833/6a95e046-641b-04e6-8f9d-d1246ec14fd2.png)

`previousBlockHash`が同一で、`hash`が異なるので、同じブロック高で異なるブロックが生成されました。

`transactionsCount`を見ると、古いノードは`0`ですが、最新のノードは`1`となってます。

どうやら、古いノードはリボーカブルを付けるトランザクションを拒否しているようです。

## 別のアカウントに作成したモザイクを送信

### `29D21D29DE83A9BC`を`100`送金

送り先 `TAYBJW-6DJIB3-57BU6E-XLMYI6-U3JW4T-AIGKGR-DSI`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172833/6a724f3c-ed99-a514-b4a0-3b8c441e58b3.png)

これは普通のトランスファートランザクションです。

### 受け取り手のアカウント情報

怪しげなモザイクを`100`ほど持っているのがわかります

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172833/ff96bb02-fd0f-ac44-5201-0f52d1d30707.png)

## MosaicSupplyRevocationTransaction

sdkのドキュメント

https://docs.symbolplatform.com/symbol-sdk-typescript-javascript/1.0.3/classes/model_transaction_mosaicsupplyrevocationtransaction.mosaicsupplyrevocationtransaction.html

先ほどモザイクを送り付けたアカウントに対して、`10`ほどリボケーションしようと思います。

そのアカウントの残高は`90`になるはずです。

### ソースコード

モザイクリボケーションのソースコード。

```typescript:mosaic-revokable2.ts
const account: Account = Account.createFromPrivateKey(privateKey, nt);

const tx = MosaicSupplyRevocationTransaction.create(
	Deadline.create(ea),
	Address.createFromRawAddress(fromAddress),
	new Mosaic(new MosaicId(mosaicId), UInt64.fromUint(10)),
	nt,
	UInt64.fromUint(1000000)
);
```

指定したアドレスから、指定した量だけ取り消すことができます。

### 送信した

#### `10`没収

モザイクリボケーショントランザクションを送信し、`10`ほど取り消します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172833/52222a0b-fd60-67c9-7939-6ae6be16f927.png)

`signerPublicKey`は、モザイク作成者、`sourceAddress`が先ほど受け取ったアカウントのアドレスになります。

#### 没収されたアカウントの情報

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172833/4d3da5e9-e56c-307f-ef20-3650033da34a.png)

量が`10`減って`90`になっています。

#### 作成者のアカウント情報

作成者の残高が`10`増えた

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172833/ef922469-1b88-e4ca-8282-e09c4f3427ba.png)

当然ながら、モザイクのトータルサプライは変わっていませんでした

### 結果

モザイクの作成者は、他のアカウントの残高を取り消すことができる。取り消した量はモザイク作成者に戻る。

# その後

執筆時点ではブロック高`566000`ほどで、トランザクション送信後からおよそ12時間後なのですが、上記のトランザクションはきれいさっぱり無くなっていました。

何か大きな力（インポータンス）によって、すべて無かったことにされてしまったようです。

いちおう、モザイクを作成するトランザクションは、`Failure_Core_Past_Deadline`（期限切れエラー）となって、

https://sym-test-01.opening-line.jp:3001/transactionStatus/938797A23C2BBC25155D1402BB3CAD6BC9C3986FBAFFC08EF5495596947891EF

また、リボケーショントランザクションは、`Failure_Core_Insufficient_Balance`（そんなモザイクないですエラー）となって、記録には残っているようです。

https://sym-test-01.opening-line.jp:3001/transactionStatus/1B2DEAC8EF60F9E1793F2D699B467ACC03C5E8184EF912FD560C0C1EE64554D0

# まとめ

`MosaicFlag.Revokable`がオンになったモザイクでは、作成者は他アカウントのモザイクを没収できる。