Full Code of securekey/fabric-examples for AI

master 600b6db41b10 cached
63 files
310.4 KB
91.8k tokens
735 symbols
1 requests
Download .txt
Showing preview only (331K chars total). Download the full file or copy to clipboard to get everything.
Repository: securekey/fabric-examples
Branch: master
Commit: 600b6db41b10
Files: 63
Total size: 310.4 KB

Directory structure:
gitextract_8xm2cptt/

├── .gitignore
├── .gitreview
├── README.md
└── fabric-cli/
    ├── .gitignore
    ├── LICENSE
    ├── Makefile
    ├── README.md
    ├── cmd/
    │   └── fabric-cli/
    │       ├── action/
    │       │   ├── action.go
    │       │   └── svcproviderfactory.go
    │       ├── chaincode/
    │       │   ├── chaincodecmd.go
    │       │   ├── getinfocmd.go
    │       │   ├── installcmd.go
    │       │   ├── instantiatecmd.go
    │       │   ├── invokecmd.go
    │       │   ├── invokeerror/
    │       │   │   └── invokeerror.go
    │       │   ├── invoketask/
    │       │   │   └── invoketask.go
    │       │   ├── multitask/
    │       │   │   └── multitask.go
    │       │   ├── querycmd.go
    │       │   ├── querytask/
    │       │   │   └── querytask.go
    │       │   ├── task/
    │       │   │   └── task.go
    │       │   ├── upgradecmd.go
    │       │   └── utils/
    │       │       ├── test.json
    │       │       ├── util.go
    │       │       └── util_test.go
    │       ├── channel/
    │       │   ├── channelcmd.go
    │       │   ├── channelcreatecmd.go
    │       │   └── channeljoincmd.go
    │       ├── cmd/
    │       │   └── fabric-cli.go
    │       ├── config/
    │       │   └── config.go
    │       ├── event/
    │       │   ├── eventcmd.go
    │       │   ├── inputevent.go
    │       │   ├── listenblockcmd.go
    │       │   ├── listencccmd.go
    │       │   ├── listenfilteredblockcmd.go
    │       │   └── listentxcmd.go
    │       ├── executor/
    │       │   ├── executor.go
    │       │   └── worker/
    │       │       ├── worker.go
    │       │       └── workerpool.go
    │       ├── fabric-cli.go
    │       ├── go.mod
    │       ├── go.sum
    │       ├── printer/
    │       │   ├── blockprinter.go
    │       │   ├── formatter.go
    │       │   ├── printer.go
    │       │   ├── protoutils.go
    │       │   └── writer.go
    │       └── query/
    │           ├── queryblockcmd.go
    │           ├── querychannelscmd.go
    │           ├── querycmd.go
    │           ├── queryinfocmd.go
    │           ├── queryinstalledcmd.go
    │           ├── querylocalpeerscmd.go
    │           ├── querypeerscmd.go
    │           └── querytxcmd.go
    └── test/
        ├── fixtures/
        │   ├── config/
        │   │   ├── config_test_local.yaml
        │   │   └── pvtdatacollection.json
        │   └── testdata/
        │       └── src/
        │           ├── github.com/
        │           │   └── securekey/
        │           │       ├── example2_cc/
        │           │       │   └── example2_cc.go
        │           │       └── example_cc/
        │           │           └── example_cc.go
        │           ├── go.mod
        │           └── go.sum
        └── integration/
            ├── fabric-cli_test.go
            ├── go.mod
            └── go.sum

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
#
# Copyright SecureKey Technologies Inc. All Rights Reserved.
#
# SPDX-License-Identifier: Apache-2.0
#
*.db
*report.xml
.DS_Store
.vscode
debug.test
vendor/
.idea/
/fabric-cli/cmd/fabric-cli/fabric-cli


================================================
FILE: .gitreview
================================================
[gerrit]
host=gerrit.securekey.com
port=29418
project=fabric-examples


================================================
FILE: README.md
================================================
fabric-examples


================================================
FILE: fabric-cli/.gitignore
================================================
#
# Copyright SecureKey Technologies Inc. All Rights Reserved.
#
# SPDX-License-Identifier: Apache-2.0
#
vendor/
fabric-sdk-go/


================================================
FILE: fabric-cli/LICENSE
================================================
                                 Apache License
                           Version 2.0, January 2004
                        http://www.apache.org/licenses/

   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

   1. Definitions.

      "License" shall mean the terms and conditions for use, reproduction,
      and distribution as defined by Sections 1 through 9 of this document.

      "Licensor" shall mean the copyright owner or entity authorized by
      the copyright owner that is granting the License.

      "Legal Entity" shall mean the union of the acting entity and all
      other entities that control, are controlled by, or are under common
      control with that entity. For the purposes of this definition,
      "control" means (i) the power, direct or indirect, to cause the
      direction or management of such entity, whether by contract or
      otherwise, or (ii) ownership of fifty percent (50%) or more of the
      outstanding shares, or (iii) beneficial ownership of such entity.

      "You" (or "Your") shall mean an individual or Legal Entity
      exercising permissions granted by this License.

      "Source" form shall mean the preferred form for making modifications,
      including but not limited to software source code, documentation
      source, and configuration files.

      "Object" form shall mean any form resulting from mechanical
      transformation or translation of a Source form, including but
      not limited to compiled object code, generated documentation,
      and conversions to other media types.

      "Work" shall mean the work of authorship, whether in Source or
      Object form, made available under the License, as indicated by a
      copyright notice that is included in or attached to the work
      (an example is provided in the Appendix below).

      "Derivative Works" shall mean any work, whether in Source or Object
      form, that is based on (or derived from) the Work and for which the
      editorial revisions, annotations, elaborations, or other modifications
      represent, as a whole, an original work of authorship. For the purposes
      of this License, Derivative Works shall not include works that remain
      separable from, or merely link (or bind by name) to the interfaces of,
      the Work and Derivative Works thereof.

      "Contribution" shall mean any work of authorship, including
      the original version of the Work and any modifications or additions
      to that Work or Derivative Works thereof, that is intentionally
      submitted to Licensor for inclusion in the Work by the copyright owner
      or by an individual or Legal Entity authorized to submit on behalf of
      the copyright owner. For the purposes of this definition, "submitted"
      means any form of electronic, verbal, or written communication sent
      to the Licensor or its representatives, including but not limited to
      communication on electronic mailing lists, source code control systems,
      and issue tracking systems that are managed by, or on behalf of, the
      Licensor for the purpose of discussing and improving the Work, but
      excluding communication that is conspicuously marked or otherwise
      designated in writing by the copyright owner as "Not a Contribution."

      "Contributor" shall mean Licensor and any individual or Legal Entity
      on behalf of whom a Contribution has been received by Licensor and
      subsequently incorporated within the Work.

   2. Grant of Copyright License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      copyright license to reproduce, prepare Derivative Works of,
      publicly display, publicly perform, sublicense, and distribute the
      Work and such Derivative Works in Source or Object form.

   3. Grant of Patent License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      (except as stated in this section) patent license to make, have made,
      use, offer to sell, sell, import, and otherwise transfer the Work,
      where such license applies only to those patent claims licensable
      by such Contributor that are necessarily infringed by their
      Contribution(s) alone or by combination of their Contribution(s)
      with the Work to which such Contribution(s) was submitted. If You
      institute patent litigation against any entity (including a
      cross-claim or counterclaim in a lawsuit) alleging that the Work
      or a Contribution incorporated within the Work constitutes direct
      or contributory patent infringement, then any patent licenses
      granted to You under this License for that Work shall terminate
      as of the date such litigation is filed.

   4. Redistribution. You may reproduce and distribute copies of the
      Work or Derivative Works thereof in any medium, with or without
      modifications, and in Source or Object form, provided that You
      meet the following conditions:

      (a) You must give any other recipients of the Work or
          Derivative Works a copy of this License; and

      (b) You must cause any modified files to carry prominent notices
          stating that You changed the files; and

      (c) You must retain, in the Source form of any Derivative Works
          that You distribute, all copyright, patent, trademark, and
          attribution notices from the Source form of the Work,
          excluding those notices that do not pertain to any part of
          the Derivative Works; and

      (d) If the Work includes a "NOTICE" text file as part of its
          distribution, then any Derivative Works that You distribute must
          include a readable copy of the attribution notices contained
          within such NOTICE file, excluding those notices that do not
          pertain to any part of the Derivative Works, in at least one
          of the following places: within a NOTICE text file distributed
          as part of the Derivative Works; within the Source form or
          documentation, if provided along with the Derivative Works; or,
          within a display generated by the Derivative Works, if and
          wherever such third-party notices normally appear. The contents
          of the NOTICE file are for informational purposes only and
          do not modify the License. You may add Your own attribution
          notices within Derivative Works that You distribute, alongside
          or as an addendum to the NOTICE text from the Work, provided
          that such additional attribution notices cannot be construed
          as modifying the License.

      You may add Your own copyright statement to Your modifications and
      may provide additional or different license terms and conditions
      for use, reproduction, or distribution of Your modifications, or
      for any such Derivative Works as a whole, provided Your use,
      reproduction, and distribution of the Work otherwise complies with
      the conditions stated in this License.

   5. Submission of Contributions. Unless You explicitly state otherwise,
      any Contribution intentionally submitted for inclusion in the Work
      by You to the Licensor shall be under the terms and conditions of
      this License, without any additional terms or conditions.
      Notwithstanding the above, nothing herein shall supersede or modify
      the terms of any separate license agreement you may have executed
      with Licensor regarding such Contributions.

   6. Trademarks. This License does not grant permission to use the trade
      names, trademarks, service marks, or product names of the Licensor,
      except as required for reasonable and customary use in describing the
      origin of the Work and reproducing the content of the NOTICE file.

   7. Disclaimer of Warranty. Unless required by applicable law or
      agreed to in writing, Licensor provides the Work (and each
      Contributor provides its Contributions) on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
      implied, including, without limitation, any warranties or conditions
      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
      PARTICULAR PURPOSE. You are solely responsible for determining the
      appropriateness of using or redistributing the Work and assume any
      risks associated with Your exercise of permissions under this License.

   8. Limitation of Liability. In no event and under no legal theory,
      whether in tort (including negligence), contract, or otherwise,
      unless required by applicable law (such as deliberate and grossly
      negligent acts) or agreed to in writing, shall any Contributor be
      liable to You for damages, including any direct, indirect, special,
      incidental, or consequential damages of any character arising as a
      result of this License or out of the use or inability to use the
      Work (including but not limited to damages for loss of goodwill,
      work stoppage, computer failure or malfunction, or any and all
      other commercial damages or losses), even if such Contributor
      has been advised of the possibility of such damages.

   9. Accepting Warranty or Additional Liability. While redistributing
      the Work or Derivative Works thereof, You may choose to offer,
      and charge a fee for, acceptance of support, warranty, indemnity,
      or other liability obligations and/or rights consistent with this
      License. However, in accepting such obligations, You may act only
      on Your own behalf and on Your sole responsibility, not on behalf
      of any other Contributor, and only if You agree to indemnify,
      defend, and hold each Contributor harmless for any liability
      incurred by, or claims asserted against, such Contributor by reason
      of your accepting any such warranty or additional liability.

   END OF TERMS AND CONDITIONS

   APPENDIX: How to apply the Apache License to your work.

      To apply the Apache License to your work, attach the following
      boilerplate notice, with the fields enclosed by brackets "{}"
      replaced with your own identifying information. (Don't include
      the brackets!)  The text should be enclosed in the appropriate
      comment syntax for the file format. We also recommend that a
      file or class name and description of purpose be included on the
      same "printed page" as the copyright notice for easier
      identification within third-party archives.

   Copyright {yyyy} {name of copyright owner}

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.



================================================
FILE: fabric-cli/Makefile
================================================
#
# Copyright SecureKey Technologies Inc. All Rights Reserved.
#
# SPDX-License-Identifier: Apache-2.0
#

# Supported Targets:
#
# populate-sdk: retrieves all fabric-sdk-files required for tests
# fabric-sdk-go-pin: populates only upstream files (not included in git)
# example-network: start the example fabric network
# example-network-clean: stops any running network and cleans up the artifacts
# clean: removes all generated artifacts
#

# Tool commands (overridable)
GO_CMD             ?= go
GO_DEP_CMD         ?= dep
DOCKER_CMD         ?= docker
DOCKER_COMPOSE_CMD ?= docker-compose

# fabric-sdk-go version (overridable)
FABRIC_SDK_GO_BRANCH    ?= master
FABRIC_SDK_GO_COMMIT    ?= 8f3d32c9d1a66f88d405c9f5335870c5277f773a

# Test fixture paths
FIXTURE_DOCKERENV_PATH := fabric-sdk-go/test/fixtures/dockerenv

.PHONY: polulate-sdk
populate-sdk: fabric-sdk-go-pin fabric-sdk-go-populate

.PHONY: fabric-sdk-go-pin
fabric-sdk-go-pin:
	@echo "Pinning fabric-sdk-go ..."
	@UPSTREAM_COMMIT=$(FABRIC_SDK_GO_COMMIT) UPSTREAM_BRANCH=$(FABRIC_SDK_GO_BRANCH) scripts/fabric-sdk-go/apply_upstream.sh

.PHONY: fabric-sdk-go-populate
fabric-sdk-go-populate:
	@scripts/fabric-sdk-go/populate.sh

.PHONY: clean
clean: example-network-clean
	rm -Rf vendor
	rm -Rf fabric-sdk-go

.PHONY: example-network
example-network:
	@cd ./fabric-sdk-go && \
		make dockerenv-stable-up

.PHONY: example-network-clean
example-network-clean:
	@DOCKER_CMD=$(DOCKER_CMD) scripts/fabric-sdk-go/example-network-clean.sh


================================================
FILE: fabric-cli/README.md
================================================
# Fabric CLI Sample Application

Fabric CLI is a sample command-line interface built using Fabric SDK GO. It provides the following functionality:

Channel:

- Create - Create a channel
- Join - Join a peer to a channel

Query:

- Info - Displays information about the block, including the block height
- Block - Displays the contents of a given block
- Tx - Displays the contents of a transaction within a block
- Channels - Displays all channels for a peer
- Installed - Displays the chaincodes installed on a peer
- Peers - Displays the discovered peers on a channel
- Local Peers - Displays the discovered local peers in an org

Chaincode:

- Install - Installs chaincode
- Instantiate - Instantiates chaincode
- Upgrade - Upgrades chaincode
- Invoke - Invokes chaincode with a transaction proposal and a commit
- Query - Invokes chaincode without a commit
- Info - Retrieves details about the chaincode

Events:

- Listen Block - Listens for block events and displays the block when a new block is created
- Listen Filtered Block - Listens for filtered block events and displays the filtered block when a new block is created
- Listen TX - Listens for transaction events
- Listen CC - Listens for chaincode events for a specified chaincode

## Running

NOTE: If using Go 1.11 or 1.12, you'll need to set the following environment variable:

```bash
export GO111MODULE=on
```

Run the client:

```bash
go run fabric-cli.go <command> <sub-command> [options]
```

To display the available commands/options:

```bash
go run fabric-cli.go
```

## Compatability

This example is compatible with the following Hyperledger Fabric/SDK commit levels:

- fabric: v1.3.0, v1.4, v2.0
- fabric-sdk-go: master:33f4504ff8f169ebddd822443eadbe1bf4b96887

### Quick Tour

Start the example HLF network locally

```bash
make populate-sdk
make example-network
```

Open another shell and go to the CLI directory

```bash
cd $GOPATH/src/github.com/securekey/fabric-examples/fabric-cli/cmd/fabric-cli
```

Create channel 'orgchannel' and add anchor peers

```bash
go run fabric-cli.go channel create --cid orgchannel --txfile ../../fabric-sdk-go/test/fixtures/fabric/v1.4/channel/orgchannel.tx --config ../../test/fixtures/config/config_test_local.yaml
go run fabric-cli.go channel create --cid orgchannel --txfile ../../fabric-sdk-go/test/fixtures/fabric/v1.4/channel/orgchannelOrg1MSPanchors.tx --config ../../test/fixtures/config/config_test_local.yaml --orgid org1
go run fabric-cli.go channel create --cid orgchannel --txfile ../../fabric-sdk-go/test/fixtures/fabric/v1.4/channel/orgchannelOrg2MSPanchors.tx --config ../../test/fixtures/config/config_test_local.yaml --orgid org2
```

Join all peers to channel 'orgchannel'

```bash
go run fabric-cli.go channel join --cid orgchannel --config ../../test/fixtures/config/config_test_local.yaml
```

Install ExampleCC chaincode on all peers

```bash
go run fabric-cli.go chaincode install --ccp=github.com/securekey/example_cc --ccid=ExampleCC --v v0 --gopath ../../test/fixtures/testdata --config ../../test/fixtures/config/config_test_local.yaml
```

Instantiate ExampleCC chaincode with endorsement policy AND('Org1MSP.member','Org2MSP.member')

```bash
go run fabric-cli.go chaincode instantiate --cid orgchannel --ccp=github.com/securekey/example_cc --ccid ExampleCC --v v0 --args '{"Args":["A","1","B","2"]}' --policy "AND('Org1MSP.member','Org2MSP.member')" --config ../../test/fixtures/config/config_test_local.yaml
```

Query ExampleCC chaincode on a set of peers

```bash
go run fabric-cli.go chaincode query --cid orgchannel --ccid ExampleCC --args '{"Func":"query","Args":["A"]}' --peer localhost:7051,localhost:8051 --payload --config ../../test/fixtures/config/config_test_local.yaml
```

Listen for block events:

```bash
go run fabric-cli.go event listenblock --cid orgchannel --base64 --config ../../test/fixtures/config/config_test_local.yaml
```

Then invoke ExampleCC chaincode in another shell and observe block events in the first shell.

```bash
go run fabric-cli.go chaincode invoke --cid orgchannel --ccid=ExampleCC --args '{"Func":"move","Args":["A","B","1"]}' --peer localhost:7051,localhost:8051 --base64 --config ../../test/fixtures/config/config_test_local.yaml
```

To clean up example network artifacts run

```bash
make example-network-clean
```

To clean up all generated artifacts run

```bash
make clean
```

## CLI examples

### Channel

#### Create a channel

```bash
go run fabric-cli.go channel create --cid orgchannel --txfile ../../fabric-sdk-go/test/fixtures/fabric/v1.4/channel/orgchannel.tx --config ../../test/fixtures/config/config_test_local.yaml
```

#### Update anchor peers

```bash
go run fabric-cli.go channel create --cid orgchannel --txfile ../../fabric-sdk-go/test/fixtures/fabric/v1.4/channel/orgchannelOrg1MSPanchors.tx --orgid=org1 --config ../../test/fixtures/config/config_test_local.yaml
go run fabric-cli.go channel create --cid orgchannel --txfile ../../fabric-sdk-go/test/fixtures/fabric/v1.4/channel/orgchannelOrg2MSPanchors.tx --orgid=org2 --config ../../test/fixtures/config/config_test_local.yaml
```

#### Join a peer to a channel

```bash
go run fabric-cli.go channel join --cid orgchannel --peer localhost:7051 --config ../../test/fixtures/config/config_test_local.yaml
```

#### Join all peers in org1 to a channel

```bash
go run fabric-cli.go channel join --cid orgchannel --orgid org1 --config ../../test/fixtures/config/config_test_local.yaml
```

#### Join all peers to a channel

```bash
go run fabric-cli.go channel join --cid orgchannel --config ../../test/fixtures/config/config_test_local.yaml
```

### Query

#### Query info

```bash
go run fabric-cli.go query info --cid orgchannel --config ../../test/fixtures/config/config_test_local.yaml
```

#### Query block by block number

```bash
go run fabric-cli.go query block --cid orgchannel --num 0 --base64 --config ../../test/fixtures/config/config_test_local.yaml
```

#### Query block by hash (replace the example hash with a valid hash, e.g. using the output from query info)

```bash
go run fabric-cli.go query block --cid orgchannel --hash BNNsxK_Xyz2d3Yj2g6M2t3aOYkHCxvoPeIGmTWdOJ9w --base64 --config ../../test/fixtures/config/config_test_local.yaml
```

#### Query block output in JSON format

```bash
go run fabric-cli.go query block --cid orgchannel --num 0 --format json --config ../../test/fixtures/config/config_test_local.yaml
```

#### Query transaction (replace txid with a valid transaction, e.g. using the output from query block)

```bash
go run fabric-cli.go query tx --cid orgchannel --txid 0ed409872e0e6a6aa745df10d5e71e33d7e160b84519c2ad89281e65b6561364 --base64 --config ../../test/fixtures/config/config_test_local.yaml
```

#### Query channels joined by a peer

```bash
go run fabric-cli.go query channels --peer localhost:7051 --config ../../test/fixtures/config/config_test_local.yaml
```

#### Query installed chaincodes on a peer

```bash
go run fabric-cli.go query installed --peer localhost:7051 --config ../../test/fixtures/config/config_test_local.yaml
```

#### Query discovered peers on a channel

```bash
go run fabric-cli.go query peers --cid orgchannel --config ../../test/fixtures/config/config_test_local.yaml
```

#### Query discovered peers in an org

```bash
go run fabric-cli.go query localpeers --orgid org1 --config ../../test/fixtures/config/config_test_local.yaml
```

## Chaincode

### Install Chaincode

#### Install chaincode on a peer

```bash
go run fabric-cli.go chaincode install --peer localhost:7051 --ccp=github.com/securekey/example_cc --gopath ../../test/fixtures/testdata --ccid=examplecc --v v0 --config ../../test/fixtures/config/config_test_local.yaml
```

#### Install chaincode on all peers of org1

```bash
go run fabric-cli.go chaincode install --orgid org1 --ccp=github.com/securekey/example_cc --gopath ../../test/fixtures/testdata --ccid=examplecc --v v0 --config ../../test/fixtures/config/config_test_local.yaml
```

#### Install chaincode on all peers

```bash
go run fabric-cli.go chaincode install --ccp=github.com/securekey/example_cc --gopath ../../test/fixtures/testdata --ccid=examplecc --v v0 --config ../../test/fixtures/config/config_test_local.yaml
```

### Instantiate and Upgrade Chaincode

#### Instantiate chaincode with default endorsement policy (any one)

```bash
go run fabric-cli.go chaincode instantiate --cid orgchannel --ccp github.com/securekey/example_cc --ccid examplecc --v v0 --args='{"Args":["A","1","B","2"]}' --config ../../test/fixtures/config/config_test_local.yaml
```

#### Instantiate chaincode with specified endorsement policy

```bash
go run fabric-cli.go chaincode instantiate --cid orgchannel --ccp github.com/securekey/example_cc --ccid examplecc --v v0 --args='{"Args":["A","1","B","2"]}' --policy "AND('Org1MSP.member','Org2MSP.member')" --config ../../test/fixtures/config/config_test_local.yaml
```

#### Instantiate chaincode with specified private data collection configuration (Fabric 1.2 and greater)

```bash
go run fabric-cli.go chaincode install --ccp=github.com/securekey/example2_cc --gopath ../../test/fixtures/testdata --ccid=example2cc --v v0 --config ../../test/fixtures/config/config_test_local.yaml
go run fabric-cli.go chaincode instantiate --cid orgchannel --ccp github.com/securekey/example2_cc --ccid example2cc --v v0 --policy "AND('Org1MSP.member','Org2MSP.member')" --collconfig ../../test/fixtures/config/pvtdatacollection.json --config ../../test/fixtures/config/config_test_local.yaml
```

#### Upgrade chaincode

```bash
go run fabric-cli.go chaincode install --cid=orgchannel --ccp=github.com/securekey/example_cc --gopath ../../test/fixtures/testdata --ccid=examplecc --v v1 --config ../../test/fixtures/config/config_test_local.yaml
go run fabric-cli.go chaincode upgrade --cid orgchannel --ccp github.com/securekey/example_cc --ccid examplecc --v v1 --args='{"Args":["A","1","B","2"]}' --policy "OutOf(2,'Org1MSP.member','Org2MSP.member')" --config ../../test/fixtures/config/config_test_local.yaml
```

### Chaincode Info

#### Retrieve chaincode deployment info

```bash
go run fabric-cli.go chaincode info --cid orgchannel --ccid examplecc --base64 --config ../../test/fixtures/config/config_test_local.yaml
```

### Query Chaincode

#### Query chaincode on a set of peers

```bash
go run fabric-cli.go chaincode query --cid orgchannel --ccid=examplecc --args='{"Func":"query","Args":["A"]}' --peer localhost:7051,localhost:8051 --base64 --config ../../test/fixtures/config/config_test_local.yaml
```

#### Query chaincode and view payloads only

```bash
go run fabric-cli.go chaincode query --cid orgchannel --ccid=examplecc --args='{"Func":"query","Args":["A"]}' --peer localhost:7051,localhost:8051 --payload --config ../../test/fixtures/config/config_test_local.yaml
```

### Invoke Chaincode

#### Invoke chaincode on all peers in org1

```bash
go run fabric-cli.go chaincode invoke --cid orgchannel --ccid=examplecc --args='{"Func":"move","Args":["A","B","1"]}' --orgid org1 --base64 --config ../../test/fixtures/config/config_test_local.yaml
```

#### Invoke chaincode using a 'dynamic' selection provider that chooses a minimal set of peers required to satisfy the endorsement policy of the chaincode

```bash
go run fabric-cli.go chaincode invoke --cid orgchannel --ccid=examplecc --args='{"Func":"move","Args":["A","B","1"]}' --selectprovider=dynamic --base64 --config ../../test/fixtures/config/config_test_local.yaml
```

#### Invoke chaincode using Fabric's discovery service to choose a minimal set of peers required to satisfy the endorsement policy of the chaincode (Requires Fabric >=1.2)

```bash
go run fabric-cli.go chaincode invoke --cid orgchannel --ccid=examplecc --args='{"Func":"move","Args":["A","B","1"]}' --selectprovider=fabric --base64 --config ../../test/fixtures/config/config_test_local.yaml
```

#### Invoke chaincode using a selection provider automatically determined from channel capabilities ('dynamic' for v1.1; 'fabric' for >=v1.2)

```bash
go run fabric-cli.go chaincode invoke --cid orgchannel --ccid=examplecc --args='{"Func":"move","Args":["A","B","1"]}' --base64 --config ../../test/fixtures/config/config_test_local.yaml
```

#### Invoke chaincode 5 times

```bash
go run fabric-cli.go chaincode invoke --cid orgchannel --ccid=examplecc --args='{"Func":"move","Args":["A","B","1"]}' --iterations 5 --config ../../test/fixtures/config/config_test_local.yaml
```

#### Invoke chaincode 100 times in 8 Go routines with a maximum of 5 attempts for each invocation (in case the invocation fails)

```bash
go run fabric-cli.go chaincode invoke --cid orgchannel --ccid=examplecc --args='{"Func":"move","Args":["A","B","1"]}' --iterations 100 --concurrency 8 --attempts 5 --backoff 1000 --backofffactor 1.5 --maxbackoff 5000 --config ../../test/fixtures/config/config_test_local.yaml
```

#### Invoke chaincode with two sets of args, 100 times each in 8 Go routines with 3 attempts for each invocation (in case the invocation fails)

```bash
go run fabric-cli.go chaincode invoke --cid orgchannel --ccid=examplecc --args='[{"Func":"move","Args":["A","B","1"]},{"Func":"move","Args":["B","A","1"]}]' --iterations 100 --concurrency 8 --attempts=3 --config ../../test/fixtures/config/config_test_local.yaml
```

#### Invoke chaincode 100 times in 8 Go routines using randomly generated keys, values, and variables

```bash
go run fabric-cli.go chaincode invoke --cid orgchannel --ccid=example2cc --args='[{"Func":"putprivate","Args":["$set(coll,coll1)","$set(key,Key_$rand(500))","Val_$rand(1000)"]},{"Func":"getprivate","Args":["${coll}","${key}"]}]' --iterations 100 --concurrency 8 --config ../../test/fixtures/config/config_test_local.yaml
```

#### Invoke chaincode 100 times in 8 Go routines using sequentially generated keys and large values

```bash
go run fabric-cli.go chaincode invoke --cid orgchannel --ccid=example2cc --args='{"Func":"putprivate","Args":["coll1","Key_$seq()","Val_$pad(500,X)"]}' --iterations 100 --concurrency 8 --config ../../test/fixtures/config/config_test_local.yaml
```

#### Invoke chaincode 100 times in 8 Go routines using randomly generated keys and random size values

```bash
go run fabric-cli.go chaincode invoke --cid orgchannel --ccid=example2cc --args='{"Func":"putprivate","Args":["coll1","Key_$rand(500)","Val_$pad($rand(500),X)"]}' --iterations 100 --concurrency 8 --config ../../test/fixtures/config/config_test_local.yaml
```

#### Invoke a chaincode using the contents of a file as a value

```bash
go run fabric-cli.go chaincode invoke --cid orgchannel --ccid=example2cc --args='{"Func":"put","Args":["coll1","Key_1","$file(./chaincode/utils/test.json)"]}' --config ../../test/fixtures/config/config_test_local.yaml
```

## Event

### Block Events

### Listen for block events on a specific peer (output in JSON)

```bash
go run fabric-cli.go event listenblock --cid orgchannel --peer localhost:7051 --format json --config ../../test/fixtures/config/config_test_local.yaml
```

### Listen for block events starting from block number 20

```bash
go run fabric-cli.go event listenblock --cid orgchannel --peer localhost:7051 --seek from --num 20 --base64 --config ../../test/fixtures/config/config_test_local.yaml
```

### Listen for filtered block events (output in JSON)

```bash
go run fabric-cli.go event listenfilteredblock --cid orgchannel --format json --config ../../test/fixtures/config/config_test_local.yaml
```

### Listen for chaincode events

```bash
go run fabric-cli.go event listencc --cid orgchannel --ccid=examplecc --event=.* --config ../../test/fixtures/config/config_test_local.yaml
```

### Listen for tx event

```bash
go run fabric-cli.go event listentx --cid orgchannel --txid <txid> --config ../../test/fixtures/config/config_test_local.yaml
```


================================================
FILE: fabric-cli/cmd/fabric-cli/action/action.go
================================================
/*
Copyright SecureKey Technologies Inc. All Rights Reserved.

SPDX-License-Identifier: Apache-2.0
*/

package action

import (
	"encoding/json"
	"math/rand"

	"github.com/hyperledger/fabric-sdk-go/pkg/common/providers/core"
	"github.com/hyperledger/fabric-sdk-go/pkg/fabsdk/factory/defcore"

	"github.com/pkg/errors"

	"strings"

	"io"

	"fmt"

	"github.com/hyperledger/fabric-sdk-go/pkg/client/channel"
	"github.com/hyperledger/fabric-sdk-go/pkg/client/event"
	"github.com/hyperledger/fabric-sdk-go/pkg/client/ledger"
	"github.com/hyperledger/fabric-sdk-go/pkg/client/msp"
	"github.com/hyperledger/fabric-sdk-go/pkg/client/resmgmt"
	"github.com/hyperledger/fabric-sdk-go/pkg/common/logging"
	"github.com/hyperledger/fabric-sdk-go/pkg/common/providers/context"
	"github.com/hyperledger/fabric-sdk-go/pkg/common/providers/fab"
	mspapi "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/msp"
	contextImpl "github.com/hyperledger/fabric-sdk-go/pkg/context"
	cryptosuiteimpl "github.com/hyperledger/fabric-sdk-go/pkg/core/cryptosuite/bccsp/multisuite"
	"github.com/hyperledger/fabric-sdk-go/pkg/fab/orderer"
	"github.com/hyperledger/fabric-sdk-go/pkg/fabsdk"
	cliconfig "github.com/securekey/fabric-examples/fabric-cli/cmd/fabric-cli/config"
	"github.com/securekey/fabric-examples/fabric-cli/cmd/fabric-cli/printer"
	"github.com/spf13/pflag"
)

const (
	defaultUser = "User1" // pre-enrolled user
	adminUser   = "Admin"
)

// ArgStruct is used for marshalling arguments to chaincode invocations
type ArgStruct struct {
	Func string   `json:"Func"`
	Args []string `json:"Args"`
}

// Action is the base implementation of the Action interface.
type Action struct {
	flags          *pflag.FlagSet
	sdk            *fabsdk.FabricSDK
	endpointConfig fab.EndpointConfig
	peersByOrg     map[string][]fab.Peer
	peers          []fab.Peer
	orgIDByPeer    map[string]string
	printer        printer.Printer
	initError      error
	Writer         io.Writer
	sessions       map[string]context.ClientProvider
}

// Initialize initializes the action using the given flags
func (action *Action) Initialize(flags *pflag.FlagSet) error {

	action.sessions = make(map[string]context.ClientProvider)
	action.flags = flags

	if err := cliconfig.InitConfig(flags); err != nil {
		return err
	}

	var opts []fabsdk.Option
	if cliconfig.Config().SelectionProvider() != cliconfig.AutoDetectSelectionProvider {
		svcPackage, err := newServiceProviderFactory()
		if err != nil {
			return err
		}
		opts = append(opts, fabsdk.WithServicePkg(svcPackage))
	}
	opts = append(opts, fabsdk.WithCorePkg(&cryptoSuiteProviderFactory{}))

	sdk, err := fabsdk.New(cliconfig.Provider(), opts...)
	if err != nil {
		return errors.Errorf("Error initializing SDK: %s", err)
	}
	action.sdk = sdk

	ctx, err := sdk.Context()()
	if err != nil {
		return errors.WithMessage(err, "Error creating anonymous provider")
	}

	action.endpointConfig = ctx.EndpointConfig()

	networkConfig := action.endpointConfig.NetworkConfig()

	level := levelFromName(cliconfig.Config().LoggingLevel())

	logging.SetLevel("", level)

	action.orgIDByPeer = make(map[string]string)

	var allPeers []fab.Peer
	allPeersByOrg := make(map[string][]fab.Peer)
	for orgID := range networkConfig.Organizations {
		peersConfig, ok := action.endpointConfig.PeersConfig(orgID)
		if !ok {
			return errors.Errorf("failed to get peer configs for org [%s]", orgID)
		}

		cliconfig.Config().Logger().Debugf("Peers for org [%s]: %v\n", orgID, peersConfig)

		var peers []fab.Peer
		for _, p := range peersConfig {
			endorser, err := ctx.InfraProvider().CreatePeerFromConfig(&fab.NetworkPeer{PeerConfig: p})
			if err != nil {
				return errors.Wrapf(err, "failed to create peer from config")
			}
			peers = append(peers, endorser)
			action.orgIDByPeer[endorser.URL()] = orgID
		}
		allPeersByOrg[orgID] = peers
		allPeers = append(allPeers, peers...)
	}

	if cliconfig.Config().IsLoggingEnabledFor(logging.DEBUG) {
		cliconfig.Config().Logger().Debug("All Peers:")
		for orgID, peers := range allPeersByOrg {
			cliconfig.Config().Logger().Debugf("Org: %s\n", orgID)
			for i, peer := range peers {
				cliconfig.Config().Logger().Debugf("-- Peer[%d]: MSPID: %s, URL: %s\n", i, peer.MSPID(), peer.URL())
			}
		}
	}

	// Filter peers by specified peers/orgs
	peers, err := action.getPeers(allPeers, cliconfig.Config().PeerURLs(), cliconfig.Config().OrgIDs())
	if err != nil {
		return err
	}

	// Organize peers by orgs
	peersByOrg := make(map[string][]fab.Peer)
	cliconfig.Config().Logger().Debugf("Selected Peers:\n")
	for _, peer := range peers {
		cliconfig.Config().Logger().Debugf("- URL: %s\n", peer.URL())
		orgID := action.orgIDByPeer[peer.URL()]
		if orgID == "" {
			return errors.Errorf("unable to find org for peer: %s", peer.URL())
		}
		peersByOrg[orgID] = append(peersByOrg[orgID], peer)
	}

	action.peers = peers
	action.peersByOrg = peersByOrg

	action.printer = printer.NewBlockPrinterWithOpts(
		printer.AsOutputFormat(cliconfig.Config().PrintFormat()),
		printer.AsWriterType(cliconfig.Config().Writer()),
		&printer.FormatterOpts{Base64Encode: cliconfig.Config().Base64()})

	return nil
}

// Terminate closes any open connections. This function should be called at the end of every command invocation.
func (action *Action) Terminate() {
	if action.sdk != nil {
		cliconfig.Config().Logger().Info("Closing SDK")
		action.sdk.Close()
	}
}

// Flags returns the flag-set
func (action *Action) Flags() *pflag.FlagSet {
	return action.flags
}

// EndpointConfig returns the endpoint configuration
func (action *Action) EndpointConfig() fab.EndpointConfig {
	return action.endpointConfig
}

// ChannelClient creates a new channel client
func (action *Action) ChannelClient(...channel.ClientOption) (*channel.Client, error) {
	user, err := action.User()
	if err != nil {
		return nil, errors.Errorf("error getting user: %s", err)
	}
	session, err := action.context(user)
	if err != nil {
		return nil, errors.Errorf("error getting session for user [%s,%s]: %v", user.Identifier().MSPID, user.Identifier().ID, err)
	}
	channelProvider := func() (context.Channel, error) {
		return contextImpl.NewChannel(session, cliconfig.Config().ChannelID())
	}
	return channel.New(channelProvider)
}

// OrgAdminChannelClient creates a new channel client for the given org in order to perform administrative functions
func (action *Action) OrgAdminChannelClient(orgID string) (*channel.Client, error) {
	channelID := cliconfig.Config().ChannelID()
	cliconfig.Config().Logger().Debugf("Creating new channel client for channel [%s] and org [%s] ...", channelID, orgID)

	user, err := action.OrgAdminUser(orgID)
	if err != nil {
		return nil, err
	}

	channelClient, err := action.ClientForUser(channelID, user)
	if err != nil {
		return nil, errors.Errorf("error creating fabric client: %s", err)
	}

	return channelClient, nil
}

