LoginSignup
22
5

More than 1 year has passed since last update.

Metadataを刻みたい、日本語で

Last updated at Posted at 2021-12-09

nem Advent Calendar 2021のn日目ですね。(n = 10)

近畿大学でブロックチェーンや秘密鍵周りのことを学んでいるいなたつです。

早速本題

Metadataなんか、SymbolWalletで見れないんだけど。。。日本語(全角文字)入れれないんだけど。。。

って全人類思ったことがあるかと思います。

Metadataとは

アカウント、モザイク、ネームスペースに対してカスタムデータを関連付ける方法として、Symbolが提供するもの。

詳しくはこちら

プログラムでMetadataを付与する

公式様を見る。

const key = KeyGenerator.generateUInt64Key('TEST');

// replace with network type
const networkType = NetworkType.TEST_NET;

// replace with public key
const alicePublicKey =
  'D04AB232742BB4AB3A1368BD4615E4E6D0224AB71A016BAF8520A332C9778737';
const alicePublicAccount = PublicAccount.createFromPublicKey(
  alicePublicKey,
  networkType,
);
// replace with value
const value = 'TEST METADATA';

const accountMetadataTransaction = AccountMetadataTransaction.create(
  Deadline.create(epochAdjustment),
  alicePublicAccount.address,
  key,
  value.length,
  value,
  networkType,
);

keyはUInt64で表現します。今回は「TEST」にします。
valueは「TEST METADATA」という12文字(空白込み13文字)の文字列となってます。

結果を確認する

まずはSymbolWalletで確認します。
image.png

見れん。

次にexplorerで確認します。

image.png

TEST METADATAっぽい文字が見えてますね。

SymbolWalletでMetadataを付与する

今回は「Symbol Wallet」と刻みます。
image.png

結果

同じくまずはSymbolWalletから
image.png

見れるじゃん

次にexplorer
image.png

なんか数字の列ができてますね

差異について考える

公式を参考に書いたプログラムとSymbolWalletでMetadataにどのような違いがあったかを確認してみます。

  • どちらの確認方法で表示でができている

プログラムで作った際はexplorerで、SymbolWalletで作った際はSymbolWalletで表示ができている

  • ValueSizeDeltaの数値

プログラムで生成した「TEST METADATA」ではvalue.lengthで取得しているため文字数の13がValueSizeDeltaになっています。
SymbolWalletで生成した「Symbol Wallet」では13文字に対してValueSizeDeltaは26になっていますね。

日本語のメタデータをSymbolWalletから付与する

「メタデータ」と付与します。
image.png

結果
SymbolWallet
image.png
explorer
image.png

「メタデータ」という5文字に対してValueSizeDeltaは30ですね。

explorerで確認するとvalueは「E383A1E382BFE38387E383BCE382BF」ですね。

image.png

なぜこんなことになってるのか

とりあえず状況整理しましょう

  • アルファベットのときにValueSizeDeltaが文字数の2倍になっている
  • 日本語のときにValueSizeDeltaが文字数の6倍になっている
  • なんやらvalueが16進数っぽい

16進数文字列だと仮定し先程の「メタデータ」という文字列を16進数に変換してみます

image.png

e3,83,a1,e3,82,bf,e3,83,87,e3,83,bc,e3,82,bf

同じですね、つまりSymbolWalletではメタデータとして入力した文字列を16進数に変換したものをSymbolブロックチェーンに刻んでいることがわかりました。

よくない原因

公式のドキュメントで示しているソースコードでは半角文字のみを考慮していることもあり、valueをそのままメタデータとして使っている。
そのため、日本語などの全角文字をドキュメントにある実装で扱おうとすると、ValueSizeDeltaが6倍じゃないためエラーが出てしまう。
じゃあ日本語の場合6倍すればいいのか?っていうと文字化けするのでだめ。ちゃんと16進数にしないと載せれない。

公式に従ってプログラム作ったとき(ドキュメント、explorer)と公式が作ったやつ(Symbol Wallet)で実装が食い違っている。

個人的にはドキュメントで16進数で刻む実装を示してexplorerで復号して表示するようにしたら幸せになれると思う。互換があれなのでそのまま表示もできるようにしたほうがいいとは思いますが。。。

実装的にはどうするか

const tx = AccountMetadataTransaction.create(
  Deadline.create(epochAdjustment),
  apostilleAccount.publicAccount.address,
  MetadataKeyHelper.keyToKeyId(k),
  Convert.utf8ToHex(v).length,
  Convert.utf8ToHex(v),
  this.networkType
);

こんな感じでutf8からHexに変換したものと、長さでメタデータを作成する

Convert.decodeHex('E383A1E382BFE38387E383BCE382BF') // メタデータ

表示する際はこんな感じにデコードしてあげれば良い。

Convertクラスでutf8からhexにして刻んで、刻まれたhexを表示する際にutf8に戻せばちゃんと日本語も表示されます。

22
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
22
5