Chaincode namespace
対象読者: アーキテクト、アプリケーションおよびスマートコントラクト開発者、管理者
チェーンコードネームスペースによって、チェーンコードのワールドステートは他のチェーンコードと分離することが可能になります。 具体的にいうと、同じチェーンコード内のスマートコントラクトは、同じワールドステートに直接アクセスすることができますが、異なるチェーンコードのスマートコントラクトは、互いのワールドステートには直接アクセスすることができません。 もしスマートコントラクトが、他のチェーンコードのワールドステートにアクセスすることが必要な場合は、チェーンコード間呼び出しを行うことで可能です。 そして、ブロックチェーンは異なるワールドステートに関するトランザクションを格納することができます。
このトピックでは、次の項目について述べます。
- ネームスペースの重要性
- チェーンコードネームスペースとは何か
- チャネルとネームスペース
- チェーンコードネームスペースの使い方
- チェーンコードをまたいだワールドステートのアクセスのしかた
- チェーンコードネームスペースに関する設計上の留意点
Motivation
ネームスペースは、一般的な概念です。 ニューヨークのパークストリートとシアトルのパークストリートは、同じ名前であっても違う通りであるということがわかります。 パークストリートに対して、都市名はネームスペースを構成していて、同時に自由度とわかりやすさを与えています。
コンピュータシステムにおいても同様です。 ネームスペースによって、別々のユーザーが、互いに邪魔をすることなく、共有システムの異なる部分でプログラム及び処理を行うことができます。 多くのプログラミング言語は、ネームスペースをもっています。これによって、プログラムは、例えば変数名といった固有の識別子を自由に使うことができ、ほかのプログラムのことを心配する必要がありません。 Hyperledger Fabricでは、ネームスペースによって、スマートコントラクトがその台帳ワールドステートを、他のスマートコントラクトとは分離できていることを、これから見ていきましょう。
Scenario
それでは、台帳ワールドステートにおいて、チャネルの組織に対して重要なビジネスデータに関する事実をどのように構成しているかを、下記の図を用いて詳しく見ていきましょう。 これらのデータがコマーシャルペーパーか債権か自動車登録かに関わらず、また、ライフサイクル上のどこに位置していても、台帳ワールドステートデータベース内に保持されています。 スマートコントラクトは、これらのデータを台帳(ワールドステートおよびブロックチェーン)とのやりとりを行うことで管理し、ほとんどの場合には、台帳ワールドステートのクエリや更新を行います。
台帳ワールドステートが、アクセスするスマートコントラクトのチェーンコードに応じて分割されていると理解することが極めて重要です。 そしてこの分割、すなわちネームスペースをもつことは、アーキテクトや管理者やプログラマにとってきわめて重要な設計上の留意点となります。
台帳ワールドステートは、アクセスするチェーンコードに応じて分割されています。
あるチャネルにおいて、同じチェーンコード内のスマートコントラクトは同じワールドステートを共有し、異なるチェーンコードのスマートコントラクトは互いのワールドステートに直接アクセスすることはできません。
このように、ブロックチェーンは、異なるチェーンコードワールドステートに関するトランザクションを格納することができます。
ここでの例では、2つのチェーンコードで定義された4つのスマートコントラクトがあることがわかります。それぞれのチェーンコードは、その専用のチェーンコードコンテナ内にあります。
euroPaperとyenPaperの2つのスマートコントラクトは、papersチェーンコード内に定義されています。
euroBondとyenBondの2つのスマートコントラクトも、同様の状況で、bondsチェーンコード内に定義されています。
この設計によって、アプリケーションプログラマは、ユーロまたは円建てのコマーシャルペーパー(papers)あるいは債権(bonds)を扱っているのかを理解することができます。
そして、それぞれの金融商品の規則は、通貨が違ってもあまり変わらないため、同じチェーンコードでデプロイを管理することは理にかなっています。
この図は、また、このデプロイの方針による結果も表しています。
データベース管理システム(DBMS)は、papersとbondsのチェーンコードとそれに含まれるスマートコントラクトのために、チェーンコードごとに別のワールドステートデータベースを作成します。
world state Aとworld state Bは、それぞれ別のデータベースに格納されています。
データは互いに隔離されており、例えば1つのワールドステートのクエリでは、両方のワールドステートにアクセスすることはできません。
ワールドステートは、チェーンコードに応じてネームスペースに分かれているということができます。
world state Aが、2つのコマーシャルペーパーのリスト paperListEuro、paperListYenを含んでいるのがわかるでしょうか。
ステートPAP11とPAP21は、それぞれeuroPaperとyenPaperスマートコントラクトによって管理されているコマーシャルペーパーのインスタンスです。
この二つのステートは、同じチェーンコードネームスペースにあるため、キー(PAPxyz)は、papersチェーンコードのネームスペース内で一意でなくてはなりません。
これは、町の中で通りの名前が一意であるのと少し似ています。
papersチェーンコードで、ユーロ建てか円建てかにかかわらず、すべてのコマーシャルペーパーを集計するスマートコントラクトを書くことができることに注意してください。
これは、コマーシャルペーパーが同じネームスペースを共有しているためです。
債権についても状況は同様で、債権はworld state Bに格納されており、これは別のbondsデータベースにマップされており、キーはこの中でユニークでなくてはなりません。
そして同じように重要なのは、ネームスペースがあるということは、euroPaperとyenPaperは直接world state Bにはアクセスできず、euroBondとyenBondは直接world state Aにアクセスすることができないということです。
コマーシャルペーパーと債権は大きく異なる金融商品であり、異なる属性をもち異なるルールに従うため、この隔離は有用なものです。
また、異なるネームスペースにあるため、papersとbondsは、同じキーを持つこともできることを意味します。
名前付けに関して大きな自由度を与えるため、これも有用なものです。
この自由度を使って、ビジネスデータに意味のある名前付けをするのに役立てましょう。
さらに重要なことに、ブロックチェーンは、あるチャネルで動作するピアに結びつけられるものであり、world state Aとworld state B両方に影響するトランザクションを含んでいるのがわかります。
これは、ブロックチェーンは、ピアに格納される最も基本的なデータ構造であるためです。
ワールドステートは、ブロックチェーンのトランザクションの積み重なった結果であるので、いつでもブロックチェーンから再構成することが可能です。
ワールドステートは、スマートコントラクトが通常必要なのはステートの現在の値であるので、スマートコントラクトを単純にしその効率を改善するのに役立つものです。
ワールドステートをネームスペースによって分離しておくことは、スマートコントラクトが別のスマートコントラクトとロジックを隔離し、別のワールドステートに対するトランザクションの心配をする必要をなくすのに役立ちます。
たとえば、bondsのコントラクトは、paperのトランザクションを心配する必要がありません。なぜならば、bondsからは、paperのトランザクションの結果のワールドステートは見ることができないからです。
また、ピアとチェーンコードコンテナ、DBMSは全て論理的に別のプロセスであるということも注目しておくべきでしょう。 ピアとそのチェーンコードコンテナは、常にOSの物理的に別のプロセスですが、DBMSはその種類によって、設定で組み込みか分離するかを変更することができます。 LevelDBでは、DBMSは完全にピア内に含まれますが、CouchDBでは別のOSのプロセスになります。
ここでの例において、ネームスペースの選択は、異なる通貨のコマーシャルペーパーは共有し、債権からは分離するというビジネス上の要件から来ているものであることは覚えておきましょう。 全ての金融資産の種類を別々にするようなビジネス要件、あるいは、コマーシャルペーパーと債権を共有するようなビジネス要件であったなら、どのようにネームスペースの構造が変わっていたかを考えてみましょう。
Channels
ピアが複数のチャネルに参加した場合、各チャネルに対して新しいブロックチェーンが作られ管理されます。 加えて、新しいチャネルにチェーンコードがデプロイされるたびに、新しいワールドステートデータベースが作られます。 これは、ワールドステートにおけるチェーンコードのネームスペースに加えて、チャネルが一種のネームスペースを構成することを意味しています。
しかし、同じピアとチェーンコードコンテナプロセスは、複数のチャネルに同時に参加することができるため、ブロックチェーンやワールドステートデータベースと異なり、これらのプロセスは参加しているチャネルの数に応じて増えはしません。
例えば、papersとbondsチェーンコードを新しいチャネルにデプロイしたとすると、完全に別のブロックチェーンと、2つのワールドステートデータベースが作られるでしょう。しかし、ピアとチェーンコードコンテナは増加せず、ただ複数のチャネルに接続されるだけでしょう。
Usage
コマーシャルペーパーの例を用いて、アプリケーションがどのようにネームスペースとスマートコントラクトを使うのかを見てみましょう。 アプリケーションがピアと通信し、ピアは要求を適切なチェーンコードコンテナにルーティングし、チェーンコードがDBMSにアクセスする、ということは触れておくべきでしょう。 このルーティングは、図に示されているピアのコアコンポーネントによって行われます。
以下が、ユーロ建てと円建てのコマーシャルペーパー及び債権を用いるアプリケーションのコードです。 このコードは、説明が不要なほど十分わかりやすいでしょう。
const euroPaper = network.getContract(papers, euroPaper);
paper1 = euroPaper.submit(issue, PAP11);
const yenPaper = network.getContract(papers, yenPaper);
paper2 = yenPaper.submit(redeem, PAP21);
const euroBond = network.getContract(bonds, euroBond);
bond1 = euroBond.submit(buy, BON31);
const yenBond = network.getContract(bonds, yenBond);
bond2 = yenBond.submit(sell, BON41);
このアプリケーションについて下記のことがわかります。
-
papersチェーンコードを指定してgetContract()APIを使うことで、euroPaperとyenPaperコントラクトにアクセスしていること。1aと2aを参照してください。 -
bondsチェーンコードを指定してgetContract()APIを使うことで、euroBondとyenBondコントラクトにアクセスしていること。3aと4aを参照してください。 -
euroPaperコントラクトを用いて、コマーシャルペーパーPAP11のissue(発行)トランザクションを送信していること。1aを参照してください。そして、その結果world state A内のPAP11ステートで表現されるコマーシャルペーパーが作成されます(1b)。この処理は、ブロックチェーンで1cのトランザクションとして表現されています。 -
yenPaperコントラクトを用いて、コマーシャルペーパーPAP21のredeem(現金化)トランザクションを送信していること。2aを参照してください。そして、その結果world state A内のPAP21ステートで表現されるコマーシャルペーパーが更新されます(2b)。この処理は、ブロックチェーンで2cのトランザクションとして表現されています。 -
euroBondコントラクトを用いて、コマーシャルペーパーBON31のbuy(購入)トランザクションを送信していること。3aを参照してください。そして、その結果world state B内のBON31ステートで表現される債権が更新されます(3b)。この処理は、ブロックチェーンで3cのトランザクションとして表現されています。 -
yenBondコントラクトを用いて、コマーシャルペーパーBON41のsell(売却)トランザクションを送信していること。4aを参照してください。そして、その結果world state B内のBON41ステートで表現される債権が更新されます(4b)。この処理は、ブロックチェーンで4cのトランザクションとして表現されています。
スマートコントラクトのワールドステートとのやりとりについて下記のことがわかります。
-
euroPaperとyenPaperコントラクトは、world state Aに直接アクセスできますが、world state Bには直接アクセスできません。world state Aは、物理的にはpapersチェーンコードに対応するデータベース管理システム(DBMS)のpapersデータベースに格納されています。 -
euroBondとyenBondコントラクトは、world state Bに直接アクセスできますが、world state Aには直接アクセスできません。world state Bは、物理的にはbondsチェーンコードに対応するデータベース管理システム(DBMS)のbondsデータベースに格納されています。
ブロックチェーンの、全てのワールドステートに関するトランザクションを格納するやりかたについて下記のことがわかります。
-
1cと2cのやりとりは、コマーシャルペーパー
PAP11の作成、PAP21の更新を行うトランザクションにそれぞれ対応します。これらは、ともにworld state Aに含まれます。 -
3cと4cのやりとりは、債権
BON31及びBON41の更新を行うトランザクションに対応します。これらは、ともにworld state Bに含まれます。 -
world state Aあるいはworld state Bが何らかの理由で失われることがあったとしたら、ブロックチェーンに含まれるトランザクションをすべて再実行することで再度作成することができるでしょう。
Cross chaincode access
ここでの例のシナリオで見たように、euroPaperとyenPaperはworld state Bに直接アクセスすることができません。
これは、チェーンコードとスマートコントラクトが、チェーンコードとワールドステートが互いに別々となるように設計されているためです。
しかし、euroPaperがworld state Bにアクセスする必要がある場合を考えてみましょう。
どういった場合にこのようなことがあるでしょうか?
スマートコントラクトがコマーシャルペーパーを発行するとき、近い満期日の債権の現在のリターンに応じた価格をコマーシャルペーパーにつけたいという場合を考えてみてください。
この場合、euroPaperコントラクトがworld state Bにある債権の価格をクエリできることが必要でしょう。
このやりとりをどのように実現するかを、下記の図を見てみましょう。
チェーンコードとスマートコントラクトが間接的に、チェーンコードを介して他のワールドステートにアクセスする方法
以下のことに注目してください。
-
アプリケーションが
PAP11を発行するために、euroPaperスマートコントラクトにissueトランザクションを送信します。1aを参照してください。 -
euroPaperスマートコントラクト内のissueトランザクションは、euroBondスマートコントラクトのqueryトランザクションを呼び出します。1bを参照してください。 -
euroBondのqueryは、world state Bから情報を取得します。1cを参照してください。 -
issueトランザクションに制御が戻ったとき、issueは、応答にある情報を使ってコマーシャルペーパーの価格を決め、world state Aを更新します。1dを参照してください。 -
円建てのコマーシャルペーパーを発行する際の制御フローは同じです。2a・2b・2c・2dを参照してください。
invokeChaincode() APIによって、チェーンコード間を制御が渡ります。
このAPIは、あるチェーンコードから別のチェーンコードに制御を渡します。
この例ではクエリトランザクションについてのみ述べましたが、呼ばれた側のチェーンコードのワールドステートを更新するスマートコントラクトを実行(invoke)することも可能です。次の留意点を参照してください。
Considerations
-
一般的には、各チェーンコードがもつスマートコントラクトは一つだけです。
-
非常に深く関係する場合のみ、複数のスマートコントラクトを一つのチェーンコード内にデプロイするべきです。通常は、同じワールドステートを共有する場合にのみ必要となります。
-
チェーンコードネームスペースは、異なるワールドステート間を分離します。一般的に、関係ないデータを互いに分離するのは意味があります。チェーンコードネームスペースを自分で選ぶことができないことに注意してください。これは、Hyperledger Fabricによって割り当てられ、チェーンコード名に直接マップされるものです。
-
invokeChaincode()APIを用いたチェーンコード間のやりとりには、両方のチェーンコードが同じピア上にインストールされていなければなりません。-
呼ばれたチェーンコードのワールドステートのクエリのみが必要なやりとりには、呼び出し元のチェーンコードとは異なるチャネルに対して行うことができます。
-
呼ばれたチェーンコードのワールドステートを更新する必要のあるやりとりには、呼び出し元のチェーンコードと同じチャネルで行わなければなりません。
-