// AdminChannelClient creates a new channel client for performing administrative functions
func (action *Action) AdminChannelClient() (*channel.Client, error) {
	return action.OrgAdminChannelClient(action.OrgID())
}

// Printer returns the Printer
func (action *Action) Printer() printer.Printer {
	return action.printer
}

// LocalContext creates a new local context
func (action *Action) LocalContext() (context.Local, error) {
	user, err := action.User()
	if err != nil {
		return nil, errors.Errorf("error getting user: %s", err)
	}
	contextProvider, err := action.context(user)
	if err != nil {
		return nil, errors.Errorf("error getting context for user [%s,%s]: %v", user.Identifier().MSPID, user.Identifier().ID, err)
	}
	return contextImpl.NewLocal(contextProvider)
}

// ChannelProvider returns the ChannelProvider
func (action *Action) ChannelProvider() (context.ChannelProvider, error) {
	channelID := cliconfig.Config().ChannelID()
	user, err := action.User()
	if err != nil {
		return nil, err
	}
	cliconfig.Config().Logger().Debugf("creating channel provider for user [%s] in org [%s]...", user.Identifier().ID, user.Identifier().MSPID)
	clientContext, err := action.context(user)
	if err != nil {
		return nil, errors.Errorf("error getting client context for user [%s,%s]: %v", user.Identifier().MSPID, user.Identifier().ID, err)
	}
	channelProvider := func() (context.Channel, error) {
		return contextImpl.NewChannel(clientContext, channelID)
	}
	return channelProvider, nil
}

// EventClient returns the event hub.
func (action *Action) EventClient(opts ...event.ClientOption) (*event.Client, error) {
	channelProvider, err := action.ChannelProvider()
	if err != nil {
		return nil, errors.Errorf("error creating channel provider: %v", err)
	}
	c, err := event.New(channelProvider, opts...)
	if err != nil {
		return nil, errors.Errorf("error creating new event client: %v", err)
	}
	return c, nil
}

// LedgerClient returns the Fabric client for the current user
func (action *Action) LedgerClient() (*ledger.Client, error) {
	channelProvider, err := action.ChannelProvider()
	if err != nil {
		return nil, errors.Errorf("error creating channel provider: %v", err)
	}
	c, err := ledger.New(channelProvider)
	if err != nil {
		return nil, errors.Errorf("error creating new ledger client: %v", err)
	}
	return c, nil
}

// Peer returns the first peer in the list of selected peers
func (action *Action) Peer() fab.Peer {
	if len(action.peers) == 0 {
		return nil
	}
	return action.peers[0]
}

// Peers returns the peers
func (action *Action) Peers() []fab.Peer {
	return action.peers
}

// PeersByOrg returns the peers mapped by organization
func (action *Action) PeersByOrg() map[string][]fab.Peer {
	return action.peersByOrg
}

// OrgOfPeer returns the organization ID of the given peer
func (action *Action) OrgOfPeer(peerURL string) (string, error) {
	orgID, ok := action.orgIDByPeer[peerURL]
	if !ok {
		return "", errors.Errorf("org not found for peer %s", peerURL)
	}
	return orgID, nil
}

// Client returns the Fabric client for the current user
func (action *Action) Client(channelID string) (*channel.Client, error) {
	user, err := action.User()
	if err != nil {
		return nil, err
	}
	return action.ClientForUser(channelID, user)
}

// ResourceMgmtClient returns a resource management client for the current user
func (action *Action) ResourceMgmtClient() (*resmgmt.Client, error) {
	return action.ResourceMgmtClientForOrg(action.OrgID())
}

// ResourceMgmtClientForOrg returns a resource management client for the given org
func (action *Action) ResourceMgmtClientForOrg(orgID string) (*resmgmt.Client, error) {
	user, err := action.OrgAdminUser(orgID)
	if err != nil {
		return nil, err
	}
	return action.ResourceMgmtClientForUser(user)
}

// ClientForUser returns the Channel client for the given user
func (action *Action) ClientForUser(channelID string, user mspapi.SigningIdentity) (*channel.Client, error) {
	cliconfig.Config().Logger().Debugf("create resmgmt client for user [%s] in org [%s]...", user.Identifier().ID, user.Identifier().MSPID)
	session, err := action.context(user)
	if err != nil {
		return nil, errors.Errorf("error getting session for user [%s,%s]: %v", user.Identifier().MSPID, user.Identifier().ID, err)
	}
	channelProvider := func() (context.Channel, error) {
		return contextImpl.NewChannel(session, channelID)
	}
	c, err := channel.New(channelProvider)
	if err != nil {
		return nil, errors.Errorf("error creating new resmgmt client for user [%s,%s]: %v", user.Identifier().MSPID, user.Identifier().ID, err)
	}
	return c, nil
}

// ResourceMgmtClientForUser returns the Fabric client for the given user
func (action *Action) ResourceMgmtClientForUser(user mspapi.SigningIdentity) (*resmgmt.Client, error) {
	cliconfig.Config().Logger().Debugf("create resmgmt client for user [%s] in org [%s]...", user.Identifier().ID, user.Identifier().MSPID)
	session, err := action.context(user)
	if err != nil {
		return nil, errors.Errorf("error getting session for user [%s,%s]: %v", user.Identifier().MSPID, user.Identifier().ID, err)
	}
	c, err := resmgmt.New(session)
	if err != nil {
		return nil, errors.Errorf("error creating new resmgmt client for user [%s,%s]: %v", user.Identifier().MSPID, user.Identifier().ID, err)
	}
	return c, nil
}

// ChannelMgmtClientForUser returns the Fabric client for the given user
func (action *Action) ChannelMgmtClientForUser(channelID string, user mspapi.SigningIdentity) (*channel.Client, error) {
	cliconfig.Config().Logger().Debugf("create channel client for user [%s] in org [%s]...", user.Identifier().ID, user.Identifier().MSPID)
	session, err := action.context(user)
	if err != nil {
		return nil, errors.Errorf("error getting session for user [%s,%s]: %v", user.Identifier().MSPID, user.Identifier().ID, err)
	}
	channelProvider := func() (context.Channel, error) {
		return contextImpl.NewChannel(session, channelID)
	}
	c, err := channel.New(channelProvider)
	if err != nil {
		return nil, errors.Errorf("error creating new channel client for user [%s,%s]: %v", user.Identifier().MSPID, user.Identifier().ID, err)
	}
	return c, nil
}

func (action *Action) context(user mspapi.SigningIdentity) (context.ClientProvider, error) {
	key := user.Identifier().MSPID + "_" + user.Identifier().ID
	session := action.sessions[key]
	if session == nil {
		session = action.sdk.Context(fabsdk.WithIdentity(user))
		cliconfig.Config().Logger().Debugf("Created session for user [%s] in org [%s]", user.Identifier().ID, user.Identifier().MSPID)
		action.sessions[key] = session
	}
	return session, nil
}

// OrgID returns the organization ID of the first peer in the list of peers
func (action *Action) OrgID() string {
	if len(action.Peers()) == 0 {
		// This shouldn't happen since we should already have passed validation
		panic("no peers to choose from!")
	}

	peer := action.Peers()[0]
	orgID, err := action.OrgOfPeer(peer.URL())
	if err != nil {
		// This shouldn't happen since we should already have passed validation
		panic(err)
	}
	return orgID
}

// GetOrgID returns the organization ID for the given MSP ID
func (action *Action) GetOrgID(mspID string) (string, error) {
	networkConfig := action.endpointConfig.NetworkConfig()

	for orgID, orgConfig := range networkConfig.Organizations {
		if mspID == orgConfig.MSPID {
			return orgID, nil
		}
	}
	return "", errors.Errorf("unable to find org ID for MSP [%s]", mspID)
}

// User returns the enrolled user. If the user doesn't exist then a new user is enrolled.
func (action *Action) User() (mspapi.SigningIdentity, error) {
	userName := cliconfig.Config().UserName()
	if userName == "" {
		userName = defaultUser
	}
	return action.OrgUser(action.OrgID(), userName)
}

func (action *Action) newUser(orgID, username, pwd string) (mspapi.SigningIdentity, error) {

	cliconfig.Config().Logger().Infof("Enrolling user %s...\n", username)

	mspClient, err := msp.New(action.sdk.Context(), msp.WithOrg(orgID))
	if err != nil {
		return nil, errors.Errorf("error creating MSP client: %s", err)
	}

	cliconfig.Config().Logger().Infof("Creating new user %s...\n", username)
	err = mspClient.Enroll(username, msp.WithSecret(pwd))
	if err != nil {
		return nil, errors.Errorf("Enroll returned error: %v", err)
	}

	user, err := mspClient.GetSigningIdentity(username)
	if err != nil {
		return nil, errors.Errorf("GetSigningIdentity returned error: %v", err)
	}

	cliconfig.Config().Logger().Infof("Returning user [%s], MSPID [%s]\n", user.Identifier().ID, user.Identifier().MSPID)

	return user, nil
}

// OrgUser returns an already enrolled user for the given organization
func (action *Action) OrgUser(orgID, username string) (mspapi.SigningIdentity, error) {
	if username == "" {
		return nil, errors.Errorf("no username specified")
	}
	mspClient, err := msp.New(action.sdk.Context(), msp.WithOrg(orgID))
	if err != nil {
		return nil, errors.Errorf("error creating MSP client: %s", err)
	}

	user, err := mspClient.GetSigningIdentity(username)
	if err != nil {
		return nil, errors.Errorf("GetSigningIdentity returned error: %v", err)
	}

	cliconfig.Config().Logger().Infof("Returning user [%s], MSPID [%s]\n", user.Identifier().ID, user.Identifier().MSPID)

	return user, nil
}

// OrgAdminUser returns the pre-enrolled administrative user for the given organization
func (action *Action) OrgAdminUser(orgID string) (mspapi.SigningIdentity, error) {
	userName := cliconfig.Config().UserName()
	if userName == "" {
		userName = adminUser
	}
	return action.OrgUser(orgID, userName)
}

// PeerFromURL returns the peer for the given URL
func (action *Action) PeerFromURL(url string) (fab.Peer, bool) {
	for _, peer := range action.peers {
		if url == peer.URL() {
			return peer, true
		}
	}
	return nil, false
}

// Orderers returns all Orderers from the set of configured Orderers
func (action *Action) Orderers() ([]fab.Orderer, error) {
	ordererConfigs := action.endpointConfig.OrderersConfig()
	ordererURL := cliconfig.Config().OrdererURL()

	var orderers []fab.Orderer
	for _, ordererConfig := range ordererConfigs {
		if ordererURL == "" || ordererConfig.URL == ordererURL {
			newOrderer, err := orderer.New(action.endpointConfig, orderer.FromOrdererConfig(&ordererConfig))
			if err != nil {
				return nil, errors.WithMessage(err, "creating orderer failed")
			}
			orderers = append(orderers, newOrderer)
		}
	}

	return orderers, nil
}

// RandomOrderer chooses a random Orderer from the set of configured Orderers
func (action *Action) RandomOrderer() (fab.Orderer, error) {
	orderers, err := action.Orderers()
	if err != nil {
		return nil, err
	}
	if len(orderers) == 0 {
		return nil, errors.New("No orders found")
	}
	return orderers[rand.Intn(len(orderers))], nil
}

// ArgsArray returns an array of args used in chaincode invocations
func ArgsArray() ([]ArgStruct, error) {
	var argsArray []ArgStruct
	argBytes := []byte(cliconfig.Config().Args())
	if strings.HasPrefix(cliconfig.Config().Args(), "[") {
		if err := json.Unmarshal(argBytes, &argsArray); err != nil {
			return nil, errors.Errorf("Error unmarshaling JSON arg string: %v", err)
		}
	} else {
		args := ArgStruct{}
		if err := json.Unmarshal(argBytes, &args); err != nil {
			return nil, errors.Errorf("Error unmarshaling JSON arg string: %v", err)
		}
		argsArray = append(argsArray, args)
	}
	return argsArray, nil
}

func levelFromName(levelName string) logging.Level {
	switch levelName {
	case "CRITICAL":
		return logging.CRITICAL
	case "ERROR":
		return logging.ERROR
	case "WARNING":
		return logging.WARNING
	case "INFO":
		return logging.INFO
	case "DEBUG":
		return logging.DEBUG
	default:
		return logging.ERROR
	}
}

func (action *Action) getPeers(allPeers []fab.Peer, peerURLs []string, orgIDs []string) ([]fab.Peer, error) {
	selectAll := false
	if len(peerURLs) == 0 && len(orgIDs) == 0 {
		selectAll = true
	}
	var selectedPeers []fab.Peer
	var allPeerURLs []string
	for _, peer := range allPeers {
		allPeerURLs = append(allPeerURLs, peer.URL())
		orgID := action.orgIDByPeer[peer.URL()]
		if selectAll || containsString(peerURLs, peer.URL()) || len(peerURLs) == 0 && containsString(orgIDs, orgID) {
			selectedPeers = append(selectedPeers, peer)
		}
	}
	for _, url := range peerURLs {
		if !containsString(allPeerURLs, url) {
			return nil, fmt.Errorf("invalid peer URL: %s", url)
		}
	}
	return selectedPeers, nil
}

// PeerConfig returns the PeerConfig for the first peer in the current org
func (action *Action) PeerConfig() (*fab.PeerConfig, error) {
	peersConfig, ok := action.endpointConfig.PeersConfig(action.OrgID())
	if !ok {
		return nil, errors.Errorf("Error reading peers config for %s: %v", action.OrgID())
	}

	peer := action.Peer()

	for _, p := range peersConfig {
		if peer.URL() == "" || p.URL == peer.URL() {
			return &p, nil
		}
	}

	return nil, errors.Errorf("No configuration found for peer %s", peer.URL())
}

// CreateDiscoveryService returns a new DiscoveryService for the given channel.
// This is an implementation of the DiscoveryProvider interface
func (action *Action) CreateDiscoveryService(channelID string) (fab.DiscoveryService, error) {
	return action, nil
}

// GetPeers returns the peers in context.
// This is an implementation of the DiscoveryService interface
func (action *Action) GetPeers() ([]fab.Peer, error) {
	return action.Peers(), nil
}

func containsString(sarr []string, s string) bool {
	for _, str := range sarr {
		if s == str {
			return true
		}
	}
	return false
}

// cryptoSuiteProviderFactory will provide custom cryptosuite (bccsp.BCCSP)
type cryptoSuiteProviderFactory struct {
	defcore.ProviderFactory
}

// CreateCryptoSuiteProvider returns a new default implementation of BCCSP
func (f *cryptoSuiteProviderFactory) CreateCryptoSuiteProvider(config core.CryptoSuiteConfig) (core.CryptoSuite, error) {
	return cryptosuiteimpl.GetSuiteByConfig(config)
}


================================================
FILE: fabric-cli/cmd/fabric-cli/action/svcproviderfactory.go
================================================
/*
Copyright SecureKey Technologies Inc. All Rights Reserved.

SPDX-License-Identifier: Apache-2.0
*/

package action

import (
	"github.com/hyperledger/fabric-sdk-go/pkg/client/common/selection/dynamicselection"
	"github.com/hyperledger/fabric-sdk-go/pkg/client/common/selection/fabricselection"
	"github.com/hyperledger/fabric-sdk-go/pkg/client/common/selection/staticselection"
	"github.com/hyperledger/fabric-sdk-go/pkg/common/options"
	contextApi "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/context"
	"github.com/hyperledger/fabric-sdk-go/pkg/common/providers/fab"
	"github.com/hyperledger/fabric-sdk-go/pkg/fabsdk/factory/defsvc"
	"github.com/hyperledger/fabric-sdk-go/pkg/fabsdk/provider/chpvdr"
	"github.com/pkg/errors"
	cliconfig "github.com/securekey/fabric-examples/fabric-cli/cmd/fabric-cli/config"
)

// serviceProviderFactory is configured with either static or dynamic selection provider
type serviceProviderFactory struct {
	defsvc.ProviderFactory
}

func newServiceProviderFactory() (*serviceProviderFactory, error) {
	return &serviceProviderFactory{}, nil
}

type fabricSelectionChannelProvider struct {
	fab.ChannelProvider
	service   fab.ChannelService
	selection fab.SelectionService
}

type fabricSelectionChannelService struct {
	fab.ChannelService
	selection fab.SelectionService
}

// CreateChannelProvider returns a new default implementation of channel provider
func (f *serviceProviderFactory) CreateChannelProvider(config fab.EndpointConfig, opts ...options.Opt) (fab.ChannelProvider, error) {
	chProvider, err := chpvdr.New(config, opts...)
	if err != nil {
		return nil, err
	}
	return &fabricSelectionChannelProvider{
		ChannelProvider: chProvider,
	}, nil
}

type closable interface {
	Close()
}

// Close frees resources and caches.
func (cp *fabricSelectionChannelProvider) Close() {
	if c, ok := cp.ChannelProvider.(closable); ok {
		c.Close()
	}
	if cp.selection != nil {
		if c, ok := cp.selection.(closable); ok {
			c.Close()
		}
	}
}

type providerInit interface {
	Initialize(providers contextApi.Providers) error
}

func (cp *fabricSelectionChannelProvider) Initialize(providers contextApi.Providers) error {
	if init, ok := cp.ChannelProvider.(providerInit); ok {
		return init.Initialize(providers)
	}
	return nil
}

// ChannelService creates a ChannelService for an identity
func (cp *fabricSelectionChannelProvider) ChannelService(ctx fab.ClientContext, channelID string) (fab.ChannelService, error) {
	chService, err := cp.ChannelProvider.ChannelService(ctx, channelID)
	if err != nil {
		return nil, err
	}

	discovery, err := chService.Discovery()
	if err != nil {
		return nil, err
	}

	if cp.selection == nil {
		switch cliconfig.Config().SelectionProvider() {
		case cliconfig.StaticSelectionProvider:
			cliconfig.Config().Logger().Debugf("Using static selection provider.")
			cp.selection, err = staticselection.NewService(discovery)
		case cliconfig.DynamicSelectionProvider:
			cliconfig.Config().Logger().Debugf("Using dynamic selection provider.")
			cp.selection, err = dynamicselection.NewService(ctx, channelID, discovery)
		case cliconfig.FabricSelectionProvider:
			cliconfig.Config().Logger().Debugf("Using Fabric selection provider.")
			cp.selection, err = fabricselection.New(ctx, channelID, discovery)
		default:
			return nil, errors.Errorf("invalid selection provider: %s", cliconfig.Config().SelectionProvider())
		}

		if err != nil {
			return nil, err
		}
	}

	return &fabricSelectionChannelService{
		ChannelService: chService,
		selection:      cp.selection,
	}, nil
}

func (cs *fabricSelectionChannelService) Selection() (fab.SelectionService, error) {
	return cs.selection, nil
}


================================================
FILE: fabric-cli/cmd/fabric-cli/chaincode/chaincodecmd.go
================================================
/*
Copyright SecureKey Technologies Inc. All Rights Reserved.

SPDX-License-Identifier: Apache-2.0
*/

package chaincode

import (
	cliconfig "github.com/securekey/fabric-examples/fabric-cli/cmd/fabric-cli/config"
	"github.com/spf13/cobra"
)

var chaincodeCmd = &cobra.Command{
	Use:   "chaincode",
	Short: "Chaincode commands",
	Long:  "Chaincode commands",
	Run: func(cmd *cobra.Command, args []string) {
		cmd.HelpFunc()(cmd, args)
	},
}

// Cmd returns the chaincode command
func Cmd() *cobra.Command {
	cliconfig.InitChannelID(chaincodeCmd.Flags())

	chaincodeCmd.AddCommand(getInstallCmd())
	chaincodeCmd.AddCommand(getInstantiateCmd())
	chaincodeCmd.AddCommand(getInvokeCmd())
	chaincodeCmd.AddCommand(getQueryCmd())
	chaincodeCmd.AddCommand(getGetInfoCmd())
	chaincodeCmd.AddCommand(getUpgradeCmd())

	return chaincodeCmd
}


================================================
FILE: fabric-cli/cmd/fabric-cli/chaincode/getinfocmd.go
================================================
/*
Copyright SecureKey Technologies Inc. All Rights Reserved.

SPDX-License-Identifier: Apache-2.0
*/

package chaincode

import (
	"fmt"
	"strings"

	"github.com/golang/protobuf/proto"
	pb "github.com/hyperledger/fabric-protos-go/peer"
	"github.com/hyperledger/fabric-sdk-go/pkg/client/channel"
	"github.com/hyperledger/fabric-sdk-go/third_party/github.com/hyperledger/fabric/core/common/ccprovider"
	"github.com/pkg/errors"
	"github.com/securekey/fabric-examples/fabric-cli/cmd/fabric-cli/action"
	cliconfig "github.com/securekey/fabric-examples/fabric-cli/cmd/fabric-cli/config"
	"github.com/spf13/cobra"
	"github.com/spf13/pflag"
)

const (
	lifecycleSCC = "lscc"

	getCCDataFunc     = "getccdata"
	getCollConfigFunc = "getcollectionsconfig"
)

var getInfoCmd = &cobra.Command{
	Use:   "info",
	Short: "Get chaincode info",
	Long:  "Retrieves details about the chaincode",
	Run: func(cmd *cobra.Command, args []string) {
		if cliconfig.Config().ChaincodeID() == "" {
			fmt.Printf("\nMust specify the chaincode ID\n\n")
			cmd.HelpFunc()(cmd, args)
			return
		}
		action, err := newGetInfoAction(cmd.Flags())
		if err != nil {
			cliconfig.Config().Logger().Errorf("Error while initializing getAction: %v", err)
			return
		}

		defer action.Terminate()

		err = action.invoke()
		if err != nil {
			cliconfig.Config().Logger().Errorf("Error while running getAction: %v", err)
		}
	},
}

func getGetInfoCmd() *cobra.Command {
	flags := getInfoCmd.Flags()
	cliconfig.InitPeerURL(flags)
	cliconfig.InitChannelID(flags)
	cliconfig.InitChaincodeID(flags)
	return getInfoCmd
}

type getInfoAction struct {
	action.Action
}

func newGetInfoAction(flags *pflag.FlagSet) (*getInfoAction, error) {
	action := &getInfoAction{}
	err := action.Initialize(flags)
	if len(action.Peers()) == 0 {
		return nil, errors.New("a peer must be specified")
	}
	return action, err
}

func (action *getInfoAction) invoke() error {
	channelClient, err := action.ChannelClient()
	if err != nil {
		return errors.Errorf("error retrieving channel client: %v", err)
	}

	ccData, err := action.getCCData(channelClient)
	if err != nil {
		return errors.WithMessagef(err, "error querying for chaincode data")
	}

	collConfig, err := action.getCollConfig(channelClient)
	if err != nil {
		if !strings.Contains(errors.Cause(err).Error(), "collections config not defined for chaincode") {
			return errors.WithMessagef(err, "error querying for collection config")
		}
	}

	action.Printer().PrintChaincodeData(ccData, collConfig)

	return nil
}

func (action *getInfoAction) getCCData(channelClient *channel.Client) (*ccprovider.ChaincodeData, error) {
	var args [][]byte
	args = append(args, []byte(cliconfig.Config().ChannelID()))
	args = append(args, []byte(cliconfig.Config().ChaincodeID()))

	peer := action.Peer()
	fmt.Printf("querying chaincode info for %s on peer: %s...\n", cliconfig.Config().ChaincodeID(), peer.URL())

	response, err := channelClient.Query(
		channel.Request{ChaincodeID: lifecycleSCC, Fcn: getCCDataFunc, Args: args},
		channel.WithTargetEndpoints(peer.URL()))
	if err != nil {
		return nil, errors.Errorf("error querying for chaincode info: %v", err)
	}

	ccData := &ccprovider.ChaincodeData{}
	err = proto.Unmarshal(response.Payload, ccData)
	if err != nil {
		return nil, errors.Errorf("error unmarshalling chaincode data: %v", err)
	}
	return ccData, nil
}

func (action *getInfoAction) getCollConfig(channelClient *channel.Client) (*pb.CollectionConfigPackage, error) {
	var args [][]byte
	args = append(args, []byte(cliconfig.Config().ChaincodeID()))

	peer := action.Peer()
	fmt.Printf("querying collections config for %s on peer: %s...\n", cliconfig.Config().ChaincodeID(), peer.URL())

	response, err := channelClient.Query(
		channel.Request{ChaincodeID: lifecycleSCC, Fcn: getCollConfigFunc, Args: args},
		channel.WithTargetEndpoints(peer.URL()))
	if err != nil {
		return nil, errors.Errorf("error querying for collections config: %v", err)
	}

	collConfig := &pb.CollectionConfigPackage{}
	err = proto.Unmarshal(response.Payload, collConfig)
	if err != nil {
		return nil, errors.Errorf("error unmarshalling collections config: %v", err)
	}
	return collConfig, nil
}


================================================
FILE: fabric-cli/cmd/fabric-cli/chaincode/installcmd.go
================================================
/*
Copyright SecureKey Technologies Inc. All Rights Reserved.

SPDX-License-Identifier: Apache-2.0
*/

package chaincode

import (
	"fmt"
	"net/http"

	"github.com/hyperledger/fabric-sdk-go/pkg/client/resmgmt"
	"github.com/hyperledger/fabric-sdk-go/pkg/common/providers/fab"
	"github.com/hyperledger/fabric-sdk-go/pkg/fab/ccpackager/gopackager"
	"github.com/pkg/errors"
	"github.com/securekey/fabric-examples/fabric-cli/cmd/fabric-cli/action"
	cliconfig "github.com/securekey/fabric-examples/fabric-cli/cmd/fabric-cli/config"
	"github.com/spf13/cobra"
	"github.com/spf13/pflag"
)

var installCmd = &cobra.Command{
	Use:   "install",
	Short: "Install chaincode.",
	Long:  "Install chaincode",
	Run: func(cmd *cobra.Command, args []string) {
		if cliconfig.Config().ChaincodeID() == "" {
			fmt.Printf("\nMust specify the chaincode ID\n\n")
			cmd.HelpFunc()(cmd, args)
			return
		}
		if cliconfig.Config().ChaincodePath() == "" {
			fmt.Printf("\nMust specify the path of the chaincode\n\n")
			cmd.HelpFunc()(cmd, args)
			return
		}
		action, err := newInstallAction(cmd.Flags())
		if err != nil {
			cliconfig.Config().Logger().Errorf("Error while initializing installAction: %v", err)
			return
		}

		defer action.Terminate()

		err = action.invoke()
		if err != nil {
			cliconfig.Config().Logger().Errorf("Error while running installAction: %v", err)
		}
	},
}

func getInstallCmd() *cobra.Command {
	flags := installCmd.Flags()
	cliconfig.InitPeerURL(flags, "", "The URL of the peer on which to install the chaincode, e.g. localhost:7051")
	cliconfig.InitChannelID(flags)
	cliconfig.InitChaincodeID(flags)
	cliconfig.InitChaincodePath(flags)
	cliconfig.InitChaincodeVersion(flags)
	cliconfig.InitGoPath(flags)
	return installCmd
}

type installAction struct {
	action.Action
}

func newInstallAction(flags *pflag.FlagSet) (*installAction, error) {
	action := &installAction{}
	err := action.Initialize(flags)
	return action, err
}

func (action *installAction) invoke() error {
	var lastErr error
	for orgID, peers := range action.PeersByOrg() {
		fmt.Printf("Installing chaincode %s on org[%s] peers:\n", cliconfig.Config().ChaincodeID(), orgID)
		for _, peer := range peers {
			fmt.Printf("-- %s\n", peer.URL())
		}
		err := action.installChaincode(orgID, peers)
		if err != nil {
			lastErr = err
		}
	}

	return lastErr
}

func (action *installAction) installChaincode(orgID string, targets []fab.Peer) error {

	resMgmtClient, err := action.ResourceMgmtClientForOrg(orgID)
	if err != nil {
		return err
	}

	ccPkg, err := gopackager.NewCCPackage(cliconfig.Config().ChaincodePath(), cliconfig.Config().GoPath())
	if err != nil {
		return err
	}
	req := resmgmt.InstallCCRequest{
		Name:    cliconfig.Config().ChaincodeID(),
		Path:    cliconfig.Config().ChaincodePath(),
		Version: cliconfig.Config().ChaincodeVersion(),
		Package: ccPkg,
	}
	responses, err := resMgmtClient.InstallCC(req, resmgmt.WithTargets(targets...))
	if err != nil {
		return errors.Errorf("InstallChaincode returned error: %v", err)
	}

	ccIDVersion := cliconfig.Config().ChaincodeID() + "." + cliconfig.Config().ChaincodeVersion()

	var errs []error
	for _, resp := range responses {
		if resp.Info == "already installed" {
			fmt.Printf("Chaincode %s already installed on peer: %s.\n", ccIDVersion, resp.Target)
		} else if resp.Status != http.StatusOK {
			errs = append(errs, errors.Errorf("installCC returned error from peer %s: %s", resp.Target, resp.Info))
		} else {
			fmt.Printf("...successfuly installed chaincode %s on peer %s.\n", ccIDVersion, resp.Target)
		}
	}

	if len(errs) > 0 {
		cliconfig.Config().Logger().Warnf("Errors returned from InstallCC: %v\n", errs)
		return errs[0]
	}

	return nil
}


================================================
FILE: fabric-cli/cmd/fabric-cli/chaincode/instantiatecmd.go
================================================
/*
Copyright SecureKey Technologies Inc. All Rights Reserved.

SPDX-License-Identifier: Apache-2.0
*/

package chaincode

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"strings"

	"github.com/hyperledger/fabric-protos-go/common"
	pb "github.com/hyperledger/fabric-protos-go/peer"
	"github.com/hyperledger/fabric-sdk-go/pkg/client/resmgmt"
	"github.com/hyperledger/fabric-sdk-go/third_party/github.com/hyperledger/fabric/common/cauthdsl"
	"github.com/pkg/errors"
	"github.com/securekey/fabric-examples/fabric-cli/cmd/fabric-cli/action"
	"github.com/securekey/fabric-examples/fabric-cli/cmd/fabric-cli/chaincode/utils"
	cliconfig "github.com/securekey/fabric-examples/fabric-cli/cmd/fabric-cli/config"
	"github.com/spf13/cobra"
	"github.com/spf13/pflag"
)

var instantiateCmd = &cobra.Command{
	Use:   "instantiate",
	Short: "Instantiate chaincode.",
	Long:  "Instantiates the chaincode",
	Run: func(cmd *cobra.Command, args []string) {
		if cliconfig.Config().ChaincodeID() == "" {
			fmt.Printf("\nMust specify the chaincode ID\n\n")
			cmd.HelpFunc()(cmd, args)
			return
		}
		if cliconfig.Config().ChaincodePath() == "" {
			fmt.Printf("\nMust specify the path of the chaincode\n\n")
			cmd.HelpFunc()(cmd, args)
			return
		}
		action, err := newInstantiateAction(cmd.Flags())
		if err != nil {
			cliconfig.Config().Logger().Errorf("Error while initializing instantiateAction: %v", err)
			return
		}

		defer action.Terminate()

		err = action.invoke()
		if err != nil {
			cliconfig.Config().Logger().Errorf("Error while running instantiateAction: %v", err)
		}
	},
}

func getInstantiateCmd() *cobra.Command {
	flags := instantiateCmd.Flags()
	cliconfig.InitPeerURL(flags)
	cliconfig.InitChannelID(flags)
	cliconfig.InitChaincodeID(flags)
	cliconfig.InitChaincodePath(flags)
	cliconfig.InitChaincodeVersion(flags)
	cliconfig.InitArgs(flags)
	cliconfig.InitChaincodePolicy(flags)
	cliconfig.InitCollectionConfigFile(flags)
	cliconfig.InitTimeout(flags)
	return instantiateCmd
}

type instantiateAction struct {
	action.Action
}

func newInstantiateAction(flags *pflag.FlagSet) (*instantiateAction, error) {
	action := &instantiateAction{}
	err := action.Initialize(flags)
	if len(action.Peers()) == 0 {
		return nil, errors.Errorf("a peer must be specified")
	}
	return action, err
}

func (a *instantiateAction) invoke() error {
	s := cliconfig.Config().Args()
	argBytes := []byte(s)
	args := &action.ArgStruct{}

	if err := json.Unmarshal(argBytes, args); err != nil {
		return errors.Errorf("Error unmarshalling JSON arg string: %v", err)
	}

	resMgmtClient, err := a.ResourceMgmtClient()
	if err != nil {
		return err
	}

	cliconfig.Config().Logger().Infof("Sending instantiate %s ...\n", cliconfig.Config().ChaincodeID())

	chaincodePolicy, err := a.newChaincodePolicy()
	if err != nil {
		return err
	}

	// Private Data Collection Configuration
	// - see fixtures/config/pvtdatacollection.json for sample config file
	var collConfig []*pb.CollectionConfig
	collConfigFile := cliconfig.Config().CollectionConfigFile()
	if collConfigFile != "" {
		collConfig, err = getCollectionConfigFromFile(cliconfig.Config().CollectionConfigFile())
		if err != nil {
			return errors.Wrapf(err, "error getting private data collection configuration from file [%s]", cliconfig.Config().CollectionConfigFile())
		}
	}

	req := resmgmt.InstantiateCCRequest{
		Name:       cliconfig.Config().ChaincodeID(),
		Path:       cliconfig.Config().ChaincodePath(),
		Version:    cliconfig.Config().ChaincodeVersion(),
		Args:       utils.AsBytes(utils.NewContext(), args.Args),
		Policy:     chaincodePolicy,
		CollConfig: collConfig,
	}

	_, err = resMgmtClient.InstantiateCC(cliconfig.Config().ChannelID(), req, resmgmt.WithTargets(a.Peer()))
	if err != nil {
		if strings.Contains(err.Error(), "chaincode exists "+cliconfig.Config().ChaincodeID()) {
			// Ignore
			cliconfig.Config().Logger().Infof("Chaincode %s already instantiated.", cliconfig.Config().ChaincodeID())
			fmt.Printf("...chaincode %s already instantiated.\n", cliconfig.Config().ChaincodeID())
			return nil
		}
		return errors.Errorf("error instantiating chaincode: %v", err)
	}

	fmt.Printf("...successfuly instantiated chaincode %s on channel %s.\n", cliconfig.Config().ChaincodeID(), cliconfig.Config().ChannelID())

	return nil
}

func (a *instantiateAction) newChaincodePolicy() (*common.SignaturePolicyEnvelope, error) {
	if cliconfig.Config().ChaincodePolicy() != "" {
		// Create a signature policy from the policy expression passed in
		return newChaincodePolicy(cliconfig.Config().ChaincodePolicy())
	}

	// Default policy is 'signed by any member' for all known orgs
	return cauthdsl.AcceptAllPolicy, nil
}

func newChaincodePolicy(policyString string) (*common.SignaturePolicyEnvelope, error) {
	ccPolicy, err := cauthdsl.FromString(policyString)
	if err != nil {
		return nil, errors.Errorf("invalid chaincode policy [%s]: %s", policyString, err)
	}
	return ccPolicy, nil
}

type collectionConfigJSON struct {
	Name              string `json:"name"`
	Policy            string `json:"policy"`
	RequiredPeerCount int32  `json:"requiredPeerCount"`
	MaxPeerCount      int32  `json:"maxPeerCount"`
}

func getCollectionConfigFromFile(ccFile string) ([]*pb.CollectionConfig, error) {
	fileBytes, err := ioutil.ReadFile(ccFile)
	if err != nil {
		return nil, errors.Wrapf(err, "could not read file [%s]", ccFile)
	}
	cconf := &[]collectionConfigJSON{}
	if err = json.Unmarshal(fileBytes, cconf); err != nil {
		return nil, errors.Wrapf(err, "error parsing collection configuration in file [%s]", ccFile)
	}
	return getCollectionConfig(*cconf)
}

func getCollectionConfig(cconf []collectionConfigJSON) ([]*pb.CollectionConfig, error) {
	ccarray := make([]*pb.CollectionConfig, 0, len(cconf))
	for _, cconfitem := range cconf {
		p, err := cauthdsl.FromString(cconfitem.Policy)
		if err != nil {
			return nil, errors.WithMessage(err, fmt.Sprintf("invalid policy %s", cconfitem.Policy))
		}
		cpc := &pb.CollectionPolicyConfig{
			Payload: &pb.CollectionPolicyConfig_SignaturePolicy{
				SignaturePolicy: p,
			},
		}
		cc := &pb.CollectionConfig{
			Payload: &pb.CollectionConfig_StaticCollectionConfig{
				StaticCollectionConfig: &pb.StaticCollectionConfig{
					Name:              cconfitem.Name,
					MemberOrgsPolicy:  cpc,
					RequiredPeerCount: cconfitem.RequiredPeerCount,
					MaximumPeerCount:  cconfitem.MaxPeerCount,
				},
			},
		}
		ccarray = append(ccarray, cc)
	}
	return ccarray, nil
}


================================================
FILE: fabric-cli/cmd/fabric-cli/chaincode/invokecmd.go
================================================
/*
Copyright SecureKey Technologies Inc. All Rights Reserved.

SPDX-License-Identifier: Apache-2.0
*/

package chaincode

import (
	"fmt"
	"strconv"
	"sync"
	"time"

	"github.com/hyperledger/fabric-sdk-go/pkg/common/errors/retry"
	"github.com/hyperledger/fabric-sdk-go/pkg/common/providers/fab"
	"github.com/pkg/errors"
	"github.com/securekey/fabric-examples/fabric-cli/cmd/fabric-cli/action"
	"github.com/securekey/fabric-examples/fabric-cli/cmd/fabric-cli/chaincode/invoketask"
	"github.com/securekey/fabric-examples/fabric-cli/cmd/fabric-cli/chaincode/multitask"
	"github.com/securekey/fabric-examples/fabric-cli/cmd/fabric-cli/chaincode/task"
	"github.com/securekey/fabric-examples/fabric-cli/cmd/fabric-cli/chaincode/utils"
	cliconfig "github.com/securekey/fabric-examples/fabric-cli/cmd/fabric-cli/config"
	"github.com/securekey/fabric-examples/fabric-cli/cmd/fabric-cli/executor"
	"github.com/spf13/cobra"
	"github.com/spf13/pflag"
)

