├── .gitignore ├── README.md ├── deploy ├── bin │ ├── configtxgen │ └── cryptogen ├── configtx.yaml ├── crypto-config.yaml ├── docker-compose-org3.yaml ├── docker-compose-simple.yaml ├── docker-compose │ └── docker-compose.yaml ├── msp │ ├── admincerts │ │ └── admincert.pem │ ├── cacerts │ │ └── cacert.pem │ ├── keystore │ │ └── key.pem │ ├── signcerts │ │ └── peer.pem │ ├── tlscacerts │ │ └── tlsroot.pem │ └── tlsintermediatecerts │ │ └── tlsintermediate.pem ├── myc.block ├── myc.tx ├── orderer.block ├── org3 │ └── crypto.yaml ├── script.sh ├── scripts │ └── script.sh └── start.sh ├── etc ├── config.yaml └── sdk.yaml ├── go.mod ├── go.sum ├── images ├── ide中设置链码本地运行需要的环境配置参数.png ├── ide查找环境变量设置的位置图.png ├── json格式参数的操作界面.png ├── peer未启动导致链码连接不上无法运行的情况.png ├── 修改后链码调用查询方法链码输出日志.png ├── 启动环境成功界面.png ├── 浏览器启动界面.png ├── 清理环境成功界面.png ├── 版本依赖冲突解决办法.png ├── 版本依赖冲突问题.png ├── 链码安装成功日志标志.png ├── 链码安装版本指定.png ├── 链码安装项目选择.png ├── 链码实例化成功链码运行日志.png ├── 链码实例化操作界面.png ├── 链码调用查询方法.png ├── 链码调用查询方法链码输出日志.png ├── 链码调用转账方法.png ├── 链码调用转账方法链码输出日志.png └── 链码项目修改.png ├── main.go ├── src ├── config │ ├── config.go │ ├── generate.go │ └── generate_test.go ├── log │ ├── log.go │ └── log_test.go ├── service │ ├── app │ │ ├── chaincode.go │ │ ├── chaincode_test.go │ │ ├── channel.go │ │ └── invoke.go │ ├── controller.go │ ├── docker │ │ ├── chaincode.go │ │ ├── cli.go │ │ ├── container.go │ │ ├── couchdb.go │ │ ├── docker.go │ │ ├── docker_test.go │ │ ├── orderer.go │ │ └── peer.go │ ├── handle │ │ ├── chaincode.go │ │ ├── channel.go │ │ ├── common.go │ │ ├── peer.go │ │ ├── plat.go │ │ └── route.go │ └── org │ │ ├── crypto.go │ │ ├── node.go │ │ └── setup.go └── utils │ └── utils.go ├── static ├── element-ui │ ├── index.css │ └── index.js └── js │ └── jquery.min.js └── views └── index.html /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | main 3 | deploy/chaincode/* 4 | vendor/ 5 | deploy/channel-artifacts/* 6 | deploy/crypto-config/* 7 | deploy/org3 8 | deploy/scripts 9 | deploy/docker-compose -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## devplat本地链码测试工具 2 | 3 | ### 介绍 4 | 5 | ​ devplat是一款本地链码测试工具,提供了一键部署清理本地fabric开发环境的功能。解决了fabric开发环境搭建的难题。项目参照了fabric-samples中的chaincode-docker-devmode的搭建方式,使用docker-sdk的方式一键集成peer、orderer、cli、couchdb、chaincode等服务。 6 | 7 | ### 开箱即用 8 | 9 | #### 项目启动 10 | 11 | ​ 项目由go mod管理,目前支持fabric-1.4版本。如果您是Mac或者Linux平台,则可做到开箱即用: 12 | 13 | > 请保证您的电脑上已经提前安装好go和docker,go版本推荐1.13或以上,docker版本推荐ce-17.06或以上 14 | 15 | * 拉取分支代码 16 | 17 | ```shell 18 | git clone https://github.com/3115826227/devplat.git 19 | ``` 20 | 21 | * 进入项目执行 22 | 23 | ```shell 24 | # 进入项目目录,执行前请保证8080端口未被占用 25 | go run main.go 26 | ``` 27 | 28 | * 如果服务启动成功,打开浏览器,访问localhost:8080即可展现以下界面 29 | 30 | ![浏览器启动界面.png](images/浏览器启动界面.png) 31 | 32 | #### 环境管理 33 | 34 | ##### 镜像拉取 35 | 36 | > 提示:请确保您的本机docker已经存在以下图中的四个镜像,可使用docker images进行查看,如果不存在,请执行docker pull 镜像名拉取以下四个镜像,再进行环境启动操作。 37 | 38 | ```shell 39 | docker pull hyperledger/fabric-tools:latest 40 | docker pull hyperledger/fabric-couchdb:latest 41 | docker pull hyperledger/fabric-orderer:latest 42 | docker pull hyperledger/fabric-peer:latest 43 | ``` 44 | 45 | ##### 环境启动 46 | 47 | ​ 点击启动环境,会出现等待提示,项目运行日志会有相关服务启动记录。如图下所示,表示环境启动成功 48 | 49 | ![启动环境成功界面.png](images/启动环境成功界面.png) 50 | 51 | > 在windows下面可能会出现部分问题,导致项目不能启动fabric环境,相关采坑文档后续更新 52 | 53 | ##### 环境清理 54 | 55 | ​ 点击清理环境,同样会出现等待提示。如图下所示,表示环境清理成功 56 | 57 | ![清理环境成功界面.png](images/清理环境成功界面.png) 58 | 59 | #### 链码管理 60 | 61 | ​ 本项目支持链码在线运行测试,链码项目由**devplat/deploy/chaincode**目录管理,如果您需要使用本项目进行链码管理,请您把相关的链码项目提前放置在**devplat/deploy/chaincode**目录中。以下展示如果使用本项目进行example02链码管理。 62 | 63 | * 拉取fabric源码 64 | * 拷贝example02目录到**devplat/deploy/chaincode**目录下 65 | 66 | > 链码example02此时已经被拷贝到非gopath目录下,因此需要使用go mod进行管理 67 | 68 | * 使用go mod管理example02 69 | 70 | ```shell 71 | go mod init example02 # 使用go mod初始化项目,名称为example02 72 | go mod tidy # 拉取相关依赖 73 | ``` 74 | 75 | 76 | 77 | > 在执行go mod tidy的时候,可能会出现依赖冲突,如下图所示 78 | 79 | ![版本依赖冲突问题.png](images/版本依赖冲突问题.png) 80 | 81 | > 解决办法:编辑go.mod文件,添加以下红色圈中的内容。(链码开发版本可以自行制定,目前使用的是1.4.0,最好版本在1.4及以上) 82 | 83 | ![版本依赖冲突解决办法.png](images/版本依赖冲突解决办法.png) 84 | 85 | > 添加之后,再次执行go mod tidy命令,相关依赖就可以下载成功了。如果您的拉取过慢,请修改go env中的GOPROXY参数。 86 | 87 | * 编译并执行example02 88 | 89 | ```shell 90 | # 编译 91 | go build 92 | # 执行 93 | # CORE_PEER_ADDRESS参数: 设置链码需要连接的peer节点,本项目默认开启的peer节点端口是7052 94 | # CORE_CHAINCODE_ID_NAME参数:设置链码名称以及版本,中间使用冒号分割,可随意指定 95 | CORE_PEER_ADDRESS=localhost:7052 CORE_CHAINCODE_ID_NAME=example02:1.0 ./example02 96 | ``` 97 | 98 | 99 | 100 | > 执行example02链码的时候需要保证环境是正常启动的,否则会因为连接不上peer节点,结束运行 101 | 102 | ![peer未启动导致链码连接不上无法运行的情况.png](images/peer未启动导致链码连接不上无法运行的情况.png) 103 | 104 | ##### 链码安装 105 | 106 | * 选择"链码管理" 107 | * 选择"链码安装" 108 | * "选择项目安装链码" 选择项目 "example02" 109 | * 填写"链码版本"为"1.0" 110 | * 点击"安装" 111 | 112 | ![链码安装项目选择.png](images/链码安装项目选择.png) 113 | 114 | ![链码安装版本指定.png](images/链码安装版本指定.png) 115 | 116 | > 链码安装之后会给出"链码安装结束"的提示,此时链码安装的日志保存在页面中,点击"查看日志",如下图所示,出现 status:200 payload:"OK"则表示安装成功 117 | 118 | ![链码安装成功日志标志.png](images/链码安装成功日志标志.png) 119 | 120 | > 提示:查看日志,安装成功之后,需要点击"已安装成功",进行流程流转 121 | 122 | ##### 链码实例化 123 | 124 | * 选择"链码管理" 125 | * 选择"链码实例化" 126 | * "选择已安装链码"选择"example02" 127 | * 点击"新增参数",填写四个初始化参数 128 | * 点击"实例化" 129 | 130 | ![链码实例化操作界面.png](images/链码实例化操作界面.png) 131 | 132 | > 链码实例化需要example02的运行,如果出现example02实例化时打印出来的日志,则表示实例化成功,如下图所示 133 | 134 | ![链码实例化成功链码运行日志.png](images/链码实例化成功链码运行日志.png) 135 | 136 | > 提示:查看example02运行日志,实例化成功之后,同样需要点击"已实例化成功",进行流程流转 137 | 138 | ##### 链码调用 139 | 140 | * 选择"链码管理" 141 | * 选择"链码调用" 142 | * "选择已实例化链码"选择"example02" 143 | * 填写链码方法名"invoke" 144 | * 点击"新增参数",填写invoke方法需要的三个参数 145 | * 点击"调用" 146 | 147 | ![链码调用转账方法.png](images/链码调用转账方法.png) 148 | 149 | > 链码调用执行之后,example02运行日志会打印出example02链码执行invoke方法时打印出来的日志,则表示调用成功,如下图所示 150 | 151 | ![链码调用转账方法链码输出日志.png](images/链码调用转账方法链码输出日志.png) 152 | 153 | > 接下来可以使用同样的操作,填写query方法查询链码,添加一个参数a,查询a的结果,如下图所示 154 | 155 | ![链码调用查询方法.png](images/链码调用查询方法.png) 156 | 157 | ![链码调用查询方法链码输出日志.png](images/链码调用查询方法链码输出日志.png) 158 | 159 | 160 | ##### 实时修改 161 | 162 | ​ 本地开发链码的时候,测试通常不太方便,需要到真正的fabric环境中安装、实例化链码,耗费时间比较长。虽然fabric提供了MockStub可以通过编写测试文件的方式测试链码,但是MockStub不支持couchdb,有一定的局限性。本项目可通过停止链码项目运行->修改链码项目->重新运行链码项目->调用链码->获取新的结果的方式,大大提高链码开发测试的效率。 163 | 164 | ```shell 165 | # control C停止example02链码运行 166 | # 修改example02.go文件,在第55行,添加一行打印记录 167 | # 保存退出,编译example02 168 | go build 169 | # 重新执行example02 170 | CORE_PEER_ADDRESS=localhost:7052 CORE_CHAINCODE_ID_NAME=example02:1.0 ./example02 171 | ``` 172 | 173 | ![链码项目修改.png](images/链码项目修改.png) 174 | 175 | > 修改重新运行之后,再次执行query查询链码的时候,控制台日志输出多了一行记录,如下图所示 176 | 177 | ![修改后链码调用查询方法链码输出日志.png](images/修改后链码调用查询方法链码输出日志.png) 178 | 179 | 180 | #### 附1:Goland IDE运行链码说明 181 | 182 | ​ 直接用ide打开example02项目,编译执行main方法会出现报错退出的,此时需要设置环境变量,如下图所示,选择右上角的go build example02,打开Environment最右边的那个图标,进行参数配置 183 | 184 | ![ide查找环境变量设置的位置图.png](images/ide查找环境变量设置的位置图.png) 185 | 186 | ![ide中设置链码本地运行需要的环境配置参数.png](images/ide中设置链码本地运行需要的环境配置参数.png) 187 | 188 | 189 | > 提示:Environment环境配置了之后,需要先点击"OK"左边的"Apply"才能生效,生效之后重新编译运行就可以成功了。 190 | 191 | #### 附2:链码工程化部署说明 192 | 193 | ​ 简单的链码可以只放在一个文件中,但是如果比较复杂的链码,需要工程化项目管理,那么直接在链码安装会发现找不到路径,此时需要生成vendor包 194 | 195 | ```shell 196 | # 进入链码项目 197 | go mod init 链码项目名 198 | go mod tidy # 拉取项目包依赖 199 | go mod vendor # 添加vendor包依赖 200 | go build 201 | ``` 202 | 203 | > 在IDE编译器中,如果开启了go mod管理,生成了vendor包是会报错找不到路径的,我们只需要在链码安装阶段生成vendor包,链码如果安装成功了之后,是可以随时把vendor包删除的;此后,便可以在IDE中运行链码,在浏览器进行链码实例化和链码调用。 204 | 205 | #### 附3:json格式参数的支持 206 | 207 | ​ 项目已经支持在链码实例化和链码调用时传入json格式的参数,只需要在右边string下拉选择框中选择json,将数据填入框内,如下图所示 208 | 209 | ![json格式参数的操作界面.png](images/json格式参数的操作界面.png) 210 | -------------------------------------------------------------------------------- /deploy/bin/configtxgen: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3115826227/devplat/d53945465e4fd70664c0c5ab9a04190c7b2629df/deploy/bin/configtxgen -------------------------------------------------------------------------------- /deploy/bin/cryptogen: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3115826227/devplat/d53945465e4fd70664c0c5ab9a04190c7b2629df/deploy/bin/cryptogen -------------------------------------------------------------------------------- /deploy/configtx.yaml: -------------------------------------------------------------------------------- 1 | # Copyright IBM Corp. All Rights Reserved. 2 | # 3 | # SPDX-License-Identifier: Apache-2.0 4 | # 5 | 6 | --- 7 | Organizations: 8 | - &OrdererOrg 9 | Name: OrdererOrg 10 | ID: OrdererMSP 11 | MSPDir: crypto-config/ordererOrganizations/example.com/msp 12 | Policies: 13 | Readers: 14 | Type: Signature 15 | Rule: "OR('OrdererMSP.member')" 16 | Writers: 17 | Type: Signature 18 | Rule: "OR('OrdererMSP.member')" 19 | Admins: 20 | Type: Signature 21 | Rule: "OR('OrdererMSP.admin')" 22 | - &Org1 23 | Name: Org1MSP 24 | ID: Org1MSP 25 | MSPDir: crypto-config/peerOrganizations/org1.example.com/msp 26 | Policies: 27 | Readers: 28 | Type: Signature 29 | Rule: "OR('Org1MSP.admin', 'Org1MSP.peer', 'Org1MSP.client')" 30 | Writers: 31 | Type: Signature 32 | Rule: "OR('Org1MSP.admin', 'Org1MSP.client')" 33 | Admins: 34 | Type: Signature 35 | Rule: "OR('Org1MSP.admin')" 36 | AnchorPeers: 37 | - Host: peer0.org1.example.com 38 | Port: 7051 39 | 40 | Capabilities: 41 | Channel: &ChannelCapabilities 42 | V1_4_3: true 43 | V1_3: false 44 | V1_1: false 45 | Orderer: &OrdererCapabilities 46 | V1_4_2: true 47 | V1_1: false 48 | Application: &ApplicationCapabilities 49 | V1_4_2: true 50 | V1_3: false 51 | V1_2: false 52 | V1_1: false 53 | 54 | Application: &ApplicationDefaults 55 | Organizations: 56 | Policies: 57 | Readers: 58 | Type: ImplicitMeta 59 | Rule: "ANY Readers" 60 | Writers: 61 | Type: ImplicitMeta 62 | Rule: "ANY Writers" 63 | Admins: 64 | Type: ImplicitMeta 65 | Rule: "MAJORITY Admins" 66 | 67 | Capabilities: 68 | <<: *ApplicationCapabilities 69 | 70 | Orderer: &OrdererDefaults 71 | OrdererType: solo 72 | Addresses: 73 | - orderer.example.com:7050 74 | BatchTimeout: 2s 75 | BatchSize: 76 | MaxMessageCount: 10 77 | AbsoluteMaxBytes: 99 MB 78 | PreferredMaxBytes: 512 KB 79 | Kafka: 80 | Brokers: 81 | - 127.0.0.1:9092 82 | EtcdRaft: 83 | Consenters: 84 | - Host: orderer.example.com 85 | Port: 7050 86 | ClientTLSCert: crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/tls/server.crt 87 | ServerTLSCert: crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/tls/server.crt 88 | - Host: orderer2.example.com 89 | Port: 7050 90 | ClientTLSCert: crypto-config/ordererOrganizations/example.com/orderers/orderer2.example.com/tls/server.crt 91 | ServerTLSCert: crypto-config/ordererOrganizations/example.com/orderers/orderer2.example.com/tls/server.crt 92 | - Host: orderer3.example.com 93 | Port: 7050 94 | ClientTLSCert: crypto-config/ordererOrganizations/example.com/orderers/orderer3.example.com/tls/server.crt 95 | ServerTLSCert: crypto-config/ordererOrganizations/example.com/orderers/orderer3.example.com/tls/server.crt 96 | - Host: orderer4.example.com 97 | Port: 7050 98 | ClientTLSCert: crypto-config/ordererOrganizations/example.com/orderers/orderer4.example.com/tls/server.crt 99 | ServerTLSCert: crypto-config/ordererOrganizations/example.com/orderers/orderer4.example.com/tls/server.crt 100 | - Host: orderer5.example.com 101 | Port: 7050 102 | ClientTLSCert: crypto-config/ordererOrganizations/example.com/orderers/orderer5.example.com/tls/server.crt 103 | ServerTLSCert: crypto-config/ordererOrganizations/example.com/orderers/orderer5.example.com/tls/server.crt 104 | Organizations: 105 | Policies: 106 | Readers: 107 | Type: ImplicitMeta 108 | Rule: "ANY Readers" 109 | Writers: 110 | Type: ImplicitMeta 111 | Rule: "ANY Writers" 112 | Admins: 113 | Type: ImplicitMeta 114 | Rule: "MAJORITY Admins" 115 | BlockValidation: 116 | Type: ImplicitMeta 117 | Rule: "ANY Writers" 118 | 119 | Channel: &ChannelDefaults 120 | Policies: 121 | Readers: 122 | Type: ImplicitMeta 123 | Rule: "ANY Readers" 124 | Writers: 125 | Type: ImplicitMeta 126 | Rule: "ANY Writers" 127 | Admins: 128 | Type: ImplicitMeta 129 | Rule: "MAJORITY Admins" 130 | 131 | Capabilities: 132 | <<: *ChannelCapabilities 133 | 134 | Profiles: 135 | 136 | TwoOrgsOrdererGenesis: 137 | <<: *ChannelDefaults 138 | Orderer: 139 | <<: *OrdererDefaults 140 | Organizations: 141 | - *OrdererOrg 142 | Capabilities: 143 | <<: *OrdererCapabilities 144 | Consortiums: 145 | SampleConsortium: 146 | Organizations: 147 | - *Org1 148 | TwoOrgsChannel: 149 | Consortium: SampleConsortium 150 | <<: *ChannelDefaults 151 | Application: 152 | <<: *ApplicationDefaults 153 | Organizations: 154 | - *Org1 155 | Capabilities: 156 | <<: *ApplicationCapabilities 157 | 158 | SampleDevModeKafka: 159 | <<: *ChannelDefaults 160 | Capabilities: 161 | <<: *ChannelCapabilities 162 | Orderer: 163 | <<: *OrdererDefaults 164 | OrdererType: kafka 165 | Kafka: 166 | Brokers: 167 | - kafka.example.com:9092 168 | 169 | Organizations: 170 | - *OrdererOrg 171 | Capabilities: 172 | <<: *OrdererCapabilities 173 | Application: 174 | <<: *ApplicationDefaults 175 | Organizations: 176 | - <<: *OrdererOrg 177 | Consortiums: 178 | SampleConsortium: 179 | Organizations: 180 | - *Org1 181 | 182 | SampleMultiNodeEtcdRaft: 183 | <<: *ChannelDefaults 184 | Capabilities: 185 | <<: *ChannelCapabilities 186 | Orderer: 187 | <<: *OrdererDefaults 188 | OrdererType: etcdraft 189 | EtcdRaft: 190 | Consenters: 191 | - Host: orderer.example.com 192 | Port: 7050 193 | ClientTLSCert: crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/tls/server.crt 194 | ServerTLSCert: crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/tls/server.crt 195 | - Host: orderer2.example.com 196 | Port: 7050 197 | ClientTLSCert: crypto-config/ordererOrganizations/example.com/orderers/orderer2.example.com/tls/server.crt 198 | ServerTLSCert: crypto-config/ordererOrganizations/example.com/orderers/orderer2.example.com/tls/server.crt 199 | - Host: orderer3.example.com 200 | Port: 7050 201 | ClientTLSCert: crypto-config/ordererOrganizations/example.com/orderers/orderer3.example.com/tls/server.crt 202 | ServerTLSCert: crypto-config/ordererOrganizations/example.com/orderers/orderer3.example.com/tls/server.crt 203 | - Host: orderer4.example.com 204 | Port: 7050 205 | ClientTLSCert: crypto-config/ordererOrganizations/example.com/orderers/orderer4.example.com/tls/server.crt 206 | ServerTLSCert: crypto-config/ordererOrganizations/example.com/orderers/orderer4.example.com/tls/server.crt 207 | - Host: orderer5.example.com 208 | Port: 7050 209 | ClientTLSCert: crypto-config/ordererOrganizations/example.com/orderers/orderer5.example.com/tls/server.crt 210 | ServerTLSCert: crypto-config/ordererOrganizations/example.com/orderers/orderer5.example.com/tls/server.crt 211 | Addresses: 212 | - orderer.example.com:7050 213 | - orderer2.example.com:7050 214 | - orderer3.example.com:7050 215 | - orderer4.example.com:7050 216 | - orderer5.example.com:7050 217 | 218 | Organizations: 219 | - *OrdererOrg 220 | Capabilities: 221 | <<: *OrdererCapabilities 222 | Application: 223 | <<: *ApplicationDefaults 224 | Organizations: 225 | - <<: *OrdererOrg 226 | Consortiums: 227 | SampleConsortium: 228 | Organizations: 229 | - *Org1 230 | -------------------------------------------------------------------------------- /deploy/crypto-config.yaml: -------------------------------------------------------------------------------- 1 | OrdererOrgs: 2 | - Name: Orderer 3 | Domain: example.com 4 | EnableNodeOUs: true 5 | Specs: 6 | - Hostname: orderer 7 | PeerOrgs: 8 | - Name: Org1 9 | Domain: org1.example.com 10 | EnableNodeOUs: true 11 | Template: 12 | Count: 1 13 | Users: 14 | Count: 1 15 | -------------------------------------------------------------------------------- /deploy/docker-compose-org3.yaml: -------------------------------------------------------------------------------- 1 | # Copyright IBM Corp. All Rights Reserved. 2 | # 3 | # SPDX-License-Identifier: Apache-2.0 4 | # 5 | 6 | version: '2' 7 | 8 | volumes: 9 | peer0.org3.example.com: 10 | peer1.org3.example.com: 11 | 12 | networks: 13 | byfn: 14 | 15 | services: 16 | 17 | peer0.org3.example.com: 18 | container_name: peer0.org3.example.com 19 | extends: 20 | file: base/peer-base.yaml 21 | service: peer-base 22 | environment: 23 | - CORE_PEER_ID=peer0.org3.example.com 24 | - CORE_PEER_ADDRESS=peer0.org3.example.com:11051 25 | - CORE_PEER_LISTENADDRESS=0.0.0.0:11051 26 | - CORE_PEER_CHAINCODEADDRESS=peer0.org3.example.com:11052 27 | - CORE_PEER_CHAINCODELISTENADDRESS=0.0.0.0:11052 28 | - CORE_PEER_GOSSIP_BOOTSTRAP=peer1.org3.example.com:12051 29 | - CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer0.org3.example.com:11051 30 | - CORE_PEER_LOCALMSPID=Org3MSP 31 | volumes: 32 | - /var/run/:/host/var/run/ 33 | - ./org3-artifacts/crypto-config/peerOrganizations/org3.example.com/peers/peer0.org3.example.com/msp:/etc/hyperledger/fabric/msp 34 | - ./org3-artifacts/crypto-config/peerOrganizations/org3.example.com/peers/peer0.org3.example.com/tls:/etc/hyperledger/fabric/tls 35 | - peer0.org3.example.com:/var/hyperledger/production 36 | ports: 37 | - 11051:11051 38 | networks: 39 | - byfn 40 | 41 | peer1.org3.example.com: 42 | container_name: peer1.org3.example.com 43 | extends: 44 | file: base/peer-base.yaml 45 | service: peer-base 46 | environment: 47 | - CORE_PEER_ID=peer1.org3.example.com 48 | - CORE_PEER_ADDRESS=peer1.org3.example.com:12051 49 | - CORE_PEER_LISTENADDRESS=0.0.0.0:12051 50 | - CORE_PEER_CHAINCODEADDRESS=peer1.org3.example.com:12052 51 | - CORE_PEER_CHAINCODELISTENADDRESS=0.0.0.0:12052 52 | - CORE_PEER_GOSSIP_BOOTSTRAP=peer0.org3.example.com:11051 53 | - CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer1.org3.example.com:12051 54 | - CORE_PEER_LOCALMSPID=Org3MSP 55 | volumes: 56 | - /var/run/:/host/var/run/ 57 | - ./org3-artifacts/crypto-config/peerOrganizations/org3.example.com/peers/peer1.org3.example.com/msp:/etc/hyperledger/fabric/msp 58 | - ./org3-artifacts/crypto-config/peerOrganizations/org3.example.com/peers/peer1.org3.example.com/tls:/etc/hyperledger/fabric/tls 59 | - peer1.org3.example.com:/var/hyperledger/production 60 | ports: 61 | - 12051:12051 62 | networks: 63 | - byfn 64 | 65 | 66 | Org3cli: 67 | container_name: Org3cli 68 | image: hyperledger/fabric-tools:$IMAGE_TAG 69 | tty: true 70 | stdin_open: true 71 | environment: 72 | - GOPATH=/opt/gopath 73 | - CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock 74 | - FABRIC_LOGGING_SPEC=INFO 75 | #- FABRIC_LOGGING_SPEC=DEBUG 76 | - CORE_PEER_ID=Org3cli 77 | - CORE_PEER_ADDRESS=peer0.org3.example.com:11051 78 | - CORE_PEER_LOCALMSPID=Org3MSP 79 | - CORE_PEER_TLS_ENABLED=true 80 | - CORE_PEER_TLS_CERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org3.example.com/peers/peer0.org3.example.com/tls/server.crt 81 | - CORE_PEER_TLS_KEY_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org3.example.com/peers/peer0.org3.example.com/tls/server.key 82 | - CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org3.example.com/peers/peer0.org3.example.com/tls/ca.crt 83 | - CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org3.example.com/users/Admin@org3.example.com/msp 84 | working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer 85 | command: /bin/bash 86 | volumes: 87 | - /var/run/:/host/var/run/ 88 | - ./../chaincode/:/opt/gopath/src/github.com/chaincode 89 | - ./org3-artifacts/crypto-config:/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ 90 | - ./crypto-config/peerOrganizations/org1.example.com:/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com 91 | - ./crypto-config/peerOrganizations/org2.example.com:/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com 92 | - ./scripts:/opt/gopath/src/github.com/hyperledger/fabric/peer/scripts/ 93 | depends_on: 94 | - peer0.org3.example.com 95 | - peer1.org3.example.com 96 | networks: 97 | - byfn 98 | 99 | -------------------------------------------------------------------------------- /deploy/docker-compose-simple.yaml: -------------------------------------------------------------------------------- 1 | version: '2' 2 | 3 | services: 4 | orderer: 5 | container_name: orderer 6 | image: hyperledger/fabric-orderer 7 | environment: 8 | - FABRIC_LOGGING_SPEC=debug 9 | - ORDERER_GENERAL_LISTENADDRESS=orderer 10 | - ORDERER_GENERAL_GENESISMETHOD=file 11 | - ORDERER_GENERAL_GENESISFILE=orderer.block 12 | - ORDERER_GENERAL_LOCALMSPID=DEFAULT 13 | - ORDERER_GENERAL_LOCALMSPDIR=/etc/hyperledger/msp 14 | - GRPC_TRACE=all=true, 15 | - GRPC_VERBOSITY=debug 16 | working_dir: /opt/gopath/src/github.com/hyperledger/fabric 17 | command: orderer 18 | volumes: 19 | - ./msp:/etc/hyperledger/msp 20 | - ./orderer.block:/etc/hyperledger/fabric/orderer.block 21 | ports: 22 | - 7050:7050 23 | peer: 24 | container_name: peer 25 | image: hyperledger/fabric-peer 26 | environment: 27 | - CORE_LEDGER_STATE_STATEDATABASE=CouchDB 28 | - CORE_LEDGER_STATE_COUCHDBCONFIG_COUCHDBADDRESS=couchdb:5984 29 | - CORE_PEER_ID=peer 30 | - CORE_PEER_ADDRESS=peer:7051 31 | - CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer:7051 32 | - CORE_PEER_LOCALMSPID=DEFAULT 33 | - CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock 34 | - FABRIC_LOGGING_SPEC=DEBUG 35 | - CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/msp 36 | volumes: 37 | - /var/run/:/host/var/run/ 38 | - ./msp:/etc/hyperledger/msp 39 | working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer 40 | command: peer node start --peer-chaincodedev=true 41 | ports: 42 | - 7051:7051 43 | - 7052:7052 44 | - 7053:7053 45 | depends_on: 46 | - couchdb 47 | - orderer 48 | 49 | cli: 50 | container_name: cli 51 | image: hyperledger/fabric-tools 52 | tty: true 53 | environment: 54 | - GOPATH=/opt/gopath 55 | - CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock 56 | - FABRIC_LOGGING_SPEC=DEBUG 57 | - CORE_PEER_ID=cli 58 | - CORE_PEER_ADDRESS=peer:7051 59 | - CORE_PEER_LOCALMSPID=DEFAULT 60 | - CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/msp 61 | working_dir: /opt/gopath/src/chaincodedev 62 | command: /bin/bash -c './script.sh' 63 | volumes: 64 | - /var/run/:/host/var/run/ 65 | - ./msp:/etc/hyperledger/msp 66 | - ./chaincode:/opt/gopath/src/chaincodedev/chaincode 67 | - ./:/opt/gopath/src/chaincodedev/ 68 | depends_on: 69 | - orderer 70 | - peer 71 | 72 | chaincode: 73 | container_name: chaincode 74 | image: hyperledger/fabric-ccenv 75 | tty: true 76 | environment: 77 | - GOPATH=/opt/gopath 78 | - CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock 79 | - FABRIC_LOGGING_SPEC=DEBUG 80 | - CORE_PEER_ID=example_cc 81 | - CORE_PEER_ADDRESS=peer:7051 82 | - CORE_PEER_LOCALMSPID=DEFAULT 83 | - CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/msp 84 | working_dir: /opt/gopath/src/chaincode 85 | command: /bin/sh -c 'sleep 6000000' 86 | volumes: 87 | - /var/run/:/host/var/run/ 88 | - ./msp:/etc/hyperledger/msp 89 | - ./chaincode:/opt/gopath/src/chaincode 90 | depends_on: 91 | - orderer 92 | - peer 93 | couchdb: 94 | container_name: couchdb 95 | image: hyperledger/fabric-couchdb 96 | ports: 97 | - 5984:5984 98 | networks: 99 | - default 100 | -------------------------------------------------------------------------------- /deploy/docker-compose/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | version: '2' 2 | 3 | services: 4 | orderer.example.com: 5 | container_name: orderer.example.com 6 | image: hyperledger/fabric-orderer 7 | environment: 8 | - ORDERER_GENERAL_LOGLEVEL=debug 9 | - ORDERER_GENERAL_LISTENADDRESS=0.0.0.0 10 | - ORDERER_GENERAL_GENESISMETHOD=file 11 | - ORDERER_GENERAL_GENESISFILE=/var/hyperledger/orderer/orderer.genesis.block 12 | - ORDERER_GENERAL_LOCALMSPID=OrdererMSP 13 | - ORDERER_GENERAL_LOCALMSPDIR=/var/hyperledger/orderer/msp 14 | - GRPC_TRACE=all=true, 15 | - GRPC_VERBOSITY=debug 16 | working_dir: /opt/gopath/src/github.com/hyperledger/fabric 17 | command: orderer 18 | volumes: 19 | - ../channel-artifacts/genesis.block:/var/hyperledger/orderer/orderer.genesis.block 20 | - ../crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/msp:/var/hyperledger/orderer/msp 21 | ports: 22 | - 7050:7050 23 | 24 | peer0.org1.example.com: 25 | container_name: peer0.org1.example.com 26 | image: hyperledger/fabric-peer 27 | environment: 28 | - CORE_LEDGER_STATE_STATEDATABASE=CouchDB 29 | - CORE_LEDGER_STATE_COUCHDBCONFIG_COUCHDBADDRESS=peer0.org1.example.com.couchdb:5984 30 | - CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock 31 | - CORE_LOGGING_LEVEL=DEBUG 32 | - CORE_PEER_ID=peer0.org1.example.com 33 | - CORE_PEER_ADDRESS=peer0.org1.example.com:7051 34 | - CORE_PEER_CHAINCODELISTENADDRESS=peer0.org1.example.com:7052 35 | - CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer0.org1.example.com:7051 36 | - CORE_PEER_LOCALMSPID=Org1MSP 37 | - CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp 38 | working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer 39 | command: peer node start --peer-chaincodedev=true 40 | volumes: 41 | - /var/run/:/host/var/run/ 42 | - ../crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/msp:/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp 43 | ports: 44 | - 7051:7051 45 | - 7052:7052 46 | - 7053:7053 47 | depends_on: 48 | - orderer.example.com 49 | - peer0.org1.example.com.couchdb 50 | 51 | cli: 52 | container_name: cli 53 | image: hyperledger/fabric-tools 54 | tty: true 55 | environment: 56 | - GOPATH=/opt/gopath 57 | - CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock 58 | - CORE_LOGGING_LEVEL=DEBUG 59 | - FABRIC_LOGGING_SPEC=DEBUG 60 | - CORE_PEER_ID=cli 61 | - CORE_PEER_ADDRESS=peer0.org1.example.com:7051 62 | - CORE_PEER_LOCALMSPID=Org1MSP 63 | - CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp 64 | working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer 65 | command: /bin/bash -c './scripts/script.sh' 66 | volumes: 67 | - /var/run/:/host/var/run/ 68 | - ../chaincode:/opt/gopath/src/github.com/hyperledger/fabric/chaincode/ 69 | - ../crypto-config:/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ 70 | - ../scripts:/opt/gopath/src/github.com/hyperledger/fabric/peer/scripts/ 71 | - ../channel-artifacts:/opt/gopath/src/github.com/hyperledger/fabric/peer/channel-artifacts 72 | depends_on: 73 | - orderer.example.com 74 | - peer0.org1.example.com 75 | 76 | chaincode: 77 | container_name: chaincode 78 | image: hyperledger/fabric-tools 79 | tty: true 80 | environment: 81 | - GOPATH=/opt/gopath 82 | - CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock 83 | - FABRIC_LOGGING_SPEC=DEBUG 84 | - CORE_PEER_ID=example_cc 85 | - CORE_PEER_ADDRESS=peer0.org1.example.com:7051 86 | - CORE_PEER_LOCALMSPID=Org1MSP 87 | - CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp 88 | working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer 89 | command: /bin/sh -c 'sleep 6000000' 90 | volumes: 91 | - /var/run/:/host/var/run/ 92 | - ../crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/msp:/etc/hyperledger/fabric/msp 93 | - ../crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls:/etc/hyperledger/fabric/tls 94 | - ../chaincode:/opt/gopath/src/github.com/hyperledger/fabric/examples/chaincode/ 95 | depends_on: 96 | - orderer.example.com 97 | - peer0.org1.example.com 98 | peer0.org1.example.com.couchdb: 99 | container_name: peer0.org1.example.com.couchdb 100 | image: hyperledger/fabric-couchdb 101 | ports: 102 | - 5984:5984 -------------------------------------------------------------------------------- /deploy/msp/admincerts/admincert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIICNjCCAd2gAwIBAgIRAMnf9/dmV9RvCCVw9pZQUfUwCgYIKoZIzj0EAwIwgYEx 3 | CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1TYW4g 4 | RnJhbmNpc2NvMRkwFwYDVQQKExBvcmcxLmV4YW1wbGUuY29tMQwwCgYDVQQLEwND 5 | T1AxHDAaBgNVBAMTE2NhLm9yZzEuZXhhbXBsZS5jb20wHhcNMTcxMTEyMTM0MTEx 6 | WhcNMjcxMTEwMTM0MTExWjBpMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZv 7 | cm5pYTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEMMAoGA1UECxMDQ09QMR8wHQYD 8 | VQQDExZwZWVyMC5vcmcxLmV4YW1wbGUuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0D 9 | AQcDQgAEZ8S4V71OBJpyMIVZdwYdFXAckItrpvSrCf0HQg40WW9XSoOOO76I+Umf 10 | EkmTlIJXP7/AyRRSRU38oI8Ivtu4M6NNMEswDgYDVR0PAQH/BAQDAgeAMAwGA1Ud 11 | EwEB/wQCMAAwKwYDVR0jBCQwIoAginORIhnPEFZUhXm6eWBkm7K7Zc8R4/z7LW4H 12 | ossDlCswCgYIKoZIzj0EAwIDRwAwRAIgVikIUZzgfuFsGLQHWJUVJCU7pDaETkaz 13 | PzFgsCiLxUACICgzJYlW7nvZxP7b6tbeu3t8mrhMXQs956mD4+BoKuNI 14 | -----END CERTIFICATE----- 15 | -------------------------------------------------------------------------------- /deploy/msp/cacerts/cacert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIICYjCCAgigAwIBAgIRAL1fEAnz5zp4moJ8MdSb/lYwCgYIKoZIzj0EAwIwgYEx 3 | CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1TYW4g 4 | RnJhbmNpc2NvMRkwFwYDVQQKExBvcmcxLmV4YW1wbGUuY29tMQwwCgYDVQQLEwND 5 | T1AxHDAaBgNVBAMTE2NhLm9yZzEuZXhhbXBsZS5jb20wHhcNMTcxMTEyMTM0MTEx 6 | WhcNMjcxMTEwMTM0MTExWjCBgTELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlm 7 | b3JuaWExFjAUBgNVBAcTDVNhbiBGcmFuY2lzY28xGTAXBgNVBAoTEG9yZzEuZXhh 8 | bXBsZS5jb20xDDAKBgNVBAsTA0NPUDEcMBoGA1UEAxMTY2Eub3JnMS5leGFtcGxl 9 | LmNvbTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABGrsQ6oJpk6hDWf63HU3OSNd 10 | bou9KNw/VIee1IngPDI4YJU7O+Xa/XLJuwnFv7BpR8Ytl3f+njC8i/RZP2/svO+j 11 | XzBdMA4GA1UdDwEB/wQEAwIBpjAPBgNVHSUECDAGBgRVHSUAMA8GA1UdEwEB/wQF 12 | MAMBAf8wKQYDVR0OBCIEIIpzkSIZzxBWVIV5unlgZJuyu2XPEeP8+y1uB6LLA5Qr 13 | MAoGCCqGSM49BAMCA0gAMEUCIQDUh/+CC2dAICnYtACXspwUaaEbiyZxYIx+XDvW 14 | o8VVcgIgGz5S4iC5+xkxgeaISPfxKTTVy6yzTdYGzCw1vPppjzo= 15 | -----END CERTIFICATE----- 16 | -------------------------------------------------------------------------------- /deploy/msp/keystore/key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgXa3mln4anewXtqrM 3 | hMw6mfZhslkRa/j9P790ToKjlsihRANCAARnxLhXvU4EmnIwhVl3Bh0VcByQi2um 4 | 9KsJ/QdCDjRZb1dKg447voj5SZ8SSZOUglc/v8DJFFJFTfygjwi+27gz 5 | -----END PRIVATE KEY----- 6 | -------------------------------------------------------------------------------- /deploy/msp/signcerts/peer.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIICNjCCAd2gAwIBAgIRAMnf9/dmV9RvCCVw9pZQUfUwCgYIKoZIzj0EAwIwgYEx 3 | CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1TYW4g 4 | RnJhbmNpc2NvMRkwFwYDVQQKExBvcmcxLmV4YW1wbGUuY29tMQwwCgYDVQQLEwND 5 | T1AxHDAaBgNVBAMTE2NhLm9yZzEuZXhhbXBsZS5jb20wHhcNMTcxMTEyMTM0MTEx 6 | WhcNMjcxMTEwMTM0MTExWjBpMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZv 7 | cm5pYTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEMMAoGA1UECxMDQ09QMR8wHQYD 8 | VQQDExZwZWVyMC5vcmcxLmV4YW1wbGUuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0D 9 | AQcDQgAEZ8S4V71OBJpyMIVZdwYdFXAckItrpvSrCf0HQg40WW9XSoOOO76I+Umf 10 | EkmTlIJXP7/AyRRSRU38oI8Ivtu4M6NNMEswDgYDVR0PAQH/BAQDAgeAMAwGA1Ud 11 | EwEB/wQCMAAwKwYDVR0jBCQwIoAginORIhnPEFZUhXm6eWBkm7K7Zc8R4/z7LW4H 12 | ossDlCswCgYIKoZIzj0EAwIDRwAwRAIgVikIUZzgfuFsGLQHWJUVJCU7pDaETkaz 13 | PzFgsCiLxUACICgzJYlW7nvZxP7b6tbeu3t8mrhMXQs956mD4+BoKuNI 14 | -----END CERTIFICATE----- 15 | -------------------------------------------------------------------------------- /deploy/msp/tlscacerts/tlsroot.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIB8jCCAZigAwIBAgIRANxd4D3sY0656NqOh8Rha0AwCgYIKoZIzj0EAwIwWDEL 3 | MAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNhbiBG 4 | cmFuY2lzY28xDTALBgNVBAoTBE9yZzIxDTALBgNVBAMTBE9yZzIwHhcNMTcwNTA4 5 | MDkzMDM0WhcNMjcwNTA2MDkzMDM0WjBYMQswCQYDVQQGEwJVUzETMBEGA1UECBMK 6 | Q2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzENMAsGA1UEChMET3Jn 7 | MjENMAsGA1UEAxMET3JnMjBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABDYy+qzS 8 | J/8CMfhpBFhUhhz+7up4+lwjBWDSS01koszNh8camHTA8vS4ZsN+DZ2DRsSmRZgs 9 | tG2oogLLIdh6Z1CjQzBBMA4GA1UdDwEB/wQEAwIBpjAPBgNVHSUECDAGBgRVHSUA 10 | MA8GA1UdEwEB/wQFMAMBAf8wDQYDVR0OBAYEBAECAwQwCgYIKoZIzj0EAwIDSAAw 11 | RQIgWnMmH0yxAjub3qfzxQioHKQ8+WvUjAXm0ejId9Q+rDICIQDr30UCPj+SXzOb 12 | Cu4psMMBfLujKoiBNdLE1KEpt8lN1g== 13 | -----END CERTIFICATE----- 14 | -------------------------------------------------------------------------------- /deploy/msp/tlsintermediatecerts/tlsintermediate.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIICETCCAbagAwIBAgIQNpgoASE9fi0ooZVKcnwnZzAKBggqhkjOPQQDAjBYMQsw 3 | CQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZy 4 | YW5jaXNjbzENMAsGA1UEChMET3JnMjENMAsGA1UEAxMET3JnMjAeFw0xNzA1MDgw 5 | OTMwMzRaFw0yNzA1MDYwOTMwMzRaMGYxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpD 6 | YWxpZm9ybmlhMRYwFAYDVQQHEw1TYW4gRnJhbmNpc2NvMRQwEgYDVQQKEwtPcmcy 7 | LWNoaWxkMTEUMBIGA1UEAxMLT3JnMi1jaGlsZDEwWTATBgcqhkjOPQIBBggqhkjO 8 | PQMBBwNCAARTBJ8/o1tpHPwuixYDgRwcrzAru0cWJJhE6KWHAa0vBCG4nl0zjjRS 9 | og+iAuUcY4Z/gJoHol6dKSHk9h5jrqtEo1QwUjAOBgNVHQ8BAf8EBAMCAaYwDwYD 10 | VR0lBAgwBgYEVR0lADAPBgNVHRMBAf8EBTADAQH/MA0GA1UdDgQGBAQBAgMEMA8G 11 | A1UdIwQIMAaABAECAwQwCgYIKoZIzj0EAwIDSQAwRgIhAIkPzk7ORV/WhfG7QY/6 12 | /OJg4++ftz2SZc44NIuogMArAiEAqbnpnmmHnzo2Qc6gnliCegpGnJ18RUT/jZlj 13 | 1qXHcvg= 14 | -----END CERTIFICATE----- 15 | -------------------------------------------------------------------------------- /deploy/myc.block: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3115826227/devplat/d53945465e4fd70664c0c5ab9a04190c7b2629df/deploy/myc.block -------------------------------------------------------------------------------- /deploy/myc.tx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3115826227/devplat/d53945465e4fd70664c0c5ab9a04190c7b2629df/deploy/myc.tx -------------------------------------------------------------------------------- /deploy/orderer.block: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3115826227/devplat/d53945465e4fd70664c0c5ab9a04190c7b2629df/deploy/orderer.block -------------------------------------------------------------------------------- /deploy/org3/crypto.yaml: -------------------------------------------------------------------------------- 1 | OrdererOrgs: 2 | - Name: Orderer3 3 | Domain: example.com 4 | EnableNodeOUs: true 5 | Specs: 6 | - Hostname: orderer 7 | PeerOrgs: 8 | - Name: Org3 9 | Domain: org3.example.com 10 | EnableNodeOUs: true 11 | Template: 12 | Count: 2 13 | Users: 14 | Count: 1 15 | -------------------------------------------------------------------------------- /deploy/script.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright London Stock Exchange Group All Rights Reserved. 3 | # 4 | # SPDX-License-Identifier: Apache-2.0 5 | set -e 6 | 7 | sleep 5 8 | 9 | go env -w GO111MODULE=off 10 | #go env -w GOPROXY="https://goproxy.io, direct" 11 | # This script expedites the chaincode development process by automating the 12 | # requisite channel create/join commands 13 | 14 | # We use a pre-generated orderer.block and channel transaction artifact (myc.tx), 15 | # both of which are created using the configtxgen tool 16 | 17 | # first we create the channel against the specified configuration in myc.tx 18 | # this call returns a channel configuration block - myc.block - to the CLI container 19 | peer channel create -c myc -f myc.tx -o orderer:7050 20 | 21 | # now we will join the channel and start the chain with myc.block serving as the 22 | # channel's first block (i.e. the genesis block) 23 | peer channel join -b myc.block 24 | 25 | # Now the user can proceed to build and start chaincode in one terminal 26 | # And leverage the CLI container to issue install instantiate invoke query commands in another 27 | 28 | #we should have bailed if above commands failed. 29 | #we are here, so they worked 30 | sleep 600000 31 | exit 0 32 | -------------------------------------------------------------------------------- /deploy/scripts/script.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | #CORE_PEER_LOCALMSPID="Org1MSP" 5 | #CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp 6 | #CORE_PEER_ADDRESS=peer0.org1.example.com:7051 7 | 8 | peer channel create -o orderer.example.com:7050 -c mychannel -f ./channel-artifacts/channel.tx 9 | res=$? 10 | echo "===================== Channel is created successfully ===================== " 11 | sleep 2 12 | peer channel join -b ./mychannel.block 13 | sleep 600000 14 | exit 0 15 | -------------------------------------------------------------------------------- /deploy/start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ## 设置配置环境 4 | export FABRIC_CFG_PATH=$PWD 5 | ## 生成证书 6 | bin/cryptogen generate --config=./crypto-config.yaml 7 | ## 生成创世块 8 | bin/configtxgen -profile TwoOrgsOrdererGenesis -outputBlock ./channel-artifacts/genesis.block 9 | ## 生成配置区块 10 | bin/configtxgen -profile TwoOrgsChannel -outputCreateChannelTx ./channel-artifacts/channel.tx -channelID mychannel 11 | ## 更新锚节点配置 12 | bin/configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org1MSPanchors.tx -channelID mychannel -asOrg Org1MSP 13 | sleep 3 14 | ## 启动服务 15 | docker-compose -f docker-compose/docker-compose.yaml up -d -------------------------------------------------------------------------------- /etc/config.yaml: -------------------------------------------------------------------------------- 1 | releasemode: false 2 | chaincodepath: ./chaincode 3 | sdkcfgpath: etc/sdk.yaml 4 | orgname: Org1 5 | username: Admin 6 | channelname: mychannel 7 | peerimage: hyperledger/fabric-peer:latest 8 | ordererimage: hyperledger/fabric-orderer:latest 9 | ccenvimage: hyperledger/fabric-ccenv:latest 10 | couchdbimage: hyperledger/fabric-couchdb:latest 11 | peers: 12 | - peer0.org1.example.com 13 | orderer: 14 | - orderer.example.com -------------------------------------------------------------------------------- /etc/sdk.yaml: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright SecureKey Technologies Inc. All Rights Reserved. 3 | # 4 | # SPDX-License-Identifier: Apache-2.0 5 | # 6 | # 7 | # The network connection profile provides client applications the information about the target 8 | # blockchain network that are necessary for the applications to interact with it. These are all 9 | # knowledge that must be acquired from out-of-band sources. This file provides such a source. 10 | # 11 | 12 | # copied from fabric-sdk-go/test/fixtures/config/config_e2e_pkcs11.yaml 13 | 14 | # 15 | # Schema version of the content. Used by the SDK to apply the corresponding parsing rules. 16 | # 17 | version: 1.0.0 18 | 19 | # 20 | # The client section used by GO SDK. 21 | # 22 | client: 23 | # Which organization does this application instance belong to? The value must be the name of an org 24 | # defined under "organizations" 25 | organization: Org1 26 | logging: 27 | # Develope can using debug to get more information 28 | # level: debug 29 | level: info 30 | cryptoconfig: 31 | path: /Users/test01/gomod/devplat/deploy/crypto-config 32 | # Some SDKs support pluggable KV stores, the properties under "credentialStore" 33 | # are implementation specific 34 | credentialStore: 35 | # [Optional]. Used by user store. Not needed if all credentials are embedded in configuration 36 | # and enrollments are performed elswhere. 37 | path: "/tmp/examplestore" 38 | 39 | 40 | # [Optional] BCCSP config for the client. Used by GO SDK. 41 | BCCSP: 42 | security: 43 | enabled: true 44 | default: 45 | provider: "SW" 46 | hashAlgorithm: "SHA2" 47 | softVerify: true 48 | level: 256 49 | 50 | tlsCerts: 51 | # [Optional]. Use system certificate pool when connecting to peers, orderers (for negotiating TLS) Default: false 52 | systemCertPool: false 53 | # [Optional]. Client key and cert for TLS handshake with peers and orderers 54 | client: 55 | # 使用byfn中User1@org1的证书 56 | keyfile: /Users/test01/gomod/devplat/deploy/crypto-config/peerOrganizations/org1.example.com/users/User1@org1.example.com/tls/client.key 57 | certfile: /Users/test01/gomod/devplat/deploy/crypto-config/peerOrganizations/org1.example.com/users/User1@org1.example.com/tls/client.cert 58 | 59 | 60 | 61 | ################################## General part ################################## 62 | 63 | 64 | # 65 | # [Optional]. But most apps would have this section so that channel objects can be constructed 66 | # based on the content below. If an app is creating channels, then it likely will not need this 67 | # section. 68 | # 69 | channels: 70 | # name of the channel 71 | mychannel: 72 | # Required. list of orderers designated by the application to use for transactions on this 73 | # channel. This list can be a result of access control ("org1" can only access "ordererA"), or 74 | # operational decisions to share loads from applications among the orderers. The values must 75 | # be "names" of orgs defined under "organizations/peers" 76 | # deprecated: not recommended, to override any orderer configuration items, entity matchers should be used. 77 | # orderers: 78 | # - orderer.example.com 79 | 80 | # 不要缺少当前channel的orderer节点 81 | orderers: 82 | - orderer.example.com 83 | # - orderer2.example.com 84 | # - orderer3.example.com 85 | # - orderer4.example.com 86 | # - orderer5.example.com 87 | 88 | # Required. list of peers from participating orgs 89 | peers: 90 | peer0.org1.example.com: 91 | # [Optional]. will this peer be sent transaction proposals for endorsement? The peer must 92 | # have the chaincode installed. The app can also use this property to decide which peers 93 | # to send the chaincode install request. Default: true 94 | endorsingPeer: true 95 | 96 | # [Optional]. will this peer be sent query proposals? The peer must have the chaincode 97 | # installed. The app can also use this property to decide which peers to send the 98 | # chaincode install request. Default: true 99 | chaincodeQuery: true 100 | 101 | # [Optional]. will this peer be sent query proposals that do not require chaincodes, like 102 | # queryBlock(), queryTransaction(), etc. Default: true 103 | ledgerQuery: true 104 | 105 | # [Optional]. will this peer be the target of the SDK's listener registration? All peers can 106 | # produce events but the app typically only needs to connect to one to listen to events. 107 | # Default: true 108 | eventSource: false 109 | 110 | # [Optional]. The application can use these options to perform channel operations like retrieving channel 111 | # config etc. 112 | policies: 113 | #[Optional] options for retrieving channel configuration blocks 114 | queryChannelConfig: 115 | #[Optional] min number of success responses (from targets/peers) 116 | minResponses: 1 117 | #[Optional] channel config will be retrieved for these number of random targets 118 | maxTargets: 1 119 | #[Optional] retry options for query config block 120 | retryOpts: 121 | #[Optional] number of retry attempts 122 | attempts: 5 123 | #[Optional] the back off interval for the first retry attempt 124 | initialBackoff: 500ms 125 | #[Optional] the maximum back off interval for any retry attempt 126 | maxBackoff: 5s 127 | #[Optional] he factor by which the initial back off period is exponentially incremented 128 | backoffFactor: 2.0 129 | 130 | # 131 | # list of participating organizations in this network 132 | # 133 | organizations: 134 | Org1: 135 | mspid: Org1MSP 136 | # set msp files path 137 | cryptoPath: /Users/test01/gomod/devplat/deploy/crypto-config/peerOrganizations/org1.example.com/users/{username}@org1.example.com/msp 138 | 139 | # Add peers for org1 140 | peers: 141 | - peer0.org1.example.com 142 | 143 | # Orderer Org name 144 | ordererorg: 145 | # Membership Service Provider ID for this organization 146 | mspID: OrdererMSP 147 | cryptoPath: /Users/test01/gomod/devplat/deploy/crypto-config/ordererOrganizations/example.com/users/Admin@example.com/msp 148 | 149 | 150 | # 151 | # List of orderers to send transaction and channel create/update requests to. For the time 152 | # being only one orderer is needed. If more than one is defined, which one get used by the 153 | # SDK is implementation specific. Consult each SDK's documentation for its handling of orderers. 154 | # 155 | orderers: 156 | orderer.example.com: 157 | # [Optional] Default: Infer from hostname 158 | url: localhost:7050 159 | 160 | # these are standard properties defined by the gRPC library 161 | # they will be passed in as-is to gRPC client constructor 162 | grpcOptions: 163 | ssl-target-name-override: orderer.example.com 164 | keep-alive-time: 0s 165 | keep-alive-timeout: 20s 166 | keep-alive-permit: false 167 | fail-fast: false 168 | 169 | #will be taken into consideration if address has no protocol defined, if true then grpc or else grpcs 170 | allow-insecure: false 171 | 172 | tlsCACerts: 173 | # Certificate location absolute path 174 | # Replace to orderer cert path 175 | path: /Users/test01/gomod/devplat/deploy/crypto-config/ordererOrganizations/example.com/tlsca/tlsca.example.com-cert.pem 176 | 177 | # 178 | # List of peers to send various requests to, including endorsement, query 179 | # and event listener registration. 180 | # 181 | peers: 182 | peer0.org1.example.com: 183 | # this URL is used to send endorsement and query requests 184 | # [Optional] Default: Infer from hostname 185 | # 表明使用grpcs协议,设置IP和端口号,使用域名会无法连接 186 | # url: grpcs://peer0.org1.example.com:7051 187 | url: localhost:7051 188 | 189 | grpcOptions: 190 | ssl-target-name-override: peer0.org1.example.com 191 | keep-alive-time: 0s 192 | keep-alive-timeout: 20s 193 | keep-alive-permit: false 194 | fail-fast: false 195 | 196 | #will be taken into consideration if address has no protocol defined, if true then grpc or else grpcs 197 | allow-insecure: false 198 | 199 | tlsCACerts: 200 | # Certificate location absolute path 201 | path: /Users/test01/gomod/devplat/deploy/crypto-config/peerOrganizations/org1.example.com/tlsca/tlsca.org1.example.com-cert.pem 202 | 203 | #entitymatchers: 204 | # peer: 205 | # - pattern: (\w*)peer0.org1.example.com(\w*) 206 | # urlsubstitutionexp: localhost:7051 207 | # ssltargetoverrideurlsubstitutionexp: peer0.org1.example.com 208 | # mappedhost: peer0.org1.example.com 209 | # 210 | # orderer: 211 | # - pattern: (\w*)orderer.example.com(\w*) 212 | # urlsubstitutionexp: localhost:7050 213 | # ssltargetoverrideurlsubstitutionexp: orderer.example.com 214 | # mappedhost: orderer.example.com -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module devplat 2 | 3 | go 1.14 4 | 5 | require ( 6 | github.com/Microsoft/go-winio v0.4.14 // indirect 7 | github.com/docker/distribution v2.7.1+incompatible // indirect 8 | github.com/docker/docker v1.13.1 9 | github.com/docker/go-connections v0.4.0 10 | github.com/docker/go-units v0.4.0 // indirect 11 | github.com/gin-gonic/gin v1.6.3 12 | github.com/hyperledger/fabric-protos-go v0.0.0-20191121202242-f5500d5e3e85 13 | github.com/hyperledger/fabric-sdk-go v1.0.0-beta2 14 | github.com/opencontainers/go-digest v1.0.0 // indirect 15 | github.com/pkg/errors v0.8.1 16 | github.com/spf13/viper v1.7.0 17 | go.uber.org/zap v1.15.0 18 | gopkg.in/natefinch/lumberjack.v2 v2.0.0 19 | gopkg.in/yaml.v2 v2.2.8 20 | ) 21 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 2 | cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 3 | cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= 4 | cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= 5 | cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= 6 | cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= 7 | cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= 8 | cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= 9 | cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= 10 | cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= 11 | cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= 12 | cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= 13 | dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= 14 | github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= 15 | github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= 16 | github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= 17 | github.com/Knetic/govaluate v3.0.0+incompatible h1:7o6+MAPhYTCF0+fdvoz1xDedhRb4f6s9Tn1Tt7/WTEg= 18 | github.com/Knetic/govaluate v3.0.0+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= 19 | github.com/Microsoft/go-winio v0.4.14 h1:+hMXMk01us9KgxGb7ftKQt2Xpf5hH/yky+TDA+qxleU= 20 | github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= 21 | github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= 22 | github.com/VividCortex/gohistogram v1.0.0 h1:6+hBz+qvs0JOrrNhhmR7lFxo5sINxBCGXrdtl/UvroE= 23 | github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= 24 | github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= 25 | github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= 26 | github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= 27 | github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= 28 | github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= 29 | github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= 30 | github.com/beorn7/perks v1.0.0 h1:HWo1m869IqiPhD389kmkxeTalrjNbbJTC8LXupb+sl0= 31 | github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= 32 | github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= 33 | github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= 34 | github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= 35 | github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= 36 | github.com/cloudflare/cfssl v0.0.0-20180223231731-4e2dcbde5004 h1:lkAMpLVBDaj17e85keuznYcH5rqI438v41pKcBl4ZxQ= 37 | github.com/cloudflare/cfssl v0.0.0-20180223231731-4e2dcbde5004/go.mod h1:yMWuSON2oQp+43nFtAV/uvKQIFpSPerB57DCt9t8sSA= 38 | github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= 39 | github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= 40 | github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= 41 | github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= 42 | github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= 43 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 44 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 45 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 46 | github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= 47 | github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= 48 | github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug= 49 | github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= 50 | github.com/docker/docker v1.13.1 h1:IkZjBSIc8hBjLpqeAbeE5mca5mNgeatLHBy3GO78BWo= 51 | github.com/docker/docker v1.13.1/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= 52 | github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= 53 | github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= 54 | github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= 55 | github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= 56 | github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= 57 | github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= 58 | github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= 59 | github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= 60 | github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= 61 | github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= 62 | github.com/gin-gonic/gin v1.6.3 h1:ahKqKTFpO5KTPHxWZjEdPScmYaGtLo8Y4DMHoEsnp14= 63 | github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M= 64 | github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= 65 | github.com/go-kit/kit v0.8.0 h1:Wz+5lgoB0kkuqLEc6NVmwRknTKP6dTGbSqvhZtBI/j0= 66 | github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= 67 | github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= 68 | github.com/go-logfmt/logfmt v0.4.0 h1:MP4Eh7ZCb31lleYCFuwm0oe4/YGak+5l1vA2NOE80nA= 69 | github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= 70 | github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A= 71 | github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= 72 | github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= 73 | github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= 74 | github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no= 75 | github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= 76 | github.com/go-playground/validator/v10 v10.2.0 h1:KgJ0snyC2R9VXYN2rneOtQcw5aHQB1Vv0sFl1UcHBOY= 77 | github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI= 78 | github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= 79 | github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= 80 | github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= 81 | github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE= 82 | github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= 83 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= 84 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= 85 | github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 86 | github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 87 | github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 88 | github.com/golang/mock v1.3.1 h1:qGJ6qTW+x6xX/my+8YUVl4WNpX9B7+/l2tRsHGZ7f2s= 89 | github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= 90 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 91 | github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 92 | github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 93 | github.com/golang/protobuf v1.3.3 h1:gyjaxf+svBWX08ZjK86iN9geUJF0H6gp2IRKX6Nf6/I= 94 | github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= 95 | github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= 96 | github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= 97 | github.com/google/certificate-transparency-go v0.0.0-20180222191210-5ab67e519c93 h1:qdfmdGwtm13OVx+AxguOWUTbgmXGn2TbdUHipo3chMg= 98 | github.com/google/certificate-transparency-go v0.0.0-20180222191210-5ab67e519c93/go.mod h1:QeJfpSbVSfYc7RgB3gJFj9cbuQMMchQxrWXz8Ruopmg= 99 | github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= 100 | github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 101 | github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 102 | github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= 103 | github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= 104 | github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= 105 | github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= 106 | github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= 107 | github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= 108 | github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= 109 | github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= 110 | github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= 111 | github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= 112 | github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= 113 | github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= 114 | github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= 115 | github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= 116 | github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= 117 | github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= 118 | github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= 119 | github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= 120 | github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= 121 | github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= 122 | github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= 123 | github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= 124 | github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= 125 | github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= 126 | github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= 127 | github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= 128 | github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= 129 | github.com/hashicorp/hcl v0.0.0-20180404174102-ef8a98b0bbce/go.mod h1:oZtUIOe8dh44I2q6ScRibXws4Ajl+d+nod3AaR9vL5w= 130 | github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= 131 | github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= 132 | github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= 133 | github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= 134 | github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= 135 | github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= 136 | github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= 137 | github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= 138 | github.com/hyperledger/fabric v1.4.7 h1:weX0z8WybFIj2TTF0QOa+vBxwxBRZToRms3E1wtfRZk= 139 | github.com/hyperledger/fabric v1.4.8 h1:G0PeG/WHHAApO/PXkDAcwjur5L5+FNiVbhKidzNX4Z4= 140 | github.com/hyperledger/fabric v2.1.1+incompatible h1:cYYRv3vVg4kA6DmrixLxwn1nwBEUuYda8DsMwlaMKbY= 141 | github.com/hyperledger/fabric-lib-go v1.0.0 h1:UL1w7c9LvHZUSkIvHTDGklxFv2kTeva1QI2emOVc324= 142 | github.com/hyperledger/fabric-lib-go v1.0.0/go.mod h1:H362nMlunurmHwkYqR5uHL2UDWbQdbfz74n8kbCFsqc= 143 | github.com/hyperledger/fabric-protos-go v0.0.0-20191121202242-f5500d5e3e85 h1:bNgEcCg5NVRWs/T+VUEfhgh5Olx/N4VB+0+ybW+oSuA= 144 | github.com/hyperledger/fabric-protos-go v0.0.0-20191121202242-f5500d5e3e85/go.mod h1:xVYTjK4DtZRBxZ2D9aE4y6AbLaPwue2o/criQyQbVD0= 145 | github.com/hyperledger/fabric-sdk-go v1.0.0-beta2 h1:FBYygns0Qga+mQ4PXycyTU5m4N9KAZM+Ttf7agiV7M8= 146 | github.com/hyperledger/fabric-sdk-go v1.0.0-beta2/go.mod h1:/s224b8NLvOJOCIqBvWd9O6u7GE33iuIOT6OfcTE1OE= 147 | github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= 148 | github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= 149 | github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns= 150 | github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= 151 | github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= 152 | github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= 153 | github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= 154 | github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= 155 | github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= 156 | github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= 157 | github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= 158 | github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515 h1:T+h1c/A9Gawja4Y9mFVWj2vyii2bbUNDw3kt9VxK2EY= 159 | github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= 160 | github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= 161 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= 162 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 163 | github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= 164 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 165 | github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= 166 | github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= 167 | github.com/magiconair/properties v1.7.6/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= 168 | github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4= 169 | github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= 170 | github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= 171 | github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= 172 | github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= 173 | github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= 174 | github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= 175 | github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= 176 | github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= 177 | github.com/miekg/pkcs11 v0.0.0-20190329070431-55f3fac3af27 h1:XA/VH+SzpYyukhgh7v2mTp8rZoKKITXR/x3FIizVEXs= 178 | github.com/miekg/pkcs11 v0.0.0-20190329070431-55f3fac3af27/go.mod h1:WCBAbTOdfhHhz7YXujeZMF7owC4tPb1naKFsgfUISjo= 179 | github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= 180 | github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= 181 | github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= 182 | github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= 183 | github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= 184 | github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= 185 | github.com/mitchellh/mapstructure v0.0.0-20180220230111-00c29f56e238/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= 186 | github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= 187 | github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= 188 | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= 189 | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 190 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= 191 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 192 | github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg= 193 | github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= 194 | github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= 195 | github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= 196 | github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= 197 | github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= 198 | github.com/onsi/ginkgo v1.6.0 h1:Ix8l273rp3QzYgXSR+c8d1fTG7UPgYkOSELPhiY/YGw= 199 | github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= 200 | github.com/onsi/gomega v1.4.2 h1:3mYCb7aPxS/RU7TI1y4rkEn1oKmPRjNJLNEXgw7MH2I= 201 | github.com/onsi/gomega v1.4.2/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= 202 | github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= 203 | github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= 204 | github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= 205 | github.com/pelletier/go-toml v1.1.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= 206 | github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc= 207 | github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= 208 | github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 209 | github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= 210 | github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 211 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 212 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 213 | github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= 214 | github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= 215 | github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= 216 | github.com/prometheus/client_golang v0.9.3 h1:9iH4JKXLzFbOAdtqv/a+j8aewx2Y8lAjAydhbaScPF8= 217 | github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= 218 | github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= 219 | github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90 h1:S/YWwWx/RA8rT8tKFRuGUZhuA90OyIBpPCXkcbwU8DE= 220 | github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 221 | github.com/prometheus/common v0.0.0-20180518154759-7600349dcfe1/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= 222 | github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= 223 | github.com/prometheus/common v0.4.0 h1:7etb9YClo3a6HjLzfl6rIQaU+FDfi0VSX39io3aQ+DM= 224 | github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= 225 | github.com/prometheus/procfs v0.0.0-20180705121852-ae68e2d4c00f/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= 226 | github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= 227 | github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084 h1:sofwID9zm4tzrgykg80hfFph1mryUeLRsUfoocVVmRY= 228 | github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= 229 | github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= 230 | github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= 231 | github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= 232 | github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= 233 | github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= 234 | github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= 235 | github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= 236 | github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= 237 | github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= 238 | github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= 239 | github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= 240 | github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= 241 | github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= 242 | github.com/spf13/afero v1.1.0/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= 243 | github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI= 244 | github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= 245 | github.com/spf13/cast v1.2.0/go.mod h1:r2rcYCSwa1IExKTDiTfzaxqT2FNHs8hODu4LnUfgKEg= 246 | github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8= 247 | github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= 248 | github.com/spf13/jwalterweatherman v0.0.0-20180109140146-7c0cea34c8ec/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= 249 | github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk= 250 | github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= 251 | github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= 252 | github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg= 253 | github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= 254 | github.com/spf13/viper v1.0.2/go.mod h1:A8kyI5cUJhb8N+3pkfONlcEcZbueH6nhAm0Fq7SrnBM= 255 | github.com/spf13/viper v1.7.0 h1:xVKxvI7ouOI5I+U9s2eeiUfMaWBVoXA3AWskkrqK0VM= 256 | github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= 257 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 258 | github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 259 | github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 260 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 261 | github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= 262 | github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= 263 | github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= 264 | github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= 265 | github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= 266 | github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo= 267 | github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= 268 | github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs= 269 | github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= 270 | github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= 271 | go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= 272 | go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= 273 | go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= 274 | go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= 275 | go.uber.org/atomic v1.6.0 h1:Ezj3JGmsOnG1MoRWQkPBsKLe9DwWD9QeXzTRzzldNVk= 276 | go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= 277 | go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= 278 | go.uber.org/multierr v1.5.0 h1:KCa4XfM8CWFCpxXRGok+Q0SS/0XBhMDbHHGABQLvD2A= 279 | go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= 280 | go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee h1:0mgffUl7nfd+FpvXMVz4IDEaUSmT1ysygQC7qYo7sG4= 281 | go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= 282 | go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= 283 | go.uber.org/zap v1.15.0 h1:ZZCA22JRF2gQE5FoNmhmrf7jeJJ2uhqDUNRYKm8dvmM= 284 | go.uber.org/zap v1.15.0/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc= 285 | golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 286 | golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 287 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 288 | golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 289 | golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5 h1:58fnuSXlxZmFdJyvtTFVmVhcMLU6v5fEb/ok4wyqtNU= 290 | golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 291 | golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 292 | golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 293 | golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= 294 | golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= 295 | golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= 296 | golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= 297 | golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= 298 | golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 299 | golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= 300 | golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 301 | golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 302 | golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 303 | golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 304 | golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs= 305 | golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 306 | golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= 307 | golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= 308 | golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= 309 | golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= 310 | golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 311 | golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 312 | golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 313 | golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 314 | golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 315 | golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 316 | golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 317 | golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 318 | golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 319 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 320 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 321 | golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 322 | golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 323 | golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= 324 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI= 325 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 326 | golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 327 | golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 328 | golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 329 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 330 | golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 331 | golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 332 | golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 333 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 334 | golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 335 | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 336 | golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 337 | golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 338 | golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 339 | golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 340 | golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 341 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 342 | golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 343 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 344 | golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 345 | golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 346 | golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 347 | golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 348 | golang.org/x/sys v0.0.0-20200116001909-b77594299b42 h1:vEOn+mP2zCOVzKckCZy6YsCtDblrpj/w7B9nxGNELpg= 349 | golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 350 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 351 | golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 352 | golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= 353 | golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= 354 | golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 355 | golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 356 | golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 357 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 358 | golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 359 | golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= 360 | golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 361 | golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 362 | golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 363 | golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 364 | golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 365 | golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 366 | golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 367 | golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= 368 | golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= 369 | golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= 370 | golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 371 | golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 372 | golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 373 | golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 374 | golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5 h1:hKsoRgsbwY1NafxrwTs+k64bikrLBkAgPir1TNCj3Zs= 375 | golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 376 | golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc h1:NCy3Ohtk6Iny5V/reW2Ktypo4zIpWBdRJ1uFMjBxdg8= 377 | golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 378 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 379 | google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= 380 | google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= 381 | google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= 382 | google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= 383 | google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= 384 | google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= 385 | google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 386 | google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 387 | google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= 388 | google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= 389 | google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 390 | google.golang.org/genproto v0.0.0-20190327125643-d831d65fe17d/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 391 | google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 392 | google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 393 | google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 394 | google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= 395 | google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= 396 | google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= 397 | google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a h1:Ob5/580gVHBJZgXnff1cZDbG+xLtMVE5mDRTe+nIsX4= 398 | google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 399 | google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= 400 | google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= 401 | google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= 402 | google.golang.org/grpc v1.23.0 h1:AzbTB6ux+okLTzP8Ru1Xs41C303zdcfEht7MQnYJt5A= 403 | google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= 404 | gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= 405 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 406 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= 407 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 408 | gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= 409 | gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= 410 | gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= 411 | gopkg.in/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno= 412 | gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= 413 | gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= 414 | gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= 415 | gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= 416 | gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= 417 | gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= 418 | gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= 419 | gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 420 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 421 | gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 422 | gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= 423 | gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 424 | honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 425 | honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 426 | honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 427 | honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 428 | honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM= 429 | honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= 430 | rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= 431 | -------------------------------------------------------------------------------- /images/ide中设置链码本地运行需要的环境配置参数.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3115826227/devplat/d53945465e4fd70664c0c5ab9a04190c7b2629df/images/ide中设置链码本地运行需要的环境配置参数.png -------------------------------------------------------------------------------- /images/ide查找环境变量设置的位置图.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3115826227/devplat/d53945465e4fd70664c0c5ab9a04190c7b2629df/images/ide查找环境变量设置的位置图.png -------------------------------------------------------------------------------- /images/json格式参数的操作界面.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3115826227/devplat/d53945465e4fd70664c0c5ab9a04190c7b2629df/images/json格式参数的操作界面.png -------------------------------------------------------------------------------- /images/peer未启动导致链码连接不上无法运行的情况.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3115826227/devplat/d53945465e4fd70664c0c5ab9a04190c7b2629df/images/peer未启动导致链码连接不上无法运行的情况.png -------------------------------------------------------------------------------- /images/修改后链码调用查询方法链码输出日志.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3115826227/devplat/d53945465e4fd70664c0c5ab9a04190c7b2629df/images/修改后链码调用查询方法链码输出日志.png -------------------------------------------------------------------------------- /images/启动环境成功界面.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3115826227/devplat/d53945465e4fd70664c0c5ab9a04190c7b2629df/images/启动环境成功界面.png -------------------------------------------------------------------------------- /images/浏览器启动界面.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3115826227/devplat/d53945465e4fd70664c0c5ab9a04190c7b2629df/images/浏览器启动界面.png -------------------------------------------------------------------------------- /images/清理环境成功界面.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3115826227/devplat/d53945465e4fd70664c0c5ab9a04190c7b2629df/images/清理环境成功界面.png -------------------------------------------------------------------------------- /images/版本依赖冲突解决办法.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3115826227/devplat/d53945465e4fd70664c0c5ab9a04190c7b2629df/images/版本依赖冲突解决办法.png -------------------------------------------------------------------------------- /images/版本依赖冲突问题.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3115826227/devplat/d53945465e4fd70664c0c5ab9a04190c7b2629df/images/版本依赖冲突问题.png -------------------------------------------------------------------------------- /images/链码安装成功日志标志.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3115826227/devplat/d53945465e4fd70664c0c5ab9a04190c7b2629df/images/链码安装成功日志标志.png -------------------------------------------------------------------------------- /images/链码安装版本指定.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3115826227/devplat/d53945465e4fd70664c0c5ab9a04190c7b2629df/images/链码安装版本指定.png -------------------------------------------------------------------------------- /images/链码安装项目选择.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3115826227/devplat/d53945465e4fd70664c0c5ab9a04190c7b2629df/images/链码安装项目选择.png -------------------------------------------------------------------------------- /images/链码实例化成功链码运行日志.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3115826227/devplat/d53945465e4fd70664c0c5ab9a04190c7b2629df/images/链码实例化成功链码运行日志.png -------------------------------------------------------------------------------- /images/链码实例化操作界面.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3115826227/devplat/d53945465e4fd70664c0c5ab9a04190c7b2629df/images/链码实例化操作界面.png -------------------------------------------------------------------------------- /images/链码调用查询方法.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3115826227/devplat/d53945465e4fd70664c0c5ab9a04190c7b2629df/images/链码调用查询方法.png -------------------------------------------------------------------------------- /images/链码调用查询方法链码输出日志.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3115826227/devplat/d53945465e4fd70664c0c5ab9a04190c7b2629df/images/链码调用查询方法链码输出日志.png -------------------------------------------------------------------------------- /images/链码调用转账方法.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3115826227/devplat/d53945465e4fd70664c0c5ab9a04190c7b2629df/images/链码调用转账方法.png -------------------------------------------------------------------------------- /images/链码调用转账方法链码输出日志.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3115826227/devplat/d53945465e4fd70664c0c5ab9a04190c7b2629df/images/链码调用转账方法链码输出日志.png -------------------------------------------------------------------------------- /images/链码项目修改.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3115826227/devplat/d53945465e4fd70664c0c5ab9a04190c7b2629df/images/链码项目修改.png -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "devplat/src/config" 6 | "devplat/src/log" 7 | "devplat/src/service" 8 | "devplat/src/service/app" 9 | "devplat/src/service/handle" 10 | "devplat/src/service/org" 11 | "github.com/gin-gonic/gin" 12 | "net/http" 13 | "os" 14 | "os/signal" 15 | "time" 16 | ) 17 | 18 | func init() { 19 | //获取工作目录 20 | config.WorkPath, _ = os.Getwd() 21 | config.GoPath = os.Getenv("GOPATH") 22 | //初始化Controller 23 | service.InitDevPlatController() 24 | 25 | app.InitChaincodeProvider() 26 | } 27 | 28 | func IndexHandle(c *gin.Context) { 29 | c.HTML(http.StatusOK, "index.html", nil) 30 | } 31 | 32 | func newCrypto() { 33 | var peers = make([]org.PeerNode, 0) 34 | peers = append(peers, org.PeerNode{ 35 | Node: org.Node{ 36 | Address: "0.0.0.0", 37 | Port: []int{7050}, 38 | EnableNodeOUs: true, 39 | Name: "", 40 | Domain: "", 41 | }, 42 | TemplateCount: 0, 43 | UserCount: 0, 44 | }) 45 | var orderers = make([]org.OrdererNode, 0) 46 | o := org.NewOrg("exampleOrg", peers, orderers) 47 | org.NewOrgCrypto(*o) 48 | return 49 | } 50 | 51 | func main() { 52 | 53 | engine := gin.Default() 54 | 55 | engine.Static("static", "static") 56 | engine.LoadHTMLGlob("views/*") 57 | engine.GET("/", IndexHandle) 58 | 59 | handle.Router(engine) 60 | 61 | srv := &http.Server{ 62 | Addr: ":8080", 63 | Handler: engine, 64 | } 65 | 66 | go func() { 67 | // 服务连接 68 | if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed { 69 | log.Logger.Error("listen: " + err.Error()) 70 | } 71 | }() 72 | 73 | // 等待中断信号以优雅地关闭服务器(设置 5 秒的超时时间) 74 | quit := make(chan os.Signal) 75 | signal.Notify(quit, os.Interrupt) 76 | 77 | select { 78 | case <-quit: 79 | //清理环境 80 | service.GetDevPlatController().Clean() 81 | } 82 | 83 | log.Logger.Info("Shutdown Server ...") 84 | ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) 85 | defer cancel() 86 | if err := srv.Shutdown(ctx); err != nil { 87 | log.Logger.Error("Server Shutdown:" + err.Error()) 88 | return 89 | } 90 | log.Logger.Info("Server exiting") 91 | } 92 | -------------------------------------------------------------------------------- /src/config/config.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | import "github.com/spf13/viper" 4 | 5 | var ( 6 | WorkPath string 7 | GoPath string 8 | IP string 9 | Config ConfigStruct 10 | TransientMap = make(map[string][]byte) 11 | ) 12 | 13 | type ConfigStruct struct { 14 | ReleaseMode bool `env:"RELEASE_MODE" default:"false"` 15 | ChainCodePath string `env:"CHAIN_CODE_PATH" required:"true"` 16 | SdkCfgPath string `env:"SDK_CFG_PATH" required:"true"` 17 | OrgName string `env:"ORG_NAME" required:"true"` 18 | UserName string `env:"USER_NAME" required:"true"` 19 | 20 | PeerImage string `env:"PEER_IMAGE" required:"true"` 21 | OrdererImage string `env:"ORDERER_IMAGE" required:"true"` 22 | CcenvImage string `env:"CCENV_IMAGE" required:"true"` 23 | CouchdbName string `env:"COUCHDB_IMAGE" required:"true"` 24 | ChannelName string `env:"CHANNEL_NAME"` 25 | Peers []string `env:"PEERS" required:"true"` 26 | Orderer []string `env:"ORDERER" required:"true"` 27 | TransientMap map[string]string `env:"TRANSIENT_MAP" default:""` 28 | } 29 | 30 | func setConfigYaml() { 31 | //设置配置文件的名字 32 | viper.SetConfigName("config") 33 | //设置配置文件读取路径 34 | viper.AddConfigPath("./etc") //idea跑的时候直接读取项目etc/目录 35 | //viper.AddConfigPath("/etc") //部署到docker容器中挂载到/etc目录下 36 | //设置配置文件类型 37 | viper.SetConfigType("yaml") 38 | } 39 | 40 | func init() { 41 | setConfigYaml() 42 | //读取配置文件内容 43 | if err := viper.ReadInConfig(); err != nil { 44 | panic(err) 45 | } 46 | 47 | var c ConfigStruct 48 | if err := viper.Unmarshal(&c); err != nil { 49 | panic(err) 50 | } 51 | Config = c 52 | for key, value := range Config.TransientMap { 53 | TransientMap[key] = []byte(value) 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/config/generate.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | import ( 4 | "devplat/src/log" 5 | "gopkg.in/yaml.v2" 6 | "os" 7 | ) 8 | 9 | type OrdererOrgs struct { 10 | Name string `yaml:"Name"` 11 | Domain string `yaml:"Domain"` 12 | EnableNodeOUs bool `yaml:"EnableNodeOUs"` 13 | Specs []OrdererSpec `yaml:"Specs"` 14 | } 15 | 16 | type OrdererSpec struct { 17 | Hostname string `yaml:"Hostname"` 18 | } 19 | 20 | type PeerOrgs struct { 21 | Name string `yaml:"Name"` 22 | Domain string `yaml:"Domain"` 23 | EnableNodeOUs bool `yaml:"EnableNodeOUs"` 24 | Template PeerTemplate `yaml:"Template"` 25 | Users PeerUsers `yaml:"Users"` 26 | } 27 | 28 | type PeerTemplate struct { 29 | Count int `yaml:"Count"` 30 | } 31 | 32 | type PeerUsers struct { 33 | Count int `yaml:"Count"` 34 | } 35 | 36 | type CryptoConfig struct { 37 | OrdererOrgs []OrdererOrgs `yaml:"OrdererOrgs"` 38 | PeerOrgs []PeerOrgs `yaml:"PeerOrgs"` 39 | } 40 | 41 | var ( 42 | cryptoCfg CryptoConfig 43 | ) 44 | 45 | func init() { 46 | cryptoCfg = CryptoConfig{ 47 | OrdererOrgs: []OrdererOrgs{ 48 | { 49 | Name: "Orderer", 50 | Domain: "example.com", 51 | EnableNodeOUs: true, 52 | Specs: []OrdererSpec{ 53 | { 54 | Hostname: "orderer", 55 | }, 56 | }, 57 | }, 58 | }, 59 | PeerOrgs: []PeerOrgs{ 60 | { 61 | Name: "Org1", 62 | Domain: "org1.example.com", 63 | EnableNodeOUs: true, 64 | Template: PeerTemplate{Count: 2}, 65 | Users: PeerUsers{Count: 1}, 66 | }, 67 | { 68 | Name: "Org2", 69 | Domain: "org2.example.com", 70 | EnableNodeOUs: true, 71 | Template: PeerTemplate{Count: 2}, 72 | Users: PeerUsers{Count: 1}, 73 | }, 74 | }, 75 | } 76 | } 77 | 78 | func checkFileIsExist(filename string) bool { 79 | var exist = true 80 | if _, err := os.Stat(filename); os.IsNotExist(err) { 81 | exist = false 82 | } 83 | return exist 84 | } 85 | 86 | func write(filename string, data []byte) { 87 | var f *os.File 88 | var err error 89 | if checkFileIsExist(filename) { 90 | f, err = os.OpenFile(filename, os.O_APPEND, 0666) //打开文件 91 | if err != nil { 92 | log.Logger.Error(err.Error()) 93 | return 94 | } 95 | } else { 96 | f, err = os.Create(filename) 97 | if err != nil { 98 | log.Logger.Error(err.Error()) 99 | return 100 | } 101 | } 102 | if _, err = f.Write(data); err != nil { 103 | log.Logger.Error(err.Error()) 104 | return 105 | } 106 | } 107 | 108 | func GenerateConfig(fileName string, config CryptoConfig) { 109 | data, err := yaml.Marshal(config) 110 | if err != nil { 111 | log.Logger.Error(err.Error()) 112 | return 113 | } 114 | write(fileName, data) 115 | } 116 | -------------------------------------------------------------------------------- /src/config/generate_test.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | import "testing" 4 | 5 | func TestGenerateConfig(t *testing.T) { 6 | GenerateConfig("crypto-config.yaml", cryptoCfg) 7 | } 8 | -------------------------------------------------------------------------------- /src/log/log.go: -------------------------------------------------------------------------------- 1 | package log 2 | 3 | import ( 4 | "go.uber.org/zap" 5 | "go.uber.org/zap/zapcore" 6 | "gopkg.in/natefinch/lumberjack.v2" 7 | "log" 8 | "os" 9 | "path" 10 | ) 11 | 12 | var ( 13 | Logger *zap.Logger 14 | levels = map[string]zapcore.Level{ 15 | "DEBUG": zap.DebugLevel, 16 | "INFO": zap.InfoLevel, 17 | "WARN": zap.WarnLevel, 18 | "ERROR": zap.ErrorLevel, 19 | } 20 | ) 21 | 22 | func init() { 23 | log.SetFlags(log.LstdFlags | log.Llongfile) 24 | encoderConfig := zap.NewProductionEncoderConfig() 25 | encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder 26 | var logLevel zapcore.Level 27 | logLevelStr := os.Getenv("LOG_LEVEL") 28 | var exists bool 29 | logLevel, exists = levels[logLevelStr] 30 | if !exists { 31 | logLevel = zap.DebugLevel 32 | } 33 | 34 | logPath := os.Getenv("LOG_PATH") 35 | if logPath != "" { 36 | logDir := path.Dir(logPath) 37 | if _, err := os.Stat(logDir); os.IsNotExist(err) { 38 | log.Fatal("ERROR 日志目录 ", logDir, " 不存在") 39 | } 40 | // 打印到文件,自动分裂 41 | w := zapcore.AddSync(&lumberjack.Logger{ 42 | Filename: logPath, 43 | MaxSize: 64, // megabytes 44 | MaxBackups: 10, 45 | MaxAge: 28, // days 46 | }) 47 | core := zapcore.NewCore( 48 | zapcore.NewJSONEncoder(encoderConfig), 49 | w, 50 | zap.NewAtomicLevelAt(logLevel), 51 | ) 52 | Logger = zap.New(core, zap.AddCaller()) 53 | } else { 54 | // 打印到控制台 55 | cfg := zap.NewProductionConfig() 56 | cfg.Level = zap.NewAtomicLevelAt(logLevel) 57 | cfg.Encoding = "console" 58 | cfg.EncoderConfig = encoderConfig 59 | //cfg.DisableStacktrace = true 60 | var err error 61 | Logger, err = cfg.Build() 62 | if err != nil { 63 | log.Fatal("ERROR ", err) 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/log/log_test.go: -------------------------------------------------------------------------------- 1 | package log 2 | 3 | import ( 4 | "go.uber.org/zap" 5 | "testing" 6 | ) 7 | 8 | func TestInitLogger(t *testing.T) { 9 | s := []string{ 10 | "hello info", 11 | "hello error", 12 | "hello debug", 13 | "hello fatal", 14 | } 15 | Logger.Info("info:", zap.String("s", s[0])) 16 | Logger.Error("info:", zap.String("s", s[1])) 17 | Logger.Debug("info:", zap.String("s", s[2])) 18 | Logger.Fatal("info:", zap.String("s", s[3])) 19 | } 20 | -------------------------------------------------------------------------------- /src/service/app/chaincode.go: -------------------------------------------------------------------------------- 1 | package app 2 | 3 | import ( 4 | "devplat/src/config" 5 | "devplat/src/log" 6 | "io/ioutil" 7 | "os" 8 | ) 9 | 10 | type ChaincodeInfo struct { 11 | Name string `json:"name"` 12 | Version string `json:"version"` 13 | } 14 | 15 | type ChaincodeProvider struct { 16 | status bool 17 | uninstallChaincodes []string 18 | installedChaincodes []ChaincodeInfo 19 | instantiatedChaincodes []string 20 | } 21 | 22 | var ( 23 | chaincodeProvider *ChaincodeProvider 24 | ) 25 | 26 | func InitChaincodeProvider() { 27 | chaincodeProvider = &ChaincodeProvider{ 28 | uninstallChaincodes: make([]string, 0), 29 | installedChaincodes: make([]ChaincodeInfo, 0), 30 | instantiatedChaincodes: make([]string, 0), 31 | } 32 | } 33 | 34 | func findAllChaincodeDir() (subDirs []string, err error) { 35 | var dir = config.WorkPath + "/deploy/chaincode/" 36 | var fileInfo []os.FileInfo 37 | fileInfo, err = ioutil.ReadDir(dir) 38 | if err != nil { 39 | return 40 | } 41 | for _, f := range fileInfo { 42 | if f.IsDir() { 43 | if f.Name()[0] != '.' { 44 | subDirs = append(subDirs, f.Name()) 45 | } 46 | } 47 | } 48 | return 49 | } 50 | 51 | func GetChaincodeProvider() *ChaincodeProvider { 52 | return chaincodeProvider 53 | } 54 | 55 | func (provider *ChaincodeProvider) Start() { 56 | provider.status = true 57 | } 58 | 59 | func (provider *ChaincodeProvider) GetUninstallChaincode() []string { 60 | if !provider.status { 61 | return nil 62 | } 63 | var installedChaincodeMap = make(map[string]struct{}) 64 | var instantiatedChaincodeMap = make(map[string]struct{}) 65 | for _, cc := range provider.installedChaincodes { 66 | installedChaincodeMap[cc.Name] = struct{}{} 67 | } 68 | for _, ccName := range provider.instantiatedChaincodes { 69 | instantiatedChaincodeMap[ccName] = struct{}{} 70 | } 71 | allChaincodes, err := findAllChaincodeDir() 72 | if err != nil { 73 | log.Logger.Error(err.Error()) 74 | return provider.uninstallChaincodes 75 | } 76 | provider.uninstallChaincodes = make([]string, 0) 77 | for _, cc := range allChaincodes { 78 | if _, exist := installedChaincodeMap[cc]; exist { 79 | continue 80 | } 81 | if _, exist := instantiatedChaincodeMap[cc]; exist { 82 | continue 83 | } 84 | provider.uninstallChaincodes = append(provider.uninstallChaincodes, cc) 85 | } 86 | return provider.uninstallChaincodes 87 | } 88 | 89 | func (provider *ChaincodeProvider) ChaincodeInstallFeedback(chaincode ChaincodeInfo) { 90 | var uninstallChaincodes = make([]string, 0) 91 | for _, ccName := range provider.uninstallChaincodes { 92 | if ccName == chaincode.Name { 93 | provider.installedChaincodes = append(provider.installedChaincodes, chaincode) 94 | continue 95 | } 96 | uninstallChaincodes = append(uninstallChaincodes, ccName) 97 | } 98 | provider.uninstallChaincodes = uninstallChaincodes 99 | } 100 | 101 | func (provider *ChaincodeProvider) JudgeChaincodeInstalled(chaincode ChaincodeInfo) bool { 102 | for _, cc := range provider.installedChaincodes { 103 | if cc.Name == chaincode.Name && cc.Version == chaincode.Version { 104 | return true 105 | } 106 | } 107 | return false 108 | } 109 | 110 | func (provider *ChaincodeProvider) GetInstantiatedChaincode() []string { 111 | if !provider.status { 112 | return nil 113 | } 114 | return provider.instantiatedChaincodes 115 | } 116 | 117 | func (provider *ChaincodeProvider) ChaincodeInstantiateFeedback(chaincode ChaincodeInfo) { 118 | var installedChaincodes = make([]ChaincodeInfo, 0) 119 | for _, cc := range provider.installedChaincodes { 120 | if cc.Name == chaincode.Name && cc.Version == chaincode.Version { 121 | provider.instantiatedChaincodes = append(provider.instantiatedChaincodes, cc.Name) 122 | continue 123 | } 124 | installedChaincodes = append(installedChaincodes, cc) 125 | } 126 | provider.installedChaincodes = installedChaincodes 127 | } 128 | 129 | func (provider *ChaincodeProvider) JudgeChaincodeInstantiate(chaincodeName string) bool { 130 | for _, ccName := range provider.instantiatedChaincodes { 131 | if ccName == chaincodeName { 132 | return true 133 | } 134 | } 135 | return false 136 | } 137 | 138 | func (provider *ChaincodeProvider) GetInstalledChaincodes() []ChaincodeInfo { 139 | if !provider.status { 140 | return nil 141 | } 142 | return provider.installedChaincodes 143 | } 144 | 145 | func (provider *ChaincodeProvider) Clean() { 146 | provider.status = false 147 | provider.uninstallChaincodes = make([]string, 0) 148 | provider.installedChaincodes = make([]ChaincodeInfo, 0) 149 | provider.instantiatedChaincodes = make([]string, 0) 150 | } 151 | -------------------------------------------------------------------------------- /src/service/app/chaincode_test.go: -------------------------------------------------------------------------------- 1 | package app 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func TestFindUninstallChaincode(t *testing.T) { 9 | dirs, err := findAllChaincodeDir() 10 | fmt.Println(dirs, err) 11 | } 12 | -------------------------------------------------------------------------------- /src/service/app/channel.go: -------------------------------------------------------------------------------- 1 | package app 2 | 3 | import ( 4 | "devplat/src/config" 5 | "devplat/src/log" 6 | "github.com/hyperledger/fabric-protos-go/peer" 7 | "github.com/hyperledger/fabric-sdk-go/pkg/client/resmgmt" 8 | ) 9 | 10 | func GetChannels() (channels []string, err error) { 11 | var response *peer.ChannelQueryResponse 12 | var opts []resmgmt.RequestOption 13 | opts = append(opts, resmgmt.WithTargetEndpoints(config.Config.Peers[0])) 14 | response, err = GetClient().resmgmtClient.QueryChannels(opts...) 15 | if err != nil { 16 | log.Logger.Error(err.Error()) 17 | return 18 | } 19 | for _, c := range response.Channels { 20 | channels = append(channels, c.ChannelId) 21 | } 22 | return 23 | } 24 | -------------------------------------------------------------------------------- /src/service/app/invoke.go: -------------------------------------------------------------------------------- 1 | package app 2 | 3 | import ( 4 | Config "devplat/src/config" 5 | "devplat/src/log" 6 | "github.com/hyperledger/fabric-sdk-go/pkg/client/channel" 7 | "github.com/hyperledger/fabric-sdk-go/pkg/client/resmgmt" 8 | "github.com/hyperledger/fabric-sdk-go/pkg/core/config" 9 | "github.com/hyperledger/fabric-sdk-go/pkg/fabsdk" 10 | "github.com/pkg/errors" 11 | "go.uber.org/zap" 12 | ) 13 | 14 | type ChaincodeInvokeProvider struct { 15 | Peers []string 16 | Orders []string 17 | } 18 | 19 | var ccip *ChaincodeInvokeProvider 20 | 21 | func init() { 22 | ccip = NewChaincodeInvokeProvider() 23 | go ccip.Start() 24 | cfg := Config.Config 25 | cli = getClient(cfg.SdkCfgPath, cfg.OrgName, cfg.UserName) 26 | } 27 | 28 | func NewChaincodeInvokeProvider() *ChaincodeInvokeProvider { 29 | return &ChaincodeInvokeProvider{} 30 | } 31 | 32 | func (ccip *ChaincodeInvokeProvider) Start() { 33 | ccip.Peers = Config.Config.Peers 34 | ccip.Orders = Config.Config.Orderer 35 | } 36 | 37 | /* 38 | Invoke或Query方法调用链码 39 | */ 40 | func invokeOrQueryCC(invoke bool, channelID, chaincode, functionName string, args [][]byte) (payload []byte, err error) { 41 | if len(ccip.Peers) == 0 { 42 | err = errors.New("no peer to invoke") 43 | log.Logger.Error(err.Error()) 44 | return nil, err 45 | } 46 | req := &channel.Request{ 47 | ChaincodeID: chaincode, 48 | Fcn: functionName, 49 | Args: args, 50 | TransientMap: Config.TransientMap, 51 | } 52 | cfg := Config.Config 53 | var resp channel.Response 54 | resp, err = invokeChainCode(req, ccip.Peers, ccip.Orders, channelID, 55 | cfg.SdkCfgPath, cfg.OrgName, cfg.UserName, invoke) 56 | return resp.Payload, err 57 | } 58 | 59 | /* 60 | Query方式调用链码 61 | */ 62 | func QueryCCRequest(channelID, chaincode, functionName string, args [][]byte) (payload []byte, err error) { 63 | return invokeOrQueryCC(false, channelID, chaincode, functionName, args) 64 | } 65 | 66 | /* 67 | Invoke方式调用链码 68 | */ 69 | func InvokeCCRequest(channelID, chaincode, functionName string, args [][]byte) (payload []byte, err error) { 70 | return invokeOrQueryCC(true, channelID, chaincode, functionName, args) 71 | } 72 | 73 | var cli *client 74 | 75 | type client struct { 76 | SDK *fabsdk.FabricSDK 77 | ChannelClients map[string]*channel.Client 78 | resmgmtClient *resmgmt.Client 79 | orgName string 80 | userName string 81 | } 82 | 83 | func GetClient() *client { 84 | return cli 85 | } 86 | 87 | func invokeChainCode(req *channel.Request, peerEndpoints, ordererEndpoint []string, channelID, sdkCfg, orgName, userName string, invoke bool) (channel.Response, error) { 88 | cli = getClient(sdkCfg, orgName, userName) 89 | if cli == nil { 90 | return channel.Response{}, errors.New("can not get controller client") 91 | } 92 | 93 | return cli.invokeChainCode(channelID, peerEndpoints, ordererEndpoint, req, invoke) 94 | } 95 | 96 | /* 97 | 获取客户端 98 | */ 99 | func getClient(sdkCfg, orgName, userName string) *client { 100 | if cli != nil { 101 | return cli 102 | } 103 | 104 | var ( 105 | err error 106 | sdk *fabsdk.FabricSDK 107 | resmgmtClient *resmgmt.Client 108 | ) 109 | 110 | if sdk, err = fabsdk.New(config.FromFile(sdkCfg)); err != nil { 111 | log.Logger.Error("create fabric sdk from file failed", 112 | zap.String("config file", sdkCfg), zap.Error(err)) 113 | return nil 114 | } 115 | 116 | rcp := sdk.Context(fabsdk.WithOrg(orgName), fabsdk.WithUser(userName)) 117 | if resmgmtClient, err = resmgmt.New(rcp); err != nil { 118 | log.Logger.Error("create resource management client failed", 119 | zap.String("org", orgName), zap.String("user", userName), 120 | zap.Error(err)) 121 | return nil 122 | } 123 | 124 | cli = &client{ 125 | SDK: sdk, 126 | ChannelClients: make(map[string]*channel.Client), 127 | resmgmtClient: resmgmtClient, 128 | orgName: orgName, 129 | userName: userName, 130 | } 131 | return cli 132 | } 133 | 134 | /* 135 | 获取具体的channel客户端 136 | */ 137 | func (c *client) getChannelClient(channelID string) (*channel.Client, error) { 138 | if cc, ok := c.ChannelClients[channelID]; ok { 139 | return cc, nil 140 | } 141 | var ( 142 | err error 143 | cc *channel.Client 144 | ) 145 | 146 | ccp := c.SDK.ChannelContext(channelID, fabsdk.WithUser(c.userName)) 147 | if cc, err = channel.New(ccp); err != nil { 148 | return nil, errors.WithMessage(err, "failed to create channel client") 149 | } 150 | c.ChannelClients[channelID] = cc 151 | 152 | return cc, nil 153 | } 154 | 155 | /* 156 | 调用链码 157 | */ 158 | func (c *client) invokeChainCode(channelID string, peerEndpoints, ordererEndpoints []string, req *channel.Request, invoke bool) (channel.Response, error) { 159 | var ( 160 | ccli *channel.Client 161 | err error 162 | ) 163 | 164 | if ccli, err = c.getChannelClient(channelID); err != nil { 165 | return channel.Response{}, errors.WithMessage(err, "invoke chaincode") 166 | } 167 | var opts []channel.RequestOption 168 | if peerEndpoints != nil { 169 | opts = append(opts, channel.WithTargetEndpoints(peerEndpoints...)) 170 | } 171 | //for _, orderer := range ordererEndpoints { 172 | // opts = append(opts, channel.WithOrdererEndpoint(orderer)) 173 | //} 174 | if invoke { 175 | return ccli.Execute(*req, opts...) 176 | } 177 | return ccli.Query(*req, opts...) 178 | } 179 | -------------------------------------------------------------------------------- /src/service/controller.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | "devplat/src/service/docker" 5 | "sort" 6 | ) 7 | 8 | var controller *DevPlatController 9 | 10 | type DevPlatController struct { 11 | dockerManager *docker.DockerManager 12 | containers map[string]docker.ContainerManagerInterface 13 | status bool 14 | } 15 | 16 | func InitDevPlatController() { 17 | controller = &DevPlatController{ 18 | dockerManager: docker.InitDockerManager(), 19 | containers: make(map[string]docker.ContainerManagerInterface), 20 | } 21 | } 22 | 23 | func GetDevPlatController() *DevPlatController { 24 | return controller 25 | } 26 | 27 | func GetDockerManager() *docker.DockerManager { 28 | return controller.dockerManager 29 | } 30 | 31 | /* 32 | 开启环境 33 | */ 34 | func (controller *DevPlatController) Setup() { 35 | if controller.status { 36 | return 37 | } 38 | controller.dockerManager.SetupDockerManager() 39 | dockerManager := controller.dockerManager 40 | controller.containers[dockerManager.ChaincodeManager.GetStatus().ContainerName] = dockerManager.ChaincodeManager 41 | controller.containers[dockerManager.CliManager.GetStatus().ContainerName] = dockerManager.CliManager 42 | controller.containers[dockerManager.PeerManager.GetStatus().ContainerName] = dockerManager.PeerManager 43 | controller.containers[dockerManager.OrdererManager.GetStatus().ContainerName] = dockerManager.OrdererManager 44 | controller.containers[dockerManager.CouchDBManager.GetStatus().ContainerName] = dockerManager.CouchDBManager 45 | controller.status = true 46 | } 47 | 48 | /* 49 | 检测容器运行情况 50 | */ 51 | func (controller *DevPlatController) checkHealthy() { 52 | controller.dockerManager.CheckHealthy() 53 | } 54 | 55 | /* 56 | 查看容器 57 | */ 58 | func (controller *DevPlatController) GetContainers() (status bool, containers []docker.ContainerManager) { 59 | containers = make([]docker.ContainerManager, 0) 60 | status = controller.status 61 | if !status { 62 | return 63 | } 64 | controller.checkHealthy() 65 | for _, manager := range controller.containers { 66 | containers = append(containers, manager.GetStatus()) 67 | } 68 | sort.Sort(docker.Managers(containers)) 69 | return 70 | } 71 | 72 | // 73 | ///* 74 | // 重启容器 75 | //*/ 76 | //func (controller *DevPlatController) RestartContainer(containerID string) { 77 | // controller.containers[containerID].Restart() 78 | // newContainer := controller.containers[containerID] 79 | // newContainerID := newContainer.GetStatus().ContainerID 80 | // controller.containers[newContainerID] = newContainer 81 | // delete(controller.containers, containerID) 82 | //} 83 | 84 | /* 85 | 清除环境 86 | */ 87 | func (controller *DevPlatController) Clean() { 88 | if controller.status { 89 | controller.dockerManager.CleanDockerManager() 90 | controller.containers = make(map[string]docker.ContainerManagerInterface) 91 | controller.status = false 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/service/docker/chaincode.go: -------------------------------------------------------------------------------- 1 | package docker 2 | 3 | import ( 4 | "devplat/src/config" 5 | "devplat/src/log" 6 | "fmt" 7 | ) 8 | 9 | type ChaincodeManager ContainerManager 10 | 11 | var chaincodeManager *ChaincodeManager 12 | 13 | func initChaincodeManager() { 14 | var conatainerName = chaincodeName 15 | chaincodeManager = &ChaincodeManager{ 16 | Env: []string{ 17 | "GOPATH=/opt/gopath", 18 | "CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock", 19 | "FABRIC_LOGGING_SPEC=DEBUG", 20 | "CORE_PEER_ID=example_cc", 21 | fmt.Sprintf("CORE_PEER_ADDRESS=%s:7051", peerName), 22 | "CORE_PEER_LOCALMSPID=DEFAULT", 23 | "CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/msp", 24 | }, 25 | Cmd: []string{"/bin/bash", "-c", "sleep 6000000"}, 26 | Image: "hyperledger/fabric-tools:latest", 27 | WorkingDir: "/opt/gopath/src/chaincode", 28 | ContainerName: conatainerName, 29 | Volumes: []string{ 30 | config.WorkPath + "/deploy/msp:/etc/hyperledger/msp", 31 | "/var/run:/host/var/run", 32 | config.WorkPath + "/deploy/chaincode:/opt/gopath/src/chaincode", 33 | }, 34 | Ports: map[string][]Port{}, 35 | } 36 | } 37 | 38 | func (manager *ChaincodeManager) AddConfig() bool { 39 | return (*ContainerManager)(manager).AddConfig() 40 | } 41 | 42 | func (manager *ChaincodeManager) Run() bool { 43 | log.Logger.Info("chaincode container start to create") 44 | return (*ContainerManager)(manager).Run() 45 | } 46 | 47 | func (manager *ChaincodeManager) Restart() (ok bool) { 48 | return (*ContainerManager)(manager).Restart() 49 | } 50 | 51 | func (manager *ChaincodeManager) StopAndRemove() (ok bool) { 52 | log.Logger.Info("chaincode container start to stop and remove") 53 | return (*ContainerManager)(manager).StopAndRemove() 54 | } 55 | 56 | func (manager *ChaincodeManager) Stop() (ok bool) { 57 | return (*ContainerManager)(manager).Stop() 58 | } 59 | 60 | func (manager *ChaincodeManager) Remove() (ok bool) { 61 | return (*ContainerManager)(manager).Remove() 62 | } 63 | 64 | func (manager *ChaincodeManager) Exec(cmd []string) (content string, ok bool) { 65 | return (*ContainerManager)(manager).Exec(cmd) 66 | } 67 | 68 | func (manager *ChaincodeManager) GetStatus() ContainerManager { 69 | return (ContainerManager)(*manager) 70 | } 71 | -------------------------------------------------------------------------------- /src/service/docker/cli.go: -------------------------------------------------------------------------------- 1 | package docker 2 | 3 | import ( 4 | "devplat/src/config" 5 | "devplat/src/log" 6 | "fmt" 7 | ) 8 | 9 | type CliManager ContainerManager 10 | 11 | var cliManager *CliManager 12 | 13 | func initCliManager() { 14 | var conatainerName = cliName 15 | cliManager = &CliManager{ 16 | Env: []string{ 17 | "GOPATH=/opt/gopath", 18 | "CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock", 19 | "FABRIC_LOGGING_SPEC=DEBUG", 20 | "CORE_PEER_ID=cli", 21 | fmt.Sprintf("CORE_PEER_ADDRESS=%s:7051", peerName), 22 | "CORE_PEER_LOCALMSPID=DEFAULT", 23 | "CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/msp", 24 | }, 25 | Cmd: []string{"/bin/bash", "-c", "./script.sh"}, 26 | Image: "hyperledger/fabric-tools:latest", 27 | WorkingDir: "/opt/deploy", 28 | ContainerName: conatainerName, 29 | Volumes: []string{ 30 | config.WorkPath + "/deploy/msp:/etc/hyperledger/msp", 31 | "/var/run:/host/var/run", 32 | config.WorkPath + "/deploy/chaincode:/opt/gopath/src/", 33 | config.WorkPath + "/deploy:/opt/deploy", 34 | }, 35 | Ports: map[string][]Port{}, 36 | } 37 | } 38 | 39 | func (manager *CliManager) AddConfig() bool { 40 | return (*ContainerManager)(manager).AddConfig() 41 | } 42 | 43 | func (manager *CliManager) Run() bool { 44 | log.Logger.Info("cli container start to create") 45 | return (*ContainerManager)(manager).Run() 46 | } 47 | 48 | func (manager *CliManager) Restart() (ok bool) { 49 | return (*ContainerManager)(manager).Restart() 50 | } 51 | 52 | func (manager *CliManager) StopAndRemove() (ok bool) { 53 | log.Logger.Info("cli container start to stop and remove") 54 | return (*ContainerManager)(manager).StopAndRemove() 55 | } 56 | 57 | func (manager *CliManager) Stop() (ok bool) { 58 | return (*ContainerManager)(manager).Stop() 59 | } 60 | 61 | func (manager *CliManager) Remove() (ok bool) { 62 | return (*ContainerManager)(manager).Remove() 63 | } 64 | 65 | func (manager *CliManager) Exec(cmd []string) (content string, ok bool) { 66 | return (*ContainerManager)(manager).Exec(cmd) 67 | } 68 | 69 | func (manager *CliManager) GetStatus() ContainerManager { 70 | return (ContainerManager)(*manager) 71 | } 72 | -------------------------------------------------------------------------------- /src/service/docker/container.go: -------------------------------------------------------------------------------- 1 | package docker 2 | 3 | import ( 4 | "devplat/src/log" 5 | "github.com/docker/docker/api/types/container" 6 | "github.com/docker/docker/api/types/network" 7 | "github.com/docker/go-connections/nat" 8 | ) 9 | 10 | type Port struct { 11 | IP string `json:"ip"` 12 | Port string `json:"port"` 13 | } 14 | 15 | type ContainerManagerInterface interface { 16 | //给容器添加参数 17 | AddConfig() bool 18 | //运行容器 19 | Run() bool 20 | //重启容器 21 | Restart() bool 22 | //删除并停止容器 23 | StopAndRemove() bool 24 | //停止容器运行 25 | Stop() bool 26 | //删除容器 27 | Remove() bool 28 | //容器命令执行 29 | Exec(cmd []string) (content string, ok bool) 30 | //查看容器信息 31 | GetStatus() ContainerManager 32 | } 33 | 34 | type ContainerManager struct { 35 | ID string `json:"id"` 36 | Image string `json:"image"` 37 | ContainerID string `json:"container_id"` 38 | ContainerName string `json:"container_name"` 39 | Env []string `json:"-"` 40 | Cmd []string `json:"-"` 41 | Volumes []string `json:"volumes"` 42 | WorkingDir string `json:"working_dir"` 43 | Ports map[string][]Port `json:"ports"` 44 | Healthy bool `json:"healthy"` 45 | config *container.Config 46 | hostConfig *container.HostConfig 47 | networkConfig *network.NetworkingConfig 48 | } 49 | 50 | type Managers []ContainerManager 51 | 52 | func (managers Managers) Len() int { 53 | return len(managers) 54 | } 55 | 56 | func (managers Managers) Swap(i, j int) { 57 | managers[i], managers[j] = managers[j], managers[i] 58 | } 59 | 60 | func (managers Managers) Less(i, j int) bool { 61 | return managers[i].ContainerName < managers[j].ContainerName 62 | } 63 | 64 | func (manager *ContainerManager) Less(i, j int) { 65 | 66 | } 67 | 68 | /* 69 | 添加参数 70 | */ 71 | func (manager *ContainerManager) AddConfig() (ok bool) { 72 | var cfg = &container.Config{ 73 | Image: manager.Image, 74 | Env: manager.Env, 75 | ExposedPorts: make(map[nat.Port]struct{}), 76 | WorkingDir: manager.WorkingDir, 77 | Tty: true, 78 | Cmd: manager.Cmd, 79 | } 80 | var hostConfig = &container.HostConfig{ 81 | RestartPolicy: container.RestartPolicy{ 82 | Name: "always", 83 | }, 84 | Binds: manager.Volumes, 85 | PortBindings: make(map[nat.Port][]nat.PortBinding), 86 | Privileged: true, 87 | } 88 | for extenral, exports := range manager.Ports { 89 | port, err := nat.NewPort("tcp", extenral) 90 | if err != nil { 91 | log.Logger.Error(err.Error()) 92 | return false 93 | } 94 | cfg.ExposedPorts[port] = struct{}{} 95 | var portBindings = make([]nat.PortBinding, 0) 96 | for _, export := range exports { 97 | portBindings = append(portBindings, nat.PortBinding{ 98 | HostIP: export.IP, 99 | HostPort: export.Port, 100 | }) 101 | } 102 | hostConfig.PortBindings[port] = portBindings 103 | } 104 | var networkConfig = &network.NetworkingConfig{ 105 | EndpointsConfig: dm.network, 106 | } 107 | 108 | manager.config = cfg 109 | manager.hostConfig = hostConfig 110 | manager.networkConfig = networkConfig 111 | return true 112 | } 113 | 114 | func (manager *ContainerManager) PullImage() bool { 115 | return true 116 | } 117 | 118 | func (manager *ContainerManager) Run() bool { 119 | if manager.AddConfig() { 120 | containerID, ok := dm.RunContainer(manager.config, manager.hostConfig, manager.networkConfig, manager.ContainerName) 121 | manager.ContainerID = containerID 122 | return ok 123 | } 124 | return false 125 | } 126 | 127 | func (manager *ContainerManager) Restart() (ok bool) { 128 | if manager.StopAndRemove() { 129 | return manager.Run() 130 | } 131 | return false 132 | } 133 | 134 | func (manager *ContainerManager) StopAndRemove() (ok bool) { 135 | if dm.StopContainer(manager.ContainerID) { 136 | return dm.RemoveContainer(manager.ContainerID) 137 | } 138 | return false 139 | } 140 | 141 | func (manager *ContainerManager) Stop() (ok bool) { 142 | return dm.StopContainer(manager.ContainerID) 143 | } 144 | 145 | func (manager *ContainerManager) Remove() (ok bool) { 146 | return dm.RemoveContainer(manager.ContainerID) 147 | } 148 | 149 | func (manager *ContainerManager) Exec(cmd []string) (content string, ok bool) { 150 | return dm.Exec(cmd, manager.ContainerID) 151 | } 152 | 153 | func (manager *ContainerManager) GetStatus() ContainerManager { 154 | return *manager 155 | } 156 | -------------------------------------------------------------------------------- /src/service/docker/couchdb.go: -------------------------------------------------------------------------------- 1 | package docker 2 | 3 | import "devplat/src/log" 4 | 5 | type CouchDBManager ContainerManager 6 | 7 | var couchDBManager *CouchDBManager 8 | 9 | func initCouchDBManager() { 10 | var containerName = couchdbName 11 | couchDBManager = &CouchDBManager{ 12 | Env: []string{}, 13 | ContainerName: containerName, 14 | Image: "hyperledger/fabric-couchdb:latest", 15 | Ports: map[string][]Port{ 16 | "5984": { 17 | { 18 | IP: "0.0.0.0", 19 | Port: "5984", 20 | }, 21 | }, 22 | }, 23 | } 24 | } 25 | 26 | func (manager *CouchDBManager) AddConfig() bool { 27 | return (*ContainerManager)(manager).AddConfig() 28 | } 29 | 30 | func (manager *CouchDBManager) Run() bool { 31 | log.Logger.Info("couchdb container start to create") 32 | return (*ContainerManager)(manager).Run() 33 | } 34 | 35 | func (manager *CouchDBManager) Restart() (ok bool) { 36 | return (*ContainerManager)(manager).Restart() 37 | } 38 | 39 | func (manager *CouchDBManager) StopAndRemove() (ok bool) { 40 | log.Logger.Info("couchdb container start to stop and remove") 41 | return (*ContainerManager)(manager).StopAndRemove() 42 | } 43 | 44 | func (manager *CouchDBManager) Stop() (ok bool) { 45 | return (*ContainerManager)(manager).Stop() 46 | } 47 | 48 | func (manager *CouchDBManager) Remove() (ok bool) { 49 | return (*ContainerManager)(manager).Remove() 50 | } 51 | 52 | func (manager *CouchDBManager) Exec(cmd []string) (content string, ok bool) { 53 | return (*ContainerManager)(manager).Exec(cmd) 54 | } 55 | 56 | func (manager *CouchDBManager) GetStatus() ContainerManager { 57 | return (ContainerManager)(*manager) 58 | } 59 | -------------------------------------------------------------------------------- /src/service/docker/docker.go: -------------------------------------------------------------------------------- 1 | package docker 2 | 3 | import ( 4 | "context" 5 | "devplat/src/config" 6 | "devplat/src/log" 7 | "fmt" 8 | "github.com/docker/docker/api/types" 9 | "github.com/docker/docker/api/types/container" 10 | "github.com/docker/docker/api/types/network" 11 | "github.com/docker/docker/client" 12 | "io" 13 | "net" 14 | "strings" 15 | "time" 16 | ) 17 | 18 | const ( 19 | networkName = "chaincode-docker-devmode-default" 20 | 21 | peerName = "peer" 22 | ordererName = "orderer" 23 | couchdbName = "couchdb" 24 | cliName = "cli" 25 | chaincodeName = "chaincode" 26 | ) 27 | 28 | type DockerManager struct { 29 | cli *client.Client 30 | ctx context.Context 31 | CouchDBManager *CouchDBManager 32 | OrdererManager *OrdererManager 33 | PeerManager *PeerManager 34 | CliManager *CliManager 35 | ChaincodeManager *ChaincodeManager 36 | ip string 37 | network map[string]*network.EndpointSettings 38 | timeout time.Duration 39 | dockerRunIntervals time.Duration 40 | } 41 | 42 | var dm *DockerManager 43 | 44 | func InitDockerManager() *DockerManager { 45 | initCouchDBManager() 46 | initOrdererManager() 47 | initPeerManager() 48 | initCliManager() 49 | initChaincodeManager() 50 | cli, err := client.NewEnvClient() 51 | if err != nil { 52 | panic(err) 53 | } 54 | config.IP, _ = getIp() 55 | var timeout = time.Second * 10 56 | dm = &DockerManager{ 57 | cli: cli, 58 | ctx: context.Background(), 59 | ip: config.IP, 60 | CouchDBManager: couchDBManager, 61 | OrdererManager: ordererManager, 62 | PeerManager: peerManager, 63 | CliManager: cliManager, 64 | ChaincodeManager: chaincodeManager, 65 | network: make(map[string]*network.EndpointSettings), 66 | timeout: timeout, 67 | dockerRunIntervals: 2 * time.Second, 68 | } 69 | 70 | dm.getImageID() 71 | return dm 72 | } 73 | 74 | func (dm *DockerManager) ImageInsure(imageIDMap map[string]string) { 75 | if _, exist := imageIDMap[dm.CouchDBManager.Image]; !exist { 76 | dm.PullImage(dm.CouchDBManager.Image) 77 | } 78 | if _, exist := imageIDMap[dm.OrdererManager.Image]; !exist { 79 | dm.PullImage(dm.OrdererManager.Image) 80 | } 81 | if _, exist := imageIDMap[dm.PeerManager.Image]; !exist { 82 | dm.PullImage(dm.PeerManager.Image) 83 | } 84 | if _, exist := imageIDMap[dm.CliManager.Image]; !exist { 85 | dm.PullImage(dm.CliManager.Image) 86 | } 87 | if _, exist := imageIDMap[dm.ChaincodeManager.Image]; !exist { 88 | dm.PullImage(dm.ChaincodeManager.Image) 89 | } 90 | } 91 | 92 | func (dm *DockerManager) getImageID() { 93 | images, err := dm.ListImages() 94 | if err != nil { 95 | log.Logger.Error(err.Error()) 96 | return 97 | } 98 | imageIDMap := make(map[string]string) 99 | for _, image := range images { 100 | for _, repoTag := range image.RepoTags { 101 | imageIDMap[repoTag] = strings.Split(image.ID, ":")[1] 102 | } 103 | } 104 | dm.ImageInsure(imageIDMap) 105 | dm.CouchDBManager.ID = imageIDMap[dm.CouchDBManager.Image] 106 | dm.OrdererManager.ID = imageIDMap[dm.OrdererManager.Image] 107 | dm.PeerManager.ID = imageIDMap[dm.PeerManager.Image] 108 | dm.CliManager.ID = imageIDMap[dm.CliManager.Image] 109 | dm.ChaincodeManager.ID = imageIDMap[dm.ChaincodeManager.Image] 110 | } 111 | 112 | func (dm *DockerManager) SetupDockerManager() { 113 | log.Logger.Info("start to setup fabric dev environment") 114 | initNetwork() 115 | 116 | if ok := dm.CouchDBManager.Run(); !ok { 117 | log.Logger.Warn("couchdb container create failed") 118 | } else { 119 | log.Logger.Info("couchdb container create success") 120 | } 121 | time.Sleep(dm.dockerRunIntervals) 122 | 123 | if ok := dm.OrdererManager.Run(); !ok { 124 | log.Logger.Warn("orderer container create failed") 125 | } else { 126 | log.Logger.Info("orderer container create success") 127 | } 128 | time.Sleep(dm.dockerRunIntervals) 129 | 130 | if ok := dm.PeerManager.Run(); !ok { 131 | log.Logger.Warn("peer container create failed") 132 | } else { 133 | log.Logger.Info("peer container create success") 134 | } 135 | time.Sleep(dm.dockerRunIntervals) 136 | 137 | if ok := dm.CliManager.Run(); !ok { 138 | log.Logger.Warn("cli container create failed") 139 | } else { 140 | log.Logger.Info("cli container create success") 141 | } 142 | time.Sleep(dm.dockerRunIntervals) 143 | 144 | if ok := dm.ChaincodeManager.Run(); !ok { 145 | log.Logger.Warn("chaincode container create failed") 146 | } else { 147 | log.Logger.Info("chaincode container create success") 148 | } 149 | } 150 | 151 | func (dm *DockerManager) CleanDockerManager() { 152 | log.Logger.Info("start to clean fabric dev environment") 153 | if ok := dm.ChaincodeManager.StopAndRemove(); !ok { 154 | log.Logger.Warn("chaincode container stop and remove failed") 155 | } else { 156 | log.Logger.Info("chaincode container stop and remove success") 157 | } 158 | 159 | if ok := dm.CliManager.StopAndRemove(); !ok { 160 | log.Logger.Warn("cli container stop and remove failed") 161 | } else { 162 | log.Logger.Info("cli container stop and remove success") 163 | } 164 | 165 | if ok := dm.PeerManager.StopAndRemove(); !ok { 166 | log.Logger.Warn("peer container stop and remove failed") 167 | } else { 168 | log.Logger.Info("peer container stop and remove success") 169 | } 170 | 171 | if ok := dm.OrdererManager.StopAndRemove(); !ok { 172 | log.Logger.Warn("orderer container stop and remove failed") 173 | } else { 174 | log.Logger.Info("orderer container stop and remove success") 175 | } 176 | 177 | if ok := dm.CouchDBManager.StopAndRemove(); !ok { 178 | log.Logger.Warn("couchdb container stop and remove failed") 179 | } else { 180 | log.Logger.Info("couchdb container stop and remove success") 181 | } 182 | dm.deleteNetwork() 183 | } 184 | 185 | func (dm *DockerManager) CheckHealthy() { 186 | containers, err := dm.ListContainer() 187 | if err != nil { 188 | log.Logger.Error(err.Error()) 189 | return 190 | } 191 | var containerMap = make(map[string]struct{}) 192 | for _, c := range containers { 193 | containerMap[c.ID] = struct{}{} 194 | } 195 | _, dm.CouchDBManager.Healthy = containerMap[dm.CouchDBManager.ContainerID] 196 | _, dm.PeerManager.Healthy = containerMap[dm.PeerManager.ContainerID] 197 | _, dm.OrdererManager.Healthy = containerMap[dm.OrdererManager.ContainerID] 198 | _, dm.CliManager.Healthy = containerMap[dm.CliManager.ContainerID] 199 | _, dm.ChaincodeManager.Healthy = containerMap[dm.ChaincodeManager.ContainerID] 200 | } 201 | 202 | func (dm *DockerManager) deleteNetwork() (ok bool) { 203 | networkID := dm.network[networkName].NetworkID 204 | if err := dm.DeleteNetwork(networkID); err != nil { 205 | log.Logger.Error(err.Error()) 206 | return false 207 | } 208 | delete(dm.network, networkName) 209 | return true 210 | } 211 | 212 | func initNetwork() { 213 | log.Logger.Info("start to init network") 214 | networks, err := dm.ListNetwork() 215 | if err != nil { 216 | log.Logger.Error(err.Error()) 217 | return 218 | } 219 | for _, nw := range networks { 220 | if nw.Name == networkName { 221 | dm.network[networkName] = &network.EndpointSettings{ 222 | NetworkID: nw.ID, 223 | } 224 | return 225 | } 226 | } 227 | dm.CreateNetwork(networkName) 228 | log.Logger.Info(fmt.Sprintf("network %v created success", networkName)) 229 | } 230 | 231 | func getIp() (ip string, err error) { 232 | addrs, err := net.InterfaceAddrs() 233 | if err != nil { 234 | log.Logger.Error(err.Error()) 235 | return 236 | } 237 | for _, address := range addrs { 238 | // 检查ip地址判断是否回环地址 239 | if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() { 240 | if ipnet.IP.To4() != nil { 241 | ip = ipnet.IP.String() 242 | } 243 | } 244 | } 245 | return 246 | } 247 | 248 | func (dm *DockerManager) ClientVersion() string { 249 | return dm.cli.ClientVersion() 250 | } 251 | 252 | func (dm *DockerManager) CreateNetwork(name string) { 253 | resp, err := dm.cli.NetworkCreate(dm.ctx, name, types.NetworkCreate{}) 254 | if err != nil { 255 | log.Logger.Error(err.Error()) 256 | return 257 | } 258 | dm.network[name] = &network.EndpointSettings{ 259 | NetworkID: resp.ID, 260 | } 261 | } 262 | 263 | func (dm *DockerManager) DeleteNetwork(networkID string) error { 264 | return dm.cli.NetworkRemove(dm.ctx, networkID) 265 | } 266 | 267 | func (dm *DockerManager) ListNetwork() (networks []types.NetworkResource, err error) { 268 | return dm.cli.NetworkList(dm.ctx, types.NetworkListOptions{}) 269 | } 270 | 271 | func (dm *DockerManager) PullImage(imageName string) { 272 | dm.cli.ImagePull(dm.ctx, imageName, types.ImagePullOptions{}) 273 | } 274 | 275 | func (dm *DockerManager) ListImages() ([]types.ImageSummary, error) { 276 | return dm.cli.ImageList(dm.ctx, types.ImageListOptions{}) 277 | } 278 | 279 | func (dm *DockerManager) ListContainer() (containers []types.Container, err error) { 280 | return dm.cli.ContainerList(dm.ctx, types.ContainerListOptions{}) 281 | } 282 | 283 | func (dm *DockerManager) RunContainer(config *container.Config, hostConfig *container.HostConfig, networkConfig *network.NetworkingConfig, containerName string) (containerID string, ok bool) { 284 | c, err := dm.cli.ContainerCreate(dm.ctx, config, hostConfig, networkConfig, containerName) 285 | if err != nil { 286 | log.Logger.Error(err.Error()) 287 | return 288 | } 289 | if err := dm.cli.ContainerStart(dm.ctx, c.ID, types.ContainerStartOptions{}); err != nil { 290 | log.Logger.Error(err.Error()) 291 | return 292 | } 293 | return c.ID, true 294 | } 295 | 296 | func (dm *DockerManager) StopContainer(containerID string) (ok bool) { 297 | err := dm.cli.ContainerStop(dm.ctx, containerID, &dm.timeout) 298 | if err != nil { 299 | log.Logger.Error(err.Error()) 300 | return false 301 | } 302 | return true 303 | } 304 | 305 | func (dm *DockerManager) RemoveContainer(containerID string) (ok bool) { 306 | err := dm.cli.ContainerRemove(dm.ctx, containerID, types.ContainerRemoveOptions{}) 307 | if err != nil { 308 | log.Logger.Error(err.Error()) 309 | return false 310 | } 311 | return true 312 | } 313 | 314 | func (dm *DockerManager) Exec(cmd []string, containerID string) (content string, ok bool) { 315 | var cfg = types.ExecConfig{ 316 | Privileged: true, 317 | Tty: true, 318 | AttachStdin: true, 319 | AttachStderr: true, 320 | AttachStdout: true, 321 | Cmd: cmd, 322 | } 323 | execID, err := dm.cli.ContainerExecCreate(dm.ctx, containerID, cfg) 324 | if err != nil { 325 | log.Logger.Error(err.Error()) 326 | return 327 | } 328 | res, err := dm.cli.ContainerExecAttach(dm.ctx, execID.ID, types.ExecConfig{}) 329 | if err != nil { 330 | log.Logger.Error(err.Error()) 331 | return 332 | } 333 | err = dm.cli.ContainerExecStart(dm.ctx, execID.ID, types.ExecStartCheck{}) 334 | if err != nil { 335 | log.Logger.Error(err.Error()) 336 | return 337 | } 338 | var slice = make([]string, 0) 339 | for { 340 | line, err := res.Reader.ReadBytes('\n') 341 | if err == io.EOF { 342 | break 343 | } 344 | if err != nil { 345 | log.Logger.Error(err.Error()) 346 | return 347 | } 348 | slice = append(slice, string(line)) 349 | } 350 | return strings.Join(slice, ""), true 351 | } 352 | -------------------------------------------------------------------------------- /src/service/docker/docker_test.go: -------------------------------------------------------------------------------- 1 | package docker 2 | 3 | import ( 4 | "fmt" 5 | "github.com/docker/docker/api/types" 6 | "testing" 7 | ) 8 | 9 | func TestNewDockerManager(t *testing.T) { 10 | //fmt.Println(dm.ClientVersion()) 11 | InitDockerManager() 12 | images, err := dm.ListImages() 13 | if err != nil { 14 | return 15 | } 16 | imageMap := make(map[string]types.ImageSummary) 17 | for _, image := range images { 18 | for _, repoTag := range image.RepoTags { 19 | imageMap[repoTag] = image 20 | } 21 | } 22 | fmt.Println(imageMap) 23 | } 24 | 25 | func TestGetPath(t *testing.T) { 26 | } 27 | -------------------------------------------------------------------------------- /src/service/docker/orderer.go: -------------------------------------------------------------------------------- 1 | package docker 2 | 3 | import ( 4 | "devplat/src/config" 5 | "devplat/src/log" 6 | "fmt" 7 | ) 8 | 9 | type OrdererManager ContainerManager 10 | 11 | var ordererManager *OrdererManager 12 | 13 | func initOrdererManager() { 14 | var conatainerName = ordererName 15 | ordererManager = &OrdererManager{ 16 | Env: []string{ 17 | "FABRIC_LOGGING_SPEC=debug", 18 | fmt.Sprintf("ORDERER_GENERAL_LISTENADDRESS=%s", conatainerName), 19 | "ORDERER_GENERAL_GENESISMETHOD=file", 20 | "ORDERER_GENERAL_GENESISFILE=orderer.block", 21 | "ORDERER_GENERAL_LOCALMSPID=DEFAULT", 22 | "ORDERER_GENERAL_LOCALMSPDIR=/etc/hyperledger/msp", 23 | "GRPC_TRACE=all=true,", 24 | "GRPC_VERBOSITY=debug", 25 | }, 26 | Cmd: []string{"orderer"}, 27 | WorkingDir: "/opt/gopath/src/github.com/hyperledger/fabric", 28 | ContainerName: conatainerName, 29 | Image: "hyperledger/fabric-orderer:latest", 30 | Volumes: []string{ 31 | config.WorkPath + "/deploy/msp:/etc/hyperledger/msp", 32 | config.WorkPath + "/deploy/orderer.block:/etc/hyperledger/fabric/orderer.block", 33 | }, 34 | Ports: map[string][]Port{ 35 | "7050": { 36 | { 37 | IP: "0.0.0.0", 38 | Port: "7050", 39 | }, 40 | }, 41 | }, 42 | } 43 | } 44 | 45 | func (manager *OrdererManager) AddConfig() bool { 46 | return (*ContainerManager)(manager).AddConfig() 47 | } 48 | 49 | func (manager *OrdererManager) Run() bool { 50 | log.Logger.Info("orderer container start to create") 51 | return (*ContainerManager)(manager).Run() 52 | } 53 | 54 | func (manager *OrdererManager) Restart() (ok bool) { 55 | return (*ContainerManager)(manager).Restart() 56 | } 57 | 58 | func (manager *OrdererManager) StopAndRemove() (ok bool) { 59 | log.Logger.Info("orderer container start to stop and remove") 60 | return (*ContainerManager)(manager).StopAndRemove() 61 | } 62 | 63 | func (manager *OrdererManager) Stop() (ok bool) { 64 | return (*ContainerManager)(manager).Stop() 65 | } 66 | 67 | func (manager *OrdererManager) Remove() (ok bool) { 68 | return (*ContainerManager)(manager).Remove() 69 | } 70 | 71 | func (manager *OrdererManager) Exec(cmd []string) (content string, ok bool) { 72 | return (*ContainerManager)(manager).Exec(cmd) 73 | } 74 | 75 | func (manager *OrdererManager) GetStatus() ContainerManager { 76 | return (ContainerManager)(*manager) 77 | } 78 | -------------------------------------------------------------------------------- /src/service/docker/peer.go: -------------------------------------------------------------------------------- 1 | package docker 2 | 3 | import ( 4 | "devplat/src/config" 5 | "devplat/src/log" 6 | "fmt" 7 | ) 8 | 9 | type PeerManager ContainerManager 10 | 11 | var peerManager *PeerManager 12 | 13 | func NewPeerManager(orgName, containerName string, port int) *PeerManager { 14 | return &PeerManager{ 15 | Env: []string{ 16 | //"CORE_LEDGER_STATE_STATEDATABASE=CouchDB", 17 | //fmt.Sprintf("CORE_LEDGER_STATE_COUCHDBCONFIG_COUCHDBADDRESS=%s:5984", couchdbName), 18 | fmt.Sprintf("CORE_PEER_ID=%s", containerName), 19 | fmt.Sprintf("CORE_PEER_ADDRESS=%s:%v", containerName, port), 20 | fmt.Sprintf("CORE_PEER_GOSSIP_EXTERNALENDPOINT=%s:%v", containerName, port), 21 | fmt.Sprintf("CORE_PEER_LOCALMSPID=%v", orgName), 22 | "CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock", 23 | "FABRIC_LOGGING_SPEC=DEBUG", 24 | "CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/msp", 25 | }, 26 | Cmd: []string{"peer", "node", "start", "--peer-chaincodedev=true"}, 27 | Image: config.Config.PeerImage, 28 | WorkingDir: "/opt/gopath/src/github.com/hyperledger/fabric/peer", 29 | ContainerName: containerName, 30 | Volumes: []string{ 31 | config.WorkPath + "/deploy/msp:/etc/hyperledger/msp", 32 | "/var/run:/host/var/run", 33 | }, 34 | Ports: map[string][]Port{ 35 | "7051": { 36 | { 37 | IP: "0.0.0.0", 38 | Port: "7051", 39 | }, 40 | }, 41 | "7052": { 42 | { 43 | IP: "0.0.0.0", 44 | Port: "7052", 45 | }, 46 | }, 47 | "7053": { 48 | { 49 | IP: "0.0.0.0", 50 | Port: "7053", 51 | }, 52 | }, 53 | }, 54 | } 55 | } 56 | 57 | func initPeerManager() { 58 | var conatainerName = peerName 59 | peerManager = &PeerManager{ 60 | Env: []string{ 61 | "CORE_LEDGER_STATE_STATEDATABASE=CouchDB", 62 | fmt.Sprintf("CORE_LEDGER_STATE_COUCHDBCONFIG_COUCHDBADDRESS=%s:5984", couchdbName), 63 | fmt.Sprintf("CORE_PEER_ID=%s", conatainerName), 64 | fmt.Sprintf("CORE_PEER_ADDRESS=%s:7051", conatainerName), 65 | fmt.Sprintf("CORE_PEER_GOSSIP_EXTERNALENDPOINT=%s:7051", conatainerName), 66 | "CORE_PEER_LOCALMSPID=DEFAULT", 67 | "CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock", 68 | "FABRIC_LOGGING_SPEC=DEBUG", 69 | "CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/msp", 70 | }, 71 | Cmd: []string{"peer", "node", "start", "--peer-chaincodedev=true"}, 72 | Image: "hyperledger/fabric-peer:latest", 73 | WorkingDir: "/opt/gopath/src/github.com/hyperledger/fabric/peer", 74 | ContainerName: conatainerName, 75 | Volumes: []string{ 76 | config.WorkPath + "/deploy/msp:/etc/hyperledger/msp", 77 | "/var/run:/host/var/run", 78 | }, 79 | Ports: map[string][]Port{ 80 | "7051": { 81 | { 82 | IP: "0.0.0.0", 83 | Port: "7051", 84 | }, 85 | }, 86 | "7052": { 87 | { 88 | IP: "0.0.0.0", 89 | Port: "7052", 90 | }, 91 | }, 92 | "7053": { 93 | { 94 | IP: "0.0.0.0", 95 | Port: "7053", 96 | }, 97 | }, 98 | }, 99 | } 100 | } 101 | 102 | func (manager *PeerManager) AddConfig() bool { 103 | return (*ContainerManager)(manager).AddConfig() 104 | } 105 | 106 | func (manager *PeerManager) Run() bool { 107 | log.Logger.Info("peer container start to create") 108 | return (*ContainerManager)(manager).Run() 109 | } 110 | 111 | func (manager *PeerManager) Restart() (ok bool) { 112 | return (*ContainerManager)(manager).Restart() 113 | } 114 | 115 | func (manager *PeerManager) StopAndRemove() (ok bool) { 116 | log.Logger.Info("peer container start to stop and remove") 117 | return (*ContainerManager)(manager).StopAndRemove() 118 | } 119 | 120 | func (manager *PeerManager) Stop() (ok bool) { 121 | return (*ContainerManager)(manager).Stop() 122 | } 123 | 124 | func (manager *PeerManager) Remove() (ok bool) { 125 | return (*ContainerManager)(manager).Remove() 126 | } 127 | 128 | func (manager *PeerManager) Exec(cmd []string) (content string, ok bool) { 129 | return (*ContainerManager)(manager).Exec(cmd) 130 | } 131 | 132 | func (manager *PeerManager) GetStatus() ContainerManager { 133 | return (ContainerManager)(*manager) 134 | } 135 | -------------------------------------------------------------------------------- /src/service/handle/chaincode.go: -------------------------------------------------------------------------------- 1 | package handle 2 | 3 | import ( 4 | "devplat/src/config" 5 | "devplat/src/log" 6 | "devplat/src/service/app" 7 | "encoding/json" 8 | "github.com/gin-gonic/gin" 9 | ) 10 | 11 | type InstallChaincodeReq struct { 12 | Result bool `json:"result"` 13 | Log string `json:"log"` 14 | } 15 | 16 | func InstallChaincodeHandle(c *gin.Context) { 17 | } 18 | 19 | type InvokeChaincodeReq struct { 20 | Name string `json:"name" binding:"required"` 21 | FunctionName string `json:"function_name" binding:"required"` 22 | Args []interface{} 23 | } 24 | 25 | func InvokeChaincodeHandle(c *gin.Context) { 26 | var req InvokeChaincodeReq 27 | if err := c.BindJSON(&req); err != nil { 28 | log.Logger.Error(err.Error()) 29 | ErrorResp(c, paramError) 30 | return 31 | } 32 | 33 | var args [][]byte 34 | for _, arg := range req.Args { 35 | switch arg.(type) { 36 | case string: 37 | args = append(args, []byte((arg).(string))) 38 | default: 39 | data, err := json.Marshal(arg) 40 | if err != nil { 41 | log.Logger.Error(err.Error()) 42 | ErrorResp(c, paramError) 43 | return 44 | } 45 | args = append(args, data) 46 | } 47 | } 48 | var cfg = config.Config 49 | payload, err := app.InvokeCCRequest(cfg.ChannelName, req.Name, req.FunctionName, args) 50 | if err != nil { 51 | log.Logger.Error(err.Error()) 52 | ErrorResp(c, err.Error()) 53 | return 54 | } 55 | SuccessResp(c, "", string(payload)) 56 | } 57 | -------------------------------------------------------------------------------- /src/service/handle/channel.go: -------------------------------------------------------------------------------- 1 | package handle 2 | 3 | import ( 4 | "devplat/src/log" 5 | "devplat/src/service/app" 6 | "github.com/gin-gonic/gin" 7 | ) 8 | 9 | func GetChannelsHandle(c *gin.Context) { 10 | channels, err := app.GetChannels() 11 | if err != nil { 12 | log.Logger.Error(err.Error()) 13 | ErrorResp(c, paramError) 14 | return 15 | } 16 | SuccessResp(c, "", channels) 17 | } 18 | -------------------------------------------------------------------------------- /src/service/handle/common.go: -------------------------------------------------------------------------------- 1 | package handle 2 | 3 | import ( 4 | "devplat/src/log" 5 | "encoding/json" 6 | "errors" 7 | "fmt" 8 | "github.com/gin-gonic/gin" 9 | "net/http" 10 | "strings" 11 | ) 12 | 13 | const ( 14 | paramError = "参数错误" 15 | ) 16 | 17 | func SuccessResp(c *gin.Context, message string, data interface{}) { 18 | c.JSON(http.StatusOK, gin.H{"ret_code": 0, "ret_msg": message, "data": data}) 19 | } 20 | 21 | func ErrorResp(c *gin.Context, message string) { 22 | c.JSON(http.StatusOK, gin.H{ 23 | "ret_code": 400, 24 | "ret_msg": message, 25 | "data": struct{}{}, 26 | }) 27 | } 28 | 29 | func ArgsHandle(args []interface{}) (argsStr string, err error) { 30 | for _, arg := range args { 31 | switch arg.(type) { 32 | case string: 33 | var str = arg.(string) 34 | str = strings.Replace(str, " ", "", -1) 35 | str = strings.Replace(str, "\n", "", -1) 36 | str = strings.Replace(str, "\"", "\\\"", -1) 37 | argsStr = fmt.Sprintf(`%v,"%v"`, argsStr, str) 38 | case map[string]interface{}: 39 | data, _ := json.Marshal(arg) 40 | newData := strings.Replace(string(data), `"`, `\"`, len(string(data))) 41 | argsStr = fmt.Sprintf(`%v,"%v"`, argsStr, newData) 42 | default: 43 | err = errors.New("参数类型错误") 44 | log.Logger.Error(err.Error()) 45 | return 46 | } 47 | } 48 | return 49 | } 50 | -------------------------------------------------------------------------------- /src/service/handle/peer.go: -------------------------------------------------------------------------------- 1 | package handle 2 | 3 | import ( 4 | "devplat/src/log" 5 | "devplat/src/service" 6 | "devplat/src/service/app" 7 | "fmt" 8 | "github.com/gin-gonic/gin" 9 | "strings" 10 | ) 11 | 12 | //获取未安装链码项目 13 | func ChaincodeUninstallGetHandle(c *gin.Context) { 14 | SuccessResp(c, "", app.GetChaincodeProvider().GetUninstallChaincode()) 15 | } 16 | 17 | //获取已安装未实例化链码 18 | func ChaincodeInstalledGetHandle(c *gin.Context) { 19 | SuccessResp(c, "", app.GetChaincodeProvider().GetInstalledChaincodes()) 20 | } 21 | 22 | //获取已安装链码 23 | func ChaincodeInstantiatedGetHandle(c *gin.Context) { 24 | SuccessResp(c, "", app.GetChaincodeProvider().GetInstantiatedChaincode()) 25 | } 26 | 27 | type ChaincodeReq struct { 28 | Name string `json:"name" binding:"required"` 29 | Version string `json:"version" binding:"required"` 30 | } 31 | 32 | type ChaincodeInstallReq ChaincodeReq 33 | 34 | type ChaincodeInstallRsp struct { 35 | Result bool `json:"result"` 36 | Log string `json:"log"` 37 | } 38 | 39 | //链码安装 40 | func ChaincodeInstallHandle(c *gin.Context) { 41 | var req ChaincodeInstallReq 42 | if err := c.BindJSON(&req); err != nil { 43 | log.Logger.Error(err.Error()) 44 | ErrorResp(c, paramError) 45 | return 46 | } 47 | var cmdStr = fmt.Sprintf("peer chaincode install -p %v -n %s -v %s", req.Name, req.Name, req.Version) 48 | var cmd = strings.Split(cmdStr, " ") 49 | content, ok := service.GetDockerManager().CliManager.Exec(cmd) 50 | SuccessResp(c, "", ChaincodeInstallRsp{ 51 | Result: ok, 52 | Log: content, 53 | }) 54 | } 55 | 56 | type ChaincodeInstallFeedbackReq ChaincodeReq 57 | 58 | // 链码安装反馈 59 | func ChaincodeInstallFeedbackHandle(c *gin.Context) { 60 | var req ChaincodeInstallFeedbackReq 61 | if err := c.BindJSON(&req); err != nil { 62 | log.Logger.Error(err.Error()) 63 | ErrorResp(c, paramError) 64 | return 65 | } 66 | var chaincodeInfo = app.ChaincodeInfo{ 67 | Name: req.Name, 68 | Version: req.Version, 69 | } 70 | app.GetChaincodeProvider().ChaincodeInstallFeedback(chaincodeInfo) 71 | SuccessResp(c, "", chaincodeInfo) 72 | } 73 | 74 | type ChaincodeInstantiateReq struct { 75 | Name string `json:"name"` 76 | Version string `json:"version"` 77 | Args []interface{} `json:"args"` 78 | } 79 | 80 | // 链码实例化 81 | func ChaincodeInstantiateHandle(c *gin.Context) { 82 | var req ChaincodeInstantiateReq 83 | if err := c.BindJSON(&req); err != nil { 84 | log.Logger.Error(err.Error()) 85 | ErrorResp(c, paramError) 86 | return 87 | } 88 | var chaincodeInfo = app.ChaincodeInfo{ 89 | Name: req.Name, 90 | Version: req.Version, 91 | } 92 | if !app.GetChaincodeProvider().JudgeChaincodeInstalled(chaincodeInfo) { 93 | ErrorResp(c, paramError) 94 | return 95 | } 96 | argsStr, err := ArgsHandle(req.Args) 97 | if err != nil { 98 | ErrorResp(c, paramError) 99 | return 100 | } 101 | var cmdStr = fmt.Sprintf(`peer chaincode instantiate -n %s -v %s -c {"Args":["init"%v]} -C myc`, 102 | req.Name, req.Version, argsStr) 103 | var cmd = strings.Split(cmdStr, " ") 104 | content, ok := service.GetDockerManager().CliManager.Exec(cmd) 105 | SuccessResp(c, "", ChaincodeInstallRsp{ 106 | Result: ok, 107 | Log: content, 108 | }) 109 | } 110 | 111 | type ChaincodeInstantiateFeedbackReq ChaincodeInstallReq 112 | 113 | // 链码实例化反馈 114 | func ChaincodeInstantiateFeedbackHandle(c *gin.Context) { 115 | var req ChaincodeInstantiateFeedbackReq 116 | if err := c.BindJSON(&req); err != nil { 117 | log.Logger.Error(err.Error()) 118 | ErrorResp(c, paramError) 119 | return 120 | } 121 | var chaincodeInfo = app.ChaincodeInfo{ 122 | Name: req.Name, 123 | Version: req.Version, 124 | } 125 | app.GetChaincodeProvider().ChaincodeInstantiateFeedback(chaincodeInfo) 126 | SuccessResp(c, "", chaincodeInfo) 127 | } 128 | 129 | type ChaincodeInvokeReq struct { 130 | Name string `json:"name" binding:"required"` 131 | FunctionName string `json:"function_name" binding:"required"` 132 | Args []interface{} `json:"args"` 133 | } 134 | 135 | type ChaincodeInvokeRsp struct { 136 | Result bool `json:"result"` 137 | Response string `json:"response"` 138 | } 139 | 140 | // 链码调用 141 | func ChaincodeInvokeHandle(c *gin.Context) { 142 | var req ChaincodeInvokeReq 143 | if err := c.BindJSON(&req); err != nil { 144 | log.Logger.Error(err.Error()) 145 | ErrorResp(c, paramError) 146 | return 147 | } 148 | if !app.GetChaincodeProvider().JudgeChaincodeInstantiate(req.Name) { 149 | ErrorResp(c, paramError) 150 | return 151 | } 152 | argsStr, err := ArgsHandle(req.Args) 153 | if err != nil { 154 | ErrorResp(c, paramError) 155 | return 156 | } 157 | var cmdStr = fmt.Sprintf(`peer chaincode invoke -n %s -c {"Args":["%v"%v]} -C myc`, 158 | req.Name, req.FunctionName, argsStr) 159 | var cmd = strings.Split(cmdStr, " ") 160 | content, ok := service.GetDockerManager().CliManager.Exec(cmd) 161 | SuccessResp(c, "", ChaincodeInvokeRsp{ 162 | Result: ok, 163 | Response: content, 164 | }) 165 | } 166 | -------------------------------------------------------------------------------- /src/service/handle/plat.go: -------------------------------------------------------------------------------- 1 | package handle 2 | 3 | import ( 4 | "devplat/src/service" 5 | "devplat/src/service/app" 6 | "github.com/gin-gonic/gin" 7 | "net/http" 8 | ) 9 | 10 | func SetupPlatHandle(c *gin.Context) { 11 | service.GetDevPlatController().Setup() 12 | status, containers := service.GetDevPlatController().GetContainers() 13 | app.GetChaincodeProvider().Start() 14 | SuccessResp(c, "", gin.H{ 15 | "status": status, 16 | "containers": containers, 17 | }) 18 | } 19 | 20 | func CleanPlatHandle(c *gin.Context) { 21 | service.GetDevPlatController().Clean() 22 | app.GetChaincodeProvider().Clean() 23 | c.JSON(http.StatusOK, gin.H{ 24 | "code": 0, 25 | "msg": "清理成功", 26 | }) 27 | } 28 | 29 | func GetStatusHandle(c *gin.Context) { 30 | status, containers := service.GetDevPlatController().GetContainers() 31 | SuccessResp(c, "", gin.H{ 32 | "status": status, 33 | "containers": containers, 34 | }) 35 | } 36 | -------------------------------------------------------------------------------- /src/service/handle/route.go: -------------------------------------------------------------------------------- 1 | package handle 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | ) 6 | 7 | func Router(engine *gin.Engine) { 8 | engine.GET("/setup", SetupPlatHandle) 9 | engine.GET("/clean", CleanPlatHandle) 10 | engine.GET("/status", GetStatusHandle) 11 | 12 | engine.GET("/chaincode/uninstall", ChaincodeUninstallGetHandle) 13 | engine.GET("/chaincode/instantiated", ChaincodeInstantiatedGetHandle) 14 | engine.GET("/chaincode/installed", ChaincodeInstalledGetHandle) 15 | engine.POST("/chaincode/install", ChaincodeInstallHandle) 16 | engine.POST("/chaincode/install/feedback", ChaincodeInstallFeedbackHandle) 17 | engine.POST("/chaincode/instantiate", ChaincodeInstantiateHandle) 18 | engine.POST("/chaincode/instantiate/feedback", ChaincodeInstantiateFeedbackHandle) 19 | engine.POST("/chaincode/invoke", ChaincodeInvokeHandle) 20 | engine.POST("/chaincode/invokes", InvokeChaincodeHandle) 21 | engine.GET("/channel", GetChannelsHandle) 22 | } 23 | -------------------------------------------------------------------------------- /src/service/org/crypto.go: -------------------------------------------------------------------------------- 1 | package org 2 | 3 | import ( 4 | "devplat/src/config" 5 | "devplat/src/log" 6 | "devplat/src/utils" 7 | "fmt" 8 | ) 9 | 10 | const ( 11 | CryptoConfigFileName = "crypto-config.yaml" 12 | CryptoCommandName = "./bin/cryptogen" 13 | ) 14 | 15 | func NewOrgCrypto(org Org) { 16 | ordererOrgs := make([]config.OrdererOrgs, 0) 17 | peerOrgs := make([]config.PeerOrgs, 0) 18 | var cryptoConfig = config.CryptoConfig{ 19 | OrdererOrgs: ordererOrgs, 20 | PeerOrgs: peerOrgs, 21 | } 22 | fileName := fmt.Sprintf("%v-%v", org.OrgName, CryptoConfigFileName) 23 | config.GenerateConfig(fileName, cryptoConfig) 24 | if err := utils.CommonRun(CryptoCommandName, []string{"generate", "--config=./deploy/%v", fileName}); err != nil { 25 | log.Logger.Error(err.Error()) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/service/org/node.go: -------------------------------------------------------------------------------- 1 | package org 2 | 3 | type Node struct { 4 | Address string 5 | Port []int 6 | EnableNodeOUs bool 7 | Name string 8 | Domain string 9 | } 10 | 11 | type PeerNode struct { 12 | Node 13 | TemplateCount int 14 | UserCount int 15 | } 16 | 17 | type OrdererNode struct { 18 | Node 19 | Hostname string 20 | } 21 | -------------------------------------------------------------------------------- /src/service/org/setup.go: -------------------------------------------------------------------------------- 1 | package org 2 | 3 | type Org struct { 4 | OrgName string `json:"org_name"` 5 | Peers []PeerNode `json:"peers"` 6 | Orderers []OrdererNode `json:"orderers"` 7 | } 8 | 9 | func NewOrg(orgName string, peers []PeerNode, orderers []OrdererNode) *Org { 10 | return &Org{ 11 | OrgName: orgName, 12 | Peers: peers, 13 | Orderers: orderers, 14 | } 15 | } 16 | 17 | func (org *Org) Setup() { 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/utils/utils.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import "os/exec" 4 | 5 | func CommonRun(name string, args []string) error { 6 | return exec.Command(name, args...).Run() 7 | } 8 | -------------------------------------------------------------------------------- /views/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 首页 6 | {{/* */}} 7 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 |
17 |
18 | 19 | 环境管理 20 | 21 | 22 | 链码安装 23 | 链码实例化 24 | 链码调用 25 | 26 | 27 |
28 |
29 |
30 |
31 | 启动环境 32 | 清理环境 33 | 刷新 34 | 35 | 当前状态: 36 | 未启动环境 37 | 环境已启动 38 | 39 |
40 |
41 | 42 | 43 | 44 | 45 | 46 | 47 | 55 | 56 | 57 |
58 |
59 |
60 | 61 | 62 | 63 | 64 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 安装 76 | 77 | 查看日志 78 | 79 | 80 | 已安装成功 81 | 82 | 83 | 84 |
85 |
86 | 87 | 88 | 89 | 90 | 92 | 93 | 94 | 95 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 删除 119 | 120 | 121 | 122 | 新增参数 123 | 实例化 124 | 125 | 查看日志 126 | 127 | 128 | 已实例化成功 129 | 130 | 131 | 132 |
133 |
134 | 135 | 136 | 137 | 138 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 删除 172 | 173 | 174 | 175 | 新增参数 176 | 调用 177 | 178 | 查看日志 179 | 180 | 181 | 182 |
183 |
184 |
185 | 186 | 190 |
191 |
${log}
192 |
193 | 194 | 关闭 195 | 196 |
197 |
198 | 199 | 200 | 201 | 202 | 255 | 256 | 567 | --------------------------------------------------------------------------------