github.com/kchristidis/fabric@v1.0.4-0.20171028114726-837acd08cde1/test/tools/PTE/README.md (about)

     1  
     2  # Performance Traffic Engine - PTE
     3  
     4  The Performance Traffic Engine (PTE) uses [Hyperledger Fabric Client (HFC) Node SDK](https://fabric-sdk-node.github.io/index.html)
     5  to interact with a [Hyperledger Fabric](http://hyperledger-fabric.readthedocs.io/en/latest/) network.
     6  
     7  ## Table Of Contents:
     8  - [Prerequisites](#prerequisites)
     9  - [Setup](#setup)
    10  - [Running PTE](#running-pte)
    11       - [Usage](#usage)
    12       - [Transaction Execution](#transaction-execution)
    13       - [Transaction Type](#transaction-type)
    14       - [Sample Use Cases](#sample-use-cases)
    15       - [Chaincodes](#chaincodes)
    16       - [Output](#output)
    17   - [Reference](#reference)
    18      - [User Input File](#user-input-file)
    19      - [Service Credentials File](#service-credentials-file)
    20      - [Creating a Local Fabric Network](#creating-a-local-fabric-network)
    21  
    22  ---
    23  
    24  ### Code Base for v1.0.0-alpha2
    25  
    26  - Fabric commit level: `6b6bfcfbd1e798a8a08fa9c3bf4dc0ff766a6b87`
    27  - fabric-sdk-node commit level: `f13f4b42e7155ec0dc3d7485b202bb6a6ca73aed`
    28  - fabric-ca commit level: `97ca16ca4f883a65072da860fce9eb76da269d62`
    29  - PTE commit level: `latest`
    30  
    31  ### Code Base for v1.0.0-alpha
    32  For v1.0.0-alpha support, use v1performance commit level `aa73747ccf5f511fbcd10a962dd1e588bde1a8b0`.
    33  Below is the v1.0.0-alpha commit levels.
    34  
    35  - Fabric commit level: `fa3d88cde177750804c7175ae000e0923199735c`
    36  - fabric-sdk-node commit level: `196d0484c884ab894374c73df89bfe047bcc9f00`
    37  - fabric-ca commit level: `29385879bc2931cce9ec833acf796129908b72fb`
    38  - PTE v1performance commit level: `aa73747ccf5f511fbcd10a962dd1e588bde1a8b0`
    39  
    40  ### Future items
    41  
    42  - PTE needs to supports any number of organizations in a channel. PTE supports two organizations per channel now (FAB-3809).
    43  - PTE can only send transactions to the anchor peer of an organization. It will need to be able to send transactions to any peer.
    44  - Endorsement policy is not supported yet.
    45  - Replace `git clone https://github.com/hyperledger/fabric-sdk-node.git` with fabric-client and fabric-ca-client.
    46  - Post-alpha2, remove v1performance info.
    47  
    48  ## Prerequisites
    49  To build and test the following prerequisites must be installed first:
    50  
    51  - node and npm lts/boron release (v6.10.x and v3.10.x)
    52      -  node v7 is not currently supported
    53  - gulp command
    54      - `npm install -g gulp`
    55  - go (v1.7 or later)
    56      - refer to [Go - Getting Started](https://golang.org/doc/install)
    57  - others:
    58      - in Ubuntu: `apt install -y build-essential python libltdl-dev`
    59      - or refer to your distribution's repository
    60  
    61  If planning to run your Fabric network locally, you'll need docker and a bit more. See [Hyperledger Fabric - Getting Started](http://hyperledger-fabric.readthedocs.io/en/latest/getting_started.html) for details.
    62  
    63  ## Setup
    64  1. Download fabric sources and checkout appropriate commit levels (v1.0.0-alpha2 shown here):
    65      - `go get -d github.com/hyperledger/fabric`
    66      - `cd $GOPATH/src/github.com/hyperledger/fabric/`
    67      - `git checkout v1.0.0-alpha2`
    68      - Optional: `make docker`
    69      - `go get -d github.com/hyperledger/fabric-ca`
    70      - `cd $GOPATH/src/github.com/hyperledger/fabric-ca/`
    71      - `git checkout v1.0.0-alpha2`
    72      - Optional: `make docker`
    73      - `go get -d github.com/hyperledger/fabric-sdk-node`
    74      - `cd $GOPATH/src/github.com/hyperledger/fabric-sdk-node`
    75      - `git checkout v1.0.0-alpha2`
    76  
    77      If `make docker` is skipped, the assumption is that the user will either acquire docker images from another source, or PTE will run against a remote Fabric network. See [Creating a local Fabric network](#creating-a-local-fabric-network) for additional information on this.
    78  
    79  2. Install node packages and build the ca libraries:
    80      - `npm install`
    81          -  you should be able to safely ignore any warnings
    82      -  `gulp ca`
    83  
    84  3. Clone PTE
    85      **Note:** This will not be necessary in future releases (post-alpha2) as PTE has been merged into Fabric.
    86      - If testing v1-alpha or v1-alpha2, clone the v1performance repo:
    87          - `cd test`
    88          - `git clone https://github.com/dongmingh/v1performance`
    89          - `cd v1performance`
    90          - If testing v1.0.0-alpha: `git reset --hard aa73747ccf5f511fbcd10a962dd1e588bde1a8b0`
    91      - If testing against latest Fabric commit, copy from Fabric repo:
    92          - `cp -r $GOPATH/src/github.com/hyperledger/fabric/test/tools/PTE .`
    93          - `cd PTE`
    94  
    95  4. Create Service Credentials file(s) for your Fabric network:
    96      - See the examples in `SCFiles` and change the address to your own Fabric addresses and credentials. Add a block for each organization and peer, ensuring correctness.
    97  
    98  5. Specify run scenarios:
    99      - Create your own version of runCases.txt and User Input json files, according to the test requirements. Use the desired chaincode name, channel name, organizations, etc. Using the information in your own network profiles, remember to "create" all channels, and "join" and "install" for each org, to ensure all peers are set up correctly. Additional information can be found below.
   100  
   101  ## Running PTE
   102  Before attempting to run PTE ensure your network is running!
   103  If you do not have access to a Fabric network, please see the section on [Creating a local Fabric network](#creating-a-local-fabric-network).
   104  
   105  ### Usage
   106  `./pte_driver.sh <run cases file>`
   107  ### Example
   108  `./pte_driver.sh userInputs/runCases.txt`
   109  
   110  `userInputs/runCases.txt` contains the list of user specified test cases to be executed. Each line is a test case and includes two parameters: **SDK type** and **user input file**.  
   111  
   112  For instance, a run cases file containing two test cases using the node SDK would be:
   113  ```
   114  sdk=node userInputs/samplecc-chan1-i.json
   115  sdk=node userInputs/samplecc-chan2-i.json
   116  ```
   117  
   118  **Note:** Available SDK types are node, go, python and java; however, only the node SDK is currently supported.
   119  
   120  See [User Input file](#user-input-file) in the Reference section below for more information about these files.
   121  
   122  ### Transaction Execution
   123  A single test case is described by a user input file. User input files define all the parameters for executing a test; including transaction type, number of threads, number of transactions, duration, etc. All threads in one test case will concurrently execute the specified transaction. Different transactions may be used in different test cases and then combined into a single run cases file, making it possible to create more complicated scenarios. For example, in a single run of PTE, a user could send a specific number of invokes to all peers and then query each peer separately.
   124  
   125  There are two ways to control transaction execution:
   126  * **transaction number**: Each thread executes the specified number of transactions specified by nRequest in the user input file.
   127  * **run time duration**: Each thread executes the same transaction concurrently for the specified time duration specified by runDur in the user input file, note that nRequest is set to 0.
   128  
   129  ### Transaction Type
   130  * ### Invoke (move)
   131      To execute invoke (move) transactions, set the transType to Invoke and invokeType to Move, and specify the network parameters and desired execution parameters:
   132      ```
   133      "invokeCheck": "TRUE",
   134      "transMode": "Constant",
   135      "transType": "Invoke",
   136      "invokeType": "Move",
   137      "nOrderer": "1",
   138      "nOrg": "2",
   139      "nPeerPerOrg": "2",
   140      "nProc": "4",
   141      "nRequest": "1000",
   142      "runDur": "600",
   143      "TLS": "Disabled",
   144      ```
   145      And set the channel name in channelOpt:
   146      ```
   147      "channelOpt": {
   148          "name": "testChannel1",
   149          "action":  "create",
   150          "orgName": [
   151              "testOrg1"
   152          ]
   153      },
   154      ```
   155  * ### Invoke (query)
   156      To execute invoke (move) transactions, set the transType to Invoke and invokeType to Query, and specify the network parameters and desired execution parameters:
   157      ```
   158      "invokeCheck": "TRUE",
   159      "transMode": "Constant",
   160      "transType": "Invoke",
   161      "invokeType": "Query",
   162      "nOrderer": "1",
   163      "nOrg": "2",
   164      "nPeerPerOrg": "2",
   165      "nProc": "4",
   166      "nRequest": "1000",
   167      "runDur": "600",
   168      "TLS": "Disabled",
   169      ```
   170      And set the channel name in channelOpt:
   171      ```
   172      "channelOpt": {
   173          "name": "testChannel1",
   174          "action":  "create",
   175          "orgName": [
   176              "testOrg1"
   177          ]
   178      },
   179      ```
   180  
   181  ### Sample Use Cases
   182  * ### Latency
   183      Example: `userInputs/samplecc-latency-i.json`
   184      Performs 1000 invokes (Move) with 1 thread on 1 network using the sample_cc chaincode. The average of the execution result (execution time (ms)/1000 transactions) represents the latency of 1 invoke (Move).
   185  * ### Long run
   186      Example: `userInputs/samplecc-longrun-i.json`
   187      Performs invokes (Move) of various payload size ranging from 1kb-2kb with 1 threads on one network using sample_cc chaincode for 72 hours at 1 transaction per second.
   188  * ### Concurrency
   189      Example: `userInputs/samplecc-concurrency-i.json`
   190      Performs invokes (Move) of 1kb payload with 50 threads on one 4-peer network using sample_cc chaincode for 10 minutes.
   191  * ### Complex
   192      Example: `userInputs/samplecc-complex-i.json`
   193      Performs invokes (Move) of various payload size ranging from 10kb-500kb with 10 threads on one 4-peer network using sample_cc chaincode for 10 minutes. Each invoke (Move) is followed by an invoke (Query).
   194  * ### More complicated scenarios
   195      * For multiple different chaincode deployments and transactions, configure each user input file to deploy different chaincodes and drive the transactions appropriately.
   196      * For a density test, configure multiple SCFiles, one for each network. Then concurrently execute the test against these multiple networks with unique workloads specified in the user input files.
   197      * For a stress test on a single network, set all SCFiles to same network. Then concurrent execution of the test is performed against the network but with the workload specified in each user input file.
   198  
   199  ## Additional Use Cases
   200  Although PTE's primary use case is to drive transactions into a Fabric network, it can be used for creating and joining channels, and chaincode installation and instantiation. This gives the ability for more complete end-to-end scenarios.
   201  * ### Channel Operations
   202      For any channel activities (create or join), set transType to `Channel`:
   203      ```
   204      "transMode": "Simple",
   205      "transType": "Channel",
   206      "invokeType": "Move",
   207      ```
   208      * ### Create a channel
   209          To create a channel, set the action in channelOpt to `create`, and set the name to the channel name. Note that orgName is ignored in this operation:
   210          ```
   211          "channelOpt": {
   212              "name": "testChannel1",
   213              "action":  "create",
   214              "orgName": [
   215                  "testOrg1"
   216              ]
   217          },
   218          ```
   219      * ### Join a channel
   220          To join all peers in an org to a channel, set the action in channelOpt to `join`, set name to channel name, and set orgName to the list of orgs to join:
   221          ```
   222          "channelOpt": {
   223              "name": "testChannel1",
   224              "action":  "join",
   225              "orgName": [
   226                  "testOrg1"
   227              ]
   228          },
   229          ```
   230  * ### Chaincode Operations
   231      For chaincode setup (install or instantiate) set `deploy` according to the test. For example:
   232      ```
   233      "deploy": {
   234          "chaincodePath": "github.com/sample_cc",
   235          "fcn": "init",
   236          "args": []
   237      },
   238      ```
   239      * ### Install a chaincode
   240          To install a chaincode, set the transType to `install`:
   241          ```
   242          "transMode": "Simple",
   243          "transType": "install",
   244          "invokeType": "Move",
   245          ```
   246          And set channelOpt name to the channel name and orgName to a list of org names:
   247          ```
   248          "channelOpt": {
   249              "name":  "testChannel1",
   250              "action":  "create",
   251              "orgName": [
   252                  "testOrg1"
   253              ]
   254          },
   255          ```
   256          Note that action is ignored.
   257      * ### Instantiate a chaincode
   258          To instantiate a chaincode, set the transType to `instantiate`:
   259          ```
   260          "transMode": "Simple",
   261          "transType": "instantiate",
   262          "invokeType": "Move",
   263          ```
   264          and set channelOpt name to the channel name:
   265          ```
   266          "channelOpt": {
   267              "name":  "testChannel1",
   268              "action":  "create",
   269              "orgName": [
   270                  "testOrg1"
   271              ]
   272          },
   273          ```
   274          Note that action and orgName are ignored.
   275  
   276  ## Chaincodes
   277  The following chaincodes are tested and supported:
   278  * **example02**: This is a simple chaincode with limited capability.  This chaincode is **NOT** suitable for performance benchmark.
   279  * **ccchecker**:  This chaincode supports variable payload sizes.
   280  See userInput-ccchecker.json for example of userInput file. Take the following steps to install this chaincode:
   281    - `cd $GOPATH/src/github.com/hyperledger/fabric-sdk-node/test/fixtures/src/github.com`
   282    - `mkdir ccchecker`
   283    - download newkeyperinvoke.go into ccchecker directory
   284  * **sample_cc**: This chaincode supports variable (randomized) payload sizes and performs encryption and decryption on the payload. Specify ccType as ccchecker when using this chaincode.
   285  See userInput-samplecc.json for example of userInput file. Take the following steps to install this chaincode:
   286    - `cd $GOPATH/src/github.com/hyperledger/fabric-sdk-node/test/fixtures/src/github.com`
   287    - `mkdir sample_cc`
   288    - download chaincode_sample.go into sample_cc directory
   289  
   290  ## Output
   291  The output includes network id, thread id, transaction type, total transactions, completed transactions, failed transactions, starting time, ending time, and elapsed time.
   292  * For example, consider a test case that has 4 threads driving a single peer. The output shows that network 0 thread 0 executed 1000 moves with no failure in 406530 ms, network 0 thread 1 executed 1000 moves with no failure in 400421 ms, and so on.  Note that the starting and ending timestamps are provided:
   293      ```
   294      stdout: [Nid:id=0:3] eventRegister: completed 1000(1000) Invoke(Move) in 259473 ms, timestamp: start 1492024894518 end 1492025153991
   295      stdout: [Nid:id=0:2] eventRegister: completed 1000(1000) Invoke(Move) in 364174 ms, timestamp: start 1492024894499 end 1492025258673
   296      stdout: [Nid:id=0:1] eventRegister: completed 1000(1000) Invoke(Move) in 400421 ms, timestamp: start 1492024894500 end 1492025294921
   297      stdout: [Nid:id=0:0] eventRegister: completed 1000(1000) Invoke(Move) in 406530 ms, timestamp: start 1492024894498 end 1492025301028
   298      ```
   299  
   300  ## Reference
   301  
   302  ### User Input file
   303  ```
   304  {
   305      "channelID": "_ch1",
   306      "chaincodeID": "sample_cc",
   307      "chaincodeVer": "v0",
   308      "chainID": "testchainid",
   309      "logLevel": "ERROR",
   310      "invokeCheck": "TRUE",
   311      "transMode": "Simple",
   312      "transType": "Invoke",
   313      "invokeType": "Move",
   314      "nOrderer": "1",
   315      "nOrg": "2",
   316      "nPeerPerOrg": "2",
   317      "nProc": "4",
   318      "nRequest": "0",
   319      "runDur": "600",
   320      "TLS": "enabled",
   321      "channelOpt": {
   322          "name": "testOrg1",
   323          "channelTX": "/root/gopath/src/github.com/hyperledger/fabric/common/tools/cryptogen/crypto-config/ordererOrganizations/testOrgsChannel1.tx",
   324          "action":  "create",
   325          "orgName": [
   326              "testOrg1"
   327          ]
   328      },
   329      "burstOpt": {
   330          "burstFreq0":  "500",
   331          "burstDur0":  "3000",
   332          "burstFreq1": "2000",
   333          "burstDur1": "10000"
   334      },
   335      "mixOpt": {
   336          "mixFreq": "2000"
   337      },
   338      "constantOpt": {
   339          "recHIST": "HIST",
   340          "constFreq": "1000",
   341          "devFreq": 300
   342      },
   343      "ccType": "general",
   344      "ccOpt": {
   345          "keyStart": "5000",
   346          "payLoadMin": "1024",
   347          "payLoadMax": "2048"
   348      },
   349      "deploy": {
   350          "chaincodePath": "github.com/ccchecker",
   351          "fcn": "init",
   352          "args": []
   353      },
   354      "invoke": {
   355          "query": {
   356              "fcn": "invoke",
   357              "args": ["get", "a"]
   358          },
   359          "move": {
   360              "fcn": "invoke",
   361              "args": ["put", "a", "string-msg"]
   362          }
   363      },   
   364      "SCFile": [
   365          {"ServiceCredentials":"SCFiles/config-local.json"}
   366      ]
   367  }
   368  ```
   369  where:
   370  * **channelID**: channel ID for the run.
   371  * **chaincodeID**: chaincode ID for the run.
   372  * **chaincodeVer**: chaincode version.
   373  * **chainID**: chain ID for the run. **DO NOT CHANGE.**
   374  * **logLevel**: logging level for the run. Options are ERROR, DEBUG, or INFO.  Set to ERROR for performance test. The default value is ERROR.
   375  * **invokeCheck**: if this is TRUE, then a query will be executed for the last invoke upon the receiving of the event of the last invoke. This value is ignored for query test.
   376  * **transMode**: transaction mode
   377      * **Simple**: one transaction type and rate only, the subsequent transaction is sent when the response of sending transaction (not the event handler), success or failure, of the previous transaction is received
   378      * **Burst**: various traffic rates, see burstOpt for detailed
   379      * **Mix**: mix invoke and query transactions, see mixOpt for detailed
   380      * **Constant**: the transactions are sent by the specified rate, see constantOpt for detailed
   381      * **Latency**: one transaction type and rate only, the subsequent transaction is sent when the event message (ledger update is completed) of the previous transaction is received
   382  * **transType**: transaction type
   383      * **Channel**: channel activities specified in channelOpt.action
   384      * **Install**: install chaincode
   385      * **Instantiate**: instantiate chaincode
   386      * **Invoke**: invokes transaction
   387  * **invokeType**: invoke transaction type. This parameter is valid only if the transType is set to invoke
   388      * **Move**: move transaction
   389      * **Query**: query transaction
   390  * **nOrderer**: number of orderers for traffic, this number shall not exceed the actual number of orderers in the network, or some transactions may fail. One orderer is assigned to one thread with round robin. PTE currently only supports 1 orderer.
   391  * **nOrg**: number of organitzations for the test
   392  * **nPeerPerOrg**: number of peers per organization for the test
   393  * **nProc**: number of processes for the test
   394  * **nRequest**: number of transactions to be executed for each thread
   395  * **runDur**: run duration in seconds to be executed if nRequest is 0
   396  * **TLS**: TLS setting for the test: Disabled or Enabled.
   397  * **channelOpt**: transType channel options
   398      * **name**: channel name
   399      * **channelTX**: channel transaction file
   400      * **action**: channel action: create or join
   401      * **orgName**: name of organization for the test
   402  * **burstOpt**: the frequencies and duration for Burst transaction mode traffic. Currently, two transaction rates are supported. The traffic will issue one transaction every burstFreq0 ms for burstDur0 ms, then one transaction every burstFreq1 ms for burstDur1 ms, then the pattern repeats. These parameters are valid only if the transMode is set to **Burst**.
   403      * **burstFreq0**: frequency in ms for the first transaction rate
   404      * **burstDur0**:  duration in ms for the first transaction rate
   405      * **burstFreq1**: frequency in ms for the second transaction rate
   406      * **burstDur1**: duration in ms for the second transaction rate
   407  * **mixOpt**: each invoke is followed by a query on every thread. This parameter is valid only the transMode is set to **Mix**.
   408  * **mixFreq**: frequency in ms for the transaction rate. This value should be set based on the characteristics of the chaincode to avoid the failure of the immediate query.
   409  * **constantOpt**: the transactions are sent at the specified rate. This parameter is valid only the transMode is set to **Constant**.
   410      * **recHist**: This parameter indicates if brief history of the run will be saved.  If this parameter is set to HIST, then the output is saved into a file, namely ConstantResults.txt, under the current working directory.  Otherwise, no history is saved.
   411      * **constFreq**: frequency in ms for the transaction rate.
   412      * **devFreq**: deviation of frequency in ms for the transaction rate. A random frequency is calculated between constFrq-devFreq and constFrq+devFreq for the next transaction.  The value is set to default value, 0, if this value is not set in the user input json file.  All transactions are sent at constant rate if this number is set to 0.
   413  * **ccType**: chaincode type
   414      * **ccchecker**: The first argument (key) in the query and invoke request is incremented by 1 for every transaction.  The prefix of the key is made of thread ID, ex, all keys issued from thread 4 will have prefix of **key3_**. And, the second argument (payload) in an invoke (Move) is a random string of size ranging between payLoadMin and payLoadMax defined in ccOpt.
   415      * **auction**: The first argument (key) in the query and invoke request is incremented by 1 for every transaction.  And, the invoke second argument (payload) is made of a random string with various size between payLoadMin and payLoadMax defined in ccOpt. (**to be tested**)
   416      * **general**: The arguments of transaction request are taken from the user input json file without any changes.
   417  * **ccOpt**: chaincode options
   418      * **keyStart**: the starting transaction key index, this is used when the ccType is non general which requires a unique key for each invoke.
   419      * **payLoadMin**: minimum size in bytes of the payload. The payload is made of random string with various size between payLoadMin and payLoadMax.
   420      * **payLoadMax**: maximum size in bytes of the payload
   421  * **deploy**: deploy transaction contents
   422  * **invoke** invoke transaction contents
   423      * **query**: query content
   424      * **move**: move content
   425  * **SCFile**: the service credentials json.
   426  
   427  
   428  ## Service Credentials file
   429  The service credentials contain the information of the network and are stored in the `SCFiles` directory. The following is a sample of the service credentials json file:
   430  ```
   431  {
   432      "test-network": {
   433              "orderer": {
   434                      "name": "OrdererMSP",
   435                      "mspid": "OrdererMSP",
   436                      "mspPath": "./crypto-config",
   437                      "adminPath": "./crypto-config/ordererOrganizations/example.com/users/Admin@example.com/msp",
   438                      "comName": "example.com",
   439                      "url": "grpcs://localhost:5005",
   440                      "server-hostname": "orderer0.example.com",
   441                      "tls_cacerts": "./crypto-config/ordererOrganizations/example.com/orderers/orderer0.example.com/msp/cacerts/ca.example.com-cert.pem"
   442              },
   443              "org1": {
   444                      "name": "Org1MSP",
   445                      "mspid": "Org1MSP",
   446                      "mspPath": "./crypto-config",
   447                      "adminPath": "./crypto-config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp",
   448                      "comName": "example.com",
   449                      "ca": {
   450                           "url":"https://localhost:7054",
   451                           "name": "ca-org1"
   452                      },
   453                      "username": "admin",
   454                      "secret": "adminpw",
   455                      "peer1": {
   456                              "requests": "grpc://localhost:7061",
   457                              "events": "grpc://localhost:7051",
   458                              "server-hostname": "peer0.org1.example.com",
   459                              "tls_cacerts": "../fixtures/tls/peers/peer0/ca-cert.pem"
   460                      },
   461                      "peer2": {
   462                              "requests": "grpc://localhost:7062",
   463                              "events": "grpc://localhost:7052",
   464                              "server-hostname": "peer1.org1.example.com",
   465                              "tls_cacerts": "../fixtures/tls/peers/peer0/ca-cert.pem"
   466                      }
   467              },
   468              "org2": {
   469                      "name": "Org2MSP",
   470                      "mspid": "Org2MSP",
   471                      "mspPath": "./crypto-config",
   472                      "adminPath": "./crypto-config/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp",
   473                      "comName": "example.com",
   474                      "ca": {
   475                           "url":"https://localhost:8054",
   476                           "name": "ca-org2"
   477                      },
   478                      "username": "admin",
   479                      "secret": "adminpw",
   480                      "peer1": {
   481                              "requests": "grpcs://localhost:7063",
   482                              "events": "grpcs://localhost:7053",
   483                              "server-hostname": "peer0.org2.example.com",
   484                              "tls_cacerts": "./crypto-config/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/msp/cacerts/ca.org2.example.com-cert.pem"
   485                      },
   486                      "peer2": {
   487                              "requests": "grpcs://localhost:7064",
   488                              "events": "grpcs://localhost:7054",
   489                              "server-hostname": "peer1.org2.example.com",
   490                              "tls_cacerts": "./crypto-config/peerOrganizations/org2.example.com/peers/peer1.org2.example.com/msp/cacerts/ca.org2.example.com-cert.pem"
   491                      }
   492              }
   493      }
   494  }
   495  ```
   496  
   497  
   498  ## Creating a local Fabric network
   499  - If you do not yet have the Fabric docker images in your local docker registry, please either build them from Fabric source or download them from dockerhub.
   500      - `cd $GOPATH/src/github.com/hyperledger/fabric/examples/e2e_cli/`
   501      - `sh ./download-dockerimages.sh -c x86_64-1.0.0-alpha2 -f x86_64-1.0.0-alpha2`
   502  - If you do not have an existing network already, you can start a network using the Fabric e2e example:
   503      - `cd $GOPATH/src/github.com/hyperledger/fabric/examples/e2e_cli/`
   504      - Edit `network_setup.sh` and change **COMPOSE_FILE**:
   505          ```
   506          #COMPOSE_FILE=docker-compose-cli.yaml
   507          COMPOSE_FILE=docker-compose-e2e.yaml
   508          ```
   509      - `./network_setup.sh up`
   510  - Alternatively, consider using the [NetworkLauncher](https://github.com/dongmingh/v1Launcher) tool:
   511      - `cd $GOPATH/src/github.com/hyperledger/fabric-sdk-node/test`
   512      - `git clone https://github.com/dongmingh/v1Launcher`
   513      - `cd v1Launcher`
   514      - `./NetworkLauncher.sh -?`
   515  
   516  
   517  ---
   518  
   519  <a rel="license" href="http://creativecommons.org/licenses/by/4.0/"><img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by/4.0/88x31.png" /></a><br />This work is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by/4.0/">Creative Commons Attribution 4.0 International License</a>.