var invokeCmd = &cobra.Command{
	Use:   "invoke",
	Short: "invoke chaincode.",
	Long:  "invoke chaincode",
	Run: func(cmd *cobra.Command, args []string) {
		if cliconfig.Config().ChaincodeID() == "" {
			fmt.Printf("\nMust specify the chaincode ID\n\n")
			cmd.HelpFunc()(cmd, args)
			return
		}
		action, err := newInvokeAction(cmd.Flags())
		if err != nil {
			cliconfig.Config().Logger().Errorf("Error while initializing invokeAction: %v", err)
			return
		}

		defer action.Terminate()

		err = action.invoke()
		if err != nil {
			cliconfig.Config().Logger().Errorf("Error while running invokeAction: %v", err)
		}
	},
}

func getInvokeCmd() *cobra.Command {
	flags := invokeCmd.Flags()
	cliconfig.InitPeerURL(flags)
	cliconfig.InitChannelID(flags)
	cliconfig.InitChaincodeID(flags)
	cliconfig.InitArgs(flags)
	cliconfig.InitIterations(flags)
	cliconfig.InitSleepTime(flags)
	cliconfig.InitTimeout(flags)
	cliconfig.InitPrintPayloadOnly(flags)
	cliconfig.InitConcurrency(flags)
	cliconfig.InitMaxAttempts(flags)
	cliconfig.InitInitialBackoff(flags)
	cliconfig.InitMaxBackoff(flags)
	cliconfig.InitBackoffFactor(flags)
	cliconfig.InitVerbosity(flags)
	cliconfig.InitSelectionProvider(flags)
	return invokeCmd
}

type invokeAction struct {
	action.Action
	numInvoked uint32
	done       chan bool
}

func newInvokeAction(flags *pflag.FlagSet) (*invokeAction, error) {
	action := &invokeAction{done: make(chan bool)}
	err := action.Initialize(flags)
	return action, err
}

func (a *invokeAction) invoke() error {
	channelClient, err := a.ChannelClient()
	if err != nil {
		return errors.Errorf("Error getting channel client: %v", err)
	}

	argsArray, err := action.ArgsArray()
	if err != nil {
		return err
	}

	executor := executor.NewConcurrent("Invoke Chaincode", cliconfig.Config().Concurrency())
	executor.Start()
	defer executor.Stop(true)

	success := 0
	var errs []error
	var successDurations []time.Duration
	var failDurations []time.Duration

	var targets []fab.Peer
	if len(cliconfig.Config().PeerURL()) > 0 || len(cliconfig.Config().OrgIDs()) > 0 {
		targets = a.Peers()
	}

	var wg sync.WaitGroup
	var mutex sync.RWMutex
	var tasks []task.Task
	var taskID int
	for i := 0; i < cliconfig.Config().Iterations(); i++ {
		ctxt := utils.NewContext()
		multiTask := multitask.New(wg.Done)
		for _, args := range argsArray {
			taskID++
			var startTime time.Time
			cargs := args
			task := invoketask.New(
				ctxt,
				strconv.Itoa(taskID), channelClient, targets,
				cliconfig.Config().ChaincodeID(),
				&cargs, executor,
				retry.Opts{
					Attempts:       cliconfig.Config().MaxAttempts(),
					InitialBackoff: cliconfig.Config().InitialBackoff(),
					MaxBackoff:     cliconfig.Config().MaxBackoff(),
					BackoffFactor:  cliconfig.Config().BackoffFactor(),
					RetryableCodes: retry.ChannelClientRetryableCodes,
				},
				cliconfig.Config().Verbose() || cliconfig.Config().Iterations() == 1,
				cliconfig.Config().PrintPayloadOnly(), a.Printer(),

				func() {
					startTime = time.Now()
				},
				func(err error) {
					duration := time.Since(startTime)
					mutex.Lock()
					defer mutex.Unlock()
					if err != nil {
						errs = append(errs, err)
						failDurations = append(failDurations, duration)
					} else {
						success++
						successDurations = append(successDurations, duration)
					}
				})
			multiTask.Add(task)
		}
		tasks = append(tasks, multiTask)
	}

	wg.Add(len(tasks))

	numInvocations := len(tasks) * len(argsArray)

	done := make(chan bool)
	go func() {
		ticker := time.NewTicker(10 * time.Second)
		for {
			select {
			case <-ticker.C:
				mutex.RLock()
				if len(errs) > 0 {
					fmt.Printf("*** %d failed invocation(s) out of %d\n", len(errs), numInvocations)
				}
				fmt.Printf("*** %d successfull invocation(s) out of %d\n", success, numInvocations)
				mutex.RUnlock()
			case <-done:
				return
			}
		}
	}()

	startTime := time.Now()
	sleepTime := time.Duration(cliconfig.Config().SleepTime()) * time.Millisecond

	for _, task := range tasks {
		if err := executor.Submit(task); err != nil {
			return errors.Errorf("error submitting task: %s", err)
		}
		if sleepTime > 0 {
			time.Sleep(sleepTime)
		}
	}

	// Wait for all tasks to complete
	wg.Wait()
	done <- true

	duration := time.Now().Sub(startTime)

	var allErrs []error
	var attempts int
	for _, task := range tasks {
		attempts = attempts + task.Attempts()
		if task.LastError() != nil {
			allErrs = append(allErrs, task.LastError())
		}
	}

	if len(errs) > 0 {
		fmt.Printf("\n*** %d errors invoking chaincode:\n", len(errs))
		for _, err := range errs {
			fmt.Printf("%s\n", err)
		}
	} else if len(allErrs) > 0 {
		fmt.Printf("\n*** %d transient errors invoking chaincode:\n", len(allErrs))
		for _, err := range allErrs {
			fmt.Printf("%s\n", err)
		}
	}

	if numInvocations/len(argsArray) > 1 {
		fmt.Printf("\n")
		fmt.Printf("*** ---------- Summary: ----------\n")
		fmt.Printf("***   - Invocations:     %d\n", numInvocations)
		fmt.Printf("***   - Concurrency:     %d\n", cliconfig.Config().Concurrency())
		fmt.Printf("***   - Successfull:     %d\n", success)
		fmt.Printf("***   - Total attempts:  %d\n", attempts)
		fmt.Printf("***   - Duration:        %2.2fs\n", duration.Seconds())
		fmt.Printf("***   - Rate:            %2.2f/s\n", float64(numInvocations)/duration.Seconds())
		fmt.Printf("***   - Average:         %2.2fs\n", average(append(successDurations, failDurations...)))
		fmt.Printf("***   - Average Success: %2.2fs\n", average(successDurations))
		fmt.Printf("***   - Average Fail:    %2.2fs\n", average(failDurations))
		fmt.Printf("***   - Min Success:     %2.2fs\n", min(successDurations))
		fmt.Printf("***   - Max Success:     %2.2fs\n", max(successDurations))
		fmt.Printf("*** ------------------------------\n")
	}

	return nil
}

func average(durations []time.Duration) float64 {
	if len(durations) == 0 {
		return 0
	}

	var total float64
	for _, duration := range durations {
		total += duration.Seconds()
	}
	return total / float64(len(durations))
}

func min(durations []time.Duration) float64 {
	min, _ := minMax(durations)
	return min
}

func max(durations []time.Duration) float64 {
	_, max := minMax(durations)
	return max
}

func minMax(durations []time.Duration) (min float64, max float64) {
	for _, duration := range durations {
		if min == 0 || min > duration.Seconds() {
			min = duration.Seconds()
		}
		if max == 0 || max < duration.Seconds() {
			max = duration.Seconds()
		}
	}
	return
}


================================================
FILE: fabric-cli/cmd/fabric-cli/chaincode/invokeerror/invokeerror.go
================================================
/*
Copyright SecureKey Technologies Inc. All Rights Reserved.

SPDX-License-Identifier: Apache-2.0
*/

package invokeerror

import "github.com/pkg/errors"

type ErrorCode int

const (
	// PersistentError indicates that an unknown error occurred
	// and a retry of the request would NOT be successful
	PersistentError ErrorCode = iota

	// TransientError indicates that a transient error occurred
	// and a retry of the request could be successful
	TransientError

	// TimeoutOnCommit indicates that a timeout occurred while waiting
	// for a TxStatus event
	TimeoutOnCommit
)

// Error extends error with
// additional context
type Error interface {
	error

	// Status returns the error code
	ErrorCode() ErrorCode
}

type invokeError struct {
	error
	code ErrorCode
}

// New returns a new Error
func New(code ErrorCode, msg string) Error {
	return &invokeError{
		error: errors.New(msg),
		code:  code,
	}
}

// Wrap returns a new Error
func Wrap(code ErrorCode, cause error, msg string) Error {
	return &invokeError{
		error: errors.Wrap(cause, msg),
		code:  code,
	}
}

// Wrapf returns a new Error
func Wrapf(code ErrorCode, cause error, fmt string, args ...interface{}) Error {
	return &invokeError{
		error: errors.Wrapf(cause, fmt, args...),
		code:  code,
	}
}

// Errorf returns a new Error
func Errorf(code ErrorCode, fmt string, args ...interface{}) Error {
	return &invokeError{
		error: errors.Errorf(fmt, args...),
		code:  code,
	}
}

// ErrorCode returns the error code
func (e *invokeError) ErrorCode() ErrorCode {
	return e.code
}


================================================
FILE: fabric-cli/cmd/fabric-cli/chaincode/invoketask/invoketask.go
================================================
/*
Copyright SecureKey Technologies Inc. All Rights Reserved.

SPDX-License-Identifier: Apache-2.0
*/

package invoketask

import (
	pb "github.com/hyperledger/fabric-protos-go/peer"
	"github.com/hyperledger/fabric-sdk-go/pkg/client/channel"
	"github.com/hyperledger/fabric-sdk-go/pkg/common/errors/retry"
	"github.com/hyperledger/fabric-sdk-go/pkg/common/providers/fab"
	"github.com/pkg/errors"
	"github.com/securekey/fabric-examples/fabric-cli/cmd/fabric-cli/action"
	"github.com/securekey/fabric-examples/fabric-cli/cmd/fabric-cli/chaincode/invokeerror"
	"github.com/securekey/fabric-examples/fabric-cli/cmd/fabric-cli/chaincode/utils"
	cliconfig "github.com/securekey/fabric-examples/fabric-cli/cmd/fabric-cli/config"
	"github.com/securekey/fabric-examples/fabric-cli/cmd/fabric-cli/executor"
	"github.com/securekey/fabric-examples/fabric-cli/cmd/fabric-cli/printer"
)

// Task is a Task that invokes a chaincode
type Task struct {
	ctxt          utils.Context
	executor      *executor.Executor
	channelClient *channel.Client
	targets       []fab.Peer
	id            string
	ccID          string
	args          *action.ArgStruct
	retryOpts     retry.Opts
	attempt       int
	lastErr       error
	startedCB     func()
	completedCB   func(err error)
	verbose       bool
	printer       printer.Printer
	txID          string
	payloadOnly   bool
}

// New returns a new Task
func New(ctxt utils.Context, id string, channelClient *channel.Client, targets []fab.Peer, ccID string, args *action.ArgStruct,
	executor *executor.Executor, retryOpts retry.Opts, verbose bool,
	payloadOnly bool, p printer.Printer, startedCB func(), completedCB func(err error)) *Task {
	return &Task{
		ctxt:          ctxt,
		id:            id,
		channelClient: channelClient,
		targets:       targets,
		printer:       p,
		ccID:          ccID,
		args:          args,
		executor:      executor,
		retryOpts:     retryOpts,
		startedCB:     startedCB,
		completedCB:   completedCB,
		attempt:       1,
		verbose:       verbose,
		payloadOnly:   payloadOnly,
	}
}

// Attempts returns the number of invocation attempts that were made
// in order to achieve a successful response
func (t *Task) Attempts() int {
	return t.attempt
}

// LastError returns the last error that was recorder
func (t *Task) LastError() error {
	return t.lastErr
}

// Invoke invokes the task
func (t *Task) Invoke() {
	t.startedCB()
	if err := t.doInvoke(); err != nil {
		t.lastErr = err
		t.completedCB(err)
	} else {
		cliconfig.Config().Logger().Debugf("(%s) - Successfully invoked chaincode\n", t.id)
		t.completedCB(nil)
	}
}

func (t *Task) doInvoke() error {
	cliconfig.Config().Logger().Debugf("(%s) - Invoking chaincode: %s, function: %s, args: %+v. Attempt #%d...\n",
		t.id, t.ccID, t.args.Func, t.args.Args, t.attempt)

	var opts []channel.RequestOption
	opts = append(opts, channel.WithRetry(t.retryOpts))
	opts = append(opts, channel.WithBeforeRetry(func(err error) {
		t.attempt++
	}))
	if len(t.targets) > 0 {
		opts = append(opts, channel.WithTargets(t.targets...))
	}

	response, err := t.channelClient.Execute(
		channel.Request{
			ChaincodeID: t.ccID,
			Fcn:         t.args.Func,
			Args:        utils.AsBytes(t.ctxt, t.args.Args),
		},
		opts...,
	)
	if err != nil {
		return invokeerror.Errorf(invokeerror.TransientError, "SendTransactionProposal return error: %v", err)
	}

	if t.verbose {
		t.printer.PrintTxProposalResponses(response.Responses, t.payloadOnly)
	}

	t.txID = string(response.TransactionID)

	switch pb.TxValidationCode(response.TxValidationCode) {
	case pb.TxValidationCode_VALID:
		cliconfig.Config().Logger().Debugf("(%s) - Successfully committed transaction [%s] ...\n", t.id, response.TransactionID)
		return nil
	case pb.TxValidationCode_DUPLICATE_TXID, pb.TxValidationCode_MVCC_READ_CONFLICT, pb.TxValidationCode_PHANTOM_READ_CONFLICT:
		cliconfig.Config().Logger().Debugf("(%s) - Transaction commit failed for [%s] with code [%s]. This is most likely a transient error.\n", t.id, response.TransactionID, response.TxValidationCode)
		return invokeerror.Wrapf(invokeerror.TransientError, errors.New("Duplicate TxID"), "invoke Error received from eventhub for TxID [%s]. Code: %s", response.TransactionID, response.TxValidationCode)
	default:
		cliconfig.Config().Logger().Debugf("(%s) - Transaction commit failed for [%s] with code [%s].\n", t.id, response.TransactionID, response.TxValidationCode)
		return invokeerror.Wrapf(invokeerror.PersistentError, errors.New("error"), "invoke Error received from eventhub for TxID [%s]. Code: %s", response.TransactionID, response.TxValidationCode)
	}

}


================================================
FILE: fabric-cli/cmd/fabric-cli/chaincode/multitask/multitask.go
================================================
/*
Copyright SecureKey Technologies Inc. All Rights Reserved.

SPDX-License-Identifier: Apache-2.0
*/

package multitask

import "github.com/securekey/fabric-examples/fabric-cli/cmd/fabric-cli/chaincode/task"

// MultiTask contains a set of Tasks to be invoked synchronously
type MultiTask struct {
	tasks       []task.Task
	completedCB func()
}

// New creates a new multi task
func New(completedCB func()) *MultiTask {
	return &MultiTask{
		completedCB: completedCB,
	}
}

// Add adds a task
func (m *MultiTask) Add(task task.Task) {
	m.tasks = append(m.tasks, task)
}

// Invoke invokes the task
func (m *MultiTask) Invoke() {
	defer m.completedCB()

	for _, task := range m.tasks {
		task.Invoke()
	}
}

// Attempts returns the number of invocation attempts that were made
// in order to achieve a successful response
func (m *MultiTask) Attempts() int {
	var attempts int
	for _, t := range m.tasks {
		attempts += t.Attempts()
	}
	return attempts
}

// LastError returns the last error that was recorder
func (m *MultiTask) LastError() error {
	for _, t := range m.tasks {
		if t.LastError() != nil {
			return t.LastError()
		}
	}
	return nil
}


================================================
FILE: fabric-cli/cmd/fabric-cli/chaincode/querycmd.go
================================================
/*
Copyright SecureKey Technologies Inc. All Rights Reserved.

SPDX-License-Identifier: Apache-2.0
*/

package chaincode

import (
	"fmt"
	"strconv"
	"sync"
	"time"

	"github.com/hyperledger/fabric-sdk-go/pkg/common/errors/retry"
	"github.com/hyperledger/fabric-sdk-go/pkg/common/providers/fab"
	"github.com/pkg/errors"
	"github.com/securekey/fabric-examples/fabric-cli/cmd/fabric-cli/action"
	"github.com/securekey/fabric-examples/fabric-cli/cmd/fabric-cli/chaincode/multitask"
	"github.com/securekey/fabric-examples/fabric-cli/cmd/fabric-cli/chaincode/querytask"
	"github.com/securekey/fabric-examples/fabric-cli/cmd/fabric-cli/chaincode/task"
	"github.com/securekey/fabric-examples/fabric-cli/cmd/fabric-cli/chaincode/utils"
	cliconfig "github.com/securekey/fabric-examples/fabric-cli/cmd/fabric-cli/config"
	"github.com/securekey/fabric-examples/fabric-cli/cmd/fabric-cli/executor"
	"github.com/spf13/cobra"
	"github.com/spf13/pflag"
)

var queryCmd = &cobra.Command{
	Use:   "query",
	Short: "Query chaincode.",
	Long:  "Query chaincode",
	Run: func(cmd *cobra.Command, args []string) {
		if cliconfig.Config().ChaincodeID() == "" {
			fmt.Printf("\nMust specify the chaincode ID\n\n")
			cmd.HelpFunc()(cmd, args)
			return
		}
		action, err := newQueryAction(cmd.Flags())
		if err != nil {
			cliconfig.Config().Logger().Errorf("Error while initializing queryAction: %v", err)
			return
		}

		defer action.Terminate()

		err = action.query()
		if err != nil {
			cliconfig.Config().Logger().Errorf("Error while running queryAction: %v", err)
		}
	},
}

func getQueryCmd() *cobra.Command {
	flags := queryCmd.Flags()
	cliconfig.InitPeerURL(flags)
	cliconfig.InitChannelID(flags)
	cliconfig.InitChaincodeID(flags)
	cliconfig.InitArgs(flags)
	cliconfig.InitIterations(flags)
	cliconfig.InitSleepTime(flags)
	cliconfig.InitTimeout(flags)
	cliconfig.InitPrintPayloadOnly(flags)
	cliconfig.InitConcurrency(flags)
	cliconfig.InitVerbosity(flags)
	cliconfig.InitSelectionProvider(flags)
	cliconfig.InitValidate(flags)
	return queryCmd
}

type queryAction struct {
	action.Action
	numInvoked uint32
	done       chan bool
}

func newQueryAction(flags *pflag.FlagSet) (*queryAction, error) {
	action := &queryAction{done: make(chan bool)}
	err := action.Initialize(flags)
	return action, err
}

func (a *queryAction) query() error {
	channelClient, err := a.ChannelClient()
	if err != nil {
		return errors.Errorf("Error getting channel client: %v", err)
	}

	argsArray, err := action.ArgsArray()
	if err != nil {
		return err
	}

	var targets []fab.Peer
	if len(cliconfig.Config().PeerURL()) > 0 || len(cliconfig.Config().OrgIDs()) > 0 {
		targets = a.Peers()
	}

	executor := executor.NewConcurrent("Query Chaincode", cliconfig.Config().Concurrency())
	executor.Start()
	defer executor.Stop(true)

	verbose := cliconfig.Config().Verbose() || cliconfig.Config().Iterations() == 1

	var mutex sync.RWMutex
	var tasks []task.Task
	var errs []error
	var wg sync.WaitGroup
	var taskID int
	var success int
	var successDurations []time.Duration
	var failDurations []time.Duration

	for i := 0; i < cliconfig.Config().Iterations(); i++ {
		ctxt := utils.NewContext()
		multiTask := multitask.New(wg.Done)
		for _, args := range argsArray {
			taskID++
			var startTime time.Time
			cargs := args
			task := querytask.New(
				ctxt,
				strconv.Itoa(taskID), channelClient, targets, &cargs, a.Printer(),
				retry.Opts{
					Attempts:       cliconfig.Config().MaxAttempts(),
					InitialBackoff: cliconfig.Config().InitialBackoff(),
					MaxBackoff:     cliconfig.Config().MaxBackoff(),
					BackoffFactor:  cliconfig.Config().BackoffFactor(),
					RetryableCodes: retry.ChannelClientRetryableCodes,
				},
				verbose,
				cliconfig.Config().PrintPayloadOnly(),
				cliconfig.Config().Validate(),
				func() {
					startTime = time.Now()
				},
				func(err error) {
					duration := time.Since(startTime)
					mutex.Lock()
					if err != nil {
						errs = append(errs, err)
					} else {
						success++
						successDurations = append(successDurations, duration)
					}
					mutex.Unlock()
				})
			multiTask.Add(task)
		}
		tasks = append(tasks, multiTask)
	}

	wg.Add(len(tasks))

	numInvocations := len(tasks) * len(argsArray)

	done := make(chan bool)
	go func() {
		ticker := time.NewTicker(3 * time.Second)
		for {
			select {
			case <-ticker.C:
				mutex.RLock()
				if len(errs) > 0 {
					fmt.Printf("*** %d failed query(s) out of %d\n", len(errs), numInvocations)
				}
				fmt.Printf("*** %d successfull query(s) out of %d\n", success, numInvocations)
				mutex.RUnlock()
			case <-done:
				return
			}
		}
	}()

	startTime := time.Now()
	sleepTime := time.Duration(cliconfig.Config().SleepTime()) * time.Millisecond

	for _, task := range tasks {
		if err := executor.Submit(task); err != nil {
			return errors.Errorf("error submitting task: %s", err)
		}
		if sleepTime > 0 {
			time.Sleep(sleepTime)
		}
	}

	// Wait for all tasks to complete
	wg.Wait()
	done <- true

	duration := time.Now().Sub(startTime)

	var allErrs []error
	var attempts int
	for _, task := range tasks {
		attempts = attempts + task.Attempts()
		if task.LastError() != nil {
			allErrs = append(allErrs, task.LastError())
		}
	}

	if len(errs) > 0 {
		fmt.Printf("\n*** %d errors querying chaincode:\n", len(errs))
		for _, err := range errs {
			fmt.Printf("%s\n", err)
		}
	} else if len(allErrs) > 0 {
		fmt.Printf("\n*** %d transient errors querying chaincode:\n", len(allErrs))
		for _, err := range allErrs {
			fmt.Printf("%s\n", err)
		}
	}

	if numInvocations/len(argsArray) > 1 {
		fmt.Printf("\n")
		fmt.Printf("*** ---------- Summary: ----------\n")
		fmt.Printf("***   - Queries:         %d\n", numInvocations)
		fmt.Printf("***   - Concurrency:     %d\n", cliconfig.Config().Concurrency())
		fmt.Printf("***   - Successfull:     %d\n", success)
		fmt.Printf("***   - Total attempts:  %d\n", attempts)
		fmt.Printf("***   - Duration:        %2.2fs\n", duration.Seconds())
		fmt.Printf("***   - Rate:            %2.2f/s\n", float64(numInvocations)/duration.Seconds())
		fmt.Printf("***   - Average:         %2.2fs\n", average(append(successDurations, failDurations...)))
		fmt.Printf("***   - Average Success: %2.2fs\n", average(successDurations))
		fmt.Printf("***   - Average Fail:    %2.2fs\n", average(failDurations))
		fmt.Printf("***   - Min Success:     %2.2fs\n", min(successDurations))
		fmt.Printf("***   - Max Success:     %2.2fs\n", max(successDurations))
		fmt.Printf("*** ------------------------------\n")
	}

	return nil
}


================================================
FILE: fabric-cli/cmd/fabric-cli/chaincode/querytask/querytask.go
================================================
/*
Copyright SecureKey Technologies Inc. All Rights Reserved.

SPDX-License-Identifier: Apache-2.0
*/

package querytask

import (
	"github.com/hyperledger/fabric-sdk-go/pkg/client/channel"
	"github.com/hyperledger/fabric-sdk-go/pkg/client/channel/invoke"
	"github.com/hyperledger/fabric-sdk-go/pkg/common/errors/retry"
	"github.com/hyperledger/fabric-sdk-go/pkg/common/providers/fab"
	"github.com/securekey/fabric-examples/fabric-cli/cmd/fabric-cli/action"
	"github.com/securekey/fabric-examples/fabric-cli/cmd/fabric-cli/chaincode/utils"
	cliconfig "github.com/securekey/fabric-examples/fabric-cli/cmd/fabric-cli/config"
	"github.com/securekey/fabric-examples/fabric-cli/cmd/fabric-cli/printer"
)

// Task is the query task
type Task struct {
	ctxt          utils.Context
	channelClient *channel.Client
	targets       []fab.Peer
	retryOpts     retry.Opts
	id            string
	args          *action.ArgStruct
	startedCB     func()
	completedCB   func(err error)
	printer       printer.Printer
	verbose       bool
	payloadOnly   bool
	validate      bool
	attempt       int
	lastErr       error
}

// New creates a new query Task
func New(ctxt utils.Context, id string, channelClient *channel.Client, targets []fab.Peer, args *action.ArgStruct, printer printer.Printer,
	retryOpts retry.Opts, verbose bool, payloadOnly bool, validate bool, startedCB func(), completedCB func(err error)) *Task {
	return &Task{
		ctxt:          ctxt,
		id:            id,
		channelClient: channelClient,
		targets:       targets,
		retryOpts:     retryOpts,
		args:          args,
		startedCB:     startedCB,
		completedCB:   completedCB,
		attempt:       1,
		printer:       printer,
		verbose:       verbose,
		payloadOnly:   payloadOnly,
		validate:      validate,
	}
}

// Invoke invokes the query task
func (t *Task) Invoke() {
	t.startedCB()

	var opts []channel.RequestOption
	opts = append(opts, channel.WithRetry(t.retryOpts))
	opts = append(opts, channel.WithBeforeRetry(func(err error) {
		t.attempt++
	}))
	if len(t.targets) > 0 {
		opts = append(opts, channel.WithTargets(t.targets...))
	}

	request := channel.Request{
		ChaincodeID: cliconfig.Config().ChaincodeID(),
		Fcn:         t.args.Func,
		Args:        utils.AsBytes(t.ctxt, t.args.Args),
	}

	var additionalHandlers []invoke.Handler
	if t.validate {
		// Add the validation handlers
		additionalHandlers = append(additionalHandlers,
			invoke.NewEndorsementValidationHandler(
				invoke.NewSignatureValidationHandler(),
			),
		)
	}

	response, err := t.channelClient.InvokeHandler(
		invoke.NewProposalProcessorHandler(
			invoke.NewEndorsementHandler(additionalHandlers...),
		),
		request, opts...)
	if err != nil {
		cliconfig.Config().Logger().Debugf("(%s) - Error querying chaincode: %s\n", t.id, err)
		t.lastErr = err
		t.completedCB(err)
	} else {
		cliconfig.Config().Logger().Debugf("(%s) - Chaincode query was successful\n", t.id)

		if t.verbose {
			t.printer.PrintTxProposalResponses(response.Responses, t.payloadOnly)
		}

		t.completedCB(nil)
	}
}

// Attempts returns the number of invocation attempts that were made
// in order to achieve a successful response
func (t *Task) Attempts() int {
	return t.attempt
}

// LastError returns the last error that was recorder
func (t *Task) LastError() error {
	return t.lastErr
}


================================================
FILE: fabric-cli/cmd/fabric-cli/chaincode/task/task.go
================================================
/*
Copyright SecureKey Technologies Inc. All Rights Reserved.

SPDX-License-Identifier: Apache-2.0
*/

package task

// Task is an invocable unit of work
type Task interface {
	// Invoke invokes the task
	Invoke()

	// Attempts returns the number of invocation attempts that were made
	// in order to achieve a successful response
	Attempts() int

	// LastError returns the last error that occurred
	LastError() error
}


================================================
FILE: fabric-cli/cmd/fabric-cli/chaincode/upgradecmd.go
================================================
/*
Copyright SecureKey Technologies Inc. All Rights Reserved.

SPDX-License-Identifier: Apache-2.0
*/

package chaincode

import (
	"encoding/json"
	"fmt"
	"strings"

	fabricCommon "github.com/hyperledger/fabric-protos-go/common"
	pb "github.com/hyperledger/fabric-protos-go/peer"
	"github.com/hyperledger/fabric-sdk-go/pkg/client/resmgmt"
	"github.com/hyperledger/fabric-sdk-go/third_party/github.com/hyperledger/fabric/common/cauthdsl"
	"github.com/pkg/errors"
	"github.com/securekey/fabric-examples/fabric-cli/cmd/fabric-cli/action"
	"github.com/securekey/fabric-examples/fabric-cli/cmd/fabric-cli/chaincode/utils"
	cliconfig "github.com/securekey/fabric-examples/fabric-cli/cmd/fabric-cli/config"
	"github.com/spf13/cobra"
	"github.com/spf13/pflag"
)

var upgradeCmd = &cobra.Command{
	Use:   "upgrade",
	Short: "Upgrade chaincode.",
	Long:  "Upgrades the chaincode",
	Run: func(cmd *cobra.Command, args []string) {
		if cliconfig.Config().ChaincodeID() == "" {
			fmt.Printf("\nMust specify the chaincode ID\n\n")
			cmd.HelpFunc()(cmd, args)
			return
		}
		if cliconfig.Config().ChaincodePath() == "" {
			fmt.Printf("\nMust specify the path of the chaincode\n\n")
			cmd.HelpFunc()(cmd, args)
			return
		}
		action, err := newUpgradeAction(cmd.Flags())
		if err != nil {
			cliconfig.Config().Logger().Errorf("Error while initializing upgradeAction: %v", err)
			return
		}

		defer action.Terminate()

		err = action.invoke()
		if err != nil {
			cliconfig.Config().Logger().Errorf("Error while running upgradeAction: %v", err)
		}
	},
}

func getUpgradeCmd() *cobra.Command {
	flags := upgradeCmd.Flags()
	cliconfig.InitPeerURL(flags)
	cliconfig.InitChannelID(flags)
	cliconfig.InitChaincodeID(flags)
	cliconfig.InitChaincodePath(flags)
	cliconfig.InitChaincodeVersion(flags)
	cliconfig.InitArgs(flags)
	cliconfig.InitChaincodePolicy(flags)
	cliconfig.InitCollectionConfigFile(flags)
	cliconfig.InitTimeout(flags)
	return upgradeCmd
}

type upgradeAction struct {
	action.Action
}

func newUpgradeAction(flags *pflag.FlagSet) (*upgradeAction, error) {
	action := &upgradeAction{}
	err := action.Initialize(flags)
	if len(action.Peers()) == 0 {
		return nil, errors.Errorf("a peer must be specified")
	}
	return action, err
}

func (a *upgradeAction) invoke() error {
	argBytes := []byte(cliconfig.Config().Args())
	args := &action.ArgStruct{}

	if err := json.Unmarshal(argBytes, args); err != nil {
		return errors.Errorf("Error unmarshalling JSON arg string: %v", err)
	}

	resMgmtClient, err := a.ResourceMgmtClient()
	if err != nil {
		return err
	}

	cliconfig.Config().Logger().Infof("Sending upgrade %s ...\n", cliconfig.Config().ChaincodeID())

	chaincodePolicy, err := a.newChaincodePolicy()
	if err != nil {
		return err
	}

	// Private Data Collection Configuration
	// - see fixtures/config/pvtdatacollection.json for sample config file
	var collConfig []*pb.CollectionConfig
	collConfigFile := cliconfig.Config().CollectionConfigFile()
	if collConfigFile != "" {
		collConfig, err = getCollectionConfigFromFile(cliconfig.Config().CollectionConfigFile())
		if err != nil {
			return errors.Wrapf(err, "error getting private data collection configuration from file [%s]", cliconfig.Config().CollectionConfigFile())
		}
	}

	req := resmgmt.UpgradeCCRequest{
		Name:       cliconfig.Config().ChaincodeID(),
		Path:       cliconfig.Config().ChaincodePath(),
		Version:    cliconfig.Config().ChaincodeVersion(),
		Args:       utils.AsBytes(utils.NewContext(), args.Args),
		Policy:     chaincodePolicy,
		CollConfig: collConfig,
	}

	_, err = resMgmtClient.UpgradeCC(cliconfig.Config().ChannelID(), req, resmgmt.WithTargets(a.Peers()...))
	if err != nil {
		if strings.Contains(err.Error(), "chaincode exists "+cliconfig.Config().ChaincodeID()) {
			// Ignore
			cliconfig.Config().Logger().Infof("Chaincode %s already instantiated.", cliconfig.Config().ChaincodeID())
			fmt.Printf("...chaincode %s already instantiated.\n", cliconfig.Config().ChaincodeID())
			return nil
		}
		return errors.Errorf("error instantiating chaincode: %v", err)
	}

	fmt.Printf("...successfuly upgraded chaincode %s on channel %s.\n", cliconfig.Config().ChaincodeID(), cliconfig.Config().ChannelID())

	return nil
}

func (a *upgradeAction) newChaincodePolicy() (*fabricCommon.SignaturePolicyEnvelope, error) {
	if cliconfig.Config().ChaincodePolicy() != "" {
		// Create a signature policy from the policy expression passed in
		return newChaincodePolicy(cliconfig.Config().ChaincodePolicy())
	}

	// Default policy is 'signed my any member' for all known orgs
	var mspIDs []string
	for _, orgID := range cliconfig.Config().OrgIDs() {
		orgConfig, ok := a.EndpointConfig().NetworkConfig().Organizations[orgID]
		if !ok {
			return nil, errors.Errorf("Unable to get the MSP ID from org ID %s", orgID)
		}
		mspIDs = append(mspIDs, orgConfig.MSPID)
	}
	return cauthdsl.SignedByAnyMember(mspIDs), nil
}


================================================
FILE: fabric-cli/cmd/fabric-cli/chaincode/utils/test.json
================================================
{"Field1": "Value1"}

================================================
FILE: fabric-cli/cmd/fabric-cli/chaincode/utils/util.go
================================================
/*
Copyright SecureKey Technologies Inc. All Rights Reserved.

SPDX-License-Identifier: Apache-2.0
*/

package utils

import (
	"fmt"
	"github.com/pkg/errors"
	"io/ioutil"
	"math/rand"
	"os"
	"path/filepath"
	"strconv"
	"strings"
	"sync/atomic"
	"time"

	cliconfig "github.com/securekey/fabric-examples/fabric-cli/cmd/fabric-cli/config"
)

const (
	randFunc = "$rand("
	padFunc  = "$pad("
	seqFunc  = "$seq("
	setFunc  = "$set("
	fileFunc = "$file("
	varExp   = "${"
)

var (
	sequence uint64
)

type Context interface {
	SetVar(name, value string)
	GetVar(name string) (string, bool)
}

// AsBytes converts the string array to an array of byte arrays.
// The args may contain functions $rand(n) or $pad(n,chars).
// The functions are evaluated before returning.
//
// Examples:
// - "key$rand(3)" -> "key0" or "key1" or "key2"
// - "val$pad(3,XYZ) -> "valXYZXYZXYZ"
// - "val$pad($rand(3),XYZ) -> "val" or "valXYZ" or "valXYZXYZ"
// - "key$seq()" -> "key1", "key2", "key2", ...
// - "val$pad($seq(),X)" -> "valX", "valXX", "valXX", "valXXX", ...
// - "Key_$set(x,$seq())=Val_${x}" -> Key_1=Val_1, Key_2=Val_2, ...
func AsBytes(ctxt Context, args []string) [][]byte {
	rand := rand.New(rand.NewSource(time.Now().UTC().UnixNano()))
	bytes := make([][]byte, len(args))

	if cliconfig.Config().Verbose() {
		fmt.Printf("Args:\n")
	}
	for i, a := range args {
		arg := getArg(ctxt, rand, a)
		if cliconfig.Config().Verbose() {
			fmt.Printf("- [%d]=%s\n", i, arg)
		}
		bytes[i] = []byte(arg)
	}
	return bytes
}

func getArg(ctxt Context, r *rand.Rand, arg string) string {
	arg = evaluateSeqExpression(arg)
	arg = evaluateRandExpression(r, arg)
	arg = evaluatePadExpression(arg)
	arg = evaluateFileExpression(arg)
	arg = evaluateSetExpression(ctxt, arg)
	arg = evaluateVarExpression(ctxt, arg)
	return arg
}

// evaluateSeqExpression replaces occurrences of $seq() with a sequential
// number starting at 1 and incrementing for each task
func evaluateSeqExpression(arg string) string {
	return evaluateExpression(arg, seqFunc, ")",
		func(expression string) (string, error) {
			return strconv.FormatUint(atomic.AddUint64(&sequence, 1), 10), nil
		})
}

// evaluateRandExpression replaces occurrences of $rand(n) with a random
// number between 0 and n (exclusive)
func evaluateRandExpression(r *rand.Rand, arg string) string {
	return evaluateExpression(arg, randFunc, ")",
		func(expression string) (string, error) {
			n, err := strconv.ParseInt(expression, 10, 64)
			if err != nil {
				return "", errors.Errorf("invalid number %s in $rand expression\n", expression)
			}
			return strconv.FormatInt(r.Int63n(n), 10), nil
		})
}

// evaluatePadExpression replaces occurrences of $pad(n,chars) with n of the given pad characters
func evaluatePadExpression(arg string) string {
	return evaluateExpression(arg, padFunc, ")",
		func(expression string) (string, error) {
			s := strings.Split(expression, ",")
			if len(s) != 2 {
				return "", errors.Errorf("invalid $pad expression: '%s'. Expecting $pad(n,chars)", expression)
			}

			n, err := strconv.Atoi(s[0])
			if err != nil {
				return "", errors.Errorf("invalid number %s in $pad expression\n", s[0])
			}

			result := ""
			for i := 0; i < n; i++ {
				result += s[1]
			}

			return result, nil
		})
}

