📝

初心者が「速習Symbol」をやってみる

2023/03/18に公開約16,200字

はじめに

初心者の私が「速習Symbol」をやってみました。
理解しにくいところ、躓きやすいところがあったので、
その部分だけをピックアップして自分なりの解説等を書いています。

速習symbolの横に添える位置付けの物になります。本記事だけで成り立つ書き方ではございません。

速習symbolを挫折せずにやり切る事を目的にしていますので、あまり深掘りはしていません。(できません)

※初心者の定義は、ブロックチェーン、NFTとは?という概念に触れ、基本的な仕組みを理解したつもりで、symbolを自分で触ってみたい人、Symbolブロックチェーンエクスプローラを見たことない人。

※間違っている箇所があるかもしれん、ご了承下さい。

あれこれ

こちらのSYMBOLの入門ガイドをやってみたところ
https://docs.symbol.dev/ja/getting-started/index.html
「初めてのアプリケーション作成」のsymbol-cli transaction mosaic ...
の箇所でモザイク自体作れない。「Failure_Aggregate_V1_Prohibited」
というエラーで早速詰んでしまった。

よって、「速習Symbol」に乗り換えたという経緯から書いています。

※テストネットを使います。

「速習Symbol」のご紹介

コミュニティの方々がメンテナンスされてい入門ガイドのようです。
実質これが唯一の入門書と思います。
https://learn.ja.symbol-community.com/

1.はじめに

ドキュメントのねらい、対象者、などが書かれている。
早速、できない事を書いてくれているので、最初に全体の輪郭をイメージする事が出来ます。

2.環境構築

node.jsのSDKがあり、さらにそれをブラウザで動くようにするbrowserifyというツールで変換したものが提供されているので、それを使っていくかたち。要は、node.js環境作らなくても、Chromeブラウザだけで試せる形。

  • ChromeブラウザのF12、Consoleタブから、前述のスクリプトを読み込む
  • 以降の章で使う、ノードの情報等の変数を宣言し、値を取得/格納しています。
    ※ブラウザで開いているノードから情報取得するようです。

3.アカウント

新規作成

alice = sym.Account.generateNewAccount(networkType);
console.log(alice);
※「networkType」などの変数は、2.環境構築で宣言しており、値が格納されています。

アドレスの導出

alice.address.plain();
は、string型のアドレスが戻ってきます

ちなみに...
alice.address;
は、object型のアドレス情報が戻ってきます。

アドレスクラスの生成

公開鍵クラス生成、アドレスクラス生成の方法が、例として書かれていますが、アドレスクラス生成で作られる変数「aliceAddress」は後で使うので、必ず実行しましょう。

aliceAddress = sym.Address.createFromRawAddress(
  "TBXUTAX6O6EUVPB6X7OBNX6UUXBMPPAFX7*****"
);

アカウントを作成しただけでは、エクスプローラーに表示されない。

このアドレスはまだネットワークに認識されていません。

  • フォーセットから検証用XYMを入手
    この時点で、エクスプローラーでアカウントの詳細とフォーセットで入れたXYMが確認できます。

所有モザイク一覧の取得

で出力される内容

出力例
> AccountInfo
    address: Address {address: 'TBXUTAX6O6EUVPB6X7OBNX6UUXBMPPAFX7*****', networkType: 152}
    publicKey: "0000000000000000000000000000000000000000000000000000000000000000"
  > mosaics: Array(1)
      0: Mosaic
        amount: UInt64 {lower: 10000000, higher: 0}
        id: MosaicId
          id: Id {lower: 1738574798, higher: 981735131}

表示桁数の調整

ここでの可分性とは、そのトークン(ここではXYM)が小数点以下の桁数をいくつ持つことができるかどうかを指します。モザイクの単位をどこまで細かく分割できるかを表す。もちろんXYMはすでに決められた過分性をもつ。
例)1.00(過分性:2)は、0.01~1.00

署名

アカウントの保管

各Keyを書き留めておかないと、ブラウザ閉じた時点でaliceとbobはconsole上にいなくなったりする(ネットワーク上にはいるが)、もう一度アカウント作成する羽目になったりする(泣)。
と言ってもPrivateKeyをメモっとくのは危険なのでパスワードで暗号化しましょうという感じ。
※追記→ブラウザで「名前を付けて保存」するとマルっと記録されるらしいです。

