Transaction context

対象読者: アーキテクト、アプリケーションおよびスマートコントラクト開発者

トランザクションコンテキストは、二つの機能を実現します。 一つは、開発者がスマートコントラクトでのトランザクションの実行で使えるユーザー変数を定義し管理できるようにするものです。 もう一つは、スマートコントラクト開発者がより詳細なトランザクション処理に関する操作を行える、幅広いFabric APIに対するアクセスを提供するものです。 この操作には、台帳、すなわちイミュータブルなブロックチェーンと変更可能なワールドステートの両方のクエリや更新から、トランザクションを送信したアプリケーションのデジタルアイデンティティの取得まで含みます。

トランザクションコンテキストは、スマートコントラクトがチャネルにデプロイされ、それ以降のトランザクション呼び出しで利用可能になったときに作成されます。 トランザクションコンテキストによって、スマートコントラクト開発者は、より強力で効率的で処理がわかりやすいプログラムを作成しやすくなります。

Scenario

コマーシャルペーパーのサンプルでは、papercontractは、最初に対象のコマーシャルペーパーのリストの名前を定義しています。 以降の各トランザクションはこのリストを参照し、発行トランザクションは新しいコマーシャルペーパーをそれに追加し、購入トランザクションは所有者を変更し、現金化トランザクションは完了したとマークします。 これは共通で使えるパターンで、スマートコントラクトを書く際には、ある変数を初期化し、続くトランザクションでそれを呼び出すことが有用なことが多いです。

トランザクションのシナリオ スマートコントラクトのトランザクションコンテキストによって、スマートコントラクトはトランザクション実行で使われるユーザー変数を定義し管理することができます。詳細な説明は本文を参照してください。

Programming

開発者は、スマートコントラクトが作成される際、カスタムコンテキストを作成するために、組み込みのContextクラスとcreateContextメソッドを下記のようにオーバーライドすることができます。

createContext() {
    new CommercialPaperContext();
}

ここでの例では、CommercialPaperContextは、CommercialPaperContractのために特化したものです。 下記のように、thisで参照されているカスタムコンテキストに、特有の変数であるPaperListを追加しています。

CommercialPaperContext extends Context {
    constructor () {
        this.paperList = new PaperList(this);
    }
}

上の図の(1)で、createContext()メソッドから返ったときには、カスタムコンテキストctxは作られており、その変数の一つとしてpaperListを含んでいます。

その後、発行、購入、現金化のようなスマートトランザクションが呼ばれるときには常に、このコンテキストが渡されます。 (2)(3)(4)で、同じコマーシャルペーパーのコンテキストがctx変数によって、トランザクションメソッドに渡されているのがわかります。

そして、次のように(5)でコンテキストが使われていることがわかります。

ctx.paperList.addPaper(...);
ctx.stub.putState(...);

CommercialPaperContextに作られたpaperListが、発行トランザクションで利用可能なことに注目してください。 現金化購入トランザクションでも同じようにpaperListが使われているのがわかります。 ctxによって、スマートコントラクトが効率的で処理がわかりやすくなっています。

また、CommercialPaperContextで明示的に追加されていない、コンテキストの別の要素であるctx.stubがあることもわかります。 これは、stubやその他の変数は、組み込みのコンテキストの一部であるからです。 それでは、この組み込みのコンテキストの構造と、これらの暗黙的な変数、そしてその使い方を見ていきましょう。

Structure

この例で見たように、トランザクションコンテキストは、paperListのような任意の数のユーザー変数をもつことができます。

トランザクションコンテキストは、二つの組み込みの要素を持っており、これらはトランザクションを送信したアプリケーションから台帳へのアクセスに至るまで幅広いFabricの機能へのアクセスを提供します。

以降では、スマートコントラクトがstubclientIdentityを使って、そのAPIによってなにができるかを下記の図を使って示します。

context.apis スマートコントラクトは、トランザクションコンテキストのstubclientIdentityを用いて様々なスマートコントラクトの機能にアクセスすることができます。詳細は本文を参照してください。

Stub

stubのAPIは、次のように分類されます。


これらの基本的なAPIに加えて、一つのステートでなく、ステートの集合をコントラクトが取得することができるクエリAPIがあります。(2)を参照してください。 集合は、キーの全体あるいは一部によるキーバリューの範囲として、あるいは、ワールドステートデータベースの値に応じたクエリとして定義されます。 クエリ結果が大きい場合、必要なストレージを削減するためにページネーションすることができます。