// evaluateFileExpression replaces occurrences of $file(path) with the contents of the file
func evaluateFileExpression(arg string) string {
	return evaluateExpression(arg, fileFunc, ")",
		func(expression string) (string, error) {
			return readFile(expression)
		})
}

// evaluateSetExpression sets a variable to the given value using the syntax $set(var,expression).
// The variable may be used in a subsequent expression, ${var}.
// Example: $set(v,$rand(10)) sets variable "v" to a random value that may be accessed as ${v}
func evaluateSetExpression(ctxt Context, arg string) string {
	return evaluateExpression(arg, setFunc, ")",
		func(expression string) (string, error) {
			s := strings.Split(expression, ",")
			if len(s) != 2 {
				return "", errors.Errorf("invalid $set expression: '%s'. Expecting $set(var,value)", expression)
			}

			variable := s[0]
			value := s[1]

			ctxt.SetVar(variable, value)
			return value, nil
		})
}

// evaluateVarExpression references a variable previously set with the $set(var,expression) expression.
// Example: ${someVar}
func evaluateVarExpression(ctxt Context, arg string) string {
	return evaluateExpression(arg, varExp, "}",
		func(varName string) (string, error) {
			value, ok := ctxt.GetVar(varName)
			if !ok {
				return "", errors.Errorf("variable [%s] not set", varName)
			}
			return value, nil
		})
}

func evaluateExpression(expression, funcType, endDelim string, evaluate func(string) (string, error)) string {
	result := ""
	for {
		i := strings.Index(expression, funcType)
		if i == -1 {
			result += expression
			break
		}

		j := strings.Index(expression[i:], endDelim)
		if j == -1 {
			fmt.Printf("expecting '%s' in expression '%s'", endDelim, expression)
			result = expression
			break
		}

		j = i + j

		replacement, err := evaluate(expression[i+len(funcType) : j])
		if err != nil {
			fmt.Printf("%s\n", err)
			result += expression[0 : j+1]
		} else {
			result += expression[0:i] + replacement
		}

		expression = expression[j+1:]
	}

	return result
}

func NewContext() Context {
	return &defaultContext{
		vars: make(map[string]string),
	}
}

type defaultContext struct {
	vars map[string]string
}

func (c *defaultContext) SetVar(k, v string) {
	c.vars[k] = v
}

func (c *defaultContext) GetVar(k string) (string, bool) {
	value, ok := c.vars[k]
	return value, ok
}

func readFile(filePath string) (string, error) {
	fmt.Printf("Reading file: [%s]", filePath)
	file, err := os.Open(filepath.Clean(filePath))
	if err != nil {
		return "", errors.Wrapf(err, "error opening file [%s]", filePath)
	}
	defer func() {
		fileErr := file.Close()
		if fileErr != nil {
			cliconfig.Config().Logger().Errorf("Failed to close file : %s", fileErr)
		}
	}()

	configBytes, err := ioutil.ReadAll(file)
	if err != nil {
		return "", errors.Wrapf(err, "error reading config file [%s]", filePath)
	}
	return string(configBytes), nil
}


================================================
FILE: fabric-cli/cmd/fabric-cli/chaincode/utils/util_test.go
================================================
/*
Copyright SecureKey Technologies Inc. All Rights Reserved.

SPDX-License-Identifier: Apache-2.0
*/

package utils

import (
	"fmt"
	"github.com/stretchr/testify/assert"
	"math/rand"
	"testing"
	"time"
)

func TestEvaluatePadExpression(t *testing.T) {
	result := evaluatePadExpression("Value_$pad(3,XYZ)!")
	assert.Equal(t, "Value_XYZXYZXYZ!", result)

	result = evaluatePadExpression("Value_$pad(3,XYZ)_$pad(2,123)!")
	assert.Equal(t, "Value_XYZXYZXYZ_123123!", result)
}

func TestFailEvaluatePadExpression(t *testing.T) {
	result := evaluatePadExpression("Value_$pad(3,XYZ!")
	assert.Equal(t, "Value_$pad(3,XYZ!", result)

	result = evaluatePadExpression("Value_$pad3,XYZ)!")
	assert.Equal(t, "Value_$pad3,XYZ)!", result)

	result = evaluatePadExpression("Value_$pad(3)!")
	assert.Equal(t, "Value_$pad(3)!", result)

	result = evaluatePadExpression("Value_$pad(3)_$pad(3,X)!")
	assert.Equal(t, "Value_$pad(3)_XXX!", result)
}

func TestEvaluateRandExpression(t *testing.T) {
	rand := rand.New(rand.NewSource(time.Now().UTC().UnixNano()))
	for i := 0; i < 5; i++ {
		result := evaluateRandExpression(rand, "Value_$rand(2)!")
		assert.True(t, result == "Value_0!" || result == "Value_1!")

		result = evaluateRandExpression(rand, "Value_$rand(2)_$rand(1)!")
		assert.True(t, result == "Value_0_0!" || result == "Value_1_0!")
	}
}

func TestFailEvaluateRandExpression(t *testing.T) {
	rand := rand.New(rand.NewSource(time.Now().UTC().UnixNano()))
	result := evaluateRandExpression(rand, "Value_$rand(3,!")
	assert.Equal(t, "Value_$rand(3,!", result)

	result = evaluateRandExpression(rand, "Value_$rand3)!")
	assert.Equal(t, "Value_$rand3)!", result)

	result = evaluateRandExpression(rand, "Value_$rand(X)!")
	assert.Equal(t, "Value_$rand(X)!", result)

	result = evaluateRandExpression(rand, "Value_$rand(X)_$rand(1)!")
	assert.Equal(t, "Value_$rand(X)_0!", result)
}

func TestEvaluateSeqExpression(t *testing.T) {
	assert.Equal(t, "Value_1!", evaluateSeqExpression("Value_$seq()!"))
	assert.Equal(t, "Value_2!", evaluateSeqExpression("Value_$seq()!"))
	assert.Equal(t, "Value_3!", evaluateSeqExpression("Value_$seq()!"))
}

func TestFailEvaluateSeqExpression(t *testing.T) {
	assert.Equal(t, "Value_$seq(!", evaluateSeqExpression("Value_$seq(!"))
}

func TestEvaluateFileExpression(t *testing.T) {
	assert.Equal(t, `{"Field1": "Value1"}`, evaluateFileExpression("$file(./test.json)"))
}

func TestFailEvaluateFileExpression(t *testing.T) {
	assert.Equal(t, "$file(./invalid.json)", evaluateSeqExpression("$file(./invalid.json)"))
}

func TestEvaluateSetExpression(t *testing.T) {
	ctxt := NewContext()
	assert.Equal(t, "Value_1000!", evaluateSetExpression(ctxt, "Value_$set(x,1000)!"))
	assert.Equal(t, "Value_1000!", evaluateVarExpression(ctxt, "Value_${x}!"))
}

func TestFailEvaluateSetExpression(t *testing.T) {
	ctxt := NewContext()
	assert.Equal(t, "Value_$set(x,1000", evaluateSetExpression(ctxt, "Value_$set(x,1000"))
	assert.Equal(t, "Value_${x", evaluateVarExpression(ctxt, "Value_${x"))

	// Var not set
	assert.Equal(t, "Value_${x}", evaluateVarExpression(NewContext(), "Value_${x}"))
}

func TestGetArg(t *testing.T) {
	rand := rand.New(rand.NewSource(time.Now().UTC().UnixNano()))
	result := getArg(NewContext(), rand, "Value_$pad(3,X)!")
	assert.Equal(t, "Value_XXX!", result)

	for i := 0; i < 5; i++ {
		result := getArg(NewContext(), rand, "Value_$rand(2)!")
		assert.True(t, result == "Value_0!" || result == "Value_1!")
	}

	for i := 0; i < 5; i++ {
		result := getArg(NewContext(), rand, "Value_$pad(3,X)_$rand(2)!")
		assert.True(t, result == "Value_XXX_0!" || result == "Value_XXX_1!")
	}

	for i := 0; i < 5; i++ {
		result := getArg(NewContext(), rand, "Value_$pad($rand(3),X)!")
		assert.True(t, result == "Value_!" || result == "Value_X!" || result == "Value_XX!")
	}

	n := sequence + 1
	for i := n; i <= n+5; i++ {
		result := getArg(NewContext(), rand, "Value_$seq()!")
		assert.True(t, result == fmt.Sprintf("Value_%d!", i))
	}

	n = sequence + 1
	for i := n; i <= n+5; i++ {
		ctxt := NewContext()
		assert.Equal(t, fmt.Sprintf("Key_%d=Val_%d", i, i), getArg(ctxt, rand, "Key_$set(x,$seq())=Val_${x}"))
		assert.Equal(t, fmt.Sprintf("Value_%d!", i), getArg(ctxt, rand, "Value_${x}!"))
	}
}


================================================
FILE: fabric-cli/cmd/fabric-cli/channel/channelcmd.go
================================================
/*
Copyright SecureKey Technologies Inc. All Rights Reserved.

SPDX-License-Identifier: Apache-2.0
*/

package channel

import (
	cliconfig "github.com/securekey/fabric-examples/fabric-cli/cmd/fabric-cli/config"
	"github.com/spf13/cobra"
)

var channelCmd = &cobra.Command{
	Use:   "channel",
	Short: "Channel commands",
	Long:  "Channel commands",
	Run: func(cmd *cobra.Command, args []string) {
		cmd.HelpFunc()(cmd, args)
	},
}

// Cmd returns the channel command
func Cmd() *cobra.Command {
	cliconfig.InitChannelID(channelCmd.Flags())

	channelCmd.AddCommand(getChannelCreateCmd())
	channelCmd.AddCommand(getChannelJoinCmd())

	return channelCmd
}


================================================
FILE: fabric-cli/cmd/fabric-cli/channel/channelcreatecmd.go
================================================
/*
Copyright SecureKey Technologies Inc. All Rights Reserved.

SPDX-License-Identifier: Apache-2.0
*/

package channel

import (
	"fmt"

	"github.com/hyperledger/fabric-sdk-go/pkg/client/resmgmt"
	"github.com/hyperledger/fabric-sdk-go/pkg/common/providers/msp"
	"github.com/pkg/errors"
	"github.com/securekey/fabric-examples/fabric-cli/cmd/fabric-cli/action"
	cliconfig "github.com/securekey/fabric-examples/fabric-cli/cmd/fabric-cli/config"
	"github.com/spf13/cobra"
	"github.com/spf13/pflag"
)

var channelCreateCmd = &cobra.Command{
	Use:   "create",
	Short: "Create Channel",
	Long:  "Create a new channel",
	Run: func(cmd *cobra.Command, args []string) {
		action, err := newChannelCreateAction(cmd.Flags())
		if err != nil {
			cliconfig.Config().Logger().Errorf("Error while initializing channelCreateAction: %v", err)
			return
		}

		defer action.Terminate()

		err = action.invoke()
		if err != nil {
			cliconfig.Config().Logger().Errorf("Error while running channelCreateAction: %v", err)
		}
	},
}

func getChannelCreateCmd() *cobra.Command {
	flags := channelCreateCmd.Flags()
	cliconfig.InitChannelID(flags)
	cliconfig.InitOrdererURL(flags)
	cliconfig.InitTxFile(flags)
	return channelCreateCmd
}

type channelCreateAction struct {
	action.Action
}

func newChannelCreateAction(flags *pflag.FlagSet) (*channelCreateAction, error) {
	a := &channelCreateAction{}
	err := a.Initialize(flags)
	return a, err
}

func (a *channelCreateAction) invoke() error {
	user, err := a.OrgAdminUser(a.OrgID())
	if err != nil {
		return err
	}

	chMgmtClient, err := a.ResourceMgmtClient()
	if err != nil {
		return err
	}

	fmt.Printf("Attempting to create/update channel: %s\n", cliconfig.Config().ChannelID())

	req := resmgmt.SaveChannelRequest{
		ChannelID:         cliconfig.Config().ChannelID(),
		ChannelConfigPath: cliconfig.Config().TxFile(),
		SigningIdentities: []msp.SigningIdentity{user},
	}

	orderer, err := a.RandomOrderer()
	if err != nil {
		return err
	}

	_, err = chMgmtClient.SaveChannel(req, resmgmt.WithOrderer(orderer))
	if err != nil {
		return errors.Errorf("Error from save channel: %s", err.Error())
	}

	fmt.Printf("Channel created/updated: %s\n", cliconfig.Config().ChannelID())

	return nil
}


================================================
FILE: fabric-cli/cmd/fabric-cli/channel/channeljoincmd.go
================================================
/*
Copyright SecureKey Technologies Inc. All Rights Reserved.

SPDX-License-Identifier: Apache-2.0
*/

package channel

import (
	"fmt"

	"github.com/hyperledger/fabric-sdk-go/pkg/client/resmgmt"
	"github.com/hyperledger/fabric-sdk-go/pkg/common/providers/fab"
	"github.com/pkg/errors"
	"github.com/securekey/fabric-examples/fabric-cli/cmd/fabric-cli/action"
	cliconfig "github.com/securekey/fabric-examples/fabric-cli/cmd/fabric-cli/config"
	"github.com/spf13/cobra"
	"github.com/spf13/pflag"
)

var chainJoinCmd = &cobra.Command{
	Use:   "join",
	Short: "Join Channel",
	Long:  "Join a channel",
	Run: func(cmd *cobra.Command, args []string) {
		action, err := newChannelJoinAction(cmd.Flags())
		if err != nil {
			cliconfig.Config().Logger().Errorf("Error while initializing channelJoinAction: %v", err)
			return
		}

		defer action.Terminate()

		err = action.invoke()
		if err != nil {
			cliconfig.Config().Logger().Errorf("Error while running channelJoinAction: %v", err)
		}
	},
}

func getChannelJoinCmd() *cobra.Command {
	flags := chainJoinCmd.Flags()
	cliconfig.InitChannelID(flags)
	cliconfig.InitOrdererURL(flags)
	cliconfig.InitPeerURL(flags)
	return chainJoinCmd
}

type channelJoinAction struct {
	action.Action
}

func newChannelJoinAction(flags *pflag.FlagSet) (*channelJoinAction, error) {
	action := &channelJoinAction{}
	err := action.Initialize(flags)
	if err != nil {
		return nil, err
	}
	if len(action.Peers()) == 0 {
		return nil, errors.Errorf("at least one peer is required for join")
	}
	return action, nil
}

func (a *channelJoinAction) invoke() error {
	fmt.Printf("Attempting to join channel: %s\n", cliconfig.Config().ChannelID())

	var lastErr error
	for orgID, peers := range a.PeersByOrg() {
		fmt.Printf("Joining channel %s on org[%s] peers:\n", cliconfig.Config().ChannelID(), orgID)
		for _, peer := range peers {
			fmt.Printf("-- %s\n", peer.URL())
		}
		err := a.joinChannel(orgID, peers)
		if err != nil {
			lastErr = err
		}
	}
	return lastErr
}

func (a *channelJoinAction) joinChannel(orgID string, peers []fab.Peer) error {
	cliconfig.Config().Logger().Debugf("Joining channel [%s]...\n", cliconfig.Config().ChannelID())

	fmt.Printf("==========> JOIN ORG: %s\n", orgID)

	resMgmtClient, err := a.ResourceMgmtClientForOrg(orgID)
	if err != nil {
		return err
	}

	orderer, err := a.RandomOrderer()
	if err != nil {
		return err
	}

	err = resMgmtClient.JoinChannel(cliconfig.Config().ChannelID(), resmgmt.WithTargets(peers...), resmgmt.WithOrderer(orderer))
	if err != nil {
		return errors.WithMessage(err, "Could not join channel: %v")
	}

	fmt.Printf("Channel %s joined!\n", cliconfig.Config().ChannelID())

	return nil
}


================================================
FILE: fabric-cli/cmd/fabric-cli/cmd/fabric-cli.go
================================================
/*
Copyright SecureKey Technologies Inc. All Rights Reserved.

SPDX-License-Identifier: Apache-2.0
*/

package cmd

import (
	"os"

	"github.com/securekey/fabric-examples/fabric-cli/cmd/fabric-cli/chaincode"
	"github.com/securekey/fabric-examples/fabric-cli/cmd/fabric-cli/channel"
	cliconfig "github.com/securekey/fabric-examples/fabric-cli/cmd/fabric-cli/config"
	"github.com/securekey/fabric-examples/fabric-cli/cmd/fabric-cli/event"
	"github.com/securekey/fabric-examples/fabric-cli/cmd/fabric-cli/query"
	"github.com/spf13/cobra"
)

func newFabricCLICmd() *cobra.Command {

	mainCmd := &cobra.Command{
		Use: "fabric-cli",
		PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
			return nil
		},
		Run: func(cmd *cobra.Command, args []string) {
			cmd.HelpFunc()(cmd, args)
		},
	}

	flags := mainCmd.PersistentFlags()
	cliconfig.InitConfigFile(flags)
	cliconfig.InitLoggingLevel(flags)
	cliconfig.InitUserName(flags)
	cliconfig.InitUserPassword(flags)
	cliconfig.InitOrdererTLSCertificate(flags)
	cliconfig.InitPrintFormat(flags)
	cliconfig.InitWriter(flags)
	cliconfig.InitBase64(flags)
	cliconfig.InitOrgIDs(flags)

	mainCmd.AddCommand(chaincode.Cmd())
	mainCmd.AddCommand(query.Cmd())
	mainCmd.AddCommand(channel.Cmd())
	mainCmd.AddCommand(event.Cmd())

	return mainCmd
}

func Execute() {
	if newFabricCLICmd().Execute() != nil {
		os.Exit(1)
	}
}


================================================
FILE: fabric-cli/cmd/fabric-cli/config/config.go
================================================
/*
Copyright SecureKey Technologies Inc. All Rights Reserved.

SPDX-License-Identifier: Apache-2.0
*/

package config

import (
	"fmt"
	"strconv"
	"time"

	"github.com/hyperledger/fabric-sdk-go/pkg/fab/events/deliverclient/seek"

	"strings"

	"github.com/spf13/pflag"

	"os"

	"github.com/hyperledger/fabric-sdk-go/pkg/common/logging"
	"github.com/hyperledger/fabric-sdk-go/pkg/common/providers/core"
	"github.com/hyperledger/fabric-sdk-go/pkg/common/providers/fab"
	"github.com/hyperledger/fabric-sdk-go/pkg/core/config"
)

const (
	loggerName    = "fabriccli"
	userStatePath = "/tmp/enroll_user"

	// AutoDetectSelectionProvider indicates that a selection provider is to be automatically determined using channel capabilities
	AutoDetectSelectionProvider = "auto"

	// StaticSelectionProvider indicates that a static selection provider is to be used for selecting peers for invoke/query commands
	StaticSelectionProvider = "static"

	// DynamicSelectionProvider indicates that a dynamic selection provider is to be used for selecting peers for invoke/query commands
	DynamicSelectionProvider = "dynamic"

	// FabricSelectionProvider indicates that the Fabric selection provider is to be used for selecting peers for invoke/query commands
	FabricSelectionProvider = "fabric"
)

// Flags
const (
	UserFlag        = "user"
	userDescription = "The user"
	defaultUser     = ""

	PasswordFlag        = "pw"
	passwordDescription = "The password of the user"
	defaultPassword     = ""

	ChaincodeVersionFlag        = "v"
	chaincodeVersionDescription = "The chaincode version"
	defaultChaincodeVersion     = "v0"

	LoggingLevelFlag        = "logging-level"
	loggingLevelDescription = "Logging level - ERROR, WARN, INFO, DEBUG"
	defaultLoggingLevel     = "ERROR"

	OrgIDsFlag        = "orgid"
	orgIDsDescription = "A comma-separated list of organization IDs"
	defaultOrgIDs     = ""

	ChannelIDFlag        = "cid"
	channelIDDescription = "The channel ID"
	defaultChannelID     = ""

	ChaincodeIDFlag        = "ccid"
	chaincodeIDDescription = "The Chaincode ID"
	defaultChaincodeID     = ""

	ChaincodePathFlag        = "ccp"
	chaincodePathDescription = "The chaincode path"
	defaultChaincodePath     = ""

	ConfigFileFlag        = "config"
	configFileDescription = "The path of the config.yaml file"
	defaultConfigFile     = ""

	PeerURLFlag        = "peer"
	peerURLDescription = "A comma-separated list of peer targets, e.g. 'grpcs://localhost:7051,grpcs://localhost:8051'"
	defaultPeerURL     = ""

	OrdererFlag           = "orderer"
	ordererURLDescription = "The URL of the orderer, e.g. grpcs://localhost:7050"
	defaultOrdererURL     = ""

	PrintFormatFlag        = "format"
	printFormatDescription = "The output format - display, json, raw"

	WriterFlag        = "writer"
	writerDescription = "The writer - stdout, stderr, log"

	Base64Flag        = "base64"
	base64Description = "If true then binary values are encoded in base64 (only applies to 'display' format)"

	CertificateFileFlag    = "cacert"
	certificateDescription = "The path of the ca-cert.pem file"
	defaultCertificate     = ""

	ArgsFlag        = "args"
	argsDescription = `The args in JSON format. Example: {"Func":"function","Args":["arg1","arg2"]}. Note that $rand(N) may be used anywhere within the value of the arg in order to generate a random value between 0 and N. For example {"Func":"function","Args":["arg_$rand(100)","$rand(10)"]}.`

	IterationsFlag        = "iterations"
	iterationsDescription = "The number of times to invoke the chaincode"
	defaultIterations     = "1"

	SleepFlag            = "sleep"
	sleepTimeDescription = "The number of milliseconds to sleep between invocations of the chaincode."
	defaultSleepTime     = "0"

	TxFileFlag        = "txfile"
	txFileDescription = "The path of the channel.tx file"
	defaultTxFile     = ""

	ChaincodeEventFlag        = "event"
	chaincodeEventDescription = "The name of the chaincode event to listen for"
	defaultChaincodeEvent     = ""

	SeekTypeFlag        = "seek"
	seekTypeDescription = "The seek type. Possible values: oldest - delivers all blocks from the oldest block; newest - delivers the newest block; from - delivers from the block number as specified by the '--num' flag"
	defaultSeekType     = string(seek.Newest)

	TxIDFlag        = "txid"
	txIDDescription = "The transaction ID"
	defaultTxID     = ""

	BlockNumFlag        = "num"
	blockNumDescription = "The block number"
	defaultBlockNum     = "0"

	BlockHashFlag        = "hash"
	blockHashDescription = "The block hash"
	defaultBlockHash     = ""

	TraverseFlag        = "traverse"
	traverseDescription = "Blocks will be traversed starting with the given block in reverse order up to the given number of blocks"
	defaultTraverse     = "0"

	ChaincodePolicyFlag        = "policy"
	chaincodePolicyDescription = "The chaincode policy, e.g. OutOf(1,'Org1MSP.admin','Org2MSP.admin',AND('Org3MSP.member','Org4MSP.member'))"
	defaultChaincodePolicy     = ""

	CollectionConfigFileFlag        = "collconfig"
	collectionConfigFileDescription = "The path of the JSON file that contains the private data collection configuration for the chaincode"
	defaultCollectionConfigFile     = ""

	TimeoutFlag        = "timeout"
	timeoutDescription = "The timeout (in milliseconds) for the operation"
	defaultTimeout     = "5000"

	PrintPayloadOnlyFlag        = "payload"
	printPayloadOnlyDescription = "If specified then only the payload from the transaction proposal response(s) will be output"
	defaultPrintPayloadOnly     = "false"

	ValidateFlag        = "validate"
	validateDescription = "If specified then endorsement responses from queries will be validated"
	defaultValidate     = "false"

	ConcurrencyFlag        = "concurrency"
	concurrencyDescription = "Specifies the number of concurrent requests sent on an invoke or a query chaincode request"
	defaultConcurrency     = "1"

	MaxAttemptsFlag        = "attempts"
	maxAttemptsDescription = "Specifies the maximum number of attempts to be made for a single chaincode invocation request. If >1 then retries will be attempted should transient errors occur."
	defaultMaxAttempts     = "3"

	InitialBackoffFlag        = "backoff"
	initialBackoffDescription = "The initial backoff is the time (in milliseconds) to wait before resubmitting an invocation after a transient error"
	defaultInitialBackoff     = "1000"

	MaxBackoffFlag        = "maxbackoff"
	maxBackoffDescription = "The maximum backoff time (in milliseconds)"
	defaultMaxBackoff     = "5000"

	BackoffFactorFlag        = "backofffactor"
	backoffFactorDescription = "The factor by which the backoff time is multiplied each time a retry fails. For example, if the initial backoff is 1s and factor is 2 then the next retry will have a backoff of 2s and a subsequent backoff will be 4s up to the maximum backoff"
	defaultBackoffFactor     = "2"

	VerboseFlag        = "verbose"
	verboseDescription = "If specified then the transaction proposal responses will be output when iterations > 1, otherwise transaction proposal responses are only output when iterations = 1"
	defaultVerbosity   = "false"

	SelectionProviderFlag        = "selectprovider"
	selectionProviderDescription = "The peer selection provider for invoke/query commands. The possible values are: (1) static - Selects all peers; (2) dynamic - Uses the built-in selection service from the SDK to select a minimal set of peers according to the endorsement policy of the chaincode; (3) fabric - Uses Fabric's Discovery Service to select a minimal set of peers according to the endorsement/collection policy of the chaincode; (4) auto (default) - Automatically determines which selection service to use based on channel capabilities."
	defaultSelectionProvider     = AutoDetectSelectionProvider

	GoPathFlag        = "gopath"
	goPathDescription = "GOPATH for chaincode install command. If not set, GOPATH is taken from the environment"
	defaultGoPath     = ""
)

var opts *options
var instance *CLIConfig

type options struct {
	certificate          string
	user                 string
	password             string
	loggingLevel         string
	orgIDsStr            string
	channelID            string
	chaincodeID          string
	chaincodePath        string
	chaincodeVersion     string
	peerURL              string
	ordererURL           string
	iterations           int
	sleepTime            int64
	configFile           string
	txFile               string
	txID                 string
	printFormat          string
	writer               string
	base64               bool
	args                 string
	chaincodeEvent       string
	seekType             string
	blockHash            string
	blockNum             uint64
	traverse             int
	chaincodePolicy      string
	collectionConfigFile string
	timeout              int64
	printPayloadOnly     bool
	validate             bool
	concurrency          int
	maxAttempts          int
	initialBackoff       int64
	maxBackoff           int64
	backoffFactor        float64
	verbose              bool
	selectionProvider    string
	goPath               string
}

func init() {
	opts = &options{
		user:             defaultUser,
		password:         defaultPassword,
		loggingLevel:     defaultLoggingLevel,
		channelID:        defaultChannelID,
		orgIDsStr:        defaultOrgIDs,
		chaincodeVersion: defaultChaincodeVersion,
		iterations:       1,
		concurrency:      1,
		args:             getEmptyArgs(),
	}
}

// CLIConfig overrides certain configuration values with those supplied on the command-line
type CLIConfig struct {
	core.ConfigProvider
	logger   *logging.Logger
	setFlags map[string]string
}

// InitConfig initializes the configuration
func InitConfig(flags *pflag.FlagSet) error {

	instance = &CLIConfig{
		logger:   logging.NewLogger(loggerName),
		setFlags: make(map[string]string),
	}
	flags.Visit(func(flag *pflag.Flag) {
		instance.setFlags[flag.Name] = flag.Value.String()
	})

	cnfg := config.FromFile(opts.configFile)

	instance.ConfigProvider = cnfg

	return nil
}

// IsFlagSet indicates whether or not the given flag is set
func IsFlagSet(name string) bool {
	_, ok := instance.setFlags[name]
	return ok
}

// Provider returns the config provider
func Provider() core.ConfigProvider {
	return instance.ConfigProvider
}

// Config returns the CLI configuration
func Config() *CLIConfig {
	return instance
}

// Logger returns the Logger for the CLI tool
func (c *CLIConfig) Logger() *logging.Logger {
	return c.logger
}

// LoggingLevel specifies the logging level (DEBUG, INFO, WARNING, ERROR, or CRITICAL)
func (c *CLIConfig) LoggingLevel() string {
	return opts.loggingLevel
}

// InitLoggingLevel initializes the logging level from the provided arguments
func InitLoggingLevel(flags *pflag.FlagSet, defaultValueAndDescription ...string) {
	defaultValue, description := getDefaultValueAndDescription(defaultLoggingLevel, loggingLevelDescription, defaultValueAndDescription...)
	flags.StringVar(&opts.loggingLevel, LoggingLevelFlag, defaultValue, description)
}

// InitConfigFile initializes the config file path from the provided arguments
func InitConfigFile(flags *pflag.FlagSet, defaultValueAndDescription ...string) {
	defaultValue, description := getDefaultValueAndDescription(defaultConfigFile, configFileDescription, defaultValueAndDescription...)
	flags.StringVar(&opts.configFile, ConfigFileFlag, defaultValue, description)
}

// OrgID specifies the ID of the current organization. If multiple org IDs are specified then the first one is returned.
func (c *CLIConfig) OrgID() string {
	if len(c.OrgIDs()) == 0 {
		return ""
	}
	return c.OrgIDs()[0]
}

// OrgIDs returns a comma-separated list of organization IDs
func (c *CLIConfig) OrgIDs() []string {
	var orgIDs []string
	if len(strings.TrimSpace(opts.orgIDsStr)) > 0 {
		s := strings.Split(opts.orgIDsStr, ",")
		for _, orgID := range s {
			orgIDs = append(orgIDs, orgID)
		}
	}
	return orgIDs
}

// InitOrgIDs initializes the org IDs from the provided arguments
func InitOrgIDs(flags *pflag.FlagSet, defaultValueAndDescription ...string) {
	defaultValue, description := getDefaultValueAndDescription(defaultOrgIDs, orgIDsDescription, defaultValueAndDescription...)
	flags.StringVar(&opts.orgIDsStr, OrgIDsFlag, defaultValue, description)
}

// ChannelID returns the channel ID
func (c *CLIConfig) ChannelID() string {
	return opts.channelID
}

// InitChannelID initializes the channel ID from the provided arguments
func InitChannelID(flags *pflag.FlagSet, defaultValueAndDescription ...string) {
	defaultValue, description := getDefaultValueAndDescription(defaultChannelID, channelIDDescription, defaultValueAndDescription...)
	flags.StringVar(&opts.channelID, ChannelIDFlag, defaultValue, description)
}

// UserName returns the name of the enrolled user
func (c *CLIConfig) UserName() string {
	return opts.user
}

// InitUserName initializes the user name from the provided arguments
func InitUserName(flags *pflag.FlagSet, defaultValueAndDescription ...string) {
	defaultValue, description := getDefaultValueAndDescription(defaultUser, userDescription, defaultValueAndDescription...)
	flags.StringVar(&opts.user, UserFlag, defaultValue, description)
}

// UserPassword is the password to use when enrolling a user
func (c *CLIConfig) UserPassword() string {
	return opts.password
}

// InitUserPassword initializes the user password from the provided arguments
func InitUserPassword(flags *pflag.FlagSet, defaultValueAndDescription ...string) {
	defaultValue, description := getDefaultValueAndDescription(defaultPassword, passwordDescription, defaultValueAndDescription...)
	flags.StringVar(&opts.password, PasswordFlag, defaultValue, description)
}

// ChaincodeID returns the chaicode ID
func (c *CLIConfig) ChaincodeID() string {
	return opts.chaincodeID
}

// InitChaincodeID initializes the chaincode ID from the provided arguments
func InitChaincodeID(flags *pflag.FlagSet, defaultValueAndDescription ...string) {
	defaultValue, description := getDefaultValueAndDescription(defaultChaincodeID, chaincodeIDDescription, defaultValueAndDescription...)
	flags.StringVar(&opts.chaincodeID, ChaincodeIDFlag, defaultValue, description)
}

// ChaincodeEvent the name of the chaincode event to listen for
func (c *CLIConfig) ChaincodeEvent() string {
	return opts.chaincodeEvent
}

// InitChaincodeEvent initializes the chaincode event name from the provided arguments
func InitChaincodeEvent(flags *pflag.FlagSet, defaultValueAndDescription ...string) {
	defaultValue, description := getDefaultValueAndDescription(defaultChaincodeEvent, chaincodeEventDescription, defaultValueAndDescription...)
	flags.StringVar(&opts.chaincodeEvent, ChaincodeEventFlag, defaultValue, description)
}

// SeekType the seek type for Deliver Events. Possible values:
// - Oldest - will deliver all blocks from the oldest block and will continue listening for new blocks
// - Newest - will deliver the newest block and will continue listening for new blocks
// - FromBlock - Delivers from the specific block, as specified by the "--num" flag
func (c *CLIConfig) SeekType() seek.Type {
	return seek.Type(opts.seekType)
}

// InitSeekType initializes the seek type from the provided arguments
func InitSeekType(flags *pflag.FlagSet, defaultValueAndDescription ...string) {
	defaultValue, description := getDefaultValueAndDescription(defaultSeekType, seekTypeDescription, defaultValueAndDescription...)
	flags.StringVar(&opts.seekType, SeekTypeFlag, defaultValue, description)
}

// ChaincodePath returns the source path of the chaincode to install/instantiate
func (c *CLIConfig) ChaincodePath() string {
	return opts.chaincodePath
}

// InitChaincodePath initializes the chaincode install source path from the provided arguments
func InitChaincodePath(flags *pflag.FlagSet, defaultValueAndDescription ...string) {
	defaultValue, description := getDefaultValueAndDescription(defaultChaincodePath, chaincodePathDescription, defaultValueAndDescription...)
	flags.StringVar(&opts.chaincodePath, ChaincodePathFlag, defaultValue, description)
}

// ChaincodeVersion returns the version of the chaincode
func (c *CLIConfig) ChaincodeVersion() string {
	return opts.chaincodeVersion
}

// InitChaincodeVersion initializes the chaincode version from the provided arguments
func InitChaincodeVersion(flags *pflag.FlagSet, defaultValueAndDescription ...string) {
	defaultValue, description := getDefaultValueAndDescription(defaultChaincodeVersion, chaincodeVersionDescription, defaultValueAndDescription...)
	flags.StringVar(&opts.chaincodeVersion, ChaincodeVersionFlag, defaultValue, description)
}

// PeerURL returns a comma-separated list of peers in the format host1:port1,host2:port2,...
func (c *CLIConfig) PeerURL() string {
	return opts.peerURL
}

// PeerURLs returns a list of peer URLs
func (c *CLIConfig) PeerURLs() []string {
	var urls []string
	if len(strings.TrimSpace(opts.peerURL)) > 0 {
		s := strings.Split(opts.peerURL, ",")
		for _, orgID := range s {
			urls = append(urls, orgID)
		}
	}
	return urls
}

// InitPeerURL initializes the peer URL from the provided arguments
func InitPeerURL(flags *pflag.FlagSet, defaultValueAndDescription ...string) {
	defaultValue, description := getDefaultValueAndDescription(defaultPeerURL, peerURLDescription, defaultValueAndDescription...)
	flags.StringVar(&opts.peerURL, PeerURLFlag, defaultValue, description)
}

// OrdererURL returns the URL of the orderer
func (c *CLIConfig) OrdererURL() string {
	return opts.ordererURL
}

// InitOrdererURL initializes the orderer URL from the provided arguments
func InitOrdererURL(flags *pflag.FlagSet, defaultValueAndDescription ...string) {
	defaultValue, description := getDefaultValueAndDescription(defaultOrdererURL, ordererURLDescription, defaultValueAndDescription...)
	flags.StringVar(&opts.ordererURL, OrdererFlag, defaultValue, description)
}

// Iterations returns the number of times that a chaincode should be invoked
func (c *CLIConfig) Iterations() int {
	return opts.iterations
}

// InitIterations initializes the number of query/invoke iterations from the provided arguments
func InitIterations(flags *pflag.FlagSet, defaultValueAndDescription ...string) {
	defaultValue, description := getDefaultValueAndDescription(defaultIterations, iterationsDescription, defaultValueAndDescription...)
	i, err := strconv.Atoi(defaultValue)
	if err != nil {
		fmt.Printf("Invalid number for %s: %s\n", IterationsFlag, defaultValue)
		os.Exit(-1)
	}
	flags.IntVar(&opts.iterations, IterationsFlag, i, description)
}

// SleepTime returns the number of milliseconds to sleep between invocations of a chaincode
func (c *CLIConfig) SleepTime() int64 {
	return opts.sleepTime
}

// InitSleepTime initializes the sleep time from the provided arguments
func InitSleepTime(flags *pflag.FlagSet, defaultValueAndDescription ...string) {
	defaultValue, description := getDefaultValueAndDescription(defaultSleepTime, sleepTimeDescription, defaultValueAndDescription...)
	i, err := strconv.Atoi(defaultValue)
	if err != nil {
		fmt.Printf("Invalid number for %s: %s\n", SleepFlag, defaultValue)
		os.Exit(-1)
	}
	flags.Int64Var(&opts.sleepTime, SleepFlag, int64(i), description)
}

// BlockNum returns the block number (where 0 is the first block)
func (c *CLIConfig) BlockNum() uint64 {
	return opts.blockNum
}

// InitBlockNum initializes the bluck number from the provided arguments
func InitBlockNum(flags *pflag.FlagSet, defaultValueAndDescription ...string) {
	defaultValue, description := getDefaultValueAndDescription(defaultBlockNum, blockNumDescription, defaultValueAndDescription...)
	i, err := strconv.ParseUint(defaultValue, 10, 64)
	if err != nil {
		fmt.Printf("Invalid number for %s: %s\n", BlockNumFlag, defaultValue)
		os.Exit(-1)
	}
	flags.Uint64Var(&opts.blockNum, BlockNumFlag, i, description)
}

// BlockHash specifies the hash of the block
func (c *CLIConfig) BlockHash() string {
	return opts.blockHash
}

