title: How to query Hyperledger Fabric Go Chaincode by using the node.js SDK and TLS?
body: <p>I created my own Hyperledger Fabric which is up and running. I also installed the Fabcar Sample Chaincode given by the "Writting Your First Application Tutorial" on <a href="http://hyperledger-fabric.readthedocs.io/en/release/write_first_app.html" rel="nofollow noreferrer">http://hyperledger-fabric.readthedocs.io/en/release/write_first_app.html</a>. I also started the Fabcar Sample Network (as described in the First Application Tutorial) and I was able to start the node.js JavaScript Files which help to create an Admin, an User and to query the ledger or even invoke the chaincode.</p>
  
  <p>Now I would like to do all these things with my own network. So I used the node.js files (admin.js, query.js, etc.) given by the tutorial as basis.</p>
  
  <p>BUT:</p>
  
  <p>The network I created uses TLS, the tutorial network does not. Although I was able to create the Admin and User account (just by using https instead of http), I have trouble to query (not even invoke) the chaincode on the ledger. I figured out, that I have to use grpcs instead of grpc and that I  have to provide the certificate pem file in order to be able to establish the connection. I tried so, but I got this error:</p>
  
  <pre><code>Store path:/home/artur/network-
  projects/firstNetworkStepByStep/frontend/hfc-key-store
  Successfully loaded user1 from persistence
  E0220 00:03:25.937319415   31717 ssl_transport_security.c:584] Could not load any root certificate.
  E0220 00:03:25.937350289   31717 ssl_transport_security.c:1297] Cannot load server root certificates.
  E0220 00:03:25.937362437   31717 security_connector.c:857]   Handshaker factory creation failed with TSI_INVALID_ARGUMENT.
  E0220 00:03:25.937368116   31717 secure_channel_create.c:112] Failed to create secure subchannel for secure name 'localhost:7051'
  E0220 00:03:25.937372606   31717 secure_channel_create.c:143] Failed to create subchannel arguments during subchannel creation.
  </code></pre>
  
  <p>I tried to provide different kind of pem file TLS certificates which I generated at the beginning of building my network by using the cryptogen tool provided by Hyperledger Fabic, but none of these worked. I used only the pem files in the crypto-config folder for my peer1, since I installed and instantiated the chaincode only on this peer and would like to query only this peer for test purposes first. </p>
  
  <p>So my questions are:</p>
  
  <ol>
  <li><p>Which of the all these pem TLS certificates which were generated for the organisation do I have to provide to the Hyperledger Fabric node.js SDK, when I used the Admin of my Org1, wich successfully enrolled the user User1, in order to just query the ledger?</p></li>
  <li><p>Is there a specific place where I have to put this certificate or do I specify the absolute path to the certificate in my JavaScript?</p></li>
  </ol>
  
  <p>Here is my node.js JavScript code snippet which is called:</p>
  
  <pre><code> var Fabric_Client = require('fabric-client');
      var path = require('path');
      var util = require('util');
      var os = require('os');
  
      var fabric_client = new Fabric_Client();
  
      // setup the fabric network
      var channel = fabric_client.newChannel('mychannel');
      //without tls pem certificate:
      //var peer = fabric_client.newPeer('grpcs://localhost:7051');
  
      var tls_cert_path = path.join(__dirname, 'tls_cert', 'tlsca.org1.example.com-cert.pem');
  
      console.log('tls_cert_path:' + tls_cert_path);
  
      //var peer = fabric_client.newPeer('grpcs://localhost:7051');
      var peer = fabric_client.newPeer('grpcs://localhost:7051',{pem: tls_cert_path});
  
      channel.addPeer(peer);
  
      //
      var member_user = null;
      var store_path = path.join(__dirname, 'hfc-key-store');
      console.log('Store path:'+store_path);
      var tx_id = null;
  
      // create the key value store as defined in the fabric-client/config/default.json 'key-value-store' setting
      Fabric_Client.newDefaultKeyValueStore({ path: store_path
      }).then((state_store) =&gt; {
          // assign the store to the fabric client
          fabric_client.setStateStore(state_store);
          var crypto_suite = Fabric_Client.newCryptoSuite();
          // use the same location for the state store (where the users' certificate are kept)
          // and the crypto store (where the users' keys are kept)
          var crypto_store = Fabric_Client.newCryptoKeyStore({path: store_path});
          crypto_suite.setCryptoKeyStore(crypto_store);
          fabric_client.setCryptoSuite(crypto_suite);
  
          // get the enrolled user from persistence, this user will sign all requests
          return fabric_client.getUserContext('user1', true);
      }).then((user_from_store) =&gt; {
          if (user_from_store &amp;&amp; user_from_store.isEnrolled()) {
              console.log('Successfully loaded user1 from persistence');
              member_user = user_from_store;
          } else {
              throw new Error('Failed to get user1.... run registerUser.js');
          }
  
          // queryCar chaincode function - requires 1 argument, ex: args: ['CAR4'],
          // queryAllCars chaincode function - requires no arguments , ex: args: [''],
          const request = {
              //targets : --- letting this default to the peers assigned to the channel
              chaincodeId: 'mycc',
              fcn: 'query',
              args: ['a']
          };
  
          // send the query proposal to the peer
          return channel.queryByChaincode(request);
      }).then((query_responses) =&gt; {
          console.log("Query has completed, checking results");
          // query_responses could have more than one  results if there multiple peers were used as targets
          if (query_responses &amp;&amp; query_responses.length == 1) {
              if (query_responses[0] instanceof Error) {
                  console.error("error from query = ", query_responses[0]);
              } else {
                  console.log("Response is ", query_responses[0].toString());
              }
          } else {
              console.log("No payloads were returned from query");
          }
      }).catch((err) =&gt; {
          console.error('Failed to query successfully :: ' + err);
      });
  </code></pre>
  
  <p>Any ideas or suggestions?</p>
  
  <p><strong>EDIT 2018.02.21 09:22 CET: Added crypto-config.yaml and crypto.yaml source code:</strong></p>
  
  <p>crypto-config.yaml:</p>
  
  <pre><code>OrdererOrgs:
    - Name: Orderer
      Domain: example.com
      Specs:
        - Hostname: orderer
  
  PeerOrgs:
    - Name: Org1
      Domain: org1.example.com    
      Template:
        Count: 2
      Users:
        Count: 1
  
    - Name: Org2
      Domain: org2.example.com
      Template:
        Count: 2
      Users:
        Count: 1
  
    - Name: Org3
      Domain: org3.example.com
      Template:
        Count: 2
      Users:
        Count: 1
  </code></pre>
  
  <p>configtx.yaml:</p>
  
  <pre><code>Profiles:        
      TwoOrgsOrdererGenesis:
          Orderer:
              &lt;&lt;: *OrdererDefaults
              Organizations:
                  - *OrdererOrg
          Consortiums:
              SampleConsortium:
                  Organizations:
                      - *Org1
                      - *Org2
                      - *Org3
      TwoOrgsChannel:
          Consortium: SampleConsortium
          Application:
              &lt;&lt;: *ApplicationDefaults
              Organizations:
                  - *Org1
                  - *Org2
                  - *Org3
  
  Organizations:
  
      - &amp;OrdererOrg
          Name: OrdererOrg
          ID: OrdererMSP
          MSPDir: crypto-config/ordererOrganizations/example.com/msp
  
      - &amp;Org1
          Name: Org1MSP
          ID: Org1MSP
          MSPDir: crypto-config/peerOrganizations/org1.example.com/msp
  
          AnchorPeers:
              - Host: peer0.org1.example.com
                Port: 7051
  
      - &amp;Org2
          Name: Org2MSP
          ID: Org2MSP
          MSPDir: crypto-config/peerOrganizations/org2.example.com/msp
  
          AnchorPeers:
              - Host: peer0.org2.example.com
                Port: 7051
  
      - &amp;Org3
          Name: Org3MSP
          ID: Org3MSP
  
          MSPDir: crypto-config/peerOrganizations/org3.example.com/msp
  
          AnchorPeers:
              - Host: peer0.org3.example.com
                Port: 7051
  
  Orderer: &amp;OrdererDefaults
  
      OrdererType: solo
  
      Addresses:
          - orderer.example.com:7050
  
      BatchTimeout: 2s
      BatchSize:
          MaxMessageCount: 10
          AbsoluteMaxBytes: 99 MB
         PreferredMaxBytes: 512 KB
  
      Kafka:
          Brokers:
              - 127.0.0.1:9092
  
      Organizations:
  
  Application: &amp;ApplicationDefaults
  
      Organizations:
  </code></pre>
  
  <p><strong>EDIT 2018.02.21 13:14 CET: Added docker compose file:</strong></p>
  
  <pre><code># Copyright IBM Corp. All Rights Reserved.
  #
  # SPDX-License-Identifier: Apache-2.0
  #
  
  version: '2'
  
  networks:
    byfn:
  
  services:
  
    ca0:
      image: hyperledger/fabric-ca
      environment:
        - FABRIC_CA_HOME=/etc/hyperledger/fabric-ca-server
        - FABRIC_CA_SERVER_CA_NAME=ca.org1.example.com
        - FABRIC_CA_SERVER_TLS_ENABLED=true
        - FABRIC_CA_SERVER_TLS_CERTFILE=/etc/hyperledger/fabric-ca-server-config/ca.org1.example.com-cert.pem
        - FABRIC_CA_SERVER_TLS_KEYFILE=/etc/hyperledger/fabric-ca-server-config/${CA_KEY_ORG1}
      ports:
        - "7054:7054"
      command: sh -c 'fabric-ca-server start --ca.certfile /etc/hyperledger/fabric-ca-server-config/ca.org1.example.com-cert.pem --ca.keyfile /etc/hyperledger/fabric-ca-server-config/${CA_KEY_ORG1} -b adminorg1:adminpworg1 -d'
      volumes:
        - ./crypto-config/peerOrganizations/org1.example.com/ca/:/etc/hyperledger/fabric-ca-server-config
      container_name: ca.org1.example.com
      networks:
        - byfn
  
    ca1:
      image: hyperledger/fabric-ca
      environment:
        - FABRIC_CA_HOME=/etc/hyperledger/fabric-ca-server
        - FABRIC_CA_SERVER_CA_NAME=ca.org2.example.com
        - FABRIC_CA_SERVER_TLS_ENABLED=true
        - FABRIC_CA_SERVER_TLS_CERTFILE=/etc/hyperledger/fabric-ca-server-config/ca.org2.example.com-cert.pem
        - FABRIC_CA_SERVER_TLS_KEYFILE=/etc/hyperledger/fabric-ca-server-config/${CA_KEY_ORG2}
      ports:
        - "8054:7054"
      command: sh -c 'fabric-ca-server start --ca.certfile /etc/hyperledger/fabric-ca-server-config/ca.org2.example.com-cert.pem --ca.keyfile /etc/hyperledger/fabric-ca-server-config/${CA_KEY_ORG2} -b adminorg2:adminpworg2 -d'
      volumes:
        - ./crypto-config/peerOrganizations/org2.example.com/ca/:/etc/hyperledger/fabric-ca-server-config
      container_name: ca.org2.example.com
      networks:
        - byfn 
  
    ca2:
      image: hyperledger/fabric-ca
      environment:
        - FABRIC_CA_HOME=/etc/hyperledger/fabric-ca-server
        - FABRIC_CA_SERVER_CA_NAME=ca.org3.example.com
        - FABRIC_CA_SERVER_TLS_ENABLED=true
        - FABRIC_CA_SERVER_TLS_CERTFILE=/etc/hyperledger/fabric-ca-server-config/ca.org3.example.com-cert.pem
        - FABRIC_CA_SERVER_TLS_KEYFILE=/etc/hyperledger/fabric-ca-server-config/${CA_KEY_ORG3}
      ports:
        - "9054:7054"
      command: sh -c 'fabric-ca-server start --ca.certfile /etc/hyperledger/fabric-ca-server-config/ca.org3.example.com-cert.pem --ca.keyfile /etc/hyperledger/fabric-ca-server-config/${CA_KEY_ORG3} -b adminorg3:adminpworg3 -d'
      volumes:
        - ./crypto-config/peerOrganizations/org3.example.com/ca/:/etc/hyperledger/fabric-ca-server-config
      container_name: ca.org3.example.com
      networks:
        - byfn
  
    orderer.example.com:
      networks:
        - byfn
      container_name: orderer.example.com
      image: hyperledger/fabric-orderer
      environment:
        - ORDERER_GENERAL_LOGLEVEL=debug
        - ORDERER_GENERAL_LISTENADDRESS=0.0.0.0
        - ORDERER_GENERAL_GENESISMETHOD=file
        - ORDERER_GENERAL_GENESISFILE=/var/hyperledger/orderer/orderer.genesis.block
        - ORDERER_GENERAL_LOCALMSPID=OrdererMSP
        - ORDERER_GENERAL_LOCALMSPDIR=/var/hyperledger/orderer/msp
        # enabled TLS
        - ORDERER_GENERAL_TLS_ENABLED=true
        - ORDERER_GENERAL_TLS_PRIVATEKEY=/var/hyperledger/orderer/tls/server.key
        - ORDERER_GENERAL_TLS_CERTIFICATE=/var/hyperledger/orderer/tls/server.crt
        - ORDERER_GENERAL_TLS_ROOTCAS=[/var/hyperledger/orderer/tls/ca.crt]
      working_dir: /opt/gopath/src/github.com/hyperledger/fabric
      command: orderer
      #command: tail -f /dev/null
      volumes:
      - ./channel-artifacts/genesis.block:/var/hyperledger/orderer/orderer.genesis.block
      - ./crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/msp:/var/hyperledger/orderer/msp
      - ./crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/tls/:/var/hyperledger/orderer/tls
      ports:
        - 7050:7050
  
    peer0.org1.example.com:
      networks:
        - byfn
      container_name: peer0.org1.example.com
      extends:
        file: peer-base.yaml
        service: peer-base
      environment:
        - CORE_PEER_ID=peer0.org1.example.com
        - CORE_PEER_ADDRESS=peer0.org1.example.com:7051
        - CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer0.org1.example.com:7051
        - CORE_PEER_LOCALMSPID=Org1MSP
  
        - CORE_LEDGER_STATE_STATEDATABASE=CouchDB
        - CORE_LEDGER_STATE_COUCHDBCONFIG_COUCHDBADDRESS=couchdb0:5984
        # The CORE_LEDGER_STATE_COUCHDBCONFIG_USERNAME and CORE_LEDGER_STATE_COUCHDBCONFIG_PASSWORD
        # provide the credentials for ledger to connect to CouchDB.  The username and password must
        # match the username and password set for the associated CouchDB.
        - CORE_LEDGER_STATE_COUCHDBCONFIG_USERNAME=
        - CORE_LEDGER_STATE_COUCHDBCONFIG_PASSWORD=
      depends_on:
        - couchdb0
      volumes:
          - /var/run/:/host/var/run/
          - ./crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/msp:/etc/hyperledger/fabric/msp
          - ./crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls:/etc/hyperledger/fabric/tls
      ports:
        - 7051:7051
        - 7053:7053
  
    couchdb0:
      container_name: couchdb0
      image: hyperledger/fabric-couchdb
      # Populate the COUCHDB_USER and COUCHDB_PASSWORD to set an admin user and password
      # for CouchDB.  This will prevent CouchDB from operating in an "Admin Party" mode.
      environment:
        - COUCHDB_USER=
        - COUCHDB_PASSWORD=
      # Comment/Uncomment the port mapping if you want to hide/expose the CouchDB service,
      # for example map it to utilize Fauxton User Interface in dev environments.
      ports:
        - "5984:5984"
      networks:
        - byfn
  
    peer1.org1.example.com:
      networks:
        - byfn
      container_name: peer1.org1.example.com
      extends:
        file: peer-base.yaml
        service: peer-base
      environment:
        - CORE_PEER_ID=peer1.org1.example.com
        - CORE_PEER_ADDRESS=peer1.org1.example.com:7051
        - CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer1.org1.example.com:7051
        - CORE_PEER_GOSSIP_BOOTSTRAP=peer0.org1.example.com:7051
        - CORE_PEER_LOCALMSPID=Org1MSP
  
        - CORE_LEDGER_STATE_STATEDATABASE=CouchDB
        - CORE_LEDGER_STATE_COUCHDBCONFIG_COUCHDBADDRESS=couchdb1:5984
        # The CORE_LEDGER_STATE_COUCHDBCONFIG_USERNAME and CORE_LEDGER_STATE_COUCHDBCONFIG_PASSWORD
        # provide the credentials for ledger to connect to CouchDB.  The username and password must
        # match the username and password set for the associated CouchDB.
        - CORE_LEDGER_STATE_COUCHDBCONFIG_USERNAME=
        - CORE_LEDGER_STATE_COUCHDBCONFIG_PASSWORD=
      depends_on:
        - couchdb1
      volumes:
          - /var/run/:/host/var/run/
          - ./crypto-config/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/msp:/etc/hyperledger/fabric/msp
          - ./crypto-config/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/tls:/etc/hyperledger/fabric/tls
  
      ports:
        - 8051:7051
        - 8053:7053
  
    couchdb1:
      container_name: couchdb1
      image: hyperledger/fabric-couchdb
      # Populate the COUCHDB_USER and COUCHDB_PASSWORD to set an admin user and password
      # for CouchDB.  This will prevent CouchDB from operating in an "Admin Party" mode.
      environment:
        - COUCHDB_USER=
        - COUCHDB_PASSWORD=
      # Comment/Uncomment the port mapping if you want to hide/expose the CouchDB service,
      # for example map it to utilize Fauxton User Interface in dev environments.
      ports:
        - "6984:5984"
      networks:
        - byfn
  
    peer0.org2.example.com:
      container_name: peer0.org2.example.com
      extends:
        file: peer-base.yaml
        service: peer-base
      environment:
        - CORE_PEER_ID=peer0.org2.example.com
        - CORE_PEER_ADDRESS=peer0.org2.example.com:7051
        - CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer0.org2.example.com:7051
        - CORE_PEER_GOSSIP_BOOTSTRAP=peer0.org2.example.com:7051
        - CORE_PEER_LOCALMSPID=Org2MSP
  
        - CORE_LEDGER_STATE_STATEDATABASE=CouchDB
        - CORE_LEDGER_STATE_COUCHDBCONFIG_COUCHDBADDRESS=couchdb2:5984
        # The CORE_LEDGER_STATE_COUCHDBCONFIG_USERNAME and CORE_LEDGER_STATE_COUCHDBCONFIG_PASSWORD
        # provide the credentials for ledger to connect to CouchDB.  The username and password must
        # match the username and password set for the associated CouchDB.
        - CORE_LEDGER_STATE_COUCHDBCONFIG_USERNAME=
        - CORE_LEDGER_STATE_COUCHDBCONFIG_PASSWORD=
      depends_on:
        - couchdb2
      volumes:
          - /var/run/:/host/var/run/
          - ./crypto-config/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/msp:/etc/hyperledger/fabric/msp
          - ./crypto-config/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls:/etc/hyperledger/fabric/tls
      ports:
        - 9051:7051
        - 9053:7053
      networks:
        - byfn
  
    couchdb2:
      container_name: couchdb2
      image: hyperledger/fabric-couchdb
      # Populate the COUCHDB_USER and COUCHDB_PASSWORD to set an admin user and password
      # for CouchDB.  This will prevent CouchDB from operating in an "Admin Party" mode.
      environment:
        - COUCHDB_USER=
        - COUCHDB_PASSWORD=
      # Comment/Uncomment the port mapping if you want to hide/expose the CouchDB service,
      # for example map it to utilize Fauxton User Interface in dev environments.
      ports:
        - "7984:5984"
      networks:
        - byfn
  
    peer1.org2.example.com:
      container_name: peer1.org2.example.com
      extends:
        file: peer-base.yaml
        service: peer-base
      environment:
        - CORE_PEER_ID=peer1.org2.example.com
        - CORE_PEER_ADDRESS=peer1.org2.example.com:7051
        - CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer1.org2.example.com:7051
        - CORE_PEER_GOSSIP_BOOTSTRAP=peer1.org2.example.com:7051
        - CORE_PEER_LOCALMSPID=Org2MSP
  
        - CORE_LEDGER_STATE_STATEDATABASE=CouchDB
        - CORE_LEDGER_STATE_COUCHDBCONFIG_COUCHDBADDRESS=couchdb3:5984
        # The CORE_LEDGER_STATE_COUCHDBCONFIG_USERNAME and CORE_LEDGER_STATE_COUCHDBCONFIG_PASSWORD
        # provide the credentials for ledger to connect to CouchDB.  The username and password must
        # match the username and password set for the associated CouchDB.
        - CORE_LEDGER_STATE_COUCHDBCONFIG_USERNAME=
        - CORE_LEDGER_STATE_COUCHDBCONFIG_PASSWORD=
      depends_on:
        - couchdb3
      volumes:
          - /var/run/:/host/var/run/
          - ./crypto-config/peerOrganizations/org2.example.com/peers/peer1.org2.example.com/msp:/etc/hyperledger/fabric/msp
          - ./crypto-config/peerOrganizations/org2.example.com/peers/peer1.org2.example.com/tls:/etc/hyperledger/fabric/tls
      ports:
        - 10051:7051
        - 10053:7053
      networks:
        - byfn
  
    couchdb3:
      container_name: couchdb3
      image: hyperledger/fabric-couchdb
      # Populate the COUCHDB_USER and COUCHDB_PASSWORD to set an admin user and password
      # for CouchDB.  This will prevent CouchDB from operating in an "Admin Party" mode.
      environment:
        - COUCHDB_USER=
        - COUCHDB_PASSWORD=
      # Comment/Uncomment the port mapping if you want to hide/expose the CouchDB service,
      # for example map it to utilize Fauxton User Interface in dev environments.
      ports:
        - "8984:5984"
      networks:
        - byfn
  
    peer0.org3.example.com:
      container_name: peer0.org3.example.com
      extends:
        file: peer-base.yaml
        service: peer-base
      environment:
        - CORE_PEER_ID=peer0.org3.example.com
        - CORE_PEER_ADDRESS=peer0.org3.example.com:7051
        - CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer0.org3.example.com:7051
        - CORE_PEER_GOSSIP_BOOTSTRAP=peer0.org3.example.com:7051
        - CORE_PEER_LOCALMSPID=Org3MSP
  
        - CORE_LEDGER_STATE_STATEDATABASE=CouchDB
        - CORE_LEDGER_STATE_COUCHDBCONFIG_COUCHDBADDRESS=couchdb4:5984
        # The CORE_LEDGER_STATE_COUCHDBCONFIG_USERNAME and CORE_LEDGER_STATE_COUCHDBCONFIG_PASSWORD
        # provide the credentials for ledger to connect to CouchDB.  The username and password must
        # match the username and password set for the associated CouchDB.
        - CORE_LEDGER_STATE_COUCHDBCONFIG_USERNAME=
        - CORE_LEDGER_STATE_COUCHDBCONFIG_PASSWORD=
      depends_on:
        - couchdb4
      volumes:
          - /var/run/:/host/var/run/
          - ./crypto-config/peerOrganizations/org3.example.com/peers/peer0.org3.example.com/msp:/etc/hyperledger/fabric/msp
          - ./crypto-config/peerOrganizations/org3.example.com/peers/peer0.org3.example.com/tls:/etc/hyperledger/fabric/tls
      ports:
        - 11051:7051
        - 11053:7053
      networks:
        - byfn
  
    couchdb4:
      container_name: couchdb4
      image: hyperledger/fabric-couchdb
      # Populate the COUCHDB_USER and COUCHDB_PASSWORD to set an admin user and password
      # for CouchDB.  This will prevent CouchDB from operating in an "Admin Party" mode.
      environment:
        - COUCHDB_USER=
        - COUCHDB_PASSWORD=
      # Comment/Uncomment the port mapping if you want to hide/expose the CouchDB service,
      # for example map it to utilize Fauxton User Interface in dev environments.
      ports:
        - "9984:5984"
      networks:
        - byfn
  
    peer1.org3.example.com:
      container_name: peer1.org3.example.com
      extends:
        file: peer-base.yaml
        service: peer-base
      environment:
        - CORE_PEER_ID=peer1.org3.example.com
        - CORE_PEER_ADDRESS=peer1.org3.example.com:7051
        - CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer1.org3.example.com:7051
        - CORE_PEER_GOSSIP_BOOTSTRAP=peer1.org3.example.com:7051
        - CORE_PEER_LOCALMSPID=Org3MSP
  
        - CORE_LEDGER_STATE_STATEDATABASE=CouchDB
        - CORE_LEDGER_STATE_COUCHDBCONFIG_COUCHDBADDRESS=couchdb5:5984
        # The CORE_LEDGER_STATE_COUCHDBCONFIG_USERNAME and CORE_LEDGER_STATE_COUCHDBCONFIG_PASSWORD
        # provide the credentials for ledger to connect to CouchDB.  The username and password must
        # match the username and password set for the associated CouchDB.
        - CORE_LEDGER_STATE_COUCHDBCONFIG_USERNAME=
        - CORE_LEDGER_STATE_COUCHDBCONFIG_PASSWORD=
      depends_on:
        - couchdb5
      volumes:
          - /var/run/:/host/var/run/
          - ./crypto-config/peerOrganizations/org3.example.com/peers/peer1.org3.example.com/msp:/etc/hyperledger/fabric/msp
          - ./crypto-config/peerOrganizations/org3.example.com/peers/peer1.org3.example.com/tls:/etc/hyperledger/fabric/tls
      ports:
        - 12051:7051
        - 12053:7053
      networks:
        - byfn
  
    couchdb5:
      container_name: couchdb5
      image: hyperledger/fabric-couchdb
      # Populate the COUCHDB_USER and COUCHDB_PASSWORD to set an admin user and password
      # for CouchDB.  This will prevent CouchDB from operating in an "Admin Party" mode.
      environment:
        - COUCHDB_USER=
        - COUCHDB_PASSWORD=
      # Comment/Uncomment the port mapping if you want to hide/expose the CouchDB service,
      # for example map it to utilize Fauxton User Interface in dev environments.
      ports:
        - "10984:5984"
      networks:
        - byfn
  
    cli:
      container_name: cli
      image: hyperledger/fabric-tools
      tty: true
      environment:
        - GOPATH=/opt/gopath
        - CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
        - CORE_LOGGING_LEVEL=DEBUG
        - CORE_PEER_ID=cli
        - CORE_PEER_ADDRESS=peer0.org1.example.com:7051
        - CORE_PEER_LOCALMSPID=Org1MSP
        - CORE_PEER_TLS_ENABLED=true
        - CORE_PEER_TLS_CERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/server.crt
        - CORE_PEER_TLS_KEY_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/server.key
        - CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
        - CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
      working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer
      #command: /bin/bash -c './scripts/arphi.sh; sleep infinity'
      #command: /bin/bash -c './scripts/script.sh ${CHANNEL_NAME} ${DELAY}; sleep $TIMEOUT'
      #command: tail -f /dev/null
      volumes:
          - /var/run/:/host/var/run/
          - ./../chaincode/:/opt/gopath/src/github.com/hyperledger/fabric/examples/chaincode/go
          - ./crypto-config:/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/
          - ./scripts:/opt/gopath/src/github.com/hyperledger/fabric/peer/scripts/
          - ./channel-artifacts:/opt/gopath/src/github.com/hyperledger/fabric/peer/channel-artifacts
      depends_on:
        - orderer.example.com
        - peer0.org1.example.com
        - peer1.org1.example.com
        - peer0.org2.example.com
        - peer1.org2.example.com
        - peer0.org3.example.com
        - peer1.org3.example.com
      networks:
        - byfn
  </code></pre>