* [getStateByRange()](https://hyperledger.github.io/fabric-chaincode-node/{BRANCH}/api/fabric-shim.ChaincodeStub.html#getStateByRange__anchor)
* [getStateByRangeWithPagination()](https://hyperledger.github.io/fabric-chaincode-node/{BRANCH}/api/fabric-shim.ChaincodeStub.html#getStateByRangeWithPagination__anchor)
* [getStateByPartialCompositeKey()](https://hyperledger.github.io/fabric-chaincode-node/{BRANCH}/api/fabric-shim.ChaincodeStub.html#getStateByPartialCompositeKey__anchor)
* [getStateByPartialCompositeKeyWithPagination()](https://hyperledger.github.io/fabric-chaincode-node/{BRANCH}/api/fabric-shim.ChaincodeStub.html#getStateByPartialCompositeKeyWithPagination__anchor)
* [getQueryResult()](https://hyperledger.github.io/fabric-chaincode-node/{BRANCH}/api/fabric-shim.ChaincodeStub.html#getQueryResult__anchor)
* [getQueryResultWithPagination()](https://hyperledger.github.io/fabric-chaincode-node/{BRANCH}/api/fabric-shim.ChaincodeStub.html#getQueryResultWithPagination__anchor)


このAPIに加えて、プライベートデータをクエリするAPI((4))があります。 これらのAPIによって、スマートコントラクトは、キーの全部または一部によるキーバリューの範囲、あるいは、ワールドステートデータベースの値に対するクエリに従って、プライベートデータコレクションからからステートの集合をクエリすることができます。 現在のところ、プライベートデータコレクションに対するページネーションに対応したAPIはありません。

* [getPrivateDataByRange()](https://hyperledger.github.io/fabric-chaincode-node/{BRANCH}/api/fabric-shim.ChaincodeStub.html#getPrivateDataByRange__anchor)
* [getPrivateDataByPartialCompositeKey()](https://hyperledger.github.io/fabric-chaincode-node/{BRANCH}/api/fabric-shim.ChaincodeStub.html#getPrivateDataByPartialCompositeKey__anchor)
* [getPrivateDataQueryResult()](https://hyperledger.github.io/fabric-chaincode-node/{BRANCH}/api/fabric-shim.ChaincodeStub.html#getPrivateDataQueryResult__anchor)


これらのAPIのうち、もっとも単純なものは、スマートコントラクトがコンポジットキーを作成あるいは分解するのに使われます。 もう少し高度なものとして、ValidationParameter()API群があり、これは、ワールドステート(2)およびプライベートデータ(4)に関するステートベースのエンドースメントポリシーを取得および設定するものです。 最後に、getHistoryForKey()は、ステートの履歴を取得するもので、格納された値を返します。これには、そのステート更新を行ったトランザクションの識別子を含んでおり、これによってブロックチェーン(10)からそのトランザクションを取得することができます。

* [createCompositeKey()](https://hyperledger.github.io/fabric-chaincode-node/{BRACNH}/api/fabric-shim.ChaincodeStub.html#createCompositeKey__anchor)
* [splitCompositeKey()](https://hyperledger.github.io/fabric-chaincode-node/{BRANCH}/api/fabric-shim.ChaincodeStub.html#splitCompositeKey__anchor)
* [setStateValidationParameter()](https://hyperledger.github.io/fabric-chaincode-node/{BRANCH}/api/fabric-shim.ChaincodeStub.html#setStateValidationParameter__anchor)
* [getStateValidationParameter()](https://hyperledger.github.io/fabric-chaincode-node/{BRANCH}/api/fabric-shim.ChaincodeStub.html#getStateValidationParameter__anchor)
* [getPrivateDataValidationParameter()](https://hyperledger.github.io/fabric-chaincode-node/{BRANCH}/api/fabric-shim.ChaincodeStub.html#getPrivateDataValidationParameter__anchor)
* [setPrivateDataValidationParameter()](https://hyperledger.github.io/fabric-chaincode-node/{BRANCH}/api/fabric-shim.ChaincodeStub.html#setPrivateDataValidationParameter__anchor)
* [getHistoryForKey()](https://hyperledger.github.io/fabric-chaincode-node/{BRANCH}/api/fabric-shim.ChaincodeStub.html#getHistoryForKey__anchor)


ClientIdentity

ほとんどの場合、トランザクションを送信するアプリケーションは、X.509証明書を使用するでしょう。 このでは、CA1 (7)によって発行されたX.509証明書 (6) が、Isabella (8)がアプリケーションで、トランザクションt6 (5)の提案に署名するのに使われています。

ClientIdentityは、getCreator()によって返される情報をもとに、この一般的なユースケースで簡単に使えるように、X.509のユーティリティAPI群を持っているものです。