// InitBlockHash initializes the block hash from the provided arguments
func InitBlockHash(flags *pflag.FlagSet, defaultValueAndDescription ...string) {
	defaultValue, description := getDefaultValueAndDescription(defaultBlockHash, blockHashDescription, defaultValueAndDescription...)
	flags.StringVar(&opts.blockHash, BlockHashFlag, defaultValue, description)
}

// Traverse returns the number of blocks to traverse backwards in the query block command
func (c *CLIConfig) Traverse() int {
	return opts.traverse
}

// InitTraverse initializes the 'traverse' flag from the provided arguments
func InitTraverse(flags *pflag.FlagSet, defaultValueAndDescription ...string) {
	defaultValue, description := getDefaultValueAndDescription(defaultTraverse, traverseDescription, defaultValueAndDescription...)
	i, err := strconv.Atoi(defaultValue)
	if err != nil {
		fmt.Printf("Invalid number for %s: %s\n", TimeoutFlag, defaultValue)
		i = 1
	}
	flags.IntVar(&opts.traverse, TraverseFlag, i, description)
}

// PrintFormat returns the print (output) format for a block
func (c *CLIConfig) PrintFormat() string {
	return opts.printFormat
}

// InitPrintFormat initializes the print format from the provided arguments
func InitPrintFormat(flags *pflag.FlagSet, defaultValueAndDescription ...string) {
	defaultValue, description := getDefaultValueAndDescription("display", printFormatDescription, defaultValueAndDescription...)
	flags.StringVar(&opts.printFormat, PrintFormatFlag, defaultValue, description)
}

// Writer returns the writer for output
func (c *CLIConfig) Writer() string {
	return opts.writer
}

// InitWriter initializes the print writer from the provided arguments
func InitWriter(flags *pflag.FlagSet, defaultValueAndDescription ...string) {
	defaultValue, description := getDefaultValueAndDescription("stdout", writerDescription, defaultValueAndDescription...)
	flags.StringVar(&opts.writer, WriterFlag, defaultValue, description)
}

// Base64 indicates whether binary values are to be encoded in base64. (Only applies to 'display' format.)
func (c *CLIConfig) Base64() bool {
	return opts.base64
}

// InitBase64 initializes the base64 flag from the provided arguments
func InitBase64(flags *pflag.FlagSet, defaultValueAndDescription ...string) {
	defaultValue, description := getDefaultValueAndDescription("false", writerDescription, defaultValueAndDescription...)
	flags.BoolVar(&opts.base64, Base64Flag, defaultValue == "true", description)
}

// OrdererTLSCertificate is the path of the orderer TLS certificate
func (c *CLIConfig) OrdererTLSCertificate() string {
	return opts.certificate
}

// InitOrdererTLSCertificate initializes the orderer TLS certificate from the provided arguments
func InitOrdererTLSCertificate(flags *pflag.FlagSet, defaultValueAndDescription ...string) {
	defaultValue, description := getDefaultValueAndDescription(defaultCertificate, certificateDescription, defaultValueAndDescription...)
	flags.StringVar(&opts.certificate, CertificateFileFlag, defaultValue, description)
}

// Args returns the chaincode invocation arguments as a JSON string in the format, {"Func":"function","Args":["arg1","arg2",...]}
func (c *CLIConfig) Args() string {
	return opts.args
}

// InitArgs initializes the invoke/query args from the provided arguments
func InitArgs(flags *pflag.FlagSet, defaultValueAndDescription ...string) {
	defaultValue, description := getDefaultValueAndDescription(getEmptyArgs(), argsDescription, defaultValueAndDescription...)
	flags.StringVar(&opts.args, ArgsFlag, defaultValue, description)
}

// TxFile is the path of the .tx file used to create a channel
func (c *CLIConfig) TxFile() string {
	return opts.txFile
}

// InitTxFile initializes the path of the .tx file used to create/update a channel from the provided arguments
func InitTxFile(flags *pflag.FlagSet, defaultValueAndDescription ...string) {
	defaultValue, description := getDefaultValueAndDescription(defaultTxFile, txFileDescription, defaultValueAndDescription...)
	flags.StringVar(&opts.txFile, TxFileFlag, defaultValue, description)
}

// TxID returns the transaction ID
func (c *CLIConfig) TxID() string {
	return opts.txID
}

// InitTxID initializes the transaction D from the provided arguments
func InitTxID(flags *pflag.FlagSet, defaultValueAndDescription ...string) {
	defaultValue, description := getDefaultValueAndDescription(defaultTxID, txIDDescription, defaultValueAndDescription...)
	flags.StringVar(&opts.txID, TxIDFlag, defaultValue, description)
}

// ChaincodePolicy returns the chaincode policy string, e.g Nof(1,(SignedBy(Org1Msp),SignedBy(Org2MSP)))
func (c *CLIConfig) ChaincodePolicy() string {
	return opts.chaincodePolicy
}

// InitChaincodePolicy initializes the chaincode policy from the provided arguments
func InitChaincodePolicy(flags *pflag.FlagSet, defaultValueAndDescription ...string) {
	defaultValue, description := getDefaultValueAndDescription(defaultChaincodePolicy, chaincodePolicyDescription, defaultValueAndDescription...)
	flags.StringVar(&opts.chaincodePolicy, ChaincodePolicyFlag, defaultValue, description)
}

// CollectionConfigFile returns the path of the JSON file that contains the private data collection configuration for the chaincode to be instantiated/upgraded
func (c *CLIConfig) CollectionConfigFile() string {
	return opts.collectionConfigFile
}

// InitCollectionConfigFile initializes the collection config file from the provided arguments
func InitCollectionConfigFile(flags *pflag.FlagSet, defaultValueAndDescription ...string) {
	defaultValue, description := getDefaultValueAndDescription(defaultCollectionConfigFile, collectionConfigFileDescription, defaultValueAndDescription...)
	flags.StringVar(&opts.collectionConfigFile, CollectionConfigFileFlag, defaultValue, description)
}

// Timeout returns the timeout (in milliseconds) for various operations
func (c *CLIConfig) Timeout(timeoutType fab.TimeoutType) time.Duration {
	// TODO use provided timoutType
	return time.Duration(opts.timeout) * time.Millisecond
}

// InitTimeout initializes the timeout from the provided arguments
func InitTimeout(flags *pflag.FlagSet, defaultValueAndDescription ...string) {
	defaultValue, description := getDefaultValueAndDescription(defaultTimeout, timeoutDescription, defaultValueAndDescription...)
	i, err := strconv.Atoi(defaultValue)
	if err != nil {
		fmt.Printf("Invalid number for %s: %s\n", TimeoutFlag, defaultValue)
		i = 1000
	}
	flags.Int64Var(&opts.timeout, TimeoutFlag, int64(i), description)
}

// PrintPayloadOnly indicates whether only the payload or the entire
// transaction proposal response should be printed
func (c *CLIConfig) PrintPayloadOnly() bool {
	return opts.printPayloadOnly
}

// InitPrintPayloadOnly initializes the PrintPayloadOnly flag from the provided arguments
func InitPrintPayloadOnly(flags *pflag.FlagSet, defaultValueAndDescription ...string) {
	defaultValue, description := getDefaultValueAndDescription(defaultPrintPayloadOnly, printPayloadOnlyDescription, defaultValueAndDescription...)
	flags.BoolVar(&opts.printPayloadOnly, PrintPayloadOnlyFlag, defaultValue == "true", description)
}

// Validate indicates whether the endorsement responses from a query should be validated
func (c *CLIConfig) Validate() bool {
	return opts.validate
}

// InitValidate initializes the Validate flag from the provided arguments
func InitValidate(flags *pflag.FlagSet, defaultValueAndDescription ...string) {
	defaultValue, description := getDefaultValueAndDescription(defaultValidate, validateDescription, defaultValueAndDescription...)
	flags.BoolVar(&opts.validate, ValidateFlag, defaultValue == "true", description)
}

// Concurrency returns the number of concurrent invocations/queries
func (c *CLIConfig) Concurrency() uint16 {
	return uint16(opts.concurrency)
}

// InitConcurrency initializes the 'concurrency' flag from the provided arguments
func InitConcurrency(flags *pflag.FlagSet, defaultValueAndDescription ...string) {
	defaultValue, description := getDefaultValueAndDescription(defaultConcurrency, concurrencyDescription, defaultValueAndDescription...)
	i, err := strconv.Atoi(defaultValue)
	if err != nil {
		fmt.Printf("Invalid number for %s: %s\n", TimeoutFlag, defaultValue)
		i = 1
	}
	flags.IntVar(&opts.concurrency, ConcurrencyFlag, i, description)
}

// MaxAttempts returns the maximum number of invocations attempts to be made
// for a single chaincode invocation request. If >1 then a retry will be attempted
// if a transient failure occurs.
func (c *CLIConfig) MaxAttempts() int {
	return opts.maxAttempts
}

// InitMaxAttempts initializes the 'maxAttempts' flag from the provided arguments
func InitMaxAttempts(flags *pflag.FlagSet, defaultValueAndDescription ...string) {
	defaultValue, description := getDefaultValueAndDescription(defaultMaxAttempts, maxAttemptsDescription, defaultValueAndDescription...)
	i, err := strconv.Atoi(defaultValue)
	if err != nil {
		fmt.Printf("Invalid number for %s: %s\n", TimeoutFlag, defaultValue)
		i = 1
	}
	flags.IntVar(&opts.maxAttempts, MaxAttemptsFlag, i, description)
}

// InitialBackoff returns the time (in milliseconds) to wait
// before resubmitting an invocation after a transient error
func (c *CLIConfig) InitialBackoff() time.Duration {
	return time.Duration(opts.initialBackoff) * time.Millisecond
}

// InitInitialBackoff initializes the initial backoff from the provided arguments
func InitInitialBackoff(flags *pflag.FlagSet, defaultValueAndDescription ...string) {
	defaultValue, description := getDefaultValueAndDescription(defaultInitialBackoff, initialBackoffDescription, defaultValueAndDescription...)
	i, err := strconv.Atoi(defaultValue)
	if err != nil {
		fmt.Printf("Invalid number for %s: %s\n", TimeoutFlag, defaultValue)
		i = 1000
	}
	flags.Int64Var(&opts.initialBackoff, InitialBackoffFlag, int64(i), description)
}

// MaxBackoff returns the number
func (c *CLIConfig) MaxBackoff() time.Duration {
	return time.Duration(opts.maxBackoff) * time.Millisecond
}

// InitMaxBackoff initializes the maximum backoff from the provided arguments
func InitMaxBackoff(flags *pflag.FlagSet, defaultValueAndDescription ...string) {
	defaultValue, description := getDefaultValueAndDescription(defaultMaxBackoff, maxBackoffDescription, defaultValueAndDescription...)
	i, err := strconv.Atoi(defaultValue)
	if err != nil {
		fmt.Printf("Invalid number for %s: %s\n", TimeoutFlag, defaultValue)
		i = 1000
	}
	flags.Int64Var(&opts.maxBackoff, MaxBackoffFlag, int64(i), description)
}

// BackoffFactor returns the factor by which the backoff time is multiplied each time a retry fails. For example, if the initial
// backoff is 1s and factor is 2 then the next retry will have a backoff of 2s and a subsequent backoff will be 4s up to the maximum backoff
func (c *CLIConfig) BackoffFactor() float64 {
	return opts.backoffFactor
}

// InitBackoffFactor initializes the backoff factor from the provided arguments
func InitBackoffFactor(flags *pflag.FlagSet, defaultValueAndDescription ...string) {
	defaultValue, description := getDefaultValueAndDescription(defaultBackoffFactor, backoffFactorDescription, defaultValueAndDescription...)
	i, err := strconv.Atoi(defaultValue)
	if err != nil {
		fmt.Printf("Invalid number for %s: %s\n", TimeoutFlag, defaultValue)
		i = 1000
	}
	flags.Float64Var(&opts.backoffFactor, BackoffFactorFlag, float64(i), description)
}

// Verbose indicates whether or not to print the transaction proposal responses
// when Iterations > 1
func (c *CLIConfig) Verbose() bool {
	return opts.verbose
}

// InitVerbosity initializes the Verbose flag from the provided arguments
func InitVerbosity(flags *pflag.FlagSet, defaultValueAndDescription ...string) {
	defaultValue, description := getDefaultValueAndDescription(defaultVerbosity, verboseDescription, defaultValueAndDescription...)
	flags.BoolVar(&opts.verbose, VerboseFlag, defaultValue == "true", description)
}

// SelectionProvider returns the peer selection provider - either static or dynamic
func (c *CLIConfig) SelectionProvider() string {
	return opts.selectionProvider
}

// InitSelectionProvider initializes the peer selection provider from the provided arguments
func InitSelectionProvider(flags *pflag.FlagSet, defaultValueAndDescription ...string) {
	defaultValue, description := getDefaultValueAndDescription(defaultSelectionProvider, selectionProviderDescription, defaultValueAndDescription...)
	flags.StringVar(&opts.selectionProvider, SelectionProviderFlag, defaultValue, description)
}

// InitGoPath initializes the gopath from the provided arguments
func InitGoPath(flags *pflag.FlagSet, defaultValueAndDescription ...string) {
	defaultValue, description := getDefaultValueAndDescription(defaultGoPath, goPathDescription, defaultValueAndDescription...)
	flags.StringVar(&opts.goPath, GoPathFlag, defaultValue, description)
}

// GoPath returns the gopath
func (c *CLIConfig) GoPath() string {
	gopath := opts.goPath
	if !IsFlagSet(GoPathFlag) {
		gopath = os.Getenv("GOPATH")
	}
	return gopath
}

// IsLoggingEnabledFor indicates whether the logger is enabled for the given logging level
func (c *CLIConfig) IsLoggingEnabledFor(level logging.Level) bool {
	return logging.IsEnabledFor(loggerName, level)
}

// Utility functions...

func getEmptyArgs() string {
	return "{}"
}

func getDefaultValueAndDescription(defaultValue string, defaultDescription string, overrides ...string) (value, description string) {
	if len(overrides) > 0 {
		value = overrides[0]
	} else {
		value = defaultValue
	}
	if len(overrides) > 1 {
		description = overrides[1]
	} else {
		description = defaultDescription
	}
	return value, description
}


================================================
FILE: fabric-cli/cmd/fabric-cli/event/eventcmd.go
================================================
/*
Copyright SecureKey Technologies Inc. All Rights Reserved.

SPDX-License-Identifier: Apache-2.0
*/

package event

import (
	"github.com/spf13/cobra"
)

var eventCmd = &cobra.Command{
	Use:   "event",
	Short: "Event commands",
	Long:  "Event commands",
	Run: func(cmd *cobra.Command, args []string) {
		cmd.HelpFunc()(cmd, args)
	},
}

// Cmd returns the events command
func Cmd() *cobra.Command {
	eventCmd.AddCommand(getListenCCCmd())
	eventCmd.AddCommand(getListenTXCmd())
	eventCmd.AddCommand(getListenBlockCmd())
	eventCmd.AddCommand(getListenFilteredBlockCmd())

	return eventCmd
}


================================================
FILE: fabric-cli/cmd/fabric-cli/event/inputevent.go
================================================
/*
Copyright SecureKey Technologies Inc. All Rights Reserved.

SPDX-License-Identifier: Apache-2.0
*/

package event

import (
	"bufio"
	"os"
)

type inputEvent struct {
	done chan bool
}

// WaitForEnter waits until the user presses Enter
func (c *inputEvent) WaitForEnter() chan bool {
	go c.readFromCLI()
	return c.done
}

func (c *inputEvent) readFromCLI() {
	reader := bufio.NewReader(os.Stdin)
	reader.ReadString('\n')
	c.done <- true
}


================================================
FILE: fabric-cli/cmd/fabric-cli/event/listenblockcmd.go
================================================
/*
Copyright SecureKey Technologies Inc. All Rights Reserved.

SPDX-License-Identifier: Apache-2.0
*/

package event

import (
	"fmt"

	"github.com/hyperledger/fabric-sdk-go/pkg/client/event"
	"github.com/pkg/errors"
	"github.com/securekey/fabric-examples/fabric-cli/cmd/fabric-cli/action"
	cliconfig "github.com/securekey/fabric-examples/fabric-cli/cmd/fabric-cli/config"
	"github.com/spf13/cobra"
	"github.com/spf13/pflag"
)

var listenBlockCmd = &cobra.Command{
	Use:   "listenblock",
	Short: "Listen to block events.",
	Long:  "Listen to block events",
	Run: func(cmd *cobra.Command, args []string) {
		action, err := newlistenBlockAction(cmd.Flags())
		if err != nil {
			cliconfig.Config().Logger().Errorf("Error while initializing listenBlockAction: %v", err)
			return
		}

		defer action.Terminate()

		err = action.invoke()
		if err != nil {
			cliconfig.Config().Logger().Errorf("Error while running listenBlockAction: %v", err)
		}
	},
}

func getListenBlockCmd() *cobra.Command {
	flags := listenBlockCmd.Flags()
	cliconfig.InitChannelID(flags)
	cliconfig.InitPeerURL(flags, "", "The URL of the peer on which to listen for events, e.g. localhost:7051")
	cliconfig.InitSeekType(flags)
	cliconfig.InitBlockNum(flags)
	return listenBlockCmd
}

type listenBlockAction struct {
	action.Action
	inputEvent
}

func newlistenBlockAction(flags *pflag.FlagSet) (*listenBlockAction, error) {
	action := &listenBlockAction{inputEvent: inputEvent{done: make(chan bool)}}
	err := action.Initialize(flags)
	return action, err
}

func (a *listenBlockAction) invoke() error {
	eventClient, err := a.EventClient(event.WithBlockEvents(), event.WithSeekType(cliconfig.Config().SeekType()), event.WithBlockNum(cliconfig.Config().BlockNum()))
	if err != nil {
		return err
	}

	fmt.Printf("Registering block event\n")

	breg, beventch, err := eventClient.RegisterBlockEvent()
	if err != nil {
		return errors.WithMessage(err, "Error registering for block events")
	}
	defer eventClient.Unregister(breg)

	enterch := a.WaitForEnter()
	for {
		select {
		case _, _ = <-enterch:
			return nil
		case event, ok := <-beventch:
			if !ok {
				return errors.WithMessage(err, "unexpected closed channel while waiting for block event")
			}
			a.Printer().PrintBlock(event.Block)
			fmt.Println("Press <enter> to terminate")
		}
	}
}


================================================
FILE: fabric-cli/cmd/fabric-cli/event/listencccmd.go
================================================
/*
Copyright SecureKey Technologies Inc. All Rights Reserved.

SPDX-License-Identifier: Apache-2.0
*/

package event

import (
	"fmt"

	"github.com/pkg/errors"
	"github.com/securekey/fabric-examples/fabric-cli/cmd/fabric-cli/action"
	cliconfig "github.com/securekey/fabric-examples/fabric-cli/cmd/fabric-cli/config"
	"github.com/spf13/cobra"
	"github.com/spf13/pflag"
)

var listenccCmd = &cobra.Command{
	Use:   "listencc",
	Short: "Listen to chaincode events.",
	Long:  "Listen to chaincode events",
	Run: func(cmd *cobra.Command, args []string) {
		if cliconfig.Config().ChaincodeID() == "" {
			fmt.Printf("\nMust specify the chaincode ID\n\n")
			cmd.HelpFunc()(cmd, args)
			return
		}
		if cliconfig.Config().ChaincodeEvent() == "" {
			fmt.Printf("\nMust specify the event name\n\n")
			cmd.HelpFunc()(cmd, args)
			return
		}

		action, err := newListenCCAction(cmd.Flags())
		if err != nil {
			fmt.Printf("\nError while initializing listenCCAction: %v\n", err)
			return
		}

		defer action.Terminate()

		err = action.invoke()
		if err != nil {
			fmt.Printf("\nError while running listenCCAction: %v\n", err)
		}
	},
}

func getListenCCCmd() *cobra.Command {
	flags := listenccCmd.Flags()
	cliconfig.InitChannelID(flags)
	cliconfig.InitPeerURL(flags, "", "The URL of the peer on which to listen for events, e.g. grpcs://localhost:7051")
	cliconfig.InitChaincodeID(flags)
	cliconfig.InitChaincodeEvent(flags)
	return listenccCmd
}

type listenccAction struct {
	action.Action
	inputEvent
}

func newListenCCAction(flags *pflag.FlagSet) (*listenccAction, error) {
	action := &listenccAction{inputEvent: inputEvent{done: make(chan bool)}}
	err := action.Initialize(flags)
	return action, err
}

func (a *listenccAction) invoke() error {

	fmt.Printf("Registering CC event on chaincode [%s] and event [%s]\n", cliconfig.Config().ChaincodeID(), cliconfig.Config().ChaincodeEvent())

	eventHub, err := a.EventClient()
	if err != nil {
		return err
	}

	breg, beventch, err := eventHub.RegisterChaincodeEvent(cliconfig.Config().ChaincodeID(), cliconfig.Config().ChaincodeEvent())
	if err != nil {
		return errors.WithMessage(err, "Error registering for block events")
	}
	defer eventHub.Unregister(breg)

	enterch := a.WaitForEnter()
	for {
		select {
		case _, _ = <-enterch:
			return nil
		case event, ok := <-beventch:
			if !ok {
				return errors.WithMessage(err, "unexpected closed channel while waiting for block event")
			}
			a.Printer().PrintChaincodeEvent(event)
			fmt.Println("Press <enter> to terminate")
		}
	}
}


================================================
FILE: fabric-cli/cmd/fabric-cli/event/listenfilteredblockcmd.go
================================================
/*
Copyright SecureKey Technologies Inc. All Rights Reserved.

SPDX-License-Identifier: Apache-2.0
*/

package event

import (
	"fmt"

	"github.com/hyperledger/fabric-sdk-go/pkg/client/event"
	"github.com/pkg/errors"
	"github.com/securekey/fabric-examples/fabric-cli/cmd/fabric-cli/action"
	cliconfig "github.com/securekey/fabric-examples/fabric-cli/cmd/fabric-cli/config"
	"github.com/spf13/cobra"
	"github.com/spf13/pflag"
)

var listenFilteredBlockCmd = &cobra.Command{
	Use:   "listenfilteredblock",
	Short: "Listen to filtered block events.",
	Long:  "Listen to filtered block events",
	Run: func(cmd *cobra.Command, args []string) {
		action, err := newlistenFilteredBlockAction(cmd.Flags())
		if err != nil {
			cliconfig.Config().Logger().Errorf("Error while initializing listenFilteredBlockAction: %v", err)
			return
		}

		defer action.Terminate()

		err = action.invoke()
		if err != nil {
			cliconfig.Config().Logger().Errorf("Error while running listenFilteredBlockAction: %v", err)
		}
	},
}

func getListenFilteredBlockCmd() *cobra.Command {
	flags := listenFilteredBlockCmd.Flags()
	cliconfig.InitChannelID(flags)
	cliconfig.InitPeerURL(flags, "", "The URL of the peer on which to listen for events, e.g. localhost:7051")
	cliconfig.InitSeekType(flags)
	cliconfig.InitBlockNum(flags)
	return listenFilteredBlockCmd
}

type listenFilteredBlockAction struct {
	action.Action
	inputEvent
}

func newlistenFilteredBlockAction(flags *pflag.FlagSet) (*listenFilteredBlockAction, error) {
	action := &listenFilteredBlockAction{inputEvent: inputEvent{done: make(chan bool)}}
	err := action.Initialize(flags)
	return action, err
}

func (a *listenFilteredBlockAction) invoke() error {
	eventClient, err := a.EventClient(event.WithSeekType(cliconfig.Config().SeekType()), event.WithBlockNum(cliconfig.Config().BlockNum()))
	if err != nil {
		return err
	}

	fmt.Printf("Registering filtered block event\n")

	breg, beventch, err := eventClient.RegisterFilteredBlockEvent()
	if err != nil {
		return errors.WithMessage(err, "Error registering for filtered block events")
	}
	defer eventClient.Unregister(breg)

	enterch := a.WaitForEnter()
	for {
		select {
		case _, _ = <-enterch:
			return nil
		case event, ok := <-beventch:
			if !ok {
				return errors.WithMessage(err, "unexpected closed channel while waiting for filtered block event")
			}
			a.Printer().PrintFilteredBlock(event.FilteredBlock)
			fmt.Println("Press <enter> to terminate")
		}
	}
}


================================================
FILE: fabric-cli/cmd/fabric-cli/event/listentxcmd.go
================================================
/*
Copyright SecureKey Technologies Inc. All Rights Reserved.

SPDX-License-Identifier: Apache-2.0
*/

package event

import (
	"fmt"

	"github.com/pkg/errors"
	"github.com/securekey/fabric-examples/fabric-cli/cmd/fabric-cli/action"
	cliconfig "github.com/securekey/fabric-examples/fabric-cli/cmd/fabric-cli/config"
	"github.com/spf13/cobra"
	"github.com/spf13/pflag"
)

var listenTxCmd = &cobra.Command{
	Use:   "listentx",
	Short: "Listen to transaction events.",
	Long:  "Listen to transaction events",
	Run: func(cmd *cobra.Command, args []string) {
		if cliconfig.Config().TxID() == "" {
			fmt.Printf("\nMust specify the transaction ID\n\n")
			cmd.HelpFunc()(cmd, args)
			return
		}
		action, err := newListenTXAction(cmd.Flags())
		if err != nil {
			cliconfig.Config().Logger().Errorf("Error while initializing listenTxAction: %v", err)
			return
		}

		defer action.Terminate()

		err = action.invoke()
		if err != nil {
			cliconfig.Config().Logger().Errorf("Error while running listenTxAction: %v", err)
		}
	},
}

func getListenTXCmd() *cobra.Command {
	flags := listenTxCmd.Flags()
	cliconfig.InitChannelID(flags)
	cliconfig.InitTxID(flags)
	cliconfig.InitPeerURL(flags, "", "The URL of the peer on which to listen for events, e.g. grpcs://localhost:7051")
	return listenTxCmd
}

type listentxAction struct {
	action.Action
	inputEvent
}

func newListenTXAction(flags *pflag.FlagSet) (*listentxAction, error) {
	action := &listentxAction{inputEvent: inputEvent{done: make(chan bool)}}
	err := action.Initialize(flags)
	return action, err
}

func (a *listentxAction) invoke() error {

	eventHub, err := a.EventClient()
	if err != nil {
		return err
	}

	fmt.Printf("Registering TX event for TxID [%s]\n", cliconfig.Config().TxID())

	reg, eventch, err := eventHub.RegisterTxStatusEvent(cliconfig.Config().TxID())
	if err != nil {
		return errors.WithMessage(err, "Error registering for block events")
	}
	defer eventHub.Unregister(reg)

	enterch := a.WaitForEnter()
	fmt.Println("Press <enter> to terminate")

	select {
	case _, _ = <-enterch:
		return nil
	case event, ok := <-eventch:
		if !ok {
			return errors.WithMessage(err, "unexpected closed channel while waiting for tx status event")
		}
		fmt.Printf("Received TX event. TxID: %s, Code: %s, Error: %s\n", event.TxID, event.TxValidationCode, err)
	}

	return nil
}


================================================
FILE: fabric-cli/cmd/fabric-cli/executor/executor.go
================================================
/*
Copyright SecureKey Technologies Inc. All Rights Reserved.

SPDX-License-Identifier: Apache-2.0
*/

package executor

import (
	"fmt"
	"math"
	"sync"
	"time"

	cliconfig "github.com/securekey/fabric-examples/fabric-cli/cmd/fabric-cli/config"
	"github.com/securekey/fabric-examples/fabric-cli/cmd/fabric-cli/executor/worker"
)

// State is the state of the executor
type State uint8

const (
	// NEW indicates that the executor is new and has not been started yet
	NEW State = iota

	// STARTED indicates that the executor is up and running
	STARTED

	// TERMINATED indicates that the executor has been shut down
	TERMINATED
)

// Executor maintains a pool of workers that execute Tasks in separate Go routines. The caller submits
// a Task to the Executor, which is submitted to an available worker. If a worker is not available then
// the task is queue until one becomes available. The Executor is useful for throttling requests in order
// not to overload the application.
type Executor struct {
	name        string
	state       State
	tasks       chan worker.Task
	terminating chan bool
	pool        *worker.Pool
	wg          sync.WaitGroup
}

// NewConcurrent creates a new, concurrent executor with the given concurrency.
// As tasks are submitted they are queued while waiting for a worker for execution.
//
// - name: The name of the executor (useful for debugging)
// - concurrency: The concurrency, i.e. the number of workers executing concurrently
func NewConcurrent(name string, concurrency uint16) *Executor {
	return New(name, math.MaxInt16, worker.NewPool(name, concurrency))
}

// NewBoundedConcurrent creates a new, concurrent executor with the given concurrency
// and queue length. As tasks are submitted they are queued while waiting for a worker for execution. Once the
// number of queued tasks reaches the given queue length, the Submit operation will block until a worker becomes
// available.
//
// - name: The name of the executor (useful for debugging)
// - concurrency: The concurrency, i.e. the number of workers executing concurrently
// - queueLength: The maximum number of tasks allowed to be queued while waiting for a worker
func NewBoundedConcurrent(name string, concurrency uint16, queueLength uint16) *Executor {
	return New(name, queueLength, worker.NewPool(name, concurrency))
}

// New creates a new, multi-threaded executor with the given options:
// - name: The name of the executor (useful for debugging)
// - queueLength: The maximum number of tasks allowed to be queued while waiting for a worker
// 		If queueSize == concurrency then the Submit() function will block until a worker becomes free,
//		otherwise the task will be added to the queue and Submit() will not block.
// pool - The worker pool
func New(name string, queueLength uint16, pool *worker.Pool) *Executor {
	return &Executor{
		name:        name,
		state:       NEW,
		terminating: make(chan bool),
		tasks:       make(chan worker.Task, queueLength),
		pool:        pool,
	}
}

// Start starts the Executor
func (e *Executor) Start() bool {
	if e.state != NEW {
		return false
	}

	// Start the worker pool
	e.pool.Start()

	// Start the task dispatcher
	go e.dispatch()

	e.state = STARTED

	return true
}

// Submit submits a new task
func (e *Executor) Submit(task worker.Task) error {
	if e.state != STARTED {
		return fmt.Errorf("executor [%s] is not started", e.name)
	}

	// Submit the task to the dispatcher
	cliconfig.Config().Logger().Debugf("Submit[%s] - submitting task...\n", e.name)
	e.wg.Add(1)
	e.tasks <- task
	cliconfig.Config().Logger().Debugf("...Submit[%s] - submitted task\n", e.name)

	return nil
}

// SubmitDelayed submits a new task in the future
func (e *Executor) SubmitDelayed(task worker.Task, delay time.Duration) error {
	if e.state != STARTED {
		return fmt.Errorf("executor [%s] is not started", e.name)
	}

	cliconfig.Config().Logger().Debugf("Submit[%s] - submitting task to execute in %s ...\n", e.name, delay)

	e.wg.Add(1)

	go func() {
		<-time.After(delay)
		e.Submit(task)
		e.wg.Done()
	}()

	return nil
}

// Wait waits for all outstanding tasks to complete
func (e *Executor) Wait() {
	e.wg.Wait()
}

// Stop stops the executor.
// - wait: If true then the call will block until all outstanding
//   tasks have completed; otherwise the executor will shut down immediately
func (e *Executor) Stop(wait bool) bool {
	if e.state != STARTED {
		return false
	}

	e.state = TERMINATED

	cliconfig.Config().Logger().Debugf("[%s] Stopping executor ...\n", e.name)

	// Wait for the dispatcher to purge its queue
	e.wg.Wait()

	cliconfig.Config().Logger().Debugf("[%s] Stopping the dispatcher ...\n", e.name)

	// Stop the dispatcher
	e.terminating <- true

	cliconfig.Config().Logger().Debugf("[%s] Stopping the worker pool ...\n", e.name)

	// Stop the worker pool
	e.pool.Stop(wait)

	cliconfig.Config().Logger().Debugf("[%s] ... executor stopped.\n", e.name)

	return true
}

func (e *Executor) dispatch() {
	for {
		select {
		// Wait for a task
		case task := <-e.tasks:
			e.pool.Submit(task)
			e.wg.Done()

		case <-e.terminating:
			cliconfig.Config().Logger().Debugf("[%s] ... executor dispatcher ended\n", e.name)
			return
		}
	}
}


================================================
FILE: fabric-cli/cmd/fabric-cli/executor/worker/worker.go
================================================
/*
Copyright SecureKey Technologies Inc. All Rights Reserved.

SPDX-License-Identifier: Apache-2.0
*/

package worker

import (
	cliconfig "github.com/securekey/fabric-examples/fabric-cli/cmd/fabric-cli/config"
)

// State is the state of a Worker
type State uint8

const (
	// READY indicates that a worker is ready to accept a new task
	READY State = iota

	// STOPPED indicates that the worker has terminated
	STOPPED
)

// Task is the task that the Worker invokes
type Task interface {
	Invoke()
}

// Events receives event notifications from the worker
type Events interface {
	// StateChange indicates the new state of the worker
	StateChange(w *Worker, state State)

	// TaskStarted indicates that the given worker has started executing the given task
	TaskStarted(w *Worker, task Task)

	// TaskCompleted indicates that the given worker has completed the given task
	TaskCompleted(w *Worker, task Task)
}

// Worker invokes a Task
type Worker struct {
	name   string
	events Events
	task   chan Task
	done   chan bool
}

func newWorker(name string, events Events) *Worker {
	return &Worker{
		name:   name,
		events: events,
		task:   make(chan Task),
		done:   make(chan bool),
	}
}

// Name returns the name of the worker (useful for debugging)
func (w *Worker) Name() string {
	return w.name
}

// Submit submits a task
func (w *Worker) Submit(task Task) {
	w.task <- task
}

func (w *Worker) invoke(task Task) {
	cliconfig.Config().Logger().Debugf("Worker[%s].invoke ...\n", w.name)
	defer w.events.TaskCompleted(w, task)

	w.events.TaskStarted(w, task)
	task.Invoke()
	cliconfig.Config().Logger().Debugf("Worker[%s].invoke done.\n", w.name)
}

// Start starts the worker
func (w *Worker) Start() {
	cliconfig.Config().Logger().Debugf("Worker[%s] starting...\n", w.name)
	go func() {
		for {
			cliconfig.Config().Logger().Debugf("Worker[%s] waiting for task...\n", w.name)

			// Inform the events that I'm available
			w.events.StateChange(w, READY)

			select {
			case task := <-w.task:
				w.invoke(task)

			case <-w.done:
				w.events.StateChange(w, STOPPED)
				cliconfig.Config().Logger().Debugf("Worker[%s] stopped\n", w.name)
				return
			}
		}
	}()
}

// Stop stops the worker
func (w *Worker) Stop() {
	cliconfig.Config().Logger().Debugf("Worker[%s] stopping...\n", w.name)
	w.done <- true
}


================================================
FILE: fabric-cli/cmd/fabric-cli/executor/worker/workerpool.go
================================================
/*
Copyright SecureKey Technologies Inc. All Rights Reserved.

SPDX-License-Identifier: Apache-2.0
*/

package worker

import (
	"fmt"
	"sync"

	cliconfig "github.com/securekey/fabric-examples/fabric-cli/cmd/fabric-cli/config"
)

// Pool contains a pool of workers that can each execute a Task
type Pool struct {
	name            string
	workers         []*Worker
	availableWorker chan *Worker
	taskWg          sync.WaitGroup
	wg              sync.WaitGroup
}

// NewPool creates a worker Pool with the given Factory
func NewPool(name string, concurrency uint16) *Pool {
	pool := &Pool{
		name:            name,
		availableWorker: make(chan *Worker, concurrency),
		workers:         make([]*Worker, concurrency),
	}

	// Create the workers
	for i := 0; i < int(concurrency); i++ {
		pool.workers[i] = newWorker(fmt.Sprintf("%s-%d", name, i), pool)
	}

	return pool
}

// Name returns the name of the pool
func (p *Pool) Name() string {
	return p.name
}

// Start starts the pool
func (p *Pool) Start() {
	p.wg.Add(len(p.workers))

	// Start the workers
	for _, w := range p.workers {
		w.Start()
	}
}

// Stop stops the pool and optionally waits until all tasks have completed
func (p *Pool) Stop(wait bool) {
	cliconfig.Config().Logger().Debugf("[%s] Stopping worker pool ...\n", p.name)

	if wait {
		// Wait for all the tasks to complete
		cliconfig.Config().Logger().Debugf("[%s] ... waiting for tasks to complete ...\n", p.name)
		p.taskWg.Wait()
	} else {
		cliconfig.Config().Logger().Debugf("[%s] ... forcing all tasks to stop ...\n", p.name)
	}

	// Shut down the workers
	cliconfig.Config().Logger().Debugf("[%s] ... stopping workers ...\n", p.name)
	for i := 0; i < len(p.workers); i++ {
		w := <-p.availableWorker
		w.Stop()
	}

	// Wait for all of the workers to stop
	p.wg.Wait()
}

// Submit submits a Task for execution
func (p *Pool) Submit(task Task) {
	cliconfig.Config().Logger().Debugf("worker pool.Submit[%s] - waiting for available worker\n", p.name)

	p.taskWg.Add(1)

	// Wait for an available worker
	w := <-p.availableWorker

	cliconfig.Config().Logger().Debugf("worker pool.Submit[%s] - got worker [%s]. Submitting task...\n", p.name, w.Name())

	// Submit the task to the worker
	w.Submit(task)

	cliconfig.Config().Logger().Debugf("worker pool.Submit[%s] - submitted task to worker[%s]\n", p.name, w.Name())
}

// StateChange is invoked when the state of the Worker changes
func (p *Pool) StateChange(w *Worker, state State) {
	switch state {
	case READY:
		p.availableWorker <- w
		break

	case STOPPED:
		cliconfig.Config().Logger().Debugf("...Worker[%s] stopped\n", w.Name())
		p.wg.Done()
		break

	default:
		cliconfig.Config().Logger().Warnf("Unsupported worker state: %d\n", state)
		break
	}
}