秘密鍵からアカウント生成 の項目で、復号したPrivateKeyを使い、console上にアカウントを復活させれます。

4.トランザクション

4.1 トランザクションのライフサイクル

  • トランザクション作成
    ローカルにトランザクションデータを作るだけ。
  • アナウンス
    ここでネットワークに通知している。承認されるかどうかは別。

4.2 トランザクション作成

  • Bob への転送トランザクション
    bob = sym.Account.generateNewAccount(networkType);
    送信先の Bob アドレスを作成しています、今まで使ったbobを使いたい人は実行しないとよいかもです。

  • トランザクションを作成します。

tx = sym.TransferTransaction.create(
  sym.Deadline.create(epochAdjustment), //Deadline:有効期限
  sym.Address.createFromRawAddress("TDWBA6L3CZ6VTZAZPAISL3RWM5VKMHM6J6*****"),
  [],
  sym.PlainMessage.create("Hello Symbol!"), //メッセージ
  networkType //テストネット・メインネット区分
).setMaxFee(100); //手数料

ここでは、送信先であるBobのアドレスを設定していて、送信者のAliceのアドレスは設定していません。TransferTransaction..というレスポンス内にmaxfeeなどの情報が書かれています。

  • 最大手数料
    トランザクション作成する下記のソースで、
sym.PlainMessage.create("Hello Symbol!"), //メッセージ

の"Hello Symbol!"を"Hello Symbol!Hello Symbol!Hello Symbol!"というように編集して作成すると、トランザクションのデータ量が増えて、maxfeeも増えることが確認できます。

  • アナウンス

4.6 アグリゲートトランザクション

  • 起案者の署名だけが必要な場合
    bob = sym.Account.generateNewAccount(networkType);
    carol = sym.Account.generateNewAccount(networkType);
    bobアカウントとcarolアカウントを新たに作成しています、今まで使ったbobを使いたい人は1行目は実行しないとよいかもです。
  • デジタルデータのハッシュ値(SHA256)出力方法
    ファイルのハッシュ値をトランザクションのペイロードに設置するという事と思いますが、
    前出の下記の関数で設置できるのかな?未確認。
    sym.RawMessage.create(uint8Arrays[i]);
  • >ファイルの要約値をブロックチェーンに記録することでそのファイルの存在を証明することができます。
    ここはNFTを連想しそうですが、まだ要件が足らない感じかな。

5.モザイク

5.1 モザイク生成

モザイクを定義→トランザクションを作成→署名→アナウンス、の流れです。アナウンスするとトランザクションがネットワークに登録されます。エクスプローラでaliceのアカウントのモザイクが1つ増えています。1つ目はXYM、2つ目は今作ったモザイクです。

aliceのアカウント情報
数量:1000000、可分性:2、と設定した通り、総量が10,000.00となっています。

5.2 モザイク送信

bobアカウントを新たに作成しています、今まで使ったbobを使いたい人は1行目は実行しないとよいかもです。
bob = sym.Account.generateNewAccount(networkType);

モザイクの定義はできているので、トランザクションを作成→署名→アナウンス、の流れです。

エクスプローラでbobのアカウントのモザイクを見ると、XYMが1XYM増えています。

bobのアカウント情報
また、先ほど作ったモザイクが追加され、設定した通り、0.01(可分性として最小単位の1つ)増えています。

5.3 現場で使えるヒント

  • 所有証明
    >本ドキュメントでは所有を「自分の意思で手放すことができる状態」とします。
  • NFT(non fungible token)
    ここではトランザクションの定義までのコードになっております。
    署名、アナウンスしたい人は、自分で行う必要があります。↓
    signedTx = alice.sign(aggregateTx, generationHash);
    await txRepo.announce(signedTx).toPromise();

6.ネームスペース

在り方としては、いわゆるインターネットドメインと同じ感じ。設定の仕方、名前解決のフローや情報の持ち方がsymbol風!?。

6.2 レンタル

>ルートネームスペースをレンタルします

