github.com/kaituanwang/hyperledger@v2.0.1+incompatible/docs/source/developapps/transactioncontext.md (about)

     1  # Transaction context
     2  
     3  **Audience**: Architects, application and smart contract developers
     4  
     5  A transaction context performs two functions. Firstly, it allows a developer to
     6  define and maintain user variables across transaction invocations within a smart
     7  contract. Secondly, it provides access to a wide range of Fabric APIs that allow
     8  smart contract developers to perform operations relating to detailed transaction
     9  processing. These range from querying or updating the ledger, both the immutable
    10  blockchain and the modifiable world state, to retrieving the
    11  transaction-submitting application's digital identity.
    12  
    13  A transaction context is created when a smart contract is deployed to a channel and
    14  made available to every subsequent transaction invocation. A transaction context
    15  helps smart contract developers write programs that are powerful, efficient and
    16  easy to reason about.
    17  
    18  * [Why a transaction context is important](#scenario)
    19  * [How to use a transaction context](#programming)
    20  * [What's in a transaction context](#structure)
    21  * [Using a context `stub`](#stub)
    22  * [Using a context `clientIdentity`](#clientIdentity)
    23  
    24  ## Scenario
    25  
    26  In the commercial paper sample,
    27  [papercontract](https://github.com/hyperledger/fabric-samples/blob/master/commercial-paper/organization/magnetocorp/contract/lib/papercontract.js)
    28  initially defines the name of the list of commercial papers for which it's
    29  responsible. Each transaction subsequently refers to this list; the issue
    30  transaction adds new papers to it, the buy transaction changes its owner, and
    31  the redeem transaction marks it as complete. This is a common pattern; when
    32  writing a smart contract it's often helpful to initialize and recall particular
    33  variables in sequential transactions.
    34  
    35  ![transaction.scenario](./develop.diagram.40.png) *A smart contract transaction
    36  context allows smart contracts to define and maintain user variables across
    37  transaction invocations. Refer to the text for a detailed explanation.*
    38  
    39  ## Programming
    40  
    41  When a smart contract is constructed, a developer can optionally override the
    42  built-in `Context` class `createContext` method to create a custom context:
    43  
    44  ```JavaScript
    45  createContext() {
    46      new CommercialPaperContext();
    47  }
    48  ```
    49  
    50  In our example, the `CommercialPaperContext` is specialized for
    51  `CommercialPaperContract`. See how the custom context, addressed through `this`,
    52  adds the specific variable `PaperList` to itself:
    53  
    54  ```JavaScript
    55  CommercialPaperContext extends Context {
    56      constructor () {
    57          this.paperList = new PaperList(this);
    58      }
    59  }
    60  ```
    61  
    62  When the createContext() method returns at point **(1)** in the diagram
    63  [above](#scenario), a custom context `ctx` has been created which contains
    64  `paperList` as one of its variables.
    65  
    66  Subsequently, whenever a smart contract transaction such as issue, buy or redeem
    67  is called, this context will be passed to it. See how at points **(2)**, **(3)**
    68  and **(4)** the same commercial paper context is passed into the transaction
    69  method using the `ctx` variable.
    70  
    71  See how the context is then used at point **(5)**:
    72  
    73  ```JavaScript
    74  ctx.paperList.addPaper(...);
    75  ctx.stub.putState(...);
    76  ```
    77  
    78  Notice how `paperList` created in `CommercialPaperContext` is available to the
    79  issue transaction. See how `paperList` is similarly used by the **redeem** and
    80  **buy** transactions; `ctx` makes the smart contracts efficient and easy to
    81  reason about.
    82  
    83  You can also see that there's another element in the context -- `ctx.stub` --
    84  which was not explictly added by `CommercialPaperContext`. That's because `stub`
    85  and other variables are part of the built-in context. Let's now examine the
    86  structure of this built-in context, these implicit variables and how to use
    87  them.
    88  
    89  ## Structure
    90  
    91  As we've seen from the [example](#programming), a transaction context can
    92  contain any number of user variables such as `paperList`.
    93  
    94  The transaction context also contains two built-in elements that provide access
    95  to a wide range of Fabric functionality ranging from the client application that
    96  submitted the transaction to ledger access.
    97  
    98    * `ctx.stub` is used to access APIs that provide a broad range of transaction
    99      processing operations from `putState()` and `getState()` to access the
   100      ledger, to `getTxID()` to retrieve the current transaction ID.
   101  
   102    * `ctx.clientIdentity` is used to get information about the identity of the
   103      user who submitted the transaction.
   104  
   105  We'll use the following diagram to show you what a smart contract can do using
   106  the `stub` and `clientIdentity` using the APIs available to it:
   107  
   108  ![context.apis](./develop.diagram.41.png) *A smart contract can access a
   109  range of functionality in a smart contract via the transaction context `stub`
   110  and `clientIdentity`. Refer to the text for a detailed explanation.*
   111  
   112  ## Stub
   113  
   114  The APIs in the stub fall into the following categories:
   115  
   116  * **World state data APIs**. See interaction point **(1)**. These APIs enable
   117    smart contracts to get, put and delete state corresponding to individual
   118    objects from the world state, using their key:
   119  
   120      * [getState()](https://hyperledger.github.io/fabric-chaincode-node/{BRANCH}/api/fabric-shim.ChaincodeStub.html#getState__anchor)
   121      * [putState()](https://hyperledger.github.io/fabric-chaincode-node/{BRANCH}/api/fabric-shim.ChaincodeStub.html#putState__anchor)
   122      * [deleteState()](https://hyperledger.github.io/fabric-chaincode-node/{BRANCH}/api/fabric-shim.ChaincodeStub.html#deleteState__anchor)
   123  
   124    <br> These basic APIs are complemented by query APIs which enable contracts to
   125    retrieve a set of states, rather than an individual state. See interaction
   126    point **(2)**. The set is either defined by a range of key values, using full
   127    or partial keys, or a query according to values in the underlying world state
   128    [database](../ledger/ledger.html#world-state-database-options).  For large
   129    queries, the result sets can be paginated to reduce storage requirements:
   130  
   131      * [getStateByRange()](https://hyperledger.github.io/fabric-chaincode-node/{BRANCH}/api/fabric-shim.ChaincodeStub.html#getStateByRange__anchor)
   132      * [getStateByRangeWithPagination()](https://hyperledger.github.io/fabric-chaincode-node/{BRANCH}/api/fabric-shim.ChaincodeStub.html#getStateByRangeWithPagination__anchor)
   133      * [getStateByPartialCompositeKey()](https://hyperledger.github.io/fabric-chaincode-node/{BRANCH}/api/fabric-shim.ChaincodeStub.html#getStateByPartialCompositeKey__anchor)
   134      * [getStateByPartialCompositeKeyWithPagination()](https://hyperledger.github.io/fabric-chaincode-node/{BRANCH}/api/fabric-shim.ChaincodeStub.html#getStateByPartialCompositeKeyWithPagination__anchor)
   135      * [getQueryResult()](https://hyperledger.github.io/fabric-chaincode-node/{BRANCH}/api/fabric-shim.ChaincodeStub.html#getQueryResult__anchor)
   136      * [getQueryResultWithPagination()](https://hyperledger.github.io/fabric-chaincode-node/{BRANCH}/api/fabric-shim.ChaincodeStub.html#getQueryResultWithPagination__anchor)
   137  
   138  
   139  * **Private data APIs**. See interaction point **(3)**. These APIs enable smart
   140    contracts to interact with a private data collection. They are analogous to
   141    the APIs for world state interactions, but for private data. There are APIs to
   142    get, put and delete a private data state by its key:
   143  
   144      * [getPrivateData()](https://hyperledger.github.io/fabric-chaincode-node/{BRANCH}/api/fabric-shim.ChaincodeStub.html#getPrivateData__anchor)
   145      * [putPrivateData()](https://hyperledger.github.io/fabric-chaincode-node/{BRANCH}/api/fabric-shim.ChaincodeStub.html#putPrivateData__anchor)
   146      * [deletePrivateData()](https://hyperledger.github.io/fabric-chaincode-node/{BRANCH}/api/fabric-shim.ChaincodeStub.html#deletePrivateData__anchor)
   147  
   148    <br> This set is complemented by set of APIs to query private data **(4)**.
   149    These APIs allow smart contracts to retrieve a set of states from a private
   150    data collection, according to a range of key values, either full or partial
   151    keys, or a query according to values in the underlying world state
   152    [database](../ledger/ledger.html#world-state-database-options). There are
   153    currently no pagination APIs for private data collections.
   154  
   155      * [getPrivateDataByRange()](https://hyperledger.github.io/fabric-chaincode-node/{BRANCH}/api/fabric-shim.ChaincodeStub.html#getPrivateDataByRange__anchor)
   156      * [getPrivateDataByPartialCompositeKey()](https://hyperledger.github.io/fabric-chaincode-node/{BRANCH}/api/fabric-shim.ChaincodeStub.html#getPrivateDataByPartialCompositeKey__anchor)
   157      * [getPrivateDataQueryResult()](https://hyperledger.github.io/fabric-chaincode-node/{BRANCH}/api/fabric-shim.ChaincodeStub.html#getPrivateDataQueryResult__anchor)
   158  
   159  
   160  * **Transaction APIs**. See interaction point **(5)**. These APIs are used by a
   161    smart contract to retrieve details about the current transaction proposal
   162    being processed by the smart contract. This includes the transaction
   163    identifier and the time when the transaction proposal was created.
   164  
   165      * [getTxID()](https://hyperledger.github.io/fabric-chaincode-node/{BRANCH}/api/fabric-shim.ChaincodeStub.html#getTxID__anchor)
   166        returns the identifier of the current transaction proposal **(5)**.
   167      * [getTxTimestamp()](https://hyperledger.github.io/fabric-chaincode-node/{BRANCH}/api/fabric-shim.ChaincodeStub.html#getTxTimestamp__anchor)
   168        returns the timestamp when the current transaction proposal was created by
   169        the application **(5)**.
   170      * [getCreator()](https://hyperledger.github.io/fabric-chaincode-node/{BRANCH}/api/fabric-shim.ChaincodeStub.html#getCreator__anchor)
   171        returns the raw identity (X.509 or otherwise) of the creator of
   172        transaction proposal. If this is an X.509 certificate then it is often
   173        more appropriate to use [`ctx.ClientIdentity`](#clientidentity).
   174      * [getSignedProposal()](https://hyperledger.github.io/fabric-chaincode-node/{BRANCH}/api/fabric-shim.ChaincodeStub.html#getSignedProposal__anchor)
   175        returns a signed copy of the current transaction proposal being processed
   176        by the smart contract.
   177      * [getBinding()](https://hyperledger.github.io/fabric-chaincode-node/{BRANCH}/api/fabric-shim.ChaincodeStub.html#getBinding__anchor)
   178        is used to prevent transactions being maliciously or accidentally replayed
   179        using a nonce. (For practical purposes, a nonce is a random number
   180        generated by the client application and incorporated in a cryptographic
   181        hash.) For example, this API could be used by a smart contract at **(1)**
   182        to detect a replay of the transaction **(5)**.
   183      * [getTransient()](https://hyperledger.github.io/fabric-chaincode-node/{BRANCH}/api/fabric-shim.ChaincodeStub.html#getTransient__anchor)
   184        allows a smart contract to access the transient data an application passes
   185        to a smart contract. See interaction points **(9)** and **(10)**.
   186        Transient data is private to the application-smart contract interaction.
   187        It is not recorded on the ledger and is often used in conjunction with
   188        private data collections **(3)**.
   189  
   190    <br>
   191  
   192  * **Key APIs** are used by smart contracts to manipulate state key in the world
   193    state or a private data collection. See interaction points **2** and **4**.
   194  
   195    The simplest of these APIs allows smart contracts to form and split composite
   196    keys from their individual components. Slightly more advanced are the
   197    `ValidationParameter()` APIs which get and set the state based endorsement
   198    policies for world state **(2)** and private data **(4)**. Finally,
   199    `getHistoryForKey()` retrieves the history for a state by returning the set of
   200    stored values, including the transaction identifiers that performed the state
   201    update, allowing the transactions to be read from the blockchain **(10)**.
   202  
   203      * [createCompositeKey()](https://hyperledger.github.io/fabric-chaincode-node/{BRANCH}/api/fabric-shim.ChaincodeStub.html#createCompositeKey__anchor)
   204      * [splitCompositeKey()](https://hyperledger.github.io/fabric-chaincode-node/{BRANCH}/api/fabric-shim.ChaincodeStub.html#splitCompositeKey__anchor)
   205      * [setStateValidationParameter()](https://hyperledger.github.io/fabric-chaincode-node/{BRANCH}/api/fabric-shim.ChaincodeStub.html#setStateValidationParameter__anchor)
   206      * [getStateValidationParameter()](https://hyperledger.github.io/fabric-chaincode-node/{BRANCH}/api/fabric-shim.ChaincodeStub.html#getStateValidationParameter__anchor)
   207      * [getPrivateDataValidationParameter()](https://hyperledger.github.io/fabric-chaincode-node/{BRANCH}/api/fabric-shim.ChaincodeStub.html#getPrivateDataValidationParameter__anchor)
   208      * [setPrivateDataValidationParameter()](https://hyperledger.github.io/fabric-chaincode-node/{BRANCH}/api/fabric-shim.ChaincodeStub.html#setPrivateDataValidationParameter__anchor)
   209      * [getHistoryForKey()](https://hyperledger.github.io/fabric-chaincode-node/{BRANCH}/api/fabric-shim.ChaincodeStub.html#getHistoryForKey__anchor)
   210  
   211    <br>
   212  
   213  * **Event APIs** are used manage event processing in a smart contract.
   214  
   215      * [setEvent()](https://hyperledger.github.io/fabric-chaincode-node/{BRANCH}/api/fabric-shim.ChaincodeStub.html#setEvent__anchor)
   216  
   217        Smart contracts use this API to add user events to a transaction response.
   218        See interaction point **(5)**. These events are ultimately recorded on the
   219        blockchain and sent to listening applications at interaction point
   220        **(11)**.
   221  
   222      <br>
   223  
   224  * **Utility APIs** are a collection of useful APIs that don't easily fit in a
   225    pre-defined category, so we've grouped them together! They include retrieving
   226    the current channel name and passing control to a different chaincode on the
   227    same peer.
   228  
   229      * [getChannelID()](https://hyperledger.github.io/fabric-chaincode-node/{BRANCH}/api/fabric-shim.ChaincodeStub.html#getChannelID__anchor)
   230  
   231        See interaction point **(13)**.  A smart contract running on any peer can
   232        use this API to determined on which channel the application invoked the
   233        smart contract.
   234      * [invokeChaincode()](https://hyperledger.github.io/fabric-chaincode-node/{BRANCH}/api/fabric-shim.ChaincodeStub.html#invokeChaincode__anchor)
   235  
   236        See interaction point **(14)**.  Peer3 owned by MagnetoCorp has multiple
   237        smart contracts installed on it.  These smart contracts are able to call
   238        each other using this API. The smart contracts must be collocated; it is
   239        not possible to call a smart contract on a different peer.
   240  
   241      <br> Some of these utility APIs are only used if you're using low-level
   242    chaincode, rather than smart contracts. These APIs are primarily for the
   243    detailed manipulation of chaincode input; the smart contract `Contract` class
   244    does all of this parameter marshalling automatically for developers.
   245  
   246      * [getFunctionAndParameters()](https://hyperledger.github.io/fabric-chaincode-node/{BRANCH}/api/fabric-shim.ChaincodeStub.html#getFunctionAndParameters__anchor)
   247      * [getStringArgs()](https://hyperledger.github.io/fabric-chaincode-node/{BRANCH}/api/fabric-shim.ChaincodeStub.html#getStringArgs__anchor)
   248      * [getArgs()](https://hyperledger.github.io/fabric-chaincode-node/{BRANCH}/api/fabric-shim.ChaincodeStub.html#getArgs__anchor)
   249  
   250  
   251  ## ClientIdentity
   252  
   253  In most cases, the application submitting a transaction will be using an X.509
   254  certificate. In the [example](#structure), an X.509 certificate **(6)** issued
   255  by `CA1` **(7)** is being used by `Isabella` **(8)** in her application to sign
   256  the proposal in transaction `t6` **(5)**.
   257  
   258  `ClientIdentity` takes the information returned by `getCreator()` and puts a set
   259  of X.509 utility APIs on top of it to make it easier to use for this common use
   260  case.
   261  
   262  * [getX509Certificate()](https://hyperledger.github.io/fabric-chaincode-node/{BRANCH}/api/fabric-shim.ClientIdentity.html#getX509Certificate__anchor)
   263    returns the full X.509 certificate of the transaction submitter, including all
   264    its attributes and their values. See interaction point **(6)**.
   265  * [getAttributeValue()](https://hyperledger.github.io/fabric-chaincode-node/{BRANCH}/api/fabric-shim.ClientIdentity.html#getAttributeValue__anchor)
   266    returns the value of a particular X.509 attribute, for example, the
   267    organizational unit `OU`, or distinguished name `DN`. See interaction point
   268    **(6)**.
   269  * [assertAttributeValue()](https://hyperledger.github.io/fabric-chaincode-node/{BRANCH}/api/fabric-shim.ClientIdentity.html#assertAttributeValue__anchor)
   270    returns `TRUE` if the specified attribute of the X.509 attribute has a
   271    specified value. See interaction point **(6)**.
   272  * [getID()](https://hyperledger.github.io/fabric-chaincode-node/{BRANCH}/api/fabric-shim.ClientIdentity.html#getID__anchor)
   273    returns the unique identity of the transaction submitter, according to their
   274    distinguished name and the issuing CA's distinguished name. The format is
   275    `x509::{subject DN}::{issuer DN}`. See interaction point **(6)**.
   276  * [getMSPID()](https://hyperledger.github.io/fabric-chaincode-node/{BRANCH}/api/fabric-shim.ClientIdentity.html#getMSPID__anchor)
   277    returns the channel MSP of the transaction submitter. This allows a smart
   278    contract to make processing decisions based on the submitter's organizational
   279    identity. See interaction point **(15)** or **(16)**.
   280  
   281  <!--- Licensed under Creative Commons Attribution 4.0 International License
   282  https://creativecommons.org/licenses/by/4.0/ -->