// TaskStarted is invoked when the given Worker begins executing the given Task
func (p *Pool) TaskStarted(w *Worker, task Task) {
	// Nothing to do
}

// TaskCompleted is invoked when the given Worker completed executing the given Task
func (p *Pool) TaskCompleted(w *Worker, task Task) {
	p.taskWg.Done()
}


================================================
FILE: fabric-cli/cmd/fabric-cli/fabric-cli.go
================================================
/*
Copyright SecureKey Technologies Inc. All Rights Reserved.

SPDX-License-Identifier: Apache-2.0
*/

package main

import (
	"github.com/securekey/fabric-examples/fabric-cli/cmd/fabric-cli/cmd"
)

func main() {
	cmd.Execute()
}


================================================
FILE: fabric-cli/cmd/fabric-cli/go.mod
================================================
// Copyright SecureKey Technologies Inc. All Rights Reserved.
//
// SPDX-License-Identifier: Apache-2.0

module github.com/securekey/fabric-examples/fabric-cli/cmd/fabric-cli

require (
	github.com/cloudflare/cfssl v0.0.0-20180323000720-5d63dbd981b5 // indirect
	github.com/golang/protobuf v1.3.2
	github.com/hyperledger/fabric-protos-go v0.0.0-20191121202242-f5500d5e3e85
	github.com/hyperledger/fabric-sdk-go v1.0.0-beta1.0.20200106161850-8f3d32c9d1a6
	github.com/inconshreveable/mousetrap v1.0.0 // indirect
	github.com/magiconair/properties v1.8.0 // indirect
	github.com/mitchellh/mapstructure v0.0.0-20180511142126-bb74f1db0675 // indirect
	github.com/pelletier/go-toml v1.2.0 // indirect
	github.com/pkg/errors v0.8.1
	github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e // indirect
	github.com/prometheus/procfs v0.0.0-20180920065004-418d78d0b9a7 // indirect
	github.com/spf13/afero v1.1.1 // indirect
	github.com/spf13/cobra v0.0.3
	github.com/spf13/pflag v1.0.1
	github.com/stretchr/testify v1.3.0
)

go 1.13


================================================
FILE: fabric-cli/cmd/fabric-cli/go.sum
================================================
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/Knetic/govaluate v3.0.0+incompatible h1:7o6+MAPhYTCF0+fdvoz1xDedhRb4f6s9Tn1Tt7/WTEg=
github.com/Knetic/govaluate v3.0.0+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
github.com/VividCortex/gohistogram v1.0.0 h1:6+hBz+qvs0JOrrNhhmR7lFxo5sINxBCGXrdtl/UvroE=
github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cloudflare/cfssl v0.0.0-20180223231731-4e2dcbde5004/go.mod h1:yMWuSON2oQp+43nFtAV/uvKQIFpSPerB57DCt9t8sSA=
github.com/cloudflare/cfssl v0.0.0-20180323000720-5d63dbd981b5 h1:PqZ3bA4yzwywivzk7PBQWngJp2/PAS0bWRZerKteicY=
github.com/cloudflare/cfssl v0.0.0-20180323000720-5d63dbd981b5/go.mod h1:yMWuSON2oQp+43nFtAV/uvKQIFpSPerB57DCt9t8sSA=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/go-kit/kit v0.8.0 h1:Wz+5lgoB0kkuqLEc6NVmwRknTKP6dTGbSqvhZtBI/j0=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.4.0 h1:MP4Eh7ZCb31lleYCFuwm0oe4/YGak+5l1vA2NOE80nA=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/gogo/protobuf v1.1.1 h1:72R+M5VuhED/KujmZVcIquuo8mBgX4oVda//DQb3PXo=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0 h1:28o5sBqPkBsMGnC6b4MvE2TzSr5/AT4c/1fLqVGIwlk=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/google/certificate-transparency-go v0.0.0-20180222191210-5ab67e519c93 h1:qdfmdGwtm13OVx+AxguOWUTbgmXGn2TbdUHipo3chMg=
github.com/google/certificate-transparency-go v0.0.0-20180222191210-5ab67e519c93/go.mod h1:QeJfpSbVSfYc7RgB3gJFj9cbuQMMchQxrWXz8Ruopmg=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/hashicorp/hcl v0.0.0-20180404174102-ef8a98b0bbce h1:xdsDDbiBDQTKASoGEZ+pEmF1OnWuu8AQ9I8iNbHNeno=
github.com/hashicorp/hcl v0.0.0-20180404174102-ef8a98b0bbce/go.mod h1:oZtUIOe8dh44I2q6ScRibXws4Ajl+d+nod3AaR9vL5w=
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/hyperledger/fabric-lib-go v1.0.0 h1:UL1w7c9LvHZUSkIvHTDGklxFv2kTeva1QI2emOVc324=
github.com/hyperledger/fabric-lib-go v1.0.0/go.mod h1:H362nMlunurmHwkYqR5uHL2UDWbQdbfz74n8kbCFsqc=
github.com/hyperledger/fabric-protos-go v0.0.0-20191121202242-f5500d5e3e85 h1:bNgEcCg5NVRWs/T+VUEfhgh5Olx/N4VB+0+ybW+oSuA=
github.com/hyperledger/fabric-protos-go v0.0.0-20191121202242-f5500d5e3e85/go.mod h1:xVYTjK4DtZRBxZ2D9aE4y6AbLaPwue2o/criQyQbVD0=
github.com/hyperledger/fabric-sdk-go v1.0.0-beta1.0.20200106161850-8f3d32c9d1a6 h1:oEdHFGkrXcfoJdXmxem5fCyXS23SdfHc2UPt5g8o6HM=
github.com/hyperledger/fabric-sdk-go v1.0.0-beta1.0.20200106161850-8f3d32c9d1a6/go.mod h1:/s224b8NLvOJOCIqBvWd9O6u7GE33iuIOT6OfcTE1OE=
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515 h1:T+h1c/A9Gawja4Y9mFVWj2vyii2bbUNDw3kt9VxK2EY=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/magiconair/properties v1.7.6/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/miekg/pkcs11 v0.0.0-20190329070431-55f3fac3af27 h1:XA/VH+SzpYyukhgh7v2mTp8rZoKKITXR/x3FIizVEXs=
github.com/miekg/pkcs11 v0.0.0-20190329070431-55f3fac3af27/go.mod h1:WCBAbTOdfhHhz7YXujeZMF7owC4tPb1naKFsgfUISjo=
github.com/mitchellh/mapstructure v0.0.0-20180220230111-00c29f56e238/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v0.0.0-20180511142126-bb74f1db0675 h1:/rdJjIiKG5rRdwG5yxHmSE/7ZREjpyC0kL7GxGT/qJw=
github.com/mitchellh/mapstructure v0.0.0-20180511142126-bb74f1db0675/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/onsi/ginkgo v1.6.0 h1:Ix8l273rp3QzYgXSR+c8d1fTG7UPgYkOSELPhiY/YGw=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/gomega v1.4.2 h1:3mYCb7aPxS/RU7TI1y4rkEn1oKmPRjNJLNEXgw7MH2I=
github.com/onsi/gomega v1.4.2/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/pelletier/go-toml v1.1.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v0.8.0 h1:1921Yw9Gc3iSc4VQh3PIoOqgPCZS7G/4xQNVUp8Mda8=
github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910 h1:idejC8f05m9MGOsuEi1ATq9shN03HrxNkD/luQvxCv8=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/common v0.0.0-20180518154759-7600349dcfe1/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e h1:n/3MEhJQjQxrOUCzh1Y3Re6aJUUWRp2M9+Oc3eVn/54=
github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/procfs v0.0.0-20180705121852-ae68e2d4c00f/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20180920065004-418d78d0b9a7 h1:NgR6WN8nQ4SmFC1sSUHY8SriLuWCZ6cCIQtH4vDZN3c=
github.com/prometheus/procfs v0.0.0-20180920065004-418d78d0b9a7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/spf13/afero v1.1.0/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/afero v1.1.1 h1:Lt3ihYMlE+lreX1GS4Qw4ZsNpYQLxIXKBTEOXm3nt6I=
github.com/spf13/afero v1.1.1/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/cast v1.2.0 h1:HHl1DSRbEQN2i8tJmtS6ViPyHx35+p51amrdsiTCrkg=
github.com/spf13/cast v1.2.0/go.mod h1:r2rcYCSwa1IExKTDiTfzaxqT2FNHs8hODu4LnUfgKEg=
github.com/spf13/cobra v0.0.3 h1:ZlrZ4XsMRm04Fr5pSFxBgfND2EBVa1nLpiy1stUsX/8=
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/jwalterweatherman v0.0.0-20180109140146-7c0cea34c8ec h1:2ZXvIUGghLpdTVHR1UfvfrzoVlZaE/yOWC5LueIHZig=
github.com/spf13/jwalterweatherman v0.0.0-20180109140146-7c0cea34c8ec/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/pflag v1.0.1 h1:aCvUg6QPl3ibpQUxyLkrEkCHtPqYJL4x9AuhqVqFis4=
github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/viper v1.0.2 h1:Ncr3ZIuJn322w2k1qmzXDnkLAdQMlJqBa9kfAH+irso=
github.com/spf13/viper v1.0.2/go.mod h1:A8kyI5cUJhb8N+3pkfONlcEcZbueH6nhAm0Fq7SrnBM=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd h1:HuTn7WObtcDo9uEEU7rEqL0jYthdXAmZ6PP+meazmaU=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e h1:o3PsSEY8E4eXWkXrIP9YJALUkVZqzHJT5DOasTyn8Vs=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190327125643-d831d65fe17d h1:XB2jc5XQ9uhizGTS2vWcN01bc4dI6z3C4KY5MQm8SS8=
google.golang.org/genproto v0.0.0-20190327125643-d831d65fe17d/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/grpc v1.19.0 h1:cfg4PD8YEdSFnm7qLV4++93WcmhH2nIUhMjhdCvl3j8=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.23.0 h1:AzbTB6ux+okLTzP8Ru1Xs41C303zdcfEht7MQnYJt5A=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=


================================================
FILE: fabric-cli/cmd/fabric-cli/printer/blockprinter.go
================================================
/*
Copyright SecureKey Technologies Inc. All Rights Reserved.

SPDX-License-Identifier: Apache-2.0
*/

package printer

import (
	"encoding/base64"
	"fmt"
	"net/http"
	"reflect"
	"strings"

	"github.com/golang/protobuf/proto"
	fabriccmn "github.com/hyperledger/fabric-protos-go/common"
	"github.com/hyperledger/fabric-protos-go/ledger/rwset/kvrwset"
	"github.com/hyperledger/fabric-protos-go/msp"
	ab "github.com/hyperledger/fabric-protos-go/orderer"
	pb "github.com/hyperledger/fabric-protos-go/peer"
	"github.com/hyperledger/fabric-sdk-go/pkg/common/providers/fab"
	"github.com/hyperledger/fabric-sdk-go/third_party/github.com/hyperledger/fabric/core/common/ccprovider"
	"github.com/hyperledger/fabric-sdk-go/third_party/github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/rwsetutil"
	ledgerUtil "github.com/hyperledger/fabric-sdk-go/third_party/github.com/hyperledger/fabric/core/ledger/util"
	"github.com/pkg/errors"
)

const (
	// AnchorPeersKey is the key name for the AnchorPeers ConfigValue
	AnchorPeersKey = "AnchorPeers"

	// ReadersPolicyKey is the key used for the read policy
	ReadersPolicyKey = "Readers"

	// WritersPolicyKey is the key used for the read policy
	WritersPolicyKey = "Writers"

	// AdminsPolicyKey is the key used for the read policy
	AdminsPolicyKey = "Admins"

	// MSPKey is the org key used for MSP configuration
	MSPKey = "MSP"

	// ConsensusTypeKey is the cb.ConfigItem type key name for the ConsensusType message
	ConsensusTypeKey = "ConsensusType"

	// BatchSizeKey is the cb.ConfigItem type key name for the BatchSize message
	BatchSizeKey = "BatchSize"

	// BatchTimeoutKey is the cb.ConfigItem type key name for the BatchTimeout message
	BatchTimeoutKey = "BatchTimeout"

	// ChannelRestrictionsKey is the key name for the ChannelRestrictions message
	ChannelRestrictionsKey = "ChannelRestrictions"

	// KafkaBrokersKey is the cb.ConfigItem type key name for the KafkaBrokers message
	KafkaBrokersKey = "KafkaBrokers"

	// ChannelCreationPolicyKey is the key for the ChannelCreationPolicy value
	ChannelCreationPolicyKey = "ChannelCreationPolicy"

	// ConsortiumKey is the key for the cb.ConfigValue for the Consortium message
	ConsortiumKey = "Consortium"

	// HashingAlgorithmKey is the cb.ConfigItem type key name for the HashingAlgorithm message
	HashingAlgorithmKey = "HashingAlgorithm"

	// BlockDataHashingStructureKey is the cb.ConfigItem type key name for the BlockDataHashingStructure message
	BlockDataHashingStructureKey = "BlockDataHashingStructure"

	// OrdererAddressesKey is the cb.ConfigItem type key name for the OrdererAddresses message
	OrdererAddressesKey = "OrdererAddresses"

	// ChannelGroupKey is the name of the channel group
	ChannelGroupKey = "Channel"

	// CapabilitiesKey is the key for capabilities
	CapabilitiesKey = "Capabilities"

	collectionSeparator = "~"
)

// Printer is used for printing various data structures
type Printer interface {
	// PrintBlockchainInfo outputs BlockchainInfo
	PrintBlockchainInfo(info *fabriccmn.BlockchainInfo)

	// PrintBlock outputs a Block
	PrintBlock(block *fabriccmn.Block)

	// PrintFilteredBlock outputs a Block
	PrintFilteredBlock(block *pb.FilteredBlock)

	// PrintChannels outputs the array of ChannelInfo
	PrintChannels(channels []*pb.ChannelInfo)

	// PrintChaincodes outputs the given array of ChaincodeInfo
	PrintChaincodes(chaincodes []*pb.ChaincodeInfo)

	// PrintProcessedTransaction outputs a ProcessedTransaction
	PrintProcessedTransaction(tx *pb.ProcessedTransaction)

	// PrintChaincodeData outputs ChaincodeData
	PrintChaincodeData(ccdata *ccprovider.ChaincodeData, collConfig *pb.CollectionConfigPackage)

	// PrintTxProposalResponses outputs the proposal responses
	PrintTxProposalResponses(responses []*fab.TransactionProposalResponse, payloadOnly bool)

	// PrintResponses outputs responses
	PrintResponses(response []*pb.Response)

	// PrintChaincodeEvent outputs a chaincode event
	PrintChaincodeEvent(event *fab.CCEvent)

	// PrintPeers outputs the array of Peers
	PrintPeers(peers []fab.Peer)

	// Print outputs a formatted string
	Print(frmt string, vars ...interface{})
}

// BlockPrinter is an implementation of BlockPrinter
type BlockPrinter struct {
	printer
}

// NewBlockPrinter returns a new Printer of the given OutputFormat and WriterType
func NewBlockPrinter(format OutputFormat, writerType WriterType) *BlockPrinter {
	return &BlockPrinter{
		printer: *newPrinter(format, writerType),
	}
}

// NewBlockPrinterWithOpts returns a new Printer of the given OutputFormat and WriterType
func NewBlockPrinterWithOpts(format OutputFormat, writerType WriterType, opts *FormatterOpts) *BlockPrinter {
	return &BlockPrinter{
		printer: *newPrinterWithOpts(format, writerType, opts),
	}
}

// PrintBlockchainInfo prints BlockchainInfo
func (p *BlockPrinter) PrintBlockchainInfo(info *fabriccmn.BlockchainInfo) {
	if p.Formatter == nil {
		fmt.Printf("%s\n", info)
		return
	}

	p.PrintHeader()
	p.Field("Height", info.Height)
	p.Field("CurrentBlockHash", Base64URLEncode(info.CurrentBlockHash))
	p.Field("PreviousBlockHash", Base64URLEncode(info.PreviousBlockHash))
	p.PrintFooter()
}

// PrintBlock prints a Block
func (p *BlockPrinter) PrintBlock(block *fabriccmn.Block) {
	if p.Formatter == nil {
		fmt.Printf("%s\n", block)
		return
	}

	p.PrintHeader()
	p.Element("Header")
	p.Field("Number", block.Header.Number)
	p.Field("PreviousHash", Base64URLEncode(block.Header.PreviousHash))
	p.Field("DataHash", Base64URLEncode(block.Header.DataHash))
	p.ElementEnd()

	p.Element("Metadata")
	p.PrintBlockMetadata(block.Metadata)
	p.ElementEnd()

	p.Element("Data")
	p.Array("Data")
	for i := range block.Data.Data {
		p.Item("Envelope", i)
		p.PrintEnvelope(ExtractEnvelopeOrPanic(block, i))
		p.ItemEnd()
	}
	p.ArrayEnd()
	p.ElementEnd()
	p.PrintFooter()
}

// PrintFilteredBlock prints a FilteredBlock
func (p *BlockPrinter) PrintFilteredBlock(block *pb.FilteredBlock) {
	if p.Formatter == nil {
		fmt.Printf("%s\n", block)
		return
	}

	p.PrintHeader()
	p.Field("ChannelID", block.ChannelId)
	p.Field("Number", block.Number)

	p.Element("FilteredTransactions")
	p.Array("FilteredTransactions")
	for _, tx := range block.FilteredTransactions {
		p.PrintFilteredTransaction(tx)
	}
	p.ArrayEnd()
	p.ElementEnd()
	p.PrintFooter()
}

// PrintChannels prints the array of ChannelInfo
func (p *BlockPrinter) PrintChannels(channels []*pb.ChannelInfo) {
	if p.Formatter == nil {
		fmt.Printf("%s\n", channels)
		return
	}

	p.PrintHeader()
	p.Array("Channels")
	for _, channel := range channels {
		p.Field("ChannelId", channel.ChannelId)
	}
	p.ArrayEnd()
	p.PrintFooter()
}

func (p *BlockPrinter) PrintPeers(peers []fab.Peer) {
	if p.Formatter == nil {
		fmt.Printf("%s\n", peers)
		return
	}

	p.PrintHeader()
	p.Array("Peers")
	for _, peer := range peers {
		p.Item("Peer", peer.URL())
		p.PrintPeer(peer)
		p.ItemEnd()
	}
	p.ArrayEnd()
	p.PrintFooter()
}

// PrintChaincodes prints th
Download .txt
gitextract_8xm2cptt/

├── .gitignore
├── .gitreview
├── README.md
└── fabric-cli/
    ├── .gitignore
    ├── LICENSE
    ├── Makefile
    ├── README.md
    ├── cmd/
    │   └── fabric-cli/
    │       ├── action/
    │       │   ├── action.go
    │       │   └── svcproviderfactory.go
    │       ├── chaincode/
    │       │   ├── chaincodecmd.go
    │       │   ├── getinfocmd.go
    │       │   ├── installcmd.go
    │       │   ├── instantiatecmd.go
    │       │   ├── invokecmd.go
    │       │   ├── invokeerror/
    │       │   │   └── invokeerror.go
    │       │   ├── invoketask/
    │       │   │   └── invoketask.go
    │       │   ├── multitask/
    │       │   │   └── multitask.go
    │       │   ├── querycmd.go
    │       │   ├── querytask/
    │       │   │   └── querytask.go
    │       │   ├── task/
    │       │   │   └── task.go
    │       │   ├── upgradecmd.go
    │       │   └── utils/
    │       │       ├── test.json
    │       │       ├── util.go
    │       │       └── util_test.go
    │       ├── channel/
    │       │   ├── channelcmd.go
    │       │   ├── channelcreatecmd.go
    │       │   └── channeljoincmd.go
    │       ├── cmd/
    │       │   └── fabric-cli.go
    │       ├── config/
    │       │   └── config.go
    │       ├── event/
    │       │   ├── eventcmd.go
    │       │   ├── inputevent.go
    │       │   ├── listenblockcmd.go
    │       │   ├── listencccmd.go
    │       │   ├── listenfilteredblockcmd.go
    │       │   └── listentxcmd.go
    │       ├── executor/
    │       │   ├── executor.go
    │       │   └── worker/
    │       │       ├── worker.go
    │       │       └── workerpool.go
    │       ├── fabric-cli.go
    │       ├── go.mod
    │       ├── go.sum
    │       ├── printer/
    │       │   ├── blockprinter.go
    │       │   ├── formatter.go
    │       │   ├── printer.go
    │       │   ├── protoutils.go
    │       │   └── writer.go
    │       └── query/
    │           ├── queryblockcmd.go
    │           ├── querychannelscmd.go
    │           ├── querycmd.go
    │           ├── queryinfocmd.go
    │           ├── queryinstalledcmd.go
    │           ├── querylocalpeerscmd.go
    │           ├── querypeerscmd.go
    │           └── querytxcmd.go
    └── test/
        ├── fixtures/
        │   ├── config/
        │   │   ├── config_test_local.yaml
        │   │   └── pvtdatacollection.json
        │   └── testdata/
        │       └── src/
        │           ├── github.com/
        │           │   └── securekey/
        │           │       ├── example2_cc/
        │           │       │   └── example2_cc.go
        │           │       └── example_cc/
        │           │           └── example_cc.go
        │           ├── go.mod
        │           └── go.sum
        └── integration/
            ├── fabric-cli_test.go
            ├── go.mod
            └── go.sum
Download .txt
SYMBOL INDEX (735 symbols across 47 files)