>sym.UInt64.fromUint(86400)
この86400はブロック数で、こんな計算式(たぶん)。
30日レンタルしたい場合:
30(日)*24(h)*3600(秒換算)÷30(1ブロック30秒)=86400(ブロック)

エクスプローラのaliceのアカウント情報で、指定した各ネームが表示されているのを確認。

  • 有効期限の計算
    エクスプローラのネームスペース情報で、開始高、終了高が確認でき、
    計算すると、説明通りに1日多めになっています。86400→89,280
    https://testnet.symbol.fyi/namespaces/ + 任意のネーム

レンタルするのもトランザクションです。

6.3 リンク

ここまでは、aliceがネームスペースを所有しているだけで、アカウントアドレス、モザイクIDにリンク(紐づけ)をしていない状態。

  • アカウントへのリンク
    エクスプローラのaliceのアカウント情報で、エイリアス名が指定したネームになっているのを確認。

  • モザイクへリンク
    エクスプローラのaliceのアカウント情報-所有モザイクで、エイリアスネームスペースが指定したネームになっているのを確認。
    ※モザイクは 5.モザイク で作成したものを使うとよい。

リンクするのもトランザクションです。

6.4 未解決で使用

未解決で?名前解決しないの?と思いましたが、インターネットのDNSでは名前解決してから進んでいきますが、ここでは、名前解決せずにネームのままトランザクションに署名できて、後で出てくる「レシート」に解決した経緯が書かれている。という意味と思います。
お借りしているネームスペースは、30日後とかに期限が切れるので、レシート見てねという感じ。

掲載頂いているソースコードは、aliceから誰か(ネームエイリアスのある人)に送る書き方になっていますが、おそらく、aliceのアドレスでネームスペースを登録している流れの人が多いと思いますので、bobが署名、アナウンスするように書き換えるとよいかと思います。

  • レシートの参照
receiptRepo = repo.createReceiptRepository();
state = await receiptRepo
  .searchAddressResolutionStatements({ height: 179401 })
  .toPromise();

7.メタデータ

7.1 アカウントに登録

アリスが、自身が所有し、自身が発行者となる形のメタデータをつくり、自身が署名、アナウンスしているようです。
どういったケースが想定されるのかわかりませんが、エクスプローラーのアリスのアカウント情報に、メタデータエントリーが出来ています。

>異なるアカウントのメタデータに登録する場合は…
アリスとボブのお二人が、「ボブが所有者、アリスが発行者」、となる形のメタデータをつくり、アリスとボブが署名、アナウンスしているようです。
エクスプローラーのボブのアカウント情報にメタデータエントリーが出来ています。
また、アリス→ボブのアグリゲートトランザクションも記録されていることが確認できます。
どういったケースが想定されるのかわかりませんが、連署という事で、アリスがボブのアカウント情報(プライベートキー含む)を知っている前提のようです。

7.2 モザイクに登録

エクスプローラーのアリスのアカウント情報に、メタデータエントリーが出来ています。
エクスプローラーのモザイク情報に、メタデータエントリが出来ています。

7.3 ネームスペースに登録

エクスプローラーのアリスのアカウント情報に、メタデータエントリーが出来ています。
エクスプローラーのネームスペース情報に、メタデータエントリが出来ています。

7.5 現場で使えるヒント

メタデータとして所有者(学生)、発行者(学校/信頼や権威のある人)が記録され、検証者(企業)が検証できるという仕組み。メタデータはアカウント以外に、モザイク、ネームスペースに紐づけることが出来る。と、いうイメージでよいと思います。

8.ロック

トランザクションはアナウンスするけど、内容はすぐには実行しないので「ロック」だ、とう理解でよいと思います。

8.1 ハッシュロック

>FAUCET で 10XYM ほど受信しておきます。
下記のコードで、URLがレスポンスされているので、それをブラウザにコピペし、CLAIMボタン押す。

console.log(
  "https://testnet.symbol.tools/?recipient=" +
    bob.address.plain() +
    "&amount=10"
);

aliceとbob、それぞれ計2つのブラウザを立ち上げて実施すると理解しやすいかもです。


たぶんこんな感じ?

