投稿日
CordaのTokens SDKでNFTマーケットプレイスを作ってみた
はじめに
こんにちは。ブロックチェーン推進室の鈴木です。
私の所属するブロックチェーン推進室では、企業間取引に特化したエンタープライズブロックチェーンプラットフォーム:Cordaに関して機能調査を行っております。 Cordaは世界で350社を超える金融機関、規制当局、中央銀行、業界団体、システム・インテグレーターやソフトウェアベンダーにより構成されるR3エコシステムから、エンドユーザー目線で設計・開発されています。 また、4半期に1度のバージョンアップにより機能追加がされていますが、その機能がお客様に活用できるものなのか、ドキュメントだけではわからないことも多く、ブロックチェーン推進室独自で調査を進めています。
このブログでは、そういったCordaの機能調査をした結果を機能の使い方含めて紹介していきます。
Cordaの導入方法についてはをご参照ください。
今後以下の内容で紹介しようと思います。
-
-
-
-
-
-
-
-
-
-
-
-
-
CordaのTokens SDKでNFTマーケットプレイスを作ってみた(←今回はこちらの記事)
第13回目は「CordaのTokens SDKでNFTマーケットプレイスを作ってみた」について紹介します。
概要
今回の記事はCordaのTokens SDKでNFTマーケットプレイスを作成いたしましたので紹介します。
作成した背景として、一般的によくあるようなNFTマーケットプレイスをCordaで作成したら、どのような設計・実装になるかなど今後のNFTの盛り上がりも考慮して、知っておきたかったからです。
CordaのTokens SDKを使ったNFTの実装の基礎は前回の記事で紹介していますのでそちらを参照ください。
本記事ではNFTマーケットプレイスアプリとその設計について紹介します。
アプリについて
◎概要
このアプリはユーザーが自由にNFT(Non Fungible Token)を自身で発行や出品、購入など他のユーザーとやり取りを行うことができるマーケットプレイスアプリです。
NFTの売買にあたっては、アプリ内で有効な通貨(Fungible Token)を使用します。
◎ノード・アカウント構成
今回、ノードは2台のノードと1台のNotaryの構成です。
アカウントはアカウントライブラリを使用しており、各ノード(host)に属するアカウントとしてそれぞれ1つずつ存在する構成です。
このアカウントがユーザーとしてそれぞれNFTの発行や出品を行います。
上記の図の場合において、AliceとBobはそれぞれのノードに属するアカウントになります。
◎ユースケース
このアプリのユースケースは以下の通りです。
ここから「NFTを発行する」、「NFTを出品する」、「NFTを購入する」の3つに焦点をあてて紹介します。
-
NFTを発行する
NFT発行者は発行するNFTの情報を入力してNFTを発行します。
-
NFTを出品する
NFT出品者は所有NFTを確認し、所有しているNFTの中から出品したいNFTを選択します。
-
NFTを購入する
NFT購入者は出品中NFTを確認し、出品されているNFTの中から購入したいNFTを選択します。 ※NFTを購入するにはアプリ内通貨を所持する必要があります。
2~3を繰り返すことでNFTを様々なアカウントへ転々と流通させることができます。
アプリの設計
設計について
設計に関しても発行、出品、購入に焦点をあてて紹介します。
NFTの発行
NFTの発行は、以下のようになります。 NodeAに属するアカウントのAliceがNFTを発行する場合、アカウントを使用しているためNodeAが発行し、NodeAのVaultに登録されます。
この時、NFTの発行と同時にEvolvableTokenTypeも作成していますが、NFTのHolderはAliceで、EvolvableTokenTypeのmaintainersにはNodeAを指定します。
アカウントライブラリを使用しているので、アカウントを検索する処理と新しい公開鍵を生成する処理を行います。
また、今回は取引ごとに、新しい公開鍵を生成する実装にしているため、他ノードへ公開鍵を連携する処理を行います。
他のノードへ公開鍵を連携する処理をBroadcastKeyFlowとして独自で実装し、自ノードとNotary以外のノードに、新しい公開鍵とアカウントの情報を紐づけしてもらいます。
鍵の連携については後述します。
その後、EvolvableTokenTypeとNFTを結びつけてIssueTokensを呼びだして、NFTを発行します。
<アカウントの鍵の連携について>
Transactionごとに新しい公開鍵を生成する実装をしている場合、ユースケース次第ですが他ノードへ公開鍵を連携する必要があります。
以下、公開鍵を連携する必要がある場合や、その公開鍵の連携方法などについて説明します。
-
他ノードへ公開鍵を連携する必要がある例
例えば、移転されたNFTがどのアカウントから移転されたかを確認したい場合などがあります。
Transactionのinputを検索し、そのInputのHolderから検索すれば、どのアカウントなのか知ることができるように思われます。
しかし、NFTのHolderにはAnonymousPartyが入っていますが、アカウントの情報は入っておらず、取引で使用した公開鍵しか入っていません。
この公開鍵は、そのNFTが生成されたTransactionに署名をしたアカウントの公開鍵です。そのため、その公開鍵からアカウント情報を検索する必要があります。
しかし、その公開鍵がどのアカウントものかという紐づけ情報は公開鍵を作成したノードと公開鍵の作成を依頼したノードにしか登録されていません。
ここについては後述の「ノード間の紐づけ情報の差異について」にて解説します。 -
Transactionのアカウントの公開鍵
以下の図にてNFTを発行し、移転するTransactionをアカウントの公開鍵に着目して見ていきます。
NFT発行では、その所有者となるアカウントの公開鍵を作成して発行します。
NFT移転では、NFTの所有者(移転元)のアカウントと移転先のアカウントの鍵を作成して移転します。
この時、移転元のアカウントの公開鍵が2種類あることに注意が必要です。
NodeA側には「Aliceの公開鍵①」、「Aliceの公開鍵②」、「Bobの公開鍵」の3つは、このアカウントのものであるという紐づけ情報が登録されています。一方、NodeB側では、「Bobの公開鍵」しか紐づけ情報は登録されていません。
そのため、NFT移転後にBobが受け取ったNFTの移転元を公開鍵から検索しようしても、アカウントと紐づいていないため取得することができません。このトランザクションにおいて、どのノードにどのアカウントの公開鍵の紐づけ情報が登録されているかを以下にまとめます。
NFT発行後のNodeAのVaultにはそのNFTの所有者となるアカウントと発行時に作成した公開鍵を紐づけて、登録されます。
また、NodeBのVaultには何も登録されません。
NFT移転後のNodeAのVaultには2つの紐づけ情報が登録されます。
1つ目は移転のために新しく作成された移転元のアカウントの公開鍵とそのアカウントの紐づけ情報です。
2つ目は移転先のアカウントの公開鍵とそのアカウントの紐づけ情報が登録されます。
また、NodeBのVaultには移転先のアカウントの公開鍵とそのアカウントの紐づけ情報が登録されます。
-
ノード間の紐づけ情報の差異について
上記のようにノードによって紐づけ情報の登録に差異ができています。
これはRequestKeyForAccountの処理によるものです。
NFT移転のTransactionのRequestKeyForAccountの処理シーケンスを以下の図にまとめます。
このRequestKeyForAccountは公開鍵を作成しますが、それに加え、その公開鍵とアカウントの紐づけ情報も登録(マッピング)します。
しかし、このアカウントの紐づけ情報はRequestKeyForAccountを呼び出したノードと、それにより呼び出された(対象のアカウントのホスト)ノードの両方に登録されますが、他のノードには連携されません。
NodeA側では、Aliceの公開鍵とBobの公開鍵とのそれぞれのアカウントの紐づけ情報が登録されます。
NodeB側では、Bobの公開鍵とアカウントの紐づけ情報のみ登録されます。
仮にNodeCなどが存在していた場合では、これらの公開鍵とのアカウントの紐づけ情報は一つも登録されません。 -
公開鍵の連携方法について
公開鍵の連携方法について以下の図のNFT発行を例として解説します。
アカウントAliceに対してNFTを発行する際にRequestKeyForAccountを呼び出し、公開鍵を作成します。
RequestKeyForAccountによって新しく作成された公開鍵とAliceのアカウント情報を他ノードへ送信します。
その情報を受け取ったノードはIdentityServiceのregisterKeyを呼ぶことで公開鍵とアカウントの紐づけをすることができます。また、もともと用意されているShareStateAndSyncAccountsを使うことで独自実装のFlowを使わなくとも連携することができます。
そのため、基本的にはShareStateAndSyncAccountsを使用をお勧めしますが、トランザクション終了後しか、他のノードに鍵を連携できないので注意が必要です。
今回、作成したアプリや実装次第(トランザクションの途中で鍵の連携が必要な場合など)では独自でFlowを実装してIdentityServiceのregisterKeyを使用する必要があります。
NFTの出品
NFTの出品は以下のようになります。
AliceがNFTを出品するにはNFT情報の更新を行います。
これはNFTに紐づくEvolvableTokenTypeの属性の更新のことを指します。
更新だけであれば、自身の属するノードのVaultのみ反映すればよいのですが、「出品」という行為のため、その出品されるNFTが他のアカウントから見える必要があります。
そのため他のノードにもEvolvableTokenTypeを連携します。
NFTの発行時と同様にアカウントを検索する処理と鍵を生成し他のノードへ連携する処理を行います。
NFTの購入
NFTの購入は以下のようになります。
このアプリでの購入とは、購入者が出品者にアプリ内通貨を移転し、出品者から購入者にNFTを移転してもらうことを指します。
以下ではNFTの流れを表しています。
購入者がNFTの購入をすると出品者の所有するNFTを移転してもらいます。
通貨のやり取りは②において、NodeBはNFTの価格に相当する、Bobが持っているアプリ内通貨を検索し、NodeAにsendしています。
これはBobが属するNodeBしかBobが所有するアプリ内通貨を記録していないためです。
そのため、NodeAは送られたアプリ内通貨と売却(移転)するNFTをもとにTransactionを作成します。
③のNFT移転後、NodeAは売却(移転)したNFTに紐づくEvolvableTokenTypeの属性の出品情報を未出品にし、maintainersをNodeBに変更します。
これによりNFTに紐づく情報を更新します。
アプリの紹介
以下のシナリオで今回作成したアプリを紹介します。
-
NodeAのアカウントのAliceがNFTを発行し、出品します。
-
その出品されたNFTをNodeBのアカウントのBobが購入します。
NFTの発行と出品
-
NFTの名前と詳細を入力して、画像ファイルを選択し、発行ボタンを押下します。
-
所有NFT一覧を開き、発行したNFTを確認できます。
-
NFT詳細から出品したい価格を入力し、出品するボタンを押下します。
出品されたNFTの購入
◎Bob側
-
出品中NFT一覧からAliceが出品したNFTを確認し、購入します。 ※BobへのFTの入金処理は割愛しています。
-
所有一覧に購入したNFTが表示され、残高からNFTの出品価格が引かれます。
◎Alice側
-
所有一覧から出品したNFTが表示されなくなり、残高にNFTの出品価格が足されます。
おわりに
いかがでしたでしょうか。 今回は、Tokens SDKを使ってNFTのマーケットプレイスを作成し、紹介いたしました。
アカウントライブラリとEvolvableTokenTypeとNonFungibleTokenの組み合わせについては、
公開鍵の連携やどちらのノードがTransactionを生成するかなど複雑な箇所があるため、注意が必要です。
Cordaの場合、NFTとそのメタデータを一緒にブロックチェーンに書き込めることや、DvP決済を一つのTransactionに含めることができるのは、大きなメリットであると思います。
今回の記事がCordaでのNFTの実装の参考になったら幸いです。