FILE: fabric-cli/cmd/fabric-cli/action/action.go
  constant defaultUser (line 43) | defaultUser = "User1"
  constant adminUser (line 44) | adminUser   = "Admin"
  type ArgStruct (line 48) | type ArgStruct struct
  type Action (line 54) | type Action struct
    method Initialize (line 68) | func (action *Action) Initialize(flags *pflag.FlagSet) error {
    method Terminate (line 171) | func (action *Action) Terminate() {
    method Flags (line 179) | func (action *Action) Flags() *pflag.FlagSet {
    method EndpointConfig (line 184) | func (action *Action) EndpointConfig() fab.EndpointConfig {
    method ChannelClient (line 189) | func (action *Action) ChannelClient(...channel.ClientOption) (*channel...
    method OrgAdminChannelClient (line 205) | func (action *Action) OrgAdminChannelClient(orgID string) (*channel.Cl...
    method AdminChannelClient (line 223) | func (action *Action) AdminChannelClient() (*channel.Client, error) {
    method Printer (line 228) | func (action *Action) Printer() printer.Printer {
    method LocalContext (line 233) | func (action *Action) LocalContext() (context.Local, error) {
    method ChannelProvider (line 246) | func (action *Action) ChannelProvider() (context.ChannelProvider, erro...
    method EventClient (line 264) | func (action *Action) EventClient(opts ...event.ClientOption) (*event....
    method LedgerClient (line 277) | func (action *Action) LedgerClient() (*ledger.Client, error) {
    method Peer (line 290) | func (action *Action) Peer() fab.Peer {
    method Peers (line 298) | func (action *Action) Peers() []fab.Peer {
    method PeersByOrg (line 303) | func (action *Action) PeersByOrg() map[string][]fab.Peer {
    method OrgOfPeer (line 308) | func (action *Action) OrgOfPeer(peerURL string) (string, error) {
    method Client (line 317) | func (action *Action) Client(channelID string) (*channel.Client, error) {
    method ResourceMgmtClient (line 326) | func (action *Action) ResourceMgmtClient() (*resmgmt.Client, error) {
    method ResourceMgmtClientForOrg (line 331) | func (action *Action) ResourceMgmtClientForOrg(orgID string) (*resmgmt...
    method ClientForUser (line 340) | func (action *Action) ClientForUser(channelID string, user mspapi.Sign...
    method ResourceMgmtClientForUser (line 357) | func (action *Action) ResourceMgmtClientForUser(user mspapi.SigningIde...
    method ChannelMgmtClientForUser (line 371) | func (action *Action) ChannelMgmtClientForUser(channelID string, user ...
    method context (line 387) | func (action *Action) context(user mspapi.SigningIdentity) (context.Cl...
    method OrgID (line 399) | func (action *Action) OrgID() string {
    method GetOrgID (line 415) | func (action *Action) GetOrgID(mspID string) (string, error) {
    method User (line 427) | func (action *Action) User() (mspapi.SigningIdentity, error) {
    method newUser (line 435) | func (action *Action) newUser(orgID, username, pwd string) (mspapi.Sig...
    method OrgUser (line 461) | func (action *Action) OrgUser(orgID, username string) (mspapi.SigningI...
    method OrgAdminUser (line 481) | func (action *Action) OrgAdminUser(orgID string) (mspapi.SigningIdenti...
    method PeerFromURL (line 490) | func (action *Action) PeerFromURL(url string) (fab.Peer, bool) {
    method Orderers (line 500) | func (action *Action) Orderers() ([]fab.Orderer, error) {
    method RandomOrderer (line 519) | func (action *Action) RandomOrderer() (fab.Orderer, error) {
    method getPeers (line 565) | func (action *Action) getPeers(allPeers []fab.Peer, peerURLs []string,...
    method PeerConfig (line 588) | func (action *Action) PeerConfig() (*fab.PeerConfig, error) {
    method CreateDiscoveryService (line 607) | func (action *Action) CreateDiscoveryService(channelID string) (fab.Di...
    method GetPeers (line 613) | func (action *Action) GetPeers() ([]fab.Peer, error) {
  function ArgsArray (line 531) | func ArgsArray() ([]ArgStruct, error) {
  function levelFromName (line 548) | func levelFromName(levelName string) logging.Level {
  function containsString (line 617) | func containsString(sarr []string, s string) bool {
  type cryptoSuiteProviderFactory (line 627) | type cryptoSuiteProviderFactory struct
    method CreateCryptoSuiteProvider (line 632) | func (f *cryptoSuiteProviderFactory) CreateCryptoSuiteProvider(config ...

FILE: fabric-cli/cmd/fabric-cli/action/svcproviderfactory.go
  type serviceProviderFactory (line 23) | type serviceProviderFactory struct
    method CreateChannelProvider (line 43) | func (f *serviceProviderFactory) CreateChannelProvider(config fab.Endp...
  function newServiceProviderFactory (line 27) | func newServiceProviderFactory() (*serviceProviderFactory, error) {
  type fabricSelectionChannelProvider (line 31) | type fabricSelectionChannelProvider struct
    method Close (line 58) | func (cp *fabricSelectionChannelProvider) Close() {
    method Initialize (line 73) | func (cp *fabricSelectionChannelProvider) Initialize(providers context...
    method ChannelService (line 81) | func (cp *fabricSelectionChannelProvider) ChannelService(ctx fab.Clien...
  type fabricSelectionChannelService (line 37) | type fabricSelectionChannelService struct
    method Selection (line 118) | func (cs *fabricSelectionChannelService) Selection() (fab.SelectionSer...
  type closable (line 53) | type closable interface
  type providerInit (line 69) | type providerInit interface

FILE: fabric-cli/cmd/fabric-cli/chaincode/chaincodecmd.go
  function Cmd (line 24) | func Cmd() *cobra.Command {

FILE: fabric-cli/cmd/fabric-cli/chaincode/getinfocmd.go
  constant lifecycleSCC (line 25) | lifecycleSCC = "lscc"
  constant getCCDataFunc (line 27) | getCCDataFunc     = "getccdata"
  constant getCollConfigFunc (line 28) | getCollConfigFunc = "getcollectionsconfig"
  function getGetInfoCmd (line 56) | func getGetInfoCmd() *cobra.Command {
  type getInfoAction (line 64) | type getInfoAction struct
    method invoke (line 77) | func (action *getInfoAction) invoke() error {
    method getCCData (line 100) | func (action *getInfoAction) getCCData(channelClient *channel.Client) ...
    method getCollConfig (line 123) | func (action *getInfoAction) getCollConfig(channelClient *channel.Clie...
  function newGetInfoAction (line 68) | func newGetInfoAction(flags *pflag.FlagSet) (*getInfoAction, error) {

FILE: fabric-cli/cmd/fabric-cli/chaincode/installcmd.go
  function getInstallCmd (line 53) | func getInstallCmd() *cobra.Command {
  type installAction (line 64) | type installAction struct
    method invoke (line 74) | func (action *installAction) invoke() error {
    method installChaincode (line 90) | func (action *installAction) installChaincode(orgID string, targets []...
  function newInstallAction (line 68) | func newInstallAction(flags *pflag.FlagSet) (*installAction, error) {

FILE: fabric-cli/cmd/fabric-cli/chaincode/instantiatecmd.go
  function getInstantiateCmd (line 57) | func getInstantiateCmd() *cobra.Command {
  type instantiateAction (line 71) | type instantiateAction struct
    method invoke (line 84) | func (a *instantiateAction) invoke() error {
    method newChaincodePolicy (line 141) | func (a *instantiateAction) newChaincodePolicy() (*common.SignaturePol...
  function newInstantiateAction (line 75) | func newInstantiateAction(flags *pflag.FlagSet) (*instantiateAction, err...
  function newChaincodePolicy (line 151) | func newChaincodePolicy(policyString string) (*common.SignaturePolicyEnv...
  type collectionConfigJSON (line 159) | type collectionConfigJSON struct
  function getCollectionConfigFromFile (line 166) | func getCollectionConfigFromFile(ccFile string) ([]*pb.CollectionConfig,...
  function getCollectionConfig (line 178) | func getCollectionConfig(cconf []collectionConfigJSON) ([]*pb.Collection...

FILE: fabric-cli/cmd/fabric-cli/chaincode/invokecmd.go
  function getInvokeCmd (line 54) | func getInvokeCmd() *cobra.Command {
  type invokeAction (line 74) | type invokeAction struct
    method invoke (line 86) | func (a *invokeAction) invoke() error {
  function newInvokeAction (line 80) | func newInvokeAction(flags *pflag.FlagSet) (*invokeAction, error) {
  function average (line 238) | func average(durations []time.Duration) float64 {
  function min (line 250) | func min(durations []time.Duration) float64 {
  function max (line 255) | func max(durations []time.Duration) float64 {
  function minMax (line 260) | func minMax(durations []time.Duration) (min float64, max float64) {

FILE: fabric-cli/cmd/fabric-cli/chaincode/invokeerror/invokeerror.go
  type ErrorCode (line 11) | type ErrorCode
  constant PersistentError (line 16) | PersistentError ErrorCode = iota
  constant TransientError (line 20) | TransientError
  constant TimeoutOnCommit (line 24) | TimeoutOnCommit
  type Error (line 29) | type Error interface
  type invokeError (line 36) | type invokeError struct
    method ErrorCode (line 74) | func (e *invokeError) ErrorCode() ErrorCode {
  function New (line 42) | func New(code ErrorCode, msg string) Error {
  function Wrap (line 50) | func Wrap(code ErrorCode, cause error, msg string) Error {
  function Wrapf (line 58) | func Wrapf(code ErrorCode, cause error, fmt string, args ...interface{})...
  function Errorf (line 66) | func Errorf(code ErrorCode, fmt string, args ...interface{}) Error {

FILE: fabric-cli/cmd/fabric-cli/chaincode/invoketask/invoketask.go
  type Task (line 24) | type Task struct
    method Attempts (line 67) | func (t *Task) Attempts() int {
    method LastError (line 72) | func (t *Task) LastError() error {
    method Invoke (line 77) | func (t *Task) Invoke() {
    method doInvoke (line 88) | func (t *Task) doInvoke() error {
  function New (line 44) | func New(ctxt utils.Context, id string, channelClient *channel.Client, t...

FILE: fabric-cli/cmd/fabric-cli/chaincode/multitask/multitask.go
  type MultiTask (line 12) | type MultiTask struct
    method Add (line 25) | func (m *MultiTask) Add(task task.Task) {
    method Invoke (line 30) | func (m *MultiTask) Invoke() {
    method Attempts (line 40) | func (m *MultiTask) Attempts() int {
    method LastError (line 49) | func (m *MultiTask) LastError() error {
  function New (line 18) | func New(completedCB func()) *MultiTask {

FILE: fabric-cli/cmd/fabric-cli/chaincode/querycmd.go
  function getQueryCmd (line 54) | func getQueryCmd() *cobra.Command {
  type queryAction (line 71) | type queryAction struct
    method query (line 83) | func (a *queryAction) query() error {
  function newQueryAction (line 77) | func newQueryAction(flags *pflag.FlagSet) (*queryAction, error) {

FILE: fabric-cli/cmd/fabric-cli/chaincode/querytask/querytask.go
  type Task (line 21) | type Task struct
    method Invoke (line 59) | func (t *Task) Invoke() {
    method Attempts (line 109) | func (t *Task) Attempts() int {
    method LastError (line 114) | func (t *Task) LastError() error {
  function New (line 39) | func New(ctxt utils.Context, id string, channelClient *channel.Client, t...

FILE: fabric-cli/cmd/fabric-cli/chaincode/task/task.go
  type Task (line 10) | type Task interface

FILE: fabric-cli/cmd/fabric-cli/chaincode/upgradecmd.go
  function getUpgradeCmd (line 56) | func getUpgradeCmd() *cobra.Command {
  type upgradeAction (line 70) | type upgradeAction struct
    method invoke (line 83) | func (a *upgradeAction) invoke() error {
    method newChaincodePolicy (line 139) | func (a *upgradeAction) newChaincodePolicy() (*fabricCommon.SignatureP...
  function newUpgradeAction (line 74) | func newUpgradeAction(flags *pflag.FlagSet) (*upgradeAction, error) {

FILE: fabric-cli/cmd/fabric-cli/chaincode/utils/util.go
  constant randFunc (line 25) | randFunc = "$rand("
  constant padFunc (line 26) | padFunc  = "$pad("
  constant seqFunc (line 27) | seqFunc  = "$seq("
  constant setFunc (line 28) | setFunc  = "$set("
  constant fileFunc (line 29) | fileFunc = "$file("
  constant varExp (line 30) | varExp   = "${"
  type Context (line 37) | type Context interface
  function AsBytes (line 53) | func AsBytes(ctxt Context, args []string) [][]byte {
  function getArg (line 70) | func getArg(ctxt Context, r *rand.Rand, arg string) string {
  function evaluateSeqExpression (line 82) | func evaluateSeqExpression(arg string) string {
  function evaluateRandExpression (line 91) | func evaluateRandExpression(r *rand.Rand, arg string) string {
  function evaluatePadExpression (line 103) | func evaluatePadExpression(arg string) string {
  function evaluateFileExpression (line 126) | func evaluateFileExpression(arg string) string {
  function evaluateSetExpression (line 136) | func evaluateSetExpression(ctxt Context, arg string) string {
  function evaluateVarExpression (line 154) | func evaluateVarExpression(ctxt Context, arg string) string {
  function evaluateExpression (line 165) | func evaluateExpression(expression, funcType, endDelim string, evaluate ...
  function NewContext (line 197) | func NewContext() Context {
  type defaultContext (line 203) | type defaultContext struct
    method SetVar (line 207) | func (c *defaultContext) SetVar(k, v string) {
    method GetVar (line 211) | func (c *defaultContext) GetVar(k string) (string, bool) {
  function readFile (line 216) | func readFile(filePath string) (string, error) {

FILE: fabric-cli/cmd/fabric-cli/chaincode/utils/util_test.go
  function TestEvaluatePadExpression (line 17) | func TestEvaluatePadExpression(t *testing.T) {
  function TestFailEvaluatePadExpression (line 25) | func TestFailEvaluatePadExpression(t *testing.T) {
  function TestEvaluateRandExpression (line 39) | func TestEvaluateRandExpression(t *testing.T) {
  function TestFailEvaluateRandExpression (line 50) | func TestFailEvaluateRandExpression(t *testing.T) {
  function TestEvaluateSeqExpression (line 65) | func TestEvaluateSeqExpression(t *testing.T) {
  function TestFailEvaluateSeqExpression (line 71) | func TestFailEvaluateSeqExpression(t *testing.T) {
  function TestEvaluateFileExpression (line 75) | func TestEvaluateFileExpression(t *testing.T) {
  function TestFailEvaluateFileExpression (line 79) | func TestFailEvaluateFileExpression(t *testing.T) {
  function TestEvaluateSetExpression (line 83) | func TestEvaluateSetExpression(t *testing.T) {
  function TestFailEvaluateSetExpression (line 89) | func TestFailEvaluateSetExpression(t *testing.T) {
  function TestGetArg (line 98) | func TestGetArg(t *testing.T) {

FILE: fabric-cli/cmd/fabric-cli/channel/channelcmd.go
  function Cmd (line 24) | func Cmd() *cobra.Command {

FILE: fabric-cli/cmd/fabric-cli/channel/channelcreatecmd.go
  function getChannelCreateCmd (line 41) | func getChannelCreateCmd() *cobra.Command {
  type channelCreateAction (line 49) | type channelCreateAction struct
    method invoke (line 59) | func (a *channelCreateAction) invoke() error {
  function newChannelCreateAction (line 53) | func newChannelCreateAction(flags *pflag.FlagSet) (*channelCreateAction,...

FILE: fabric-cli/cmd/fabric-cli/channel/channeljoincmd.go
  function getChannelJoinCmd (line 41) | func getChannelJoinCmd() *cobra.Command {
  type channelJoinAction (line 49) | type channelJoinAction struct
    method invoke (line 65) | func (a *channelJoinAction) invoke() error {
    method joinChannel (line 82) | func (a *channelJoinAction) joinChannel(orgID string, peers []fab.Peer...
  function newChannelJoinAction (line 53) | func newChannelJoinAction(flags *pflag.FlagSet) (*channelJoinAction, err...

FILE: fabric-cli/cmd/fabric-cli/cmd/fabric-cli.go
  function newFabricCLICmd (line 20) | func newFabricCLICmd() *cobra.Command {
  function Execute (line 51) | func Execute() {

FILE: fabric-cli/cmd/fabric-cli/config/config.go
  constant loggerName (line 29) | loggerName    = "fabriccli"
  constant userStatePath (line 30) | userStatePath = "/tmp/enroll_user"
  constant AutoDetectSelectionProvider (line 33) | AutoDetectSelectionProvider = "auto"
  constant StaticSelectionProvider (line 36) | StaticSelectionProvider = "static"
  constant DynamicSelectionProvider (line 39) | DynamicSelectionProvider = "dynamic"
  constant FabricSelectionProvider (line 42) | FabricSelectionProvider = "fabric"
  constant UserFlag (line 47) | UserFlag        = "user"
  constant userDescription (line 48) | userDescription = "The user"
  constant defaultUser (line 49) | defaultUser     = ""
  constant PasswordFlag (line 51) | PasswordFlag        = "pw"
  constant passwordDescription (line 52) | passwordDescription = "The password of the user"
  constant defaultPassword (line 53) | defaultPassword     = ""
  constant ChaincodeVersionFlag (line 55) | ChaincodeVersionFlag        = "v"
  constant chaincodeVersionDescription (line 56) | chaincodeVersionDescription = "The chaincode version"
  constant defaultChaincodeVersion (line 57) | defaultChaincodeVersion     = "v0"
  constant LoggingLevelFlag (line 59) | LoggingLevelFlag        = "logging-level"
  constant loggingLevelDescription (line 60) | loggingLevelDescription = "Logging level - ERROR, WARN, INFO, DEBUG"
  constant defaultLoggingLevel (line 61) | defaultLoggingLevel     = "ERROR"
  constant OrgIDsFlag (line 63) | OrgIDsFlag        = "orgid"
  constant orgIDsDescription (line 64) | orgIDsDescription = "A comma-separated list of organization IDs"
  constant defaultOrgIDs (line 65) | defaultOrgIDs     = ""
  constant ChannelIDFlag (line 67) | ChannelIDFlag        = "cid"
  constant channelIDDescription (line 68) | channelIDDescription = "The channel ID"
  constant defaultChannelID (line 69) | defaultChannelID     = ""
  constant ChaincodeIDFlag (line 71) | ChaincodeIDFlag        = "ccid"
  constant chaincodeIDDescription (line 72) | chaincodeIDDescription = "The Chaincode ID"
  constant defaultChaincodeID (line 73) | defaultChaincodeID     = ""
  constant ChaincodePathFlag (line 75) | ChaincodePathFlag        = "ccp"
  constant chaincodePathDescription (line 76) | chaincodePathDescription = "The chaincode path"
  constant defaultChaincodePath (line 77) | defaultChaincodePath     = ""
  constant ConfigFileFlag (line 79) | ConfigFileFlag        = "config"
  constant configFileDescription (line 80) | configFileDescription = "The path of the config.yaml file"
  constant defaultConfigFile (line 81) | defaultConfigFile     = ""
  constant PeerURLFlag (line 83) | PeerURLFlag        = "peer"
  constant peerURLDescription (line 84) | peerURLDescription = "A comma-separated list of peer targets, e.g. 'grpc...
  constant defaultPeerURL (line 85) | defaultPeerURL     = ""
  constant OrdererFlag (line 87) | OrdererFlag           = "orderer"
  constant ordererURLDescription (line 88) | ordererURLDescription = "The URL of the orderer, e.g. grpcs://localhost:...
  constant defaultOrdererURL (line 89) | defaultOrdererURL     = ""
  constant PrintFormatFlag (line 91) | PrintFormatFlag        = "format"
  constant printFormatDescription (line 92) | printFormatDescription = "The output format - display, json, raw"
  constant WriterFlag (line 94) | WriterFlag        = "writer"
  constant writerDescription (line 95) | writerDescription = "The writer - stdout, stderr, log"
  constant Base64Flag (line 97) | Base64Flag        = "base64"
  constant base64Description (line 98) | base64Description = "If true then binary values are encoded in base64 (o...
  constant CertificateFileFlag (line 100) | CertificateFileFlag    = "cacert"
  constant certificateDescription (line 101) | certificateDescription = "The path of the ca-cert.pem file"
  constant defaultCertificate (line 102) | defaultCertificate     = ""
  constant ArgsFlag (line 104) | ArgsFlag        = "args"
  constant argsDescription (line 105) | argsDescription = `The args in JSON format. Example: {"Func":"function",...
  constant IterationsFlag (line 107) | IterationsFlag        = "iterations"
  constant iterationsDescription (line 108) | iterationsDescription = "The number of times to invoke the chaincode"
  constant defaultIterations (line 109) | defaultIterations     = "1"
  constant SleepFlag (line 111) | SleepFlag            = "sleep"
  constant sleepTimeDescription (line 112) | sleepTimeDescription = "The number of milliseconds to sleep between invo...
  constant defaultSleepTime (line 113) | defaultSleepTime     = "0"
  constant TxFileFlag (line 115) | TxFileFlag        = "txfile"
  constant txFileDescription (line 116) | txFileDescription = "The path of the channel.tx file"
  constant defaultTxFile (line 117) | defaultTxFile     = ""
  constant ChaincodeEventFlag (line 119) | ChaincodeEventFlag        = "event"
  constant chaincodeEventDescription (line 120) | chaincodeEventDescription = "The name of the chaincode event to listen for"
  constant defaultChaincodeEvent (line 121) | defaultChaincodeEvent     = ""
  constant SeekTypeFlag (line 123) | SeekTypeFlag        = "seek"
  constant seekTypeDescription (line 124) | seekTypeDescription = "The seek type. Possible values: oldest - delivers...
  constant defaultSeekType (line 125) | defaultSeekType     = string(seek.Newest)
  constant TxIDFlag (line 127) | TxIDFlag        = "txid"
  constant txIDDescription (line 128) | txIDDescription = "The transaction ID"
  constant defaultTxID (line 129) | defaultTxID     = ""
  constant BlockNumFlag (line 131) | BlockNumFlag        = "num"
  constant blockNumDescription (line 132) | blockNumDescription = "The block number"
  constant defaultBlockNum (line 133) | defaultBlockNum     = "0"
  constant BlockHashFlag (line 135) | BlockHashFlag        = "hash"
  constant blockHashDescription (line 136) | blockHashDescription = "The block hash"
  constant defaultBlockHash (line 137) | defaultBlockHash     = ""
  constant TraverseFlag (line 139) | TraverseFlag        = "traverse"
  constant traverseDescription (line 140) | traverseDescription = "Blocks will be traversed starting with the given ...
  constant defaultTraverse (line 141) | defaultTraverse     = "0"
  constant ChaincodePolicyFlag (line 143) | ChaincodePolicyFlag        = "policy"
  constant chaincodePolicyDescription (line 144) | chaincodePolicyDescription = "The chaincode policy, e.g. OutOf(1,'Org1MS...
  constant defaultChaincodePolicy (line 145) | defaultChaincodePolicy     = ""
  constant CollectionConfigFileFlag (line 147) | CollectionConfigFileFlag        = "collconfig"
  constant collectionConfigFileDescription (line 148) | collectionConfigFileDescription = "The path of the JSON file that contai...
  constant defaultCollectionConfigFile (line 149) | defaultCollectionConfigFile     = ""
  constant TimeoutFlag (line 151) | TimeoutFlag        = "timeout"
  constant timeoutDescription (line 152) | timeoutDescription = "The timeout (in milliseconds) for the operation"
  constant defaultTimeout (line 153) | defaultTimeout     = "5000"
  constant PrintPayloadOnlyFlag (line 155) | PrintPayloadOnlyFlag        = "payload"
  constant printPayloadOnlyDescription (line 156) | printPayloadOnlyDescription = "If specified then only the payload from t...
  constant defaultPrintPayloadOnly (line 157) | defaultPrintPayloadOnly     = "false"
  constant ValidateFlag (line 159) | ValidateFlag        = "validate"
  constant validateDescription (line 160) | validateDescription = "If specified then endorsement responses from quer...
  constant defaultValidate (line 161) | defaultValidate     = "false"
  constant ConcurrencyFlag (line 163) | ConcurrencyFlag        = "concurrency"
  constant concurrencyDescription (line 164) | concurrencyDescription = "Specifies the number of concurrent requests se...
  constant defaultConcurrency (line 165) | defaultConcurrency     = "1"
  constant MaxAttemptsFlag (line 167) | MaxAttemptsFlag        = "attempts"
  constant maxAttemptsDescription (line 168) | maxAttemptsDescription = "Specifies the maximum number of attempts to be...
  constant defaultMaxAttempts (line 169) | defaultMaxAttempts     = "3"
  constant InitialBackoffFlag (line 171) | InitialBackoffFlag        = "backoff"
  constant initialBackoffDescription (line 172) | initialBackoffDescription = "The initial backoff is the time (in millise...
  constant defaultInitialBackoff (line 173) | defaultInitialBackoff     = "1000"
  constant MaxBackoffFlag (line 175) | MaxBackoffFlag        = "maxbackoff"
  constant maxBackoffDescription (line 176) | maxBackoffDescription = "The maximum backoff time (in milliseconds)"
  constant defaultMaxBackoff (line 177) | defaultMaxBackoff     = "5000"
  constant BackoffFactorFlag (line 179) | BackoffFactorFlag        = "backofffactor"
  constant backoffFactorDescription (line 180) | backoffFactorDescription = "The factor by which the backoff time is mult...
  constant defaultBackoffFactor (line 181) | defaultBackoffFactor     = "2"
  constant VerboseFlag (line 183) | VerboseFlag        = "verbose"
  constant verboseDescription (line 184) | verboseDescription = "If specified then the transaction proposal respons...
  constant defaultVerbosity (line 185) | defaultVerbosity   = "false"
  constant SelectionProviderFlag (line 187) | SelectionProviderFlag        = "selectprovider"
  constant selectionProviderDescription (line 188) | selectionProviderDescription = "The peer selection provider for invoke/q...
  constant defaultSelectionProvider (line 189) | defaultSelectionProvider     = AutoDetectSelectionProvider
  constant GoPathFlag (line 191) | GoPathFlag        = "gopath"
  constant goPathDescription (line 192) | goPathDescription = "GOPATH for chaincode install command. If not set, G...
  constant defaultGoPath (line 193) | defaultGoPath     = ""
  type options (line 199) | type options struct
  function init (line 240) | func init() {
  type CLIConfig (line 255) | type CLIConfig struct
    method Logger (line 296) | func (c *CLIConfig) Logger() *logging.Logger {
    method LoggingLevel (line 301) | func (c *CLIConfig) LoggingLevel() string {
    method OrgID (line 318) | func (c *CLIConfig) OrgID() string {
    method OrgIDs (line 326) | func (c *CLIConfig) OrgIDs() []string {
    method ChannelID (line 344) | func (c *CLIConfig) ChannelID() string {
    method UserName (line 355) | func (c *CLIConfig) UserName() string {
    method UserPassword (line 366) | func (c *CLIConfig) UserPassword() string {
    method ChaincodeID (line 377) | func (c *CLIConfig) ChaincodeID() string {
    method ChaincodeEvent (line 388) | func (c *CLIConfig) ChaincodeEvent() string {
    method SeekType (line 402) | func (c *CLIConfig) SeekType() seek.Type {
    method ChaincodePath (line 413) | func (c *CLIConfig) ChaincodePath() string {
    method ChaincodeVersion (line 424) | func (c *CLIConfig) ChaincodeVersion() string {
    method PeerURL (line 435) | func (c *CLIConfig) PeerURL() string {
    method PeerURLs (line 440) | func (c *CLIConfig) PeerURLs() []string {
    method OrdererURL (line 458) | func (c *CLIConfig) OrdererURL() string {
    method Iterations (line 469) | func (c *CLIConfig) Iterations() int {
    method SleepTime (line 485) | func (c *CLIConfig) SleepTime() int64 {
    method BlockNum (line 501) | func (c *CLIConfig) BlockNum() uint64 {
    method BlockHash (line 517) | func (c *CLIConfig) BlockHash() string {
    method Traverse (line 528) | func (c *CLIConfig) Traverse() int {
    method PrintFormat (line 544) | func (c *CLIConfig) PrintFormat() string {
    method Writer (line 555) | func (c *CLIConfig) Writer() string {
    method Base64 (line 566) | func (c *CLIConfig) Base64() bool {
    method OrdererTLSCertificate (line 577) | func (c *CLIConfig) OrdererTLSCertificate() string {
    method Args (line 588) | func (c *CLIConfig) Args() string {
    method TxFile (line 599) | func (c *CLIConfig) TxFile() string {
    method TxID (line 610) | func (c *CLIConfig) TxID() string {
    method ChaincodePolicy (line 621) | func (c *CLIConfig) ChaincodePolicy() string {
    method CollectionConfigFile (line 632) | func (c *CLIConfig) CollectionConfigFile() string {
    method Timeout (line 643) | func (c *CLIConfig) Timeout(timeoutType fab.TimeoutType) time.Duration {
    method PrintPayloadOnly (line 661) | func (c *CLIConfig) PrintPayloadOnly() bool {
    method Validate (line 672) | func (c *CLIConfig) Validate() bool {
    method Concurrency (line 683) | func (c *CLIConfig) Concurrency() uint16 {
    method MaxAttempts (line 701) | func (c *CLIConfig) MaxAttempts() int {
    method InitialBackoff (line 718) | func (c *CLIConfig) InitialBackoff() time.Duration {
    method MaxBackoff (line 734) | func (c *CLIConfig) MaxBackoff() time.Duration {
    method BackoffFactor (line 751) | func (c *CLIConfig) BackoffFactor() float64 {
    method Verbose (line 768) | func (c *CLIConfig) Verbose() bool {
    method SelectionProvider (line 779) | func (c *CLIConfig) SelectionProvider() string {
    method GoPath (line 796) | func (c *CLIConfig) GoPath() string {
    method IsLoggingEnabledFor (line 805) | func (c *CLIConfig) IsLoggingEnabledFor(level logging.Level) bool {
  function InitConfig (line 262) | func InitConfig(flags *pflag.FlagSet) error {
  function IsFlagSet (line 280) | func IsFlagSet(name string) bool {
  function Provider (line 286) | func Provider() core.ConfigProvider {
  function Config (line 291) | func Config() *CLIConfig {
  function InitLoggingLevel (line 306) | func InitLoggingLevel(flags *pflag.FlagSet, defaultValueAndDescription ....
  function InitConfigFile (line 312) | func InitConfigFile(flags *pflag.FlagSet, defaultValueAndDescription ......
  function InitOrgIDs (line 338) | func InitOrgIDs(flags *pflag.FlagSet, defaultValueAndDescription ...stri...
  function InitChannelID (line 349) | func InitChannelID(flags *pflag.FlagSet, defaultValueAndDescription ...s...
  function InitUserName (line 360) | func InitUserName(flags *pflag.FlagSet, defaultValueAndDescription ...st...
  function InitUserPassword (line 371) | func InitUserPassword(flags *pflag.FlagSet, defaultValueAndDescription ....
  function InitChaincodeID (line 382) | func InitChaincodeID(flags *pflag.FlagSet, defaultValueAndDescription .....
  function InitChaincodeEvent (line 393) | func InitChaincodeEvent(flags *pflag.FlagSet, defaultValueAndDescription...
  function InitSeekType (line 407) | func InitSeekType(flags *pflag.FlagSet, defaultValueAndDescription ...st...
  function InitChaincodePath (line 418) | func InitChaincodePath(flags *pflag.FlagSet, defaultValueAndDescription ...
  function InitChaincodeVersion (line 429) | func InitChaincodeVersion(flags *pflag.FlagSet, defaultValueAndDescripti...
  function InitPeerURL (line 452) | func InitPeerURL(flags *pflag.FlagSet, defaultValueAndDescription ...str...
  function InitOrdererURL (line 463) | func InitOrdererURL(flags *pflag.FlagSet, defaultValueAndDescription ......
  function InitIterations (line 474) | func InitIterations(flags *pflag.FlagSet, defaultValueAndDescription ......
  function InitSleepTime (line 490) | func InitSleepTime(flags *pflag.FlagSet, defaultValueAndDescription ...s...
  function InitBlockNum (line 506) | func InitBlockNum(flags *pflag.FlagSet, defaultValueAndDescription ...st...
  function InitBlockHash (line 522) | func InitBlockHash(flags *pflag.FlagSet, defaultValueAndDescription ...s...
  function InitTraverse (line 533) | func InitTraverse(flags *pflag.FlagSet, defaultValueAndDescription ...st...
  function InitPrintFormat (line 549) | func InitPrintFormat(flags *pflag.FlagSet, defaultValueAndDescription .....
  function InitWriter (line 560) | func InitWriter(flags *pflag.FlagSet, defaultValueAndDescription ...stri...
  function InitBase64 (line 571) | func InitBase64(flags *pflag.FlagSet, defaultValueAndDescription ...stri...
  function InitOrdererTLSCertificate (line 582) | func InitOrdererTLSCertificate(flags *pflag.FlagSet, defaultValueAndDesc...
  function InitArgs (line 593) | func InitArgs(flags *pflag.FlagSet, defaultValueAndDescription ...string) {
  function InitTxFile (line 604) | func InitTxFile(flags *pflag.FlagSet, defaultValueAndDescription ...stri...
  function InitTxID (line 615) | func InitTxID(flags *pflag.FlagSet, defaultValueAndDescription ...string) {
  function InitChaincodePolicy (line 626) | func InitChaincodePolicy(flags *pflag.FlagSet, defaultValueAndDescriptio...
  function InitCollectionConfigFile (line 637) | func InitCollectionConfigFile(flags *pflag.FlagSet, defaultValueAndDescr...
  function InitTimeout (line 649) | func InitTimeout(flags *pflag.FlagSet, defaultValueAndDescription ...str...
  function InitPrintPayloadOnly (line 666) | func InitPrintPayloadOnly(flags *pflag.FlagSet, defaultValueAndDescripti...
  function InitValidate (line 677) | func InitValidate(flags *pflag.FlagSet, defaultValueAndDescription ...st...
  function InitConcurrency (line 688) | func InitConcurrency(flags *pflag.FlagSet, defaultValueAndDescription .....
  function InitMaxAttempts (line 706) | func InitMaxAttempts(flags *pflag.FlagSet, defaultValueAndDescription .....
  function InitInitialBackoff (line 723) | func InitInitialBackoff(flags *pflag.FlagSet, defaultValueAndDescription...
  function InitMaxBackoff (line 739) | func InitMaxBackoff(flags *pflag.FlagSet, defaultValueAndDescription ......
  function InitBackoffFactor (line 756) | func InitBackoffFactor(flags *pflag.FlagSet, defaultValueAndDescription ...
  function InitVerbosity (line 773) | func InitVerbosity(flags *pflag.FlagSet, defaultValueAndDescription ...s...
  function InitSelectionProvider (line 784) | func InitSelectionProvider(flags *pflag.FlagSet, defaultValueAndDescript...
  function InitGoPath (line 790) | func InitGoPath(flags *pflag.FlagSet, defaultValueAndDescription ...stri...
  function getEmptyArgs (line 811) | func getEmptyArgs() string {
  function getDefaultValueAndDescription (line 815) | func getDefaultValueAndDescription(defaultValue string, defaultDescripti...

FILE: fabric-cli/cmd/fabric-cli/event/eventcmd.go
  function Cmd (line 23) | func Cmd() *cobra.Command {

FILE: fabric-cli/cmd/fabric-cli/event/inputevent.go
  type inputEvent (line 14) | type inputEvent struct
    method WaitForEnter (line 19) | func (c *inputEvent) WaitForEnter() chan bool {
    method readFromCLI (line 24) | func (c *inputEvent) readFromCLI() {

FILE: fabric-cli/cmd/fabric-cli/event/listenblockcmd.go
  function getListenBlockCmd (line 40) | func getListenBlockCmd() *cobra.Command {
  type listenBlockAction (line 49) | type listenBlockAction struct
    method invoke (line 60) | func (a *listenBlockAction) invoke() error {
  function newlistenBlockAction (line 54) | func newlistenBlockAction(flags *pflag.FlagSet) (*listenBlockAction, err...

FILE: fabric-cli/cmd/fabric-cli/event/listencccmd.go
  function getListenCCCmd (line 50) | func getListenCCCmd() *cobra.Command {
  type listenccAction (line 59) | type listenccAction struct
    method invoke (line 70) | func (a *listenccAction) invoke() error {
  function newListenCCAction (line 64) | func newListenCCAction(flags *pflag.FlagSet) (*listenccAction, error) {

FILE: fabric-cli/cmd/fabric-cli/event/listenfilteredblockcmd.go
  function getListenFilteredBlockCmd (line 40) | func getListenFilteredBlockCmd() *cobra.Command {
  type listenFilteredBlockAction (line 49) | type listenFilteredBlockAction struct
    method invoke (line 60) | func (a *listenFilteredBlockAction) invoke() error {
  function newlistenFilteredBlockAction (line 54) | func newlistenFilteredBlockAction(flags *pflag.FlagSet) (*listenFiltered...

FILE: fabric-cli/cmd/fabric-cli/event/listentxcmd.go
  function getListenTXCmd (line 44) | func getListenTXCmd() *cobra.Command {
  type listentxAction (line 52) | type listentxAction struct
    method invoke (line 63) | func (a *listentxAction) invoke() error {
  function newListenTXAction (line 57) | func newListenTXAction(flags *pflag.FlagSet) (*listentxAction, error) {

FILE: fabric-cli/cmd/fabric-cli/executor/executor.go
  type State (line 20) | type State
  constant NEW (line 24) | NEW State = iota
  constant STARTED (line 27) | STARTED
  constant TERMINATED (line 30) | TERMINATED
  type Executor (line 37) | type Executor struct
    method Start (line 84) | func (e *Executor) Start() bool {
    method Submit (line 101) | func (e *Executor) Submit(task worker.Task) error {
    method SubmitDelayed (line 116) | func (e *Executor) SubmitDelayed(task worker.Task, delay time.Duration...
    method Wait (line 135) | func (e *Executor) Wait() {
    method Stop (line 142) | func (e *Executor) Stop(wait bool) bool {
    method dispatch (line 169) | func (e *Executor) dispatch() {
  function NewConcurrent (line 51) | func NewConcurrent(name string, concurrency uint16) *Executor {
  function NewBoundedConcurrent (line 63) | func NewBoundedConcurrent(name string, concurrency uint16, queueLength u...
  function New (line 73) | func New(name string, queueLength uint16, pool *worker.Pool) *Executor {

FILE: fabric-cli/cmd/fabric-cli/executor/worker/worker.go
  type State (line 14) | type State
  constant READY (line 18) | READY State = iota
  constant STOPPED (line 21) | STOPPED
  type Task (line 25) | type Task interface
  type Events (line 30) | type Events interface
  type Worker (line 42) | type Worker struct
    method Name (line 59) | func (w *Worker) Name() string {
    method Submit (line 64) | func (w *Worker) Submit(task Task) {
    method invoke (line 68) | func (w *Worker) invoke(task Task) {
    method Start (line 78) | func (w *Worker) Start() {
    method Stop (line 101) | func (w *Worker) Stop() {
  function newWorker (line 49) | func newWorker(name string, events Events) *Worker {

FILE: fabric-cli/cmd/fabric-cli/executor/worker/workerpool.go
  type Pool (line 17) | type Pool struct
    method Name (line 42) | func (p *Pool) Name() string {
    method Start (line 47) | func (p *Pool) Start() {
    method Stop (line 57) | func (p *Pool) Stop(wait bool) {
    method Submit (line 80) | func (p *Pool) Submit(task Task) {
    method StateChange (line 97) | func (p *Pool) StateChange(w *Worker, state State) {
    method TaskStarted (line 115) | func (p *Pool) TaskStarted(w *Worker, task Task) {
    method TaskCompleted (line 120) | func (p *Pool) TaskCompleted(w *Worker, task Task) {
  function NewPool (line 26) | func NewPool(name string, concurrency uint16) *Pool {

FILE: fabric-cli/cmd/fabric-cli/fabric-cli.go
  function main (line 13) | func main() {

FILE: fabric-cli/cmd/fabric-cli/printer/blockprinter.go
  constant AnchorPeersKey (line 31) | AnchorPeersKey = "AnchorPeers"
  constant ReadersPolicyKey (line 34) | ReadersPolicyKey = "Readers"
  constant WritersPolicyKey (line 37) | WritersPolicyKey = "Writers"
  constant AdminsPolicyKey (line 40) | AdminsPolicyKey = "Admins"
  constant MSPKey (line 43) | MSPKey = "MSP"
  constant ConsensusTypeKey (line 46) | ConsensusTypeKey = "ConsensusType"
  constant BatchSizeKey (line 49) | BatchSizeKey = "BatchSize"
  constant BatchTimeoutKey (line 52) | BatchTimeoutKey = "BatchTimeout"
  constant ChannelRestrictionsKey (line 55) | ChannelRestrictionsKey = "ChannelRestrictions"
  constant KafkaBrokersKey (line 58) | KafkaBrokersKey = "KafkaBrokers"
  constant ChannelCreationPolicyKey (line 61) | ChannelCreationPolicyKey = "ChannelCreationPolicy"
  constant ConsortiumKey (line 64) | ConsortiumKey = "Consortium"
  constant HashingAlgorithmKey (line 67) | HashingAlgorithmKey = "HashingAlgorithm"
  constant BlockDataHashingStructureKey (line 70) | BlockDataHashingStructureKey = "BlockDataHashingStructure"
  constant OrdererAddressesKey (line 73) | OrdererAddressesKey = "OrdererAddresses"
  constant ChannelGroupKey (line 76) | ChannelGroupKey = "Channel"
  constant CapabilitiesKey (line 79) | CapabilitiesKey = "Capabilities"
  constant collectionSeparator (line 81) | collectionSeparator = "~"
  type Printer (line 85) | type Printer interface
  type BlockPrinter (line 124) | type BlockPrinter struct
    method PrintBlockchainInfo (line 143) | func (p *BlockPrinter) PrintBlockchainInfo(info *fabriccmn.BlockchainI...
    method PrintBlock (line 157) | func (p *BlockPrinter) PrintBlock(block *fabriccmn.Block) {
    method PrintFilteredBlock (line 187) | func (p *BlockPrinter) PrintFilteredBlock(block *pb.FilteredBlock) {
    method PrintChannels (line 208) | func (p *BlockPrinter) PrintChannels(channels []*pb.ChannelInfo) {
    method PrintPeers (line 223) | func (p *BlockPrinter) PrintPeers(peers []fab.Peer) {
    method PrintChaincodes (line 241) | func (p *BlockPrinter) PrintChaincodes(chaincodes []*pb.ChaincodeInfo) {
    method PrintProcessedTransaction (line 259) | func (p *BlockPrinter) PrintProcessedTransaction(tx *pb.ProcessedTrans...
    method PrintChaincodeData (line 272) | func (p *BlockPrinter) PrintChaincodeData(ccData *ccprovider.Chaincode...
    method doPrintChaincodeData (line 286) | func (p *BlockPrinter) doPrintChaincodeData(ccData *ccprovider.Chainco...
    method doPrintCollConfig (line 312) | func (p *BlockPrinter) doPrintCollConfig(collConfig *pb.CollectionConf...
    method printStaticCollectionConfig (line 327) | func (p *BlockPrinter) printStaticCollectionConfig(config *pb.StaticCo...
    method PrintTxProposalResponses (line 341) | func (p *BlockPrinter) PrintTxProposalResponses(responses []*fab.Trans...
    method PrintChaincodeEvent (line 361) | func (p *BlockPrinter) PrintChaincodeEvent(event *fab.CCEvent) {
    method PrintTxProposalResponse (line 377) | func (p *BlockPrinter) PrintTxProposalResponse(response *fab.Transacti...
    method PrintProposalResponse (line 396) | func (p *BlockPrinter) PrintProposalResponse(response *pb.ProposalResp...
    method PrintResponses (line 417) | func (p *BlockPrinter) PrintResponses(responses []*pb.Response) {
    method PrintResponse (line 437) | func (p *BlockPrinter) PrintResponse(response *pb.Response) {
    method PrintCDSData (line 444) | func (p *BlockPrinter) PrintCDSData(cdsData *ccprovider.CDSData) {
    method PrintEnvelope (line 450) | func (p *BlockPrinter) PrintEnvelope(envelope *fabriccmn.Envelope) {
    method PrintPayload (line 460) | func (p *BlockPrinter) PrintPayload(payload *fabriccmn.Payload) {
    method PrintChannelHeader (line 490) | func (p *BlockPrinter) PrintChannelHeader(chdr *fabriccmn.ChannelHeade...
    method PrintChaincodeHeaderExtension (line 507) | func (p *BlockPrinter) PrintChaincodeHeaderExtension(ccHdrExt *pb.Chai...
    method PrintChaincodeID (line 514) | func (p *BlockPrinter) PrintChaincodeID(ccID *pb.ChaincodeID) {
    method PrintChaincodeInfo (line 524) | func (p *BlockPrinter) PrintChaincodeInfo(ccInfo *pb.ChaincodeInfo) {
    method PrintSignatureHeader (line 534) | func (p *BlockPrinter) PrintSignatureHeader(sigHdr *fabriccmn.Signatur...
    method PrintData (line 540) | func (p *BlockPrinter) PrintData(headerType fabriccmn.HeaderType, data...
    method PrintConfigEnvelope (line 568) | func (p *BlockPrinter) PrintConfigEnvelope(envelope *fabriccmn.ConfigE...
    method PrintConfigUpdateEnvelope (line 578) | func (p *BlockPrinter) PrintConfigUpdateEnvelope(envelope *fabriccmn.C...
    method PrintTransaction (line 598) | func (p *BlockPrinter) PrintTransaction(tx *pb.Transaction) {
    method PrintFilteredTransaction (line 609) | func (p *BlockPrinter) PrintFilteredTransaction(tx *pb.FilteredTransac...
    method PrintTXAction (line 626) | func (p *BlockPrinter) PrintTXAction(action *pb.TransactionAction) {
    method PrintFilteredCCAction (line 649) | func (p *BlockPrinter) PrintFilteredCCAction(action *pb.FilteredChainc...
    method PrintChaincodeActionPayload (line 658) | func (p *BlockPrinter) PrintChaincodeActionPayload(chaPayload *pb.Chai...
    method PrintChaincodeProposalPayload (line 676) | func (p *BlockPrinter) PrintChaincodeProposalPayload(cpp *pb.Chaincode...
    method PrintChaincodeInvocationSpec (line 697) | func (p *BlockPrinter) PrintChaincodeInvocationSpec(cis *pb.ChaincodeI...
    method PrintAction (line 704) | func (p *BlockPrinter) PrintAction(action *pb.ChaincodeEndorsedAction) {
    method PrintProposalResponsePayload (line 722) | func (p *BlockPrinter) PrintProposalResponsePayload(prp *pb.ProposalRe...
    method PrintChaincodeAction (line 733) | func (p *BlockPrinter) PrintChaincodeAction(chaincodeAction *pb.Chainc...
    method PrintTxReadWriteSet (line 759) | func (p *BlockPrinter) PrintTxReadWriteSet(txRWSet *rwsetutil.TxRwSet) {
    method PrintNsReadWriteSet (line 770) | func (p *BlockPrinter) PrintNsReadWriteSet(nsRWSet *rwsetutil.NsRwSet) {
    method PrintKvRwSet (line 783) | func (p *BlockPrinter) PrintKvRwSet(kvRWSet *kvrwset.KVRWSet, namespac...
    method PrintCollHashedRwSets (line 814) | func (p *BlockPrinter) PrintCollHashedRwSets(collHashedRwSets []*rwset...
    method PrintCollHashedRwSet (line 825) | func (p *BlockPrinter) PrintCollHashedRwSet(collHashedRwSet *rwsetutil...
    method PrintHashedRwSet (line 835) | func (p *BlockPrinter) PrintHashedRwSet(hashedRwSet *kvrwset.HashedRWS...
    method PrintHashedReads (line 841) | func (p *BlockPrinter) PrintHashedReads(hashedReads []*kvrwset.KVReadH...
    method PrintHashedWrites (line 852) | func (p *BlockPrinter) PrintHashedWrites(hashedWrites []*kvrwset.KVWri...
    method PrintHashedRead (line 863) | func (p *BlockPrinter) PrintHashedRead(hashedRead *kvrwset.KVReadHash) {
    method PrintHashedWrite (line 869) | func (p *BlockPrinter) PrintHashedWrite(hashedWrite *kvrwset.KVWriteHa...
    method PrintRangeQueryInfo (line 876) | func (p *BlockPrinter) PrintRangeQueryInfo(rqi *kvrwset.RangeQueryInfo) {
    method PrintReadsInfo (line 886) | func (p *BlockPrinter) PrintReadsInfo(ri interface{}) {
    method PrintRawReads (line 899) | func (p *BlockPrinter) PrintRawReads(qr *kvrwset.QueryReads) {
    method PrintReadsMerkleHashes (line 910) | func (p *BlockPrinter) PrintReadsMerkleHashes(qr *kvrwset.QueryReadsMe...
    method PrintRead (line 922) | func (p *BlockPrinter) PrintRead(r *kvrwset.KVRead) {
    method PrintVersion (line 930) | func (p *BlockPrinter) PrintVersion(version *kvrwset.Version) {
    method PrintWrite (line 940) | func (p *BlockPrinter) PrintWrite(w *kvrwset.KVWrite) {
    method PrintLSCCWrite (line 947) | func (p *BlockPrinter) PrintLSCCWrite(w *kvrwset.KVWrite) {
    method printChaincodeData (line 960) | func (p *BlockPrinter) printChaincodeData(value []byte) {
    method printCollectionConfig (line 971) | func (p *BlockPrinter) printCollectionConfig(value []byte) {
    method PrintChaincodeResponse (line 982) | func (p *BlockPrinter) PrintChaincodeResponse(response *pb.Response) {
    method PrintChaincodeEventFromBlock (line 989) | func (p *BlockPrinter) PrintChaincodeEventFromBlock(chaincodeEvent *pb...
    method PrintEndorsement (line 997) | func (p *BlockPrinter) PrintEndorsement(endorsement *pb.Endorsement) {
    method PrintConfig (line 1003) | func (p *BlockPrinter) PrintConfig(config *fabriccmn.Config) {
    method PrintConfigGroup (line 1011) | func (p *BlockPrinter) PrintConfigGroup(configGroup *fabriccmn.ConfigG...
    method PrintConfigPolicy (line 1044) | func (p *BlockPrinter) PrintConfigPolicy(policy *fabriccmn.ConfigPolic...
    method PrintCapabilities (line 1079) | func (p *BlockPrinter) PrintCapabilities(capabilities *fabriccmn.Capab...
    method PrintImplicitMetaPolicy (line 1086) | func (p *BlockPrinter) PrintImplicitMetaPolicy(impMetaPolicy *fabriccm...
    method PrintSignaturePolicyEnvelope (line 1092) | func (p *BlockPrinter) PrintSignaturePolicyEnvelope(sigPolicyEnv *fabr...
    method PrintMSPPrincipal (line 1107) | func (p *BlockPrinter) PrintMSPPrincipal(principal *msp.MSPPrincipal) {
    method PrintSignaturePolicy (line 1134) | func (p *BlockPrinter) PrintSignaturePolicy(sigPolicy *fabriccmn.Signa...
    method PrintSignaturePolicySignedBy (line 1148) | func (p *BlockPrinter) PrintSignaturePolicySignedBy(sigPolicy *fabricc...
    method PrintSignaturePolicyNOutOf (line 1153) | func (p *BlockPrinter) PrintSignaturePolicyNOutOf(sigPolicy *fabriccmn...
    method PrintConfigValue (line 1165) | func (p *BlockPrinter) PrintConfigValue(name string, value *fabriccmn....
    method PrintBatchSize (line 1276) | func (p *BlockPrinter) PrintBatchSize(batchSize *ab.BatchSize) {
    method PrintMSPConfig (line 1293) | func (p *BlockPrinter) PrintMSPConfig(mspConfig *msp.MSPConfig) {
    method PrintFabricMSPConfig (line 1312) | func (p *BlockPrinter) PrintFabricMSPConfig(mspConfig *msp.FabricMSPCo...
    method PrintAnchorPeers (line 1322) | func (p *BlockPrinter) PrintAnchorPeers(anchorPeers *pb.AnchorPeers) {
    method PrintAnchorPeer (line 1333) | func (p *BlockPrinter) PrintAnchorPeer(anchorPeer *pb.AnchorPeer) {
    method PrintConfigSignature (line 1339) | func (p *BlockPrinter) PrintConfigSignature(sig *fabriccmn.ConfigSigna...
    method PrintConfigUpdate (line 1353) | func (p *BlockPrinter) PrintConfigUpdate(configUpdate *fabriccmn.Confi...
    method PrintBlockMetadata (line 1364) | func (p *BlockPrinter) PrintBlockMetadata(blockMetaData *fabriccmn.Blo...
    method PrintSignaturesMetadata (line 1372) | func (p *BlockPrinter) PrintSignaturesMetadata(metadata *fabriccmn.Met...
    method PrintLastConfigMetadata (line 1387) | func (p *BlockPrinter) PrintLastConfigMetadata(metadata *fabriccmn.Met...
    method PrintTransactionsFilterMetadata (line 1398) | func (p *BlockPrinter) PrintTransactionsFilterMetadata(txFilter ledger...
    method PrintOrdererMetadata (line 1407) | func (p *BlockPrinter) PrintOrdererMetadata(metadata *fabriccmn.Metada...
    method PrintChaincodeDeploymentSpec (line 1412) | func (p *BlockPrinter) PrintChaincodeDeploymentSpec(depSpec *pb.Chainc...
    method PrintChaincodeSpec (line 1419) | func (p *BlockPrinter) PrintChaincodeSpec(ccSpec *pb.ChaincodeSpec) {
    method PrintChaincodeInput (line 1433) | func (p *BlockPrinter) PrintChaincodeInput(ccInput *pb.ChaincodeInput) {
    method PrintPeer (line 1447) | func (p *BlockPrinter) PrintPeer(peer fab.Peer) {
  function NewBlockPrinter (line 129) | func NewBlockPrinter(format OutputFormat, writerType WriterType) *BlockP...
  function NewBlockPrinterWithOpts (line 136) | func NewBlockPrinterWithOpts(format OutputFormat, writerType WriterType,...
  type ProviderType (line 1283) | type ProviderType
  constant FABRIC (line 1287) | FABRIC ProviderType = iota
  constant IDEMIX (line 1288) | IDEMIX
  constant OTHER (line 1289) | OTHER
  function getMetadataOrPanic (line 1457) | func getMetadataOrPanic(blockMetaData *fabriccmn.BlockMetadata, index fa...
  function unmarshalOrPanic (line 1466) | func unmarshalOrPanic(buf []byte, pb proto.Message) {
  function Base64URLEncode (line 1474) | func Base64URLEncode(data []byte) string {
  function Base64URLDecode (line 1479) | func Base64URLDecode(data string) ([]byte, error) {
  function isCollectionConfigKey (line 1488) | func isCollectionConfigKey(key string) bool {

FILE: fabric-cli/cmd/fabric-cli/printer/formatter.go
  type OutputFormat (line 15) | type OutputFormat
    method String (line 28) | func (f OutputFormat) String() string {
  constant RAW (line 19) | RAW OutputFormat = iota
  constant JSON (line 22) | JSON
  constant DISPLAY (line 25) | DISPLAY
  function AsOutputFormat (line 42) | func AsOutputFormat(f string) OutputFormat {
  type Formatter (line 54) | type Formatter interface
  type FormatterOpts (line 93) | type FormatterOpts struct
  function NewFormatter (line 100) | func NewFormatter(format OutputFormat, writerType WriterType) Formatter {
  function NewFormatterWithOpts (line 106) | func NewFormatterWithOpts(format OutputFormat, writerType WriterType, op...
  type formatter (line 117) | type formatter struct
    method write (line 121) | func (f *formatter) write(format string, a ...interface{}) error {
  type displayFormatter (line 125) | type displayFormatter struct
    method Print (line 131) | func (p *displayFormatter) Print(frmt string, vars ...interface{}) {
    method Field (line 136) | func (p *displayFormatter) Field(field string, value interface{}) {
    method Element (line 144) | func (p *displayFormatter) Element(element string) {
    method ElementEnd (line 151) | func (p *displayFormatter) ElementEnd() {
    method Array (line 155) | func (p *displayFormatter) Array(element string) {
    method ArrayEnd (line 162) | func (p *displayFormatter) ArrayEnd() {
    method Item (line 167) | func (p *displayFormatter) Item(element string, index interface{}) {
    method ItemEnd (line 174) | func (p *displayFormatter) ItemEnd() {
    method ItemValue (line 178) | func (p *displayFormatter) ItemValue(element string, index interface{}...
    method Value (line 184) | func (p *displayFormatter) Value(value interface{}) {
    method PrintHeader (line 188) | func (p *displayFormatter) PrintHeader() {
    method PrintFooter (line 192) | func (p *displayFormatter) PrintFooter() {
    method prefix (line 196) | func (p *displayFormatter) prefix() string {
    method encodeValue (line 204) | func (p *displayFormatter) encodeValue(value interface{}) interface{} {
  type jsonFormatter (line 216) | type jsonFormatter struct
    method Print (line 221) | func (p *jsonFormatter) Print(frmt string, vars ...interface{}) {
    method Field (line 225) | func (p *jsonFormatter) Field(field string, value interface{}) {
    method Element (line 239) | func (p *jsonFormatter) Element(element string) {
    method ElementEnd (line 251) | func (p *jsonFormatter) ElementEnd() {
    method Array (line 256) | func (p *jsonFormatter) Array(element string) {
    method ArrayEnd (line 268) | func (p *jsonFormatter) ArrayEnd() {
    method Item (line 273) | func (p *jsonFormatter) Item(element string, index interface{}) {
    method ItemEnd (line 281) | func (p *jsonFormatter) ItemEnd() {
    method ItemValue (line 285) | func (p *jsonFormatter) ItemValue(element string, index interface{}, v...
    method Value (line 293) | func (p *jsonFormatter) Value(value interface{}) {
    method PrintHeader (line 300) | func (p *jsonFormatter) PrintHeader() {
    method PrintFooter (line 305) | func (p *jsonFormatter) PrintFooter() {
    method encodeValue (line 311) | func (p *jsonFormatter) encodeValue(value interface{}) interface{} {

FILE: fabric-cli/cmd/fabric-cli/printer/printer.go
  constant indentSize (line 12) | indentSize = 3
  type printer (line 15) | type printer struct
    method Print (line 30) | func (p *printer) Print(frmt string, vars ...interface{}) {
    method Field (line 39) | func (p *printer) Field(Field string, value interface{}) {
    method Element (line 44) | func (p *printer) Element(element string) {
    method ElementEnd (line 49) | func (p *printer) ElementEnd() {
    method Array (line 54) | func (p *printer) Array(element string) {
    method ArrayEnd (line 59) | func (p *printer) ArrayEnd() {
    method Item (line 64) | func (p *printer) Item(element string, index interface{}) {
    method ItemEnd (line 69) | func (p *printer) ItemEnd() {
    method ItemValue (line 74) | func (p *printer) ItemValue(element string, index interface{}, value i...
    method Value (line 79) | func (p *printer) Value(value interface{}) {
    method PrintHeader (line 84) | func (p *printer) PrintHeader() {
    method PrintFooter (line 89) | func (p *printer) PrintFooter() {
  function newPrinter (line 20) | func newPrinter(format OutputFormat, writerType WriterType) *printer {
  function newPrinterWithOpts (line 25) | func newPrinterWithOpts(format OutputFormat, writerType WriterType, opts...

FILE: fabric-cli/cmd/fabric-cli/printer/protoutils.go
  function ExtractEnvelopeOrPanic (line 20) | func ExtractEnvelopeOrPanic(block *cb.Block, index int) *cb.Envelope {
  function ExtractEnvelope (line 30) | func ExtractEnvelope(block *cb.Block, index int) (*cb.Envelope, error) {
  function GetEnvelopeFromBlock (line 46) | func GetEnvelopeFromBlock(data []byte) (*cb.Envelope, error) {
  function ExtractPayloadOrPanic (line 59) | func ExtractPayloadOrPanic(envelope *cb.Envelope) *cb.Payload {
  function ExtractPayload (line 68) | func ExtractPayload(envelope *cb.Envelope) (*cb.Payload, error) {
  function UnmarshalChannelHeader (line 76) | func UnmarshalChannelHeader(bytes []byte) (*cb.ChannelHeader, error) {
  function GetSignatureHeader (line 83) | func GetSignatureHeader(bytes []byte) (*cb.SignatureHeader, error) {
  function GetTransaction (line 90) | func GetTransaction(txBytes []byte) (*peer.Transaction, error) {
  function GetChaincodeActionPayload (line 98) | func GetChaincodeActionPayload(capBytes []byte) (*peer.ChaincodeActionPa...

FILE: fabric-cli/cmd/fabric-cli/printer/writer.go
  type WriterType (line 18) | type WriterType
    method String (line 37) | func (f WriterType) String() string {
  constant STDOUT (line 22) | STDOUT WriterType = iota
  constant STDERR (line 25) | STDERR
  constant LOG (line 28) | LOG
  constant stdout (line 32) | stdout = "stdout"
  constant stderr (line 33) | stderr = "stderr"
  constant log (line 34) | log    = "log"
  function AsWriterType (line 51) | func AsWriterType(t string) WriterType {
  type Writer (line 63) | type Writer interface
  function NewWriter (line 68) | func NewWriter(writerType WriterType) Writer {
  type stdOutWriter (line 79) | type stdOutWriter struct
    method Write (line 82) | func (w *stdOutWriter) Write(format string, a ...interface{}) error {
  type stdErrWriter (line 87) | type stdErrWriter struct
    method Write (line 90) | func (w *stdErrWriter) Write(format string, a ...interface{}) error {
  type logWriter (line 95) | type logWriter struct
    method Write (line 98) | func (w *logWriter) Write(format string, a ...interface{}) error {

FILE: fabric-cli/cmd/fabric-cli/query/queryblockcmd.go
  function getQueryBlockCmd (line 42) | func getQueryBlockCmd() *cobra.Command {
  type queryBlockAction (line 52) | type queryBlockAction struct
    method invoke (line 62) | func (a *queryBlockAction) invoke() error {
    method traverse (line 98) | func (a *queryBlockAction) traverse(ledgerClient *ledger.Client, curre...
  function newQueryBlockAction (line 56) | func newQueryBlockAction(flags *pflag.FlagSet) (*queryBlockAction, error) {
  function Base64URLDecode (line 117) | func Base64URLDecode(data string) ([]byte, error) {

FILE: fabric-cli/cmd/fabric-cli/query/querychannelscmd.go
  function getQueryChannelsCmd (line 45) | func getQueryChannelsCmd() *cobra.Command {
  type queryChannelsAction (line 50) | type queryChannelsAction struct
    method run (line 60) | func (a *queryChannelsAction) run() error {
  function newQueryChannelsAction (line 54) | func newQueryChannelsAction(flags *pflag.FlagSet) (*queryChannelsAction,...

FILE: fabric-cli/cmd/fabric-cli/query/querycmd.go
  function Cmd (line 24) | func Cmd() *cobra.Command {

FILE: fabric-cli/cmd/fabric-cli/query/queryinfocmd.go
  function getQueryInfoCmd (line 44) | func getQueryInfoCmd() *cobra.Command {
  type queryInfoAction (line 52) | type queryInfoAction struct
    method run (line 62) | func (a *queryInfoAction) run() error {
  function newQueryInfoAction (line 56) | func newQueryInfoAction(flags *pflag.FlagSet) (*queryInfoAction, error) {

FILE: fabric-cli/cmd/fabric-cli/query/queryinstalledcmd.go
  function getQueryInstalledCmd (line 46) | func getQueryInstalledCmd() *cobra.Command {
  type queryInstalledAction (line 51) | type queryInstalledAction struct
    method run (line 61) | func (a *queryInstalledAction) run() error {
  function newqueryInstalledAction (line 55) | func newqueryInstalledAction(flags *pflag.FlagSet) (*queryInstalledActio...

FILE: fabric-cli/cmd/fabric-cli/query/querylocalpeerscmd.go
  function getQueryLocalPeersCmd (line 43) | func getQueryLocalPeersCmd() *cobra.Command {
  type queryLocalPeersAction (line 50) | type queryLocalPeersAction struct
    method run (line 60) | func (a *queryLocalPeersAction) run() error {
  function newQueryLocalPeersAction (line 54) | func newQueryLocalPeersAction(flags *pflag.FlagSet) (*queryLocalPeersAct...

FILE: fabric-cli/cmd/fabric-cli/query/querypeerscmd.go
  function getQueryPeersCmd (line 43) | func getQueryPeersCmd() *cobra.Command {
  type queryPeersAction (line 50) | type queryPeersAction struct
    method run (line 60) | func (a *queryPeersAction) run() error {
  function newQueryPeersAction (line 54) | func newQueryPeersAction(flags *pflag.FlagSet) (*queryPeersAction, error) {

FILE: fabric-cli/cmd/fabric-cli/query/querytxcmd.go
  function getQueryTXCmd (line 45) | func getQueryTXCmd() *cobra.Command {
  type queryTXAction (line 53) | type queryTXAction struct
    method run (line 64) | func (a *queryTXAction) run() error {
  function newQueryTXAction (line 57) | func newQueryTXAction(flags *pflag.FlagSet) (*queryTXAction, error) {

FILE: fabric-cli/test/fixtures/testdata/src/github.com/securekey/example2_cc/example2_cc.go
  type invokeFunc (line 18) | type invokeFunc
  type funcMap (line 19) | type funcMap
  constant getFunc (line 22) | getFunc           = "get"
  constant putFunc (line 23) | putFunc           = "put"
  constant delFunc (line 24) | delFunc           = "del"
  constant putPrivateFunc (line 25) | putPrivateFunc    = "putprivate"
  constant getPrivateFunc (line 26) | getPrivateFunc    = "getprivate"
  constant delPrivateFunc (line 27) | delPrivateFunc    = "delprivate"
  constant putBothFunc (line 28) | putBothFunc       = "putboth"
  constant getAndPutBothFunc (line 29) | getAndPutBothFunc = "getandputboth"
  constant invokeCCFunc (line 30) | invokeCCFunc      = "invokecc"
  type ExampleCC (line 34) | type ExampleCC struct
    method Init (line 39) | func (cc *ExampleCC) Init(stub shim.ChaincodeStubInterface) pb.Response {
    method Invoke (line 44) | func (cc *ExampleCC) Invoke(stub shim.ChaincodeStubInterface) pb.Respo...
    method put (line 59) | func (cc *ExampleCC) put(stub shim.ChaincodeStubInterface, args []stri...
    method get (line 82) | func (cc *ExampleCC) get(stub shim.ChaincodeStubInterface, args []stri...
    method del (line 97) | func (cc *ExampleCC) del(stub shim.ChaincodeStubInterface, args []stri...
    method putPrivate (line 112) | func (cc *ExampleCC) putPrivate(stub shim.ChaincodeStubInterface, args...
    method getPrivate (line 128) | func (cc *ExampleCC) getPrivate(stub shim.ChaincodeStubInterface, args...
    method delPrivate (line 144) | func (cc *ExampleCC) delPrivate(stub shim.ChaincodeStubInterface, args...
    method putBoth (line 160) | func (cc *ExampleCC) putBoth(stub shim.ChaincodeStubInterface, args []...
    method getAndPutBoth (line 181) | func (cc *ExampleCC) getAndPutBoth(stub shim.ChaincodeStubInterface, a...
    method invokeCC (line 229) | func (cc *ExampleCC) invokeCC(stub shim.ChaincodeStubInterface, args [...
    method initRegistry (line 249) | func (cc *ExampleCC) initRegistry() {
    method functions (line 262) | func (cc *ExampleCC) functions() []string {
  type argStruct (line 217) | type argStruct struct
  function asBytes (line 221) | func asBytes(args []string) [][]byte {
  function main (line 270) | func main() {

FILE: fabric-cli/test/fixtures/testdata/src/github.com/securekey/example_cc/example_cc.go
  type SimpleChaincode (line 28) | type SimpleChaincode struct
    method Init (line 32) | func (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface) pb.Re...
    method Query (line 78) | func (t *SimpleChaincode) Query(stub shim.ChaincodeStubInterface) pb.R...
    method Invoke (line 84) | func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface) pb....
    method move (line 129) | func (t *SimpleChaincode) move(stub shim.ChaincodeStubInterface, args ...
    method delete (line 192) | func (t *SimpleChaincode) delete(stub shim.ChaincodeStubInterface, arg...
    method query (line 209) | func (t *SimpleChaincode) query(stub shim.ChaincodeStubInterface, args...
    method put (line 236) | func (t *SimpleChaincode) put(stub shim.ChaincodeStubInterface, args [...
    method get (line 259) | func (t *SimpleChaincode) get(stub shim.ChaincodeStubInterface, args [...
  function main (line 274) | func main() {

FILE: fabric-cli/test/integration/fabric-cli_test.go
  function run (line 22) | func run(cmd string) {
  function header (line 30) | func header(h string) {
  function TestCreate_a_channel (line 40) | func TestCreate_a_channel(t *testing.T) {
  function TestJoin_org1_peer_to_a_channel (line 47) | func TestJoin_org1_peer_to_a_channel(t *testing.T) {
  function TestJoin_org2_peer_to_a_channel (line 52) | func TestJoin_org2_peer_to_a_channel(t *testing.T) {
  function TestJoin_all_peers_in_org1_to_a_channel (line 57) | func TestJoin_all_peers_in_org1_to_a_channel(t *testing.T) {
  function TestJoin_all_peers_in_org2_to_a_channel (line 62) | func TestJoin_all_peers_in_org2_to_a_channel(t *testing.T) {
  function TestJoin_all_peers_to_a_channel (line 67) | func TestJoin_all_peers_to_a_channel(t *testing.T) {
  function TestInstall_chaincode_on_all_peers_of_org1 (line 74) | func TestInstall_chaincode_on_all_peers_of_org1(t *testing.T) {
  function TestInstall_chaincode_on_all_peers_of_org2 (line 79) | func TestInstall_chaincode_on_all_peers_of_org2(t *testing.T) {
  function TestInstall_chaincode_on_all_peers (line 84) | func TestInstall_chaincode_on_all_peers(t *testing.T) {
  function TestInstall_chaincode_on_all_peers_v1 (line 89) | func TestInstall_chaincode_on_all_peers_v1(t *testing.T) {
  function TestInstantiate_chaincode_with_default_endorsement_policy (line 96) | func TestInstantiate_chaincode_with_default_endorsement_policy(t *testin...
  function TestInstantiate_chaincode_with_specified_endorsement_policy (line 101) | func TestInstantiate_chaincode_with_specified_endorsement_policy(t *test...
  function TestInstantiate_chaincode_with_specified_private_data_collection_configuration (line 106) | func TestInstantiate_chaincode_with_specified_private_data_collection_co...
  function TestUpgrade_chaincode_to_v1 (line 113) | func TestUpgrade_chaincode_to_v1(t *testing.T) {
  function TestQuery_info (line 121) | func TestQuery_info(t *testing.T) {
  function TestQuery_block_by_block_number (line 126) | func TestQuery_block_by_block_number(t *testing.T) {
  function TestQuery_block_by_hash (line 131) | func TestQuery_block_by_hash(t *testing.T) {
  function TestQuery_block_output_in_JSON_format (line 137) | func TestQuery_block_output_in_JSON_format(t *testing.T) {
  function TestQuery_transaction (line 142) | func TestQuery_transaction(t *testing.T) {
  function TestQuery_channels_joined_by_a_peer (line 147) | func TestQuery_channels_joined_by_a_peer(t *testing.T) {
  function TestQuery_installed_chaincodes_on_a_peer (line 152) | func TestQuery_installed_chaincodes_on_a_peer(t *testing.T) {
  function TestRetrieve_chaincode_deployment_info (line 159) | func TestRetrieve_chaincode_deployment_info(t *testing.T) {
  function TestQuery_chaincode_on_a_set_of_peers (line 166) | func TestQuery_chaincode_on_a_set_of_peers(t *testing.T) {
  function TestQuery_chaincode_and_view_payloads_only (line 171) | func TestQuery_chaincode_and_view_payloads_only(t *testing.T) {
  function TestInvoke_chaincode (line 178) | func TestInvoke_chaincode(t *testing.T) {
  function TestInvoke_chaincode_5_times (line 183) | func TestInvoke_chaincode_5_times(t *testing.T) {
  function TestInvoke_chaincode_100_times_in_8_Go_routines (line 188) | func TestInvoke_chaincode_100_times_in_8_Go_routines(t *testing.T) {
  function TestInvoke_chaincode_with_two_sets_of_args (line 193) | func TestInvoke_chaincode_with_two_sets_of_args(t *testing.T) {
  function TestInvoke_chaincode_using_dynamic_selection_provider (line 198) | func TestInvoke_chaincode_using_dynamic_selection_provider(t *testing.T) {
  function TestListen_for_block_events (line 205) | func TestListen_for_block_events(t *testing.T) {
  function TestListen_for_filtered_block_events (line 210) | func TestListen_for_filtered_block_events(t *testing.T) {
  function TestListen_for_chaincode_events (line 215) | func TestListen_for_chaincode_events(t *testing.T) {
Condensed preview — 63 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (343K chars).
[
  {
    "path": ".gitignore",
    "chars": 204,
    "preview": "#\n# Copyright SecureKey Technologies Inc. All Rights Reserved.\n#\n# SPDX-License-Identifier: Apache-2.0\n#\n*.db\n*report.xm"
  },
  {
    "path": ".gitreview",
    "chars": 70,
    "preview": "[gerrit]\nhost=gerrit.securekey.com\nport=29418\nproject=fabric-examples\n"
  },
  {
    "path": "README.md",
    "chars": 16,
    "preview": "fabric-examples\n"
  },
  {
    "path": "fabric-cli/.gitignore",
    "chars": 128,
    "preview": "#\n# Copyright SecureKey Technologies Inc. All Rights Reserved.\n#\n# SPDX-License-Identifier: Apache-2.0\n#\nvendor/\nfabric-"
  },
  {
    "path": "fabric-cli/LICENSE",
    "chars": 11358,
    "preview": "                                 Apache License\n                           Version 2.0, January 2004\n                   "
  },
  {
    "path": "fabric-cli/Makefile",
    "chars": 1493,
    "preview": "#\n# Copyright SecureKey Technologies Inc. All Rights Reserved.\n#\n# SPDX-License-Identifier: Apache-2.0\n#\n\n# Supported Ta"
  },
  {
    "path": "fabric-cli/README.md",
    "chars": 15781,
    "preview": "# Fabric CLI Sample Application\n\nFabric CLI is a sample command-line interface built using Fabric SDK GO. It provides th"
  },
  {
    "path": "fabric-cli/cmd/fabric-cli/action/action.go",
    "chars": 20712,
    "preview": "/*\nCopyright SecureKey Technologies Inc. All Rights Reserved.\n\nSPDX-License-Identifier: Apache-2.0\n*/\n\npackage action\n\ni"
  },
  {
    "path": "fabric-cli/cmd/fabric-cli/action/svcproviderfactory.go",
    "chars": 3676,
    "preview": "/*\nCopyright SecureKey Technologies Inc. All Rights Reserved.\n\nSPDX-License-Identifier: Apache-2.0\n*/\n\npackage action\n\ni"
  },
  {
    "path": "fabric-cli/cmd/fabric-cli/chaincode/chaincodecmd.go",
    "chars": 832,
    "preview": "/*\nCopyright SecureKey Technologies Inc. All Rights Reserved.\n\nSPDX-License-Identifier: Apache-2.0\n*/\n\npackage chaincode"
  },
  {
    "path": "fabric-cli/cmd/fabric-cli/chaincode/getinfocmd.go",
    "chars": 4178,
    "preview": "/*\nCopyright SecureKey Technologies Inc. All Rights Reserved.\n\nSPDX-License-Identifier: Apache-2.0\n*/\n\npackage chaincode"
  },
  {
    "path": "fabric-cli/cmd/fabric-cli/chaincode/installcmd.go",
    "chars": 3702,
    "preview": "/*\nCopyright SecureKey Technologies Inc. All Rights Reserved.\n\nSPDX-License-Identifier: Apache-2.0\n*/\n\npackage chaincode"
  },
  {
    "path": "fabric-cli/cmd/fabric-cli/chaincode/instantiatecmd.go",
    "chars": 6471,
    "preview": "/*\nCopyright SecureKey Technologies Inc. All Rights Reserved.\n\nSPDX-License-Identifier: Apache-2.0\n*/\n\npackage chaincode"
  },
  {
    "path": "fabric-cli/cmd/fabric-cli/chaincode/invokecmd.go",
    "chars": 7408,
    "preview": "/*\nCopyright SecureKey Technologies Inc. All Rights Reserved.\n\nSPDX-License-Identifier: Apache-2.0\n*/\n\npackage chaincode"
  },
  {
    "path": "fabric-cli/cmd/fabric-cli/chaincode/invokeerror/invokeerror.go",
    "chars": 1551,
    "preview": "/*\nCopyright SecureKey Technologies Inc. All Rights Reserved.\n\nSPDX-License-Identifier: Apache-2.0\n*/\n\npackage invokeerr"
  },
  {
    "path": "fabric-cli/cmd/fabric-cli/chaincode/invoketask/invoketask.go",
    "chars": 4595,
    "preview": "/*\nCopyright SecureKey Technologies Inc. All Rights Reserved.\n\nSPDX-License-Identifier: Apache-2.0\n*/\n\npackage invoketas"
  },
  {
    "path": "fabric-cli/cmd/fabric-cli/chaincode/multitask/multitask.go",
    "chars": 1152,
    "preview": "/*\nCopyright SecureKey Technologies Inc. All Rights Reserved.\n\nSPDX-License-Identifier: Apache-2.0\n*/\n\npackage multitask"
  },
  {
    "path": "fabric-cli/cmd/fabric-cli/chaincode/querycmd.go",
    "chars": 6538,
    "preview": "/*\nCopyright SecureKey Technologies Inc. All Rights Reserved.\n\nSPDX-License-Identifier: Apache-2.0\n*/\n\npackage chaincode"
  },
  {
    "path": "fabric-cli/cmd/fabric-cli/chaincode/querytask/querytask.go",
    "chars": 3298,
    "preview": "/*\nCopyright SecureKey Technologies Inc. All Rights Reserved.\n\nSPDX-License-Identifier: Apache-2.0\n*/\n\npackage querytask"
  },
  {
    "path": "fabric-cli/cmd/fabric-cli/chaincode/task/task.go",
    "chars": 420,
    "preview": "/*\nCopyright SecureKey Technologies Inc. All Rights Reserved.\n\nSPDX-License-Identifier: Apache-2.0\n*/\n\npackage task\n\n// "
  },
  {
    "path": "fabric-cli/cmd/fabric-cli/chaincode/upgradecmd.go",
    "chars": 4900,
    "preview": "/*\nCopyright SecureKey Technologies Inc. All Rights Reserved.\n\nSPDX-License-Identifier: Apache-2.0\n*/\n\npackage chaincode"
  },
  {
    "path": "fabric-cli/cmd/fabric-cli/chaincode/utils/test.json",
    "chars": 20,
    "preview": "{\"Field1\": \"Value1\"}"
  },
  {
    "path": "fabric-cli/cmd/fabric-cli/chaincode/utils/util.go",
    "chars": 6168,
    "preview": "/*\nCopyright SecureKey Technologies Inc. All Rights Reserved.\n\nSPDX-License-Identifier: Apache-2.0\n*/\n\npackage utils\n\nim"
  },
  {
    "path": "fabric-cli/cmd/fabric-cli/chaincode/utils/util_test.go",
    "chars": 4228,
    "preview": "/*\nCopyright SecureKey Technologies Inc. All Rights Reserved.\n\nSPDX-License-Identifier: Apache-2.0\n*/\n\npackage utils\n\nim"
  },
  {
    "path": "fabric-cli/cmd/fabric-cli/channel/channelcmd.go",
    "chars": 653,
    "preview": "/*\nCopyright SecureKey Technologies Inc. All Rights Reserved.\n\nSPDX-License-Identifier: Apache-2.0\n*/\n\npackage channel\n\n"
  },
  {
    "path": "fabric-cli/cmd/fabric-cli/channel/channelcreatecmd.go",
    "chars": 2224,
    "preview": "/*\nCopyright SecureKey Technologies Inc. All Rights Reserved.\n\nSPDX-License-Identifier: Apache-2.0\n*/\n\npackage channel\n\n"
  },
  {
    "path": "fabric-cli/cmd/fabric-cli/channel/channeljoincmd.go",
    "chars": 2676,
    "preview": "/*\nCopyright SecureKey Technologies Inc. All Rights Reserved.\n\nSPDX-License-Identifier: Apache-2.0\n*/\n\npackage channel\n\n"
  },
  {
    "path": "fabric-cli/cmd/fabric-cli/cmd/fabric-cli.go",
    "chars": 1373,
    "preview": "/*\nCopyright SecureKey Technologies Inc. All Rights Reserved.\n\nSPDX-License-Identifier: Apache-2.0\n*/\n\npackage cmd\n\nimpo"
  },
  {
    "path": "fabric-cli/cmd/fabric-cli/config/config.go",
    "chars": 33498,
    "preview": "/*\nCopyright SecureKey Technologies Inc. All Rights Reserved.\n\nSPDX-License-Identifier: Apache-2.0\n*/\n\npackage config\n\ni"
  },
  {
    "path": "fabric-cli/cmd/fabric-cli/event/eventcmd.go",
    "chars": 591,
    "preview": "/*\nCopyright SecureKey Technologies Inc. All Rights Reserved.\n\nSPDX-License-Identifier: Apache-2.0\n*/\n\npackage event\n\nim"
  },
  {
    "path": "fabric-cli/cmd/fabric-cli/event/inputevent.go",
    "chars": 443,
    "preview": "/*\nCopyright SecureKey Technologies Inc. All Rights Reserved.\n\nSPDX-License-Identifier: Apache-2.0\n*/\n\npackage event\n\nim"
  },
  {
    "path": "fabric-cli/cmd/fabric-cli/event/listenblockcmd.go",
    "chars": 2317,
    "preview": "/*\nCopyright SecureKey Technologies Inc. All Rights Reserved.\n\nSPDX-License-Identifier: Apache-2.0\n*/\n\npackage event\n\nim"
  },
  {
    "path": "fabric-cli/cmd/fabric-cli/event/listencccmd.go",
    "chars": 2536,
    "preview": "/*\nCopyright SecureKey Technologies Inc. All Rights Reserved.\n\nSPDX-License-Identifier: Apache-2.0\n*/\n\npackage event\n\nim"
  },
  {
    "path": "fabric-cli/cmd/fabric-cli/event/listenfilteredblockcmd.go",
    "chars": 2465,
    "preview": "/*\nCopyright SecureKey Technologies Inc. All Rights Reserved.\n\nSPDX-License-Identifier: Apache-2.0\n*/\n\npackage event\n\nim"
  },
  {
    "path": "fabric-cli/cmd/fabric-cli/event/listentxcmd.go",
    "chars": 2339,
    "preview": "/*\nCopyright SecureKey Technologies Inc. All Rights Reserved.\n\nSPDX-License-Identifier: Apache-2.0\n*/\n\npackage event\n\nim"
  },
  {
    "path": "fabric-cli/cmd/fabric-cli/executor/executor.go",
    "chars": 5198,
    "preview": "/*\nCopyright SecureKey Technologies Inc. All Rights Reserved.\n\nSPDX-License-Identifier: Apache-2.0\n*/\n\npackage executor\n"
  },
  {
    "path": "fabric-cli/cmd/fabric-cli/executor/worker/worker.go",
    "chars": 2318,
    "preview": "/*\nCopyright SecureKey Technologies Inc. All Rights Reserved.\n\nSPDX-License-Identifier: Apache-2.0\n*/\n\npackage worker\n\ni"
  },
  {
    "path": "fabric-cli/cmd/fabric-cli/executor/worker/workerpool.go",
    "chars": 3042,
    "preview": "/*\nCopyright SecureKey Technologies Inc. All Rights Reserved.\n\nSPDX-License-Identifier: Apache-2.0\n*/\n\npackage worker\n\ni"
  },
  {
    "path": "fabric-cli/cmd/fabric-cli/fabric-cli.go",
    "chars": 230,
    "preview": "/*\nCopyright SecureKey Technologies Inc. All Rights Reserved.\n\nSPDX-License-Identifier: Apache-2.0\n*/\n\npackage main\n\nimp"
  },
  {
    "path": "fabric-cli/cmd/fabric-cli/go.mod",
    "chars": 1031,
    "preview": "// Copyright SecureKey Technologies Inc. All Rights Reserved.\n//\n// SPDX-License-Identifier: Apache-2.0\n\nmodule github.c"
  },
  {
    "path": "fabric-cli/cmd/fabric-cli/go.sum",
    "chars": 14938,
    "preview": "cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=\ngithub.com/BurntSushi/toml v0.3.1 h1:"
  },
  {
    "path": "fabric-cli/cmd/fabric-cli/printer/blockprinter.go",
    "chars": 42242,
    "preview": "/*\nCopyright SecureKey Technologies Inc. All Rights Reserved.\n\nSPDX-License-Identifier: Apache-2.0\n*/\n\npackage printer\n\n"
  },
  {
    "path": "fabric-cli/cmd/fabric-cli/printer/formatter.go",
    "chars": 6603,
    "preview": "/*\nCopyright SecureKey Technologies Inc. All Rights Reserved.\n\nSPDX-License-Identifier: Apache-2.0\n*/\n\npackage printer\n\n"
  },
  {
    "path": "fabric-cli/cmd/fabric-cli/printer/printer.go",
    "chars": 2363,
    "preview": "/*\nCopyright SecureKey Technologies Inc. All Rights Reserved.\n\nSPDX-License-Identifier: Apache-2.0\n*/\n\npackage printer\n\n"
  },
  {
    "path": "fabric-cli/cmd/fabric-cli/printer/protoutils.go",
    "chars": 3227,
    "preview": "/*\nCopyright IBM Corp. All Rights Reserved.\n\nSPDX-License-Identifier: Apache-2.0\n*/\n\npackage printer\n\nimport (\n\t\"fmt\"\n\n\t"
  },
  {
    "path": "fabric-cli/cmd/fabric-cli/printer/writer.go",
    "chars": 1738,
    "preview": "/*\nCopyright SecureKey Technologies Inc. All Rights Reserved.\n\nSPDX-License-Identifier: Apache-2.0\n*/\n\npackage printer\n\n"
  },
  {
    "path": "fabric-cli/cmd/fabric-cli/query/queryblockcmd.go",
    "chars": 3102,
    "preview": "/*\nCopyright SecureKey Technologies Inc. All Rights Reserved.\n\nSPDX-License-Identifier: Apache-2.0\n*/\n\npackage query\n\nim"
  },
  {
    "path": "fabric-cli/cmd/fabric-cli/query/querychannelscmd.go",
    "chars": 2146,
    "preview": "/*\nCopyright SecureKey Technologies Inc. All Rights Reserved.\n\nSPDX-License-Identifier: Apache-2.0\n*/\n\npackage query\n\nim"
  },
  {
    "path": "fabric-cli/cmd/fabric-cli/query/querycmd.go",
    "chars": 842,
    "preview": "/*\nCopyright SecureKey Technologies Inc. All Rights Reserved.\n\nSPDX-License-Identifier: Apache-2.0\n*/\n\npackage query\n\nim"
  },
  {
    "path": "fabric-cli/cmd/fabric-cli/query/queryinfocmd.go",
    "chars": 1689,
    "preview": "/*\nCopyright SecureKey Technologies Inc. All Rights Reserved.\n\nSPDX-License-Identifier: Apache-2.0\n*/\n\npackage query\n\nim"
  },
  {
    "path": "fabric-cli/cmd/fabric-cli/query/queryinstalledcmd.go",
    "chars": 2148,
    "preview": "/*\nCopyright SecureKey Technologies Inc. All Rights Reserved.\n\nSPDX-License-Identifier: Apache-2.0\n*/\n\npackage query\n\nim"
  },
  {
    "path": "fabric-cli/cmd/fabric-cli/query/querylocalpeerscmd.go",
    "chars": 1684,
    "preview": "/*\nCopyright SecureKey Technologies Inc. All Rights Reserved.\n\nSPDX-License-Identifier: Apache-2.0\n*/\n\npackage query\n\nim"
  },
  {
    "path": "fabric-cli/cmd/fabric-cli/query/querypeerscmd.go",
    "chars": 1760,
    "preview": "/*\nCopyright SecureKey Technologies Inc. All Rights Reserved.\n\nSPDX-License-Identifier: Apache-2.0\n*/\n\npackage query\n\nim"
  },
  {
    "path": "fabric-cli/cmd/fabric-cli/query/querytxcmd.go",
    "chars": 1886,
    "preview": "/*\nCopyright SecureKey Technologies Inc. All Rights Reserved.\n\nSPDX-License-Identifier: Apache-2.0\n*/\n\npackage query\n\nim"
  },
  {
    "path": "fabric-cli/test/fixtures/config/config_test_local.yaml",
    "chars": 17667,
    "preview": "#\n# Copyright SecureKey Technologies Inc. All Rights Reserved.\n#\n# SPDX-License-Identifier: Apache-2.0\n#\n#\n# The network"
  },
  {
    "path": "fabric-cli/test/fixtures/config/pvtdatacollection.json",
    "chars": 297,
    "preview": "[\n    {\n        \"name\": \"coll1\",\n        \"policy\": \"OR('Org1MSP.member', 'Org2MSP.member')\",\n        \"requiredPeerCount\""
  },
  {
    "path": "fabric-cli/test/fixtures/testdata/src/github.com/securekey/example2_cc/example2_cc.go",
    "chars": 7590,
    "preview": "/*\nCopyright SecureKey Technologies Inc. All Rights Reserved.\n\nSPDX-License-Identifier: Apache-2.0\n*/\n\npackage main\n\nimp"
  },
  {
    "path": "fabric-cli/test/fixtures/testdata/src/github.com/securekey/example_cc/example_cc.go",
    "chars": 7222,
    "preview": "/*\nCopyright IBM Corp. 2016 All Rights Reserved.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou ma"
  },
  {
    "path": "fabric-cli/test/fixtures/testdata/src/go.mod",
    "chars": 212,
    "preview": "// Copyright SecureKey Technologies Inc. All Rights Reserved.\n//\n// SPDX-License-Identifier: Apache-2.0\n\nmodule github.c"
  },
  {
    "path": "fabric-cli/test/fixtures/testdata/src/go.sum",
    "chars": 92,
    "preview": "github.com/hyperledger/fabric v1.4.0/go.mod h1:tGFAOCT696D3rG0Vofd2dyWYLySHlh0aQjf7Q1HAju0=\n"
  },
  {
    "path": "fabric-cli/test/integration/fabric-cli_test.go",
    "chars": 10427,
    "preview": "/*\nCopyright SecureKey Technologies Inc. All Rights Reserved.\n\nSPDX-License-Identifier: Apache-2.0\n*/\n\npackage integrati"
  },
  {
    "path": "fabric-cli/test/integration/go.mod",
    "chars": 336,
    "preview": "// Copyright SecureKey Technologies Inc. All Rights Reserved.\n//\n// SPDX-License-Identifier: Apache-2.0\n\nmodule github.c"
  },
  {
    "path": "fabric-cli/test/integration/go.sum",
    "chars": 15852,
    "preview": "cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=\ngithub.com/BurntSushi/toml v0.3.1 h1:"
  }
]

About this extraction

This page contains the full source code of the securekey/fabric-examples GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 63 files (310.4 KB), approximately 91.8k tokens, and a symbol index with 735 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!