・aliceのブラウザで以下行う。(bobアカウントを生成していない状態)
bobのアドレスからアドレスクラス、公開鍵から公開鍵クラスを生成しておく。
1.「ロックしたいTX」(AoB/BtoA)を作成して署名だけしておく。※アナウンスしない
2.ロック専用のTXを作成、「ロックしたいTX」を包含。
3.ロック専用のTXに署名、アナウンス。//「ロックしたいTX」がアナウンスされても実行されないようになる
確認→ハッシュロックというトランザクションができる。

ハッシュ値(メモっておく)、ステータス(Unused)、-10XYM(ハッシュロックにかかる預り金)が確認可能。

4.「ロックしたいTX」を、アナウンス。※アナウンスしても実行されない
確認→アリスのエクスプローラーでハッシュロックから該当トランザクションを表示。
アリスだけの署名がされていることが表示されている。

この時点で、bobのエクスプローラーには何もデータが追加されていない様子。

~ アリスからボブにハッシュロックのハッシュ値をメールとかで渡す。という想定 ~

・bobのブラウザで以下行う。(aliceアカウントを生成していない状態)
5.もらったハッシュロックのハッシュ値からトランザクションオブジェクトを取得、署名してアナウンス。「ロックしたいTX」が実施される。

txInfo = await txRepo
.getTransaction('アリスからもらったハッシュ値', sym.TransactionGroup.Partial)
  .toPromise();
cosignatureTx = sym.CosignatureTransaction.create(txInfo);
signedCosTx = bob.signCosignatureTransaction(cosignatureTx);
await txRepo.announceAggregateBondedCosignature(signedCosTx).toPromise();

確認→アリスとボブの署名(連署)がされていることが表示されている。

・aliceに10XYMが戻っている。
・「ロックしたいTX」が実行されている

なにができるか

  • トランザクションごとロックできる
  • bobがロック解除しているが、手数料はAliceが払っている感じ
  • 有効期限を設定するので、永遠と相手を待つことがない

8.2 シークレットロック・シークレットプルーフ


たぶんこんな感じ?

ここもalice/bobそれぞれブラウザを立ち上げて行うとイメージしやすいかもです。

>ロック・解除にかかわる共通暗号を作成します。
ランダム値(元の値)を生成し、
secret(=ハッシュ値)
proof(=元の値)
ハッシュ値から元の値は算出できないので、proofもってる人は権利のある人という感じです。

  • シークレットロック
    ロックしたいモザイクと、secret、ロック解除された時の転送先(bob)を書いたトランザクションを作成して、aliceが署名、アナウンスしています。

今回は、bob側でもトランザクションが確認できます。
ただし、「SecretLock」となっています。

alice側にはトランザクションに加えて、シークレットロック、レシートが出来ています。

>承認されたトランザクションを確認します。
これは、bob側のブラウザでも取得できます。

slRepo = repo.createSecretLockRepository();
res = await slRepo.search({ secret: secret }).toPromise();
console.log(res.data[0]);

>Bob は事前に解除用キーワードを入手しておく必要があります。
メールとかでもらう想定です。

  • シークレットプルーフ
    bob側のブラウザで行います。
    ロック解除し、bobに1XYM入っていることを確認できます。
  • モザイクをロックできる
  • Bob以外でもロック解除できるが、設定通り(Bob)に転送される。間違いがあれば失敗する。

9.マルチシグ化

9.1 マルチシグの登録

ここで今まで使いまわしていたalice/bobは忘れて、記載通り新しくしたほうがわかりやすいかもしれません。。
bobとcarol達の全員分のオブジェクト(Privatekey)を知っている人が行う前提です。
bobには必要な連署者名が、carolには連署権のあるアカウント(bob)が表示されています。

bobアカウント情報

carolアカウント情報

9.3 マルチシグ署名

aliceアカウント作成しておきましょう。
alice = sym.Account.generateNewAccount(networkType);

  • アグリゲートコンプリートトランザクションで送信

    こんな感じ?

bobからaliceへのトランザクションが確認できます。
署名者はcarol1です。

連署名はcarol2、carol3です。

内部アグリゲーショントランザクションに、bob to Aliceへのトランザクションが表示されていてShowDetailをクリックするとポップアップでトランザクション内容が表示されます。

  • アグリゲートボンデッドトランザクションで送信
    マルチシグ化したbobから、Aliceへ1XYMを送信します。
    これをcarol1がロックし、止め置いた状態でアナウンスします。
    ロック解除には連署(carol2,carol3)を必要とします。

carol1のエクスプローラーから、carol1が署名している、トランザクションが確認できます。
パーシャル署名状態です(ロック解除待ち)。

>8.ロックで紹介した連署を使用して、マルチシグアカウントで連署します。
ボンデッドトランザクションに、carol2、carol3の署名をつけるという事です。
が、ソースコードの掲載がなく、前章までの理解が少し必要になります(復習になります)。
1人づつ署名していきます。

  • carol2から署名。
    carol2用のブラウザを開くと体感的に理解しやすいかもしれません。
    他に、トランザクションのハッシュ値を知っている必要があります。
txInfo = await txRepo
  .getTransaction('トランザクションのハッシュ値', sym.TransactionGroup.Partial)
  .toPromise();
cosignatureTx = sym.CosignatureTransaction.create(txInfo);
signedCosTx = carol2.signCosignatureTransaction(cosignatureTx);
await txRepo.announceAggregateBondedCosignature(signedCosTx).toPromise();

carol2の署名が付きました。

carol3からも、carol2と同じようにして署名してください。下記のように3つの署名がそろうと、bob からAliceへ1XYM送られていることが確認できます。

10.監視

10.2 受信検知

1.トランザクションするブラウザ。
2.検知するブラウザ。
の2つで動作確認すると理解しやすいかもです。
2.はaliceのアドレスだけを知っていれば、受信可能です。

10.3 ブロック監視

2.環境構築 だけできていれば、受信可能です。

10.4 署名要求

「8.1 ハッシュロック」の章で、aliceからbobに、ボンデッドトランザクションのハッシュ値をメールで伝えて、bobが署名する。
というフローを説明しましたが、bob側で署名が必要なトランザクションを検知するようにできます。


こんな感じ?

ボブ側で下記のように通知を待つ形にして、

listener.open().then(() => {
  //署名が必要なアグリゲートボンデッドトランザクション発生の検知
  listener
    .aggregateBondedAdded(bob.address)
    .subscribe(async (tx) => console.log(tx));
});

もう一度、「8.1 ハッシュロック」を構成し、

  • アグリゲートボンデッドトランザクションのアナウンス
await txRepo.announceAggregateBonded(signedAggregateTx).toPromise();

このアナウンスによって、ボブ側で検知できることを確認できます。検知した内容の中にボンデッドトランザクションのハッシュ値が入っています。
bobはこのハッシュ値でボンデッドトランザクションを探し出し、連署することでトランザクションを実行することが出来ます。

10.5 現場で使えるヒント

  • 常時コネクション

-ノードへの接続
ノード一覧に対象となる実際のノードアドレスを記入します。

//ノード一覧
NODES = ["http://sample1.server.net:3001","http://sample2.server.net:3001","http://sample3.server.net:3001"];
~~~~

記載のコードはコールバック関数の定義のみなので、それだけでは動きません。
下記のようにコードを実行することで常時動作します。
connectNode(nodes)

-レポジトリの作成
上記と同じように、下記のようにコードを実行することで常時動作します。
createRepo(nodes)

-リスナーの常時接続
こちらは記載どおりのコードを実行することで常時動作します。

  • 未署名トランザクション自動連署
    以下の2つのことをします。
    ・これからの未署名のトランザクションを検知するリスナーを設置し、検知したら署名する。
    ・現状の未署名のトランザクションを署名する。

「8.1 ハッシュロック」の「アグリゲートボンデッドトランザクションのアナウンス」を実施して検知と署名が行われることが確認できます。

11.制限

  • アカウントを起点に、ほかの人とのトランザクションに制限をかけます。
  • モザイクを起点に、KYC(本人確認手続き)が出来ている人同士であれば、送受信できます。

11.1 アカウント制限

11.2 グローバルモザイク制限

Discussion

ログインするとコメントできます