├── .gitignore ├── README.en.md ├── README.md ├── bootstrap.sh ├── chaincode ├── VERSION └── go │ ├── ac │ └── ac.go │ ├── dc │ └── dc.go │ ├── m │ ├── policy.go │ ├── policy_test.go │ ├── request.go │ ├── request_test.go │ ├── resource.go │ └── util.go │ └── pc │ └── pc.go ├── client └── nodejs │ ├── base.js │ ├── enrollAdmin.js │ ├── init.sh │ ├── invoke.js │ ├── invoke_test.sh │ ├── package.json │ ├── registerUser.js │ └── test.js ├── daemon.json ├── docker.sh ├── network ├── cc-install.sh ├── cc-test.sh ├── cc-upgrade.sh ├── cc.sh ├── ccp-generate.sh ├── channel-artifacts │ └── readme.md ├── clear-docker.sh ├── compose-files │ ├── base │ │ ├── docker-compose-base.yaml │ │ └── peer-base.yaml │ ├── docker-compose-ca.yaml │ ├── docker-compose-cli.yaml │ ├── docker-compose-couch.yaml │ ├── docker-compose-e2e-template.yaml │ └── docker-compose-kafka.yaml ├── configtx.yaml ├── conn-conf │ ├── ccp-template.json │ └── ccp-template.yaml ├── crypto-config.yaml ├── down.sh ├── env.sh ├── generate.sh ├── restart.sh ├── scripts │ ├── script.sh │ └── utils.sh └── up.sh └── test ├── consensus ├── kafka │ ├── kafak_test.go │ └── kafka.go └── pow │ ├── pow.go │ └── pow_test.go └── tps └── test.go /.gitignore: -------------------------------------------------------------------------------- 1 | /package-lock.json 2 | /hfc-key-store/ 3 | /wallet/ 4 | node_modules/ 5 | crypto-config/ 6 | connection-* 7 | *.tx 8 | *.block 9 | .DS_Store 10 | wallet/ 11 | log.* 12 | /fabric-samples 13 | .vagrant/ 14 | *.log 15 | id_rsa.pub 16 | id_rsa -------------------------------------------------------------------------------- /README.en.md: -------------------------------------------------------------------------------- 1 | # fabric-iot is a Blockchain Based Decentralized Access Control System in IoT 2 | [中文版](/README.md) 3 | > **WHAT WE HAVE**: 4 | > 1.Using ABAC as permission control method,and chaincode is writed with golang. 5 | > 2.The Hyperledger Fabric network is easily started with a complete shell script. 6 | > 3.Detailed instructions, easy to understand. 7 | 8 | ## 0.Environment & Preparation 9 | ### 0.1.Operation System 10 | OS|VETSION 11 | -|- 12 | mac os|>=10.13 13 | ubuntu|16.04 14 | 15 | ### 0.2.Software: 16 | SDK|VERSION 17 | -|- 18 | git|>=2.0.0 19 | docker|>=19 20 | docker-compose|>=1.24 21 | node|>=12 22 | golang|>=1.10 23 | Hyperledger Fabric|>=1.4 24 | 25 | ### 0.3.Download src 26 | ```go 27 | go get github.com/newham/fabric-iot 28 | ``` 29 | 30 | ## 1.Directory Structure 31 | 32 | |-chaincode....................................chaincode folder 33 | |--go..........................................chaincode in golang 34 | |-client.......................................client of blockchain 35 | |--nodejs......................................code in nodejs of client 36 | |-network......................................fabric-iot network module folder,genesis.block 37 | |--channel-artifacts...........................channel comfig folder 38 | |--compose-files...............................docker-compose folder 39 | |--conn-conf...................................connection config of docker 40 | |--crypto-config...............................certs folder 41 | |--scripts.....................................shell scrpits of cli 42 | |--ccp-generate.sh.............................generate certs and blockchain config shell 43 | |--ccp-template.json...........................json template of connection config 44 | |--ccp-template.yaml...........................template of connection config 45 | |--clear-docker.sh.............................clearn docker images 46 | |--configtx.yaml...............................config of configtxgen 47 | |--crypto-config.yaml..........................config of ccp-generate.sh 48 | |--down.sh.....................................shutdown the network 49 | |--env.sh......................................environment of other shell scripts 50 | |--generate.sh.................................init config 51 | |--install-cc.sh...............................install chaincode 52 | |--rm-cc.sh....................................delete chaincode 53 | |--up.sh.......................................start network 54 | ## 2.Build Network of Fabric 55 | ### 2.1.Generate cers and configs 56 | open folder 57 | ```shell 58 | cd network 59 | ``` 60 | run 61 | ```shell 62 | ./generate.sh 63 | ``` 64 | cers are saved to `crypto-config` 65 | ### 2.2.Start Network 66 | ```shell 67 | ./up.sh 68 | ``` 69 | ### 2.3.Install Chaincode 70 | ```shell 71 | ./cc-install.sh 72 | ``` 73 | ### 2.4.Upgrade Chaincode 74 | ```shell 75 | ./cc-upgrade.sh [new_version] 76 | ``` 77 | *chaincode is saved to `/chaincode/go`,we only support write code with golang now. 78 | ### 2.5.Close Network 79 | ```shell 80 | ./down.sh 81 | ``` 82 | *all the stoped docker containers or images will be delete ,be carefull before you do this 83 | 84 | ## 3.Interacting with the Blockchain 85 | ### 3.1.Init Code 86 | enter the foder 87 | *we have only a client writed by nodejs 88 | ```shell 89 | cd client/nodejs 90 | ``` 91 | install modules of this program 92 | ```shell 93 | npm install 94 | ``` 95 | ### 3.2.Create Users 96 | create admin 97 | ```shell 98 | node ./enrollAdmin.js 99 | ``` 100 | create user by admin 101 | ```shell 102 | node ./registerUser.js 103 | ``` 104 | ### 3.3.Run Chaincode 105 | ```shell 106 | node ./invoke.js [chaincode_name] [function_name] [args] 107 | ``` 108 | 109 |
110 |
111 | ©2019 liuhan[liuhanshmtu@163.com] all rights reserved. 112 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # fabric-iot 是一个基于Hyperledger Fabric框架实现的物联网访问控制管理的区块链模拟实验平台 2 | [English](/README.en.md) 3 | > **WHAT WE HAVE**: 4 | > 1.采用ABAC作为权限控制方法,用golang实现了chaincode. 5 | > 2.编写了完整的脚本,轻松启动fabric-iot网络. 6 | > 3.详细的步骤说明,浅显易懂. 7 | 8 | ## 0.准备工作 9 | ### 0.0.官网 10 | [ github : hyperledger-fabric](https://github.com/hyperledger/fabric) 11 | [ doc 1.4 ](https://hyperledger-fabric.readthedocs.io/en/release-1.4/) 12 | [ node-sdk 1.4 ](https://hyperledger.github.io/fabric-sdk-node/release-1.4/module-fabric-network.html) 13 | 14 | ### 0.1.操作系统 15 | OS|版本 16 | -|- 17 | mac os|>=10.13 18 | ubuntu|16.04 19 | 20 | ### 0.2.软件: 21 | 软件|版本 22 | -|- 23 | git|>=2.0.0 24 | docker|>=19 25 | docker-compose|>=1.24 26 | node|>=12 27 | golang|>=1.10 28 | Hyperledger Fabric|=1.4.* 29 | 30 | ***请将golang、node的\bin加入PATH** 31 | 32 | ***本次实验基于Fabric 1.4.3,默认下载的Fabric版本是1.4.3** 33 | 34 | ***如果需要修改版本,请更改 `bootstrap.sh`** 35 | ``` 36 | VERSION=1.4.3 37 | 38 | CA_VERSION=1.4.3 39 | ``` 40 | 41 | 42 | ### 0.3.下载本软件 43 | ```go 44 | go get github.com/newham/fabric-iot 45 | ``` 46 | 47 | ### 0.4.下载并配置Hyperledger Fabric 48 | 下载源码和bin 49 | ```bash 50 | ./bootstrap.sh 51 | ``` 52 | export PATH 53 | ```bash 54 | export PATH=$PATH:$(pwd)/fabric-samples/bin 55 | ``` 56 | ***之后的诸如【启动网络、安装链码等操作需要先export PATH,这是让系统知道Hyperledger Fabric的bin目录】** 57 | 58 | ***也可将其加入path中** 59 | 60 | ## 1.目录结构 61 | 62 | |-chaincode....................................链码目录 63 | |--go....................................................golang编写的chaincode代码 64 | |-client............................................交互客户端 65 | |--nodejs..............................................nodejs编写的客户端代码 66 | |-network........................................fabric-iot网络配置和启动脚本 67 | |--channel-artifacts..............................channel配置文件,创世区块目录 68 | |--compose-files...................................docker-compose文件目录 69 | |--conn-conf.........................................链接docker网络配置目录 70 | |--crypto-config....................................存放证书、秘钥文件目录 71 | |--scripts...............................................cli运行脚本目录 72 | |--ccp-generate.sh...............................生成节点证书目录配置文件脚本 73 | |--ccp-template.json.............................配置文件json模板 74 | |--ccp-template.yaml.............................配置文件yaml模板 75 | |--clear-docker.sh................................清理停用docker镜像脚本 76 | |--configtx.yaml....................................configtxgen的配置文件 77 | |--crypto-config.yaml...........................生成证书、秘钥的配置文件 78 | |--down.sh............................................关闭网络shell脚本 79 | |--env.sh...............................................其他shell脚本import的公共配置 80 | |--generate.sh......................................初始化系统配置shell脚本 81 | |--install-cc.sh......................................安装链码shell脚本 82 | |--rm-cc.sh...........................................删除链码shell脚本 83 | |--up.sh................................................启动网络shell脚本 84 | ## 2.搭建网络 [分布式版本](https://github.com/newham/fabric-iot/tree/distributed) 85 | ### 2.1.生成证书、配置文件等 86 | 进入目录 87 | ```shell 88 | cd network 89 | ``` 90 | 运行脚本 91 | ```shell 92 | ./generate.sh 93 | ``` 94 | 证书保存在`crypto-config`中 95 | ### 2.2.启动网络 96 | ```shell 97 | ./up.sh 98 | ``` 99 | ### 2.3.安装链码 100 | ```shell 101 | ./cc-install.sh 102 | ``` 103 | ### *2.4.更新链码(本步骤在修改了chain code代码后再执行,[new version]要大于上一个版本) 104 | ```shell 105 | ./cc-upgrade.sh [new version] 106 | ``` 107 | *chaincode被保存在`/chaincode/go`目录中,目前只用`golang`实现 108 | ### *2.5.关闭网络 109 | ```shell 110 | ./down.sh 111 | ``` 112 | *每次关闭网络会删除所有docker容器和镜像,请谨慎操作 113 | ## 3.与区块链交互 114 | 115 | ## 3.1.使用shell脚本调用链码 116 | 进入shell脚本目录 117 | ```bash 118 | cd network 119 | ``` 120 | 调用链码(示例代码在`cc-test.sh`) 121 | ```bash 122 | # invoke 123 | # shell|action|cc_name|cc_version|cc_src|fname|args 124 | # add policy 125 | ./cc.sh invoke pc 1.0 go/pc AddPolicy '"{\"AS\":{\"userId\":\"13800010001\",\"role\":\"u1\",\"group\":\"g1\"},\"AO\":{\"deviceId\":\"D100010001\",\"MAC\":\"00:11:22:33:44:55\"}}"' 126 | # query policy 127 | ./cc.sh invoke pc 1.0 go/pc QueryPolicy '"40db810e4ccb4cc1f3d5bc5803fb61e863cf05ea7fc2f63165599ef53adf5623"' 128 | ``` 129 | ## 3.2.使用 Node JS 客户端调用链码 130 | ### 3.2.1初始化代码 131 | 进入客户端代码目录 132 | *目前只实现了nodejs的客户端 133 | 134 | ```shell 135 | cd client/nodejs 136 | ``` 137 | 安装依赖 138 | ```shell 139 | npm install 140 | ``` 141 | ### 3.2.2.创建用户 142 | 创建管理员账户 143 | ```shell 144 | node ./enrollAdmin.js 145 | ``` 146 | 用管理员账户创建子用户 147 | ```shell 148 | node ./registerUser.js 149 | ``` 150 | ### 3.2.3.调用chaincode 151 | ```shell 152 | node ./invoke.js [chaincode_name] [function_name] [args] 153 | ``` 154 | 155 |
156 |
157 | ©2019 liuhanshmtu@163.com all rights reserved. 158 | -------------------------------------------------------------------------------- /bootstrap.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Copyright IBM Corp. All Rights Reserved. 4 | # 5 | # SPDX-License-Identifier: Apache-2.0 6 | # 7 | 8 | # Delete downloaded files 9 | rm -rf ./fabric-samples 10 | 11 | # if version not passed in, default to latest released version 12 | VERSION=1.4.3 13 | # if ca version not passed in, default to latest released version 14 | CA_VERSION=1.4.3 15 | ARCH=$(echo "$(uname -s|tr '[:upper:]' '[:lower:]'|sed 's/mingw64_nt.*/windows/')-$(uname -m | sed 's/x86_64/amd64/g')") 16 | MARCH=$(uname -m) 17 | 18 | printHelp() { 19 | echo "Usage: bootstrap.sh [version [ca_version]] [options]" 20 | echo 21 | echo "options:" 22 | echo "-h : this help" 23 | echo "-d : bypass docker image download" 24 | echo "-s : bypass fabric-samples repo clone" 25 | echo "-b : bypass download of platform-specific binaries" 26 | echo 27 | echo "e.g. bootstrap.sh 2.2.0 1.4.7 -s" 28 | echo "will download docker images and binaries for Fabric v2.2.0 and Fabric CA v1.4.7" 29 | } 30 | 31 | # dockerPull() pulls docker images from fabric and chaincode repositories 32 | # note, if a docker image doesn't exist for a requested release, it will simply 33 | # be skipped, since this script doesn't terminate upon errors. 34 | 35 | dockerPull() { 36 | #three_digit_image_tag is passed in, e.g. "1.4.7" 37 | three_digit_image_tag=$1 38 | shift 39 | #two_digit_image_tag is derived, e.g. "1.4", especially useful as a local tag for two digit references to most recent baseos, ccenv, javaenv, nodeenv patch releases 40 | two_digit_image_tag=$(echo "$three_digit_image_tag" | cut -d'.' -f1,2) 41 | while [[ $# -gt 0 ]] 42 | do 43 | image_name="$1" 44 | echo "====> hyperledger/fabric-$image_name:$three_digit_image_tag" 45 | docker pull "hyperledger/fabric-$image_name:$three_digit_image_tag" 46 | docker tag "hyperledger/fabric-$image_name:$three_digit_image_tag" "hyperledger/fabric-$image_name" 47 | docker tag "hyperledger/fabric-$image_name:$three_digit_image_tag" "hyperledger/fabric-$image_name:$two_digit_image_tag" 48 | shift 49 | done 50 | } 51 | 52 | cloneSamplesRepo() { 53 | # clone (if needed) hyperledger/fabric-samples and checkout corresponding 54 | # version to the binaries and docker images to be downloaded 55 | if [ -d first-network ]; then 56 | # if we are in the fabric-samples repo, checkout corresponding version 57 | echo "===> Checking out v${VERSION} of hyperledger/fabric-samples" 58 | git checkout v${VERSION} 59 | elif [ -d fabric-samples ]; then 60 | # if fabric-samples repo already cloned and in current directory, 61 | # cd fabric-samples and checkout corresponding version 62 | echo "===> Checking out v${VERSION} of hyperledger/fabric-samples" 63 | cd fabric-samples && git checkout v${VERSION} 64 | else 65 | echo "===> Cloning hyperledger/fabric-samples repo and checkout v${VERSION}" 66 | git clone -b master https://github.com/hyperledger/fabric-samples.git && cd fabric-samples && git checkout v${VERSION} 67 | fi 68 | } 69 | 70 | # This will download the .tar.gz 71 | download() { 72 | local BINARY_FILE=$1 73 | local URL=$2 74 | echo "===> Downloading: " "${URL}" 75 | curl -L --retry 5 --retry-delay 3 "${URL}" | tar xz || rc=$? 76 | if [ -n "$rc" ]; then 77 | echo "==> There was an error downloading the binary file." 78 | return 22 79 | else 80 | echo "==> Done." 81 | fi 82 | } 83 | 84 | pullBinaries() { 85 | echo "===> Downloading version ${FABRIC_TAG} platform specific fabric binaries" 86 | download "${BINARY_FILE}" "https://github.com/hyperledger/fabric/releases/download/v${VERSION}/${BINARY_FILE}" 87 | if [ $? -eq 22 ]; then 88 | echo 89 | echo "------> ${FABRIC_TAG} platform specific fabric binary is not available to download <----" 90 | echo 91 | exit 92 | fi 93 | 94 | echo "===> Downloading version ${CA_TAG} platform specific fabric-ca-client binary" 95 | download "${CA_BINARY_FILE}" "https://github.com/hyperledger/fabric-ca/releases/download/v${CA_VERSION}/${CA_BINARY_FILE}" 96 | if [ $? -eq 22 ]; then 97 | echo 98 | echo "------> ${CA_TAG} fabric-ca-client binary is not available to download (Available from 1.1.0-rc1) <----" 99 | echo 100 | exit 101 | fi 102 | } 103 | 104 | pullDockerImages() { 105 | command -v docker >& /dev/null 106 | NODOCKER=$? 107 | if [ "${NODOCKER}" == 0 ]; then 108 | FABRIC_IMAGES=(peer orderer ccenv tools couchdb) # couchdb added by liuhan 109 | case "$VERSION" in 110 | 2.*) 111 | FABRIC_IMAGES+=(baseos) 112 | shift 113 | ;; 114 | esac 115 | echo "FABRIC_IMAGES:" "${FABRIC_IMAGES[@]}" 116 | echo "===> Pulling fabric Images" 117 | dockerPull "${FABRIC_TAG}" "${FABRIC_IMAGES[@]}" 118 | echo "===> Pulling fabric ca Image" 119 | CA_IMAGE=(ca) 120 | dockerPull "${CA_TAG}" "${CA_IMAGE[@]}" 121 | echo "===> List out hyperledger docker images" 122 | docker images | grep hyperledger 123 | else 124 | echo "=========================================================" 125 | echo "Docker not installed, bypassing download of Fabric images" 126 | echo "=========================================================" 127 | fi 128 | } 129 | 130 | DOCKER=true 131 | SAMPLES=false 132 | BINARIES=true 133 | 134 | # Parse commandline args pull out 135 | # version and/or ca-version strings first 136 | if [ -n "$1" ] && [ "${1:0:1}" != "-" ]; then 137 | VERSION=$1;shift 138 | if [ -n "$1" ] && [ "${1:0:1}" != "-" ]; then 139 | CA_VERSION=$1;shift 140 | if [ -n "$1" ] && [ "${1:0:1}" != "-" ]; then 141 | THIRDPARTY_IMAGE_VERSION=$1;shift 142 | fi 143 | fi 144 | fi 145 | 146 | # prior to 1.2.0 architecture was determined by uname -m 147 | if [[ $VERSION =~ ^1\.[0-1]\.* ]]; then 148 | export FABRIC_TAG=${MARCH}-${VERSION} 149 | export CA_TAG=${MARCH}-${CA_VERSION} 150 | export THIRDPARTY_TAG=${MARCH}-${THIRDPARTY_IMAGE_VERSION} 151 | else 152 | # starting with 1.2.0, multi-arch images will be default 153 | : "${CA_TAG:="$CA_VERSION"}" 154 | : "${FABRIC_TAG:="$VERSION"}" 155 | : "${THIRDPARTY_TAG:="$THIRDPARTY_IMAGE_VERSION"}" 156 | fi 157 | 158 | BINARY_FILE=hyperledger-fabric-${ARCH}-${VERSION}.tar.gz 159 | CA_BINARY_FILE=hyperledger-fabric-ca-${ARCH}-${CA_VERSION}.tar.gz 160 | 161 | # then parse opts 162 | while getopts "h?dsb" opt; do 163 | case "$opt" in 164 | h|\?) 165 | printHelp 166 | exit 0 167 | ;; 168 | d) DOCKER=false 169 | ;; 170 | s) SAMPLES=false 171 | ;; 172 | b) BINARIES=false 173 | ;; 174 | esac 175 | done 176 | 177 | if [ "$SAMPLES" == "true" ]; then 178 | echo 179 | echo "Clone hyperledger/fabric-samples repo" 180 | echo 181 | cloneSamplesRepo 182 | elif [ "$SAMPLES" == "false" ]; then 183 | mkdir fabric-samples && cd fabric-samples 184 | fi 185 | if [ "$BINARIES" == "true" ]; then 186 | echo 187 | echo "Pull Hyperledger Fabric binaries" 188 | echo 189 | pullBinaries 190 | # by liuhan 191 | cd ../ 192 | echo 193 | echo "Set Fabric binaries ($(pwd)/fabric-samples/bin) to PATH" 194 | echo 195 | export PATH=$PATH:$(pwd)/fabric-samples/bin 196 | fi 197 | if [ "$DOCKER" == "true" ]; then 198 | echo 199 | echo "Pull Hyperledger Fabric docker images" 200 | echo 201 | pullDockerImages 202 | fi 203 | -------------------------------------------------------------------------------- /chaincode/VERSION: -------------------------------------------------------------------------------- 1 | PC=1.0 2 | DC=1.0 3 | AC=1.0 -------------------------------------------------------------------------------- /chaincode/go/ac/ac.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | 7 | "github.com/hyperledger/fabric/core/chaincode/shim" 8 | sc "github.com/hyperledger/fabric/protos/peer" 9 | "github.com/newham/fabric-iot/chaincode/go/m" 10 | ) 11 | 12 | type AccessContract interface { 13 | Init(shim.ChaincodeStubInterface) sc.Response 14 | Invoke(shim.ChaincodeStubInterface) sc.Response 15 | Synchro() sc.Response 16 | 17 | CheckAccess(shim.ChaincodeStubInterface, []string) sc.Response 18 | Auth(string) (m.ABACRequest, error) 19 | } 20 | 21 | type ChainCode struct { 22 | AccessContract 23 | } 24 | 25 | func NewAccessContract() AccessContract { 26 | return new(ChainCode) 27 | } 28 | 29 | func (cc *ChainCode) Auth(str string) (m.ABACRequest, error) { 30 | r := m.ABACRequest{} 31 | b := []byte(str) 32 | err := json.Unmarshal(b, &r) 33 | return r, err 34 | } 35 | 36 | func (cc *ChainCode) CheckAccess(APIstub shim.ChaincodeStubInterface, args []string) sc.Response { 37 | if len(args) != 1 { 38 | return shim.Error("Incorrect number of argumentcc. Expecting 1") 39 | } 40 | r, err := cc.Auth(args[0]) 41 | if err != nil { 42 | return shim.Error("403") 43 | } 44 | attrs := r.GetAttrs() 45 | //get policy 46 | resp := APIstub.InvokeChaincode("pc", [][]byte{[]byte("QueryPolicy"), []byte(attrs.GetId())}, "iot-channel") 47 | if resp.GetStatus() != 200 { 48 | return shim.Error("403") 49 | } 50 | 51 | policy := m.Policy{} 52 | err = json.Unmarshal(resp.GetPayload(), &policy) 53 | if err != nil { 54 | return shim.Error("403") 55 | // return shim.Error(attrs.GetId() + ";" + string(resp.GetPayload()) + ";" + err.Error()) 56 | } 57 | //check AP 58 | if policy.AP != 1 { 59 | return shim.Error("403") 60 | // return shim.Error(string(policy.ToBytes()) + ": AP is deney") 61 | } 62 | //check AE 63 | if attrs.Timestamp > policy.AE.EndTime { 64 | //disable the contract 65 | // DeletePolicy(APIstub, attrs.GetId()) 66 | return shim.Error("AE is timeout") 67 | } 68 | //get URL 69 | resp = APIstub.InvokeChaincode("dc", [][]byte{[]byte("GetURL"), []byte(attrs.DeviceId)}, "iot-channel") 70 | res, err := m.NewResource(resp.GetPayload()) 71 | if err != nil { 72 | return shim.Error(err.Error()) 73 | } 74 | return shim.Success([]byte(res.URL)) 75 | } 76 | 77 | /* 78 | * The Init method is called when the Smart Contract "fabcar" is instantiated by the blockchain network 79 | * Best practice is to have any Ledger initialization in separate function -- see initLedger() 80 | */ 81 | func (cc *ChainCode) Init(APIstub shim.ChaincodeStubInterface) sc.Response { 82 | return shim.Success(m.OK) 83 | } 84 | 85 | /* 86 | * The Invoke method is called as a result of an application request to run the Smart Contract "fabcar" 87 | * The calling application program has also specified the particular smart contract function to be called, with arguments 88 | */ 89 | func (cc *ChainCode) Invoke(APIstub shim.ChaincodeStubInterface) sc.Response { 90 | 91 | // Retrieve the requested Smart Contract function and arguments 92 | function, args := APIstub.GetFunctionAndParameters() 93 | // Route to the appropriate handler function to interact with the ledger appropriately 94 | if function == "CheckAccess" { 95 | return cc.CheckAccess(APIstub, args) 96 | } else if function == "Synchro" { 97 | return cc.Synchro() 98 | } 99 | 100 | return shim.Error("Invalid Smart Contract function name.") 101 | } 102 | 103 | // base function 104 | func (cc *ChainCode) Synchro() sc.Response { 105 | return shim.Success(m.OK) 106 | } 107 | 108 | func main() { 109 | // Create a new Smart Contract 110 | err := shim.Start(NewAccessContract()) 111 | if err != nil { 112 | fmt.Printf("Error creating new Smart Contract: %s", err) 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /chaincode/go/dc/dc.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | 7 | "github.com/hyperledger/fabric/core/chaincode/shim" 8 | sc "github.com/hyperledger/fabric/protos/peer" 9 | "github.com/newham/fabric-iot/chaincode/go/m" 10 | ) 11 | 12 | type DeviceContract interface { 13 | Init(shim.ChaincodeStubInterface) sc.Response 14 | Invoke(shim.ChaincodeStubInterface) sc.Response 15 | AddURL(shim.ChaincodeStubInterface, []string) sc.Response 16 | GetURL(shim.ChaincodeStubInterface, []string) sc.Response 17 | Synchro() sc.Response 18 | } 19 | 20 | // Define the Device Contract structure 21 | type ChainCode struct { 22 | DeviceContract 23 | } 24 | 25 | func NewDeviceContract() DeviceContract { 26 | return new(ChainCode) 27 | } 28 | 29 | /* 30 | * The Init method is called when the Smart Contract "fabcar" is instantiated by the blockchain network 31 | * Best practice is to have any Ledger initialization in separate function -- see initLedger() 32 | */ 33 | func (cc *ChainCode) Init(APIstub shim.ChaincodeStubInterface) sc.Response { 34 | return shim.Success(m.OK) 35 | } 36 | 37 | /* 38 | * The Invoke method is called as a result of an application request to run the Smart Contract "fabcar" 39 | * The calling application program has also specified the particular smart contract function to be called, with arguments 40 | */ 41 | func (cc *ChainCode) Invoke(APIstub shim.ChaincodeStubInterface) sc.Response { 42 | 43 | // Retrieve the requested Smart Contract function and arguments 44 | function, args := APIstub.GetFunctionAndParameters() 45 | // Route to the appropriate handler function to interact with the ledger appropriately 46 | if function == "AddURL" { 47 | return cc.AddURL(APIstub, args) 48 | } else if function == "GetURL" { 49 | return cc.GetURL(APIstub, args) 50 | } else if function == "Synchro" { 51 | return cc.Synchro() 52 | } 53 | 54 | return shim.Error("Invalid Smart Contract function name.") 55 | } 56 | 57 | //This is the main smart contract of system 58 | func (cc *ChainCode) AddURL(APIstub shim.ChaincodeStubInterface, args []string) sc.Response { 59 | if len(args) != 2 { 60 | return shim.Error("Incorrect number of arguments. Expecting 2") 61 | } 62 | 63 | deviceId := args[0] 64 | url := args[1] 65 | r := m.Resource{Timestamp: time.Now().Unix(), URL: url} 66 | 67 | // put k-v to DB 68 | err := APIstub.PutState(deviceId, r.ToBytes()) 69 | if err != nil { 70 | return shim.Error(err.Error()) 71 | } 72 | 73 | return shim.Success(m.OK) 74 | } 75 | 76 | func (cc *ChainCode) GetURL(APIstub shim.ChaincodeStubInterface, args []string) sc.Response { 77 | if len(args) != 1 { 78 | return shim.Error("Incorrect number of arguments. Expecting 1") 79 | } 80 | b, _ := APIstub.GetState(args[0]) 81 | return shim.Success(b) 82 | } 83 | 84 | func (cc *ChainCode) Synchro() sc.Response { 85 | return shim.Success(m.OK) 86 | } 87 | 88 | // The main function is only relevant in unit test mode. Only included here for completeness. 89 | func main() { 90 | // Create a new Smart Contract 91 | err := shim.Start(NewDeviceContract()) 92 | if err != nil { 93 | fmt.Printf("Error creating new Smart Contract: %s", err) 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /chaincode/go/m/policy.go: -------------------------------------------------------------------------------- 1 | package m 2 | 3 | import ( 4 | "crypto/sha256" 5 | "encoding/json" 6 | "fmt" 7 | ) 8 | 9 | // Define the Policy structure 10 | type Policy struct { 11 | AS AS 12 | AO AO 13 | AP int //1 is allow , 0 is deney 14 | AE AE 15 | } 16 | 17 | type AS struct { 18 | UserId string `json:"userId"` 19 | Role string `json:"role"` 20 | Group string `json:"group"` 21 | } 22 | 23 | type AO struct { 24 | DeviceId string `json:"deviceId"` 25 | MAC string `json:"MAC"` 26 | } 27 | 28 | type AE struct { 29 | CreatedTime int64 `json:"createdTime"` 30 | EndTime int64 `json:"endTime"` 31 | AllowedIP string `json:"allowedIP"` 32 | } 33 | 34 | func (p *Policy) ToBytes() []byte { 35 | b, err := json.Marshal(*p) 36 | if err != nil { 37 | return nil 38 | } 39 | return b 40 | } 41 | 42 | func (p *Policy) GetID() string { 43 | return fmt.Sprintf("%x", sha256.Sum256([]byte(p.AS.UserId+p.AO.DeviceId))) 44 | } 45 | -------------------------------------------------------------------------------- /chaincode/go/m/policy_test.go: -------------------------------------------------------------------------------- 1 | package m 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | var p = Policy{ 9 | AS{"13800010002", "u1", "g1"}, 10 | AO{"D100010001", "00:11:22:33:44:55"}, 11 | 1, 12 | AE{1575468182, 1576468182, "*.*.*.*"}, 13 | } 14 | 15 | func Test_ToBytes(t *testing.T) { 16 | fmt.Printf("%s\n", p.ToBytes()) 17 | } 18 | 19 | func Test_GetID(t *testing.T) { 20 | println(p.GetID()) 21 | } 22 | -------------------------------------------------------------------------------- /chaincode/go/m/request.go: -------------------------------------------------------------------------------- 1 | package m 2 | 3 | import ( 4 | "crypto/sha256" 5 | "encoding/json" 6 | "fmt" 7 | "time" 8 | ) 9 | 10 | type ABACRequest struct { 11 | AS AS 12 | AO AO 13 | } 14 | 15 | func (r *ABACRequest) ToBytes() []byte { 16 | b, err := json.Marshal(*r) 17 | if err != nil { 18 | return nil 19 | } 20 | return b 21 | } 22 | 23 | type Attrs struct { 24 | DeviceId string 25 | UserId string 26 | Timestamp int64 27 | } 28 | 29 | func (a Attrs) GetId() string { 30 | return fmt.Sprintf("%x", sha256.Sum256([]byte(a.UserId+a.DeviceId))) 31 | } 32 | 33 | func (r ABACRequest) GetAttrs() Attrs { 34 | return Attrs{DeviceId: r.AO.DeviceId, UserId: r.AS.UserId, Timestamp: time.Now().Unix()} 35 | } 36 | -------------------------------------------------------------------------------- /chaincode/go/m/request_test.go: -------------------------------------------------------------------------------- 1 | package m 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func Test_ABACRequest(t *testing.T) { 9 | r := ABACRequest{ 10 | AS{"13800010002", "u1", "g1"}, 11 | AO{"D100010001", "00:11:22:33:44:55"}, 12 | } 13 | fmt.Printf("%s\n", r.ToBytes()) 14 | } 15 | -------------------------------------------------------------------------------- /chaincode/go/m/resource.go: -------------------------------------------------------------------------------- 1 | package m 2 | 3 | import "encoding/json" 4 | 5 | // Define the resource structure 6 | type Resource struct { 7 | Timestamp int64 `json:"timestamp"` 8 | URL string `json:"url"` 9 | } 10 | 11 | func (r Resource) ToBytes() []byte { 12 | b, err := json.Marshal(r) 13 | if err != nil { 14 | return nil 15 | } 16 | return b 17 | } 18 | 19 | func NewResource(b []byte) (Resource, error) { 20 | r := Resource{} 21 | err := json.Unmarshal(b, &r) 22 | return r, err 23 | } 24 | -------------------------------------------------------------------------------- /chaincode/go/m/util.go: -------------------------------------------------------------------------------- 1 | package m 2 | 3 | var OK = []byte("OK") 4 | -------------------------------------------------------------------------------- /chaincode/go/pc/pc.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | 7 | "github.com/hyperledger/fabric/core/chaincode/shim" 8 | sc "github.com/hyperledger/fabric/protos/peer" 9 | "github.com/newham/fabric-iot/chaincode/go/m" 10 | ) 11 | 12 | type PolicyContract interface { 13 | Init(shim.ChaincodeStubInterface) sc.Response 14 | Invoke(shim.ChaincodeStubInterface) sc.Response 15 | Synchro() sc.Response 16 | CheckPolicy(m.Policy) bool 17 | AddPolicy(shim.ChaincodeStubInterface, []string) sc.Response 18 | UpdatePolicy(shim.ChaincodeStubInterface, []string) sc.Response 19 | QueryPolicy(shim.ChaincodeStubInterface, []string) sc.Response 20 | DeletePolicy(shim.ChaincodeStubInterface, []string) sc.Response 21 | } 22 | 23 | // Define the Smart Contract structure 24 | type ChainCode struct { 25 | } 26 | 27 | /* 28 | * The Init method is called when the Smart Contract "fabcar" is instantiated by the blockchain network 29 | * Best practice is to have any Ledger initialization in separate function -- see initLedger() 30 | */ 31 | func (cc *ChainCode) Init(APIstub shim.ChaincodeStubInterface) sc.Response { 32 | return shim.Success(m.OK) 33 | } 34 | 35 | /* 36 | * The Invoke method is called as a result of an application request to run the Smart Contract "fabcar" 37 | * The calling application program has also specified the particular smart contract function to be called, with arguments 38 | */ 39 | func (cc *ChainCode) Invoke(APIstub shim.ChaincodeStubInterface) sc.Response { 40 | 41 | // Retrieve the requested Smart Contract function and arguments 42 | function, args := APIstub.GetFunctionAndParameters() 43 | // Route to the appropriate handler function to interact with the ledger appropriately 44 | if function == "AddPolicy" { 45 | return cc.AddPolicy(APIstub, args) 46 | } else if function == "Synchro" { 47 | return cc.Synchro() 48 | } else if function == "QueryPolicy" { 49 | return cc.QueryPolicy(APIstub, args) 50 | } else if function == "DeletePolicy" { 51 | return cc.DeletePolicy(APIstub, args) 52 | } else if function == "UpdatePolicy" { 53 | return cc.UpdatePolicy(APIstub, args) 54 | } 55 | 56 | return shim.Error("Invalid Smart Contract function name.") 57 | } 58 | 59 | func NewPolicyContract() PolicyContract { 60 | return new(ChainCode) 61 | } 62 | 63 | func (cc *ChainCode) parsePolicy(arg string) (m.Policy, error) { 64 | policyAsBytes := []byte(arg) 65 | policy := m.Policy{} 66 | err := json.Unmarshal(policyAsBytes, &policy) 67 | return policy, err 68 | } 69 | 70 | func (cc *ChainCode) CheckPolicy(p m.Policy) bool { 71 | return false 72 | } 73 | 74 | //This is the main smart contract of system 75 | func (cc *ChainCode) AddPolicy(APIstub shim.ChaincodeStubInterface, args []string) sc.Response { 76 | if len(args) != 1 { 77 | return shim.Error("Incorrect number of argumentcc. Expecting 1") 78 | } 79 | // parse policy 80 | policy, err := cc.parsePolicy(args[0]) 81 | if err != nil { 82 | return shim.Error(err.Error()) 83 | } 84 | // check it 85 | if cc.CheckPolicy(policy) { 86 | return shim.Error("bad policy") 87 | } 88 | // put k-v to DB 89 | err = APIstub.PutState(policy.GetID(), policy.ToBytes()) 90 | if err != nil { 91 | return shim.Error(err.Error()) 92 | } 93 | return shim.Success(m.OK) 94 | } 95 | 96 | func (cc *ChainCode) QueryPolicy(APIstub shim.ChaincodeStubInterface, args []string) sc.Response { 97 | if len(args) != 1 { 98 | return shim.Error("Incorrect number of argumentcc. Expecting 1") 99 | } 100 | policyAsBytes, _ := APIstub.GetState(args[0]) 101 | return shim.Success(policyAsBytes) 102 | } 103 | 104 | func (cc *ChainCode) UpdatePolicy(APIstub shim.ChaincodeStubInterface, args []string) sc.Response { 105 | if len(args) != 1 { 106 | return shim.Error("Incorrect number of argumentcc. Expecting 1") 107 | } 108 | // parse policy 109 | policy, err := cc.parsePolicy(args[0]) 110 | if err != nil { 111 | return shim.Error(err.Error()) 112 | } 113 | // check it 114 | if cc.CheckPolicy(policy) { 115 | return shim.Error("bad policy") 116 | } 117 | r := cc.QueryPolicy(APIstub, []string{policy.GetID()}) 118 | if r.GetStatus() != 200 { 119 | return shim.Error("policy not exist") 120 | } 121 | return cc.AddPolicy(APIstub, args) 122 | } 123 | 124 | func (cc *ChainCode) DeletePolicy(APIstub shim.ChaincodeStubInterface, args []string) sc.Response { 125 | if len(args) != 1 { 126 | return shim.Error("Incorrect number of argumentcc. Expecting 1") 127 | } 128 | err := APIstub.DelState(args[0]) 129 | if err != nil { 130 | return shim.Error(err.Error()) 131 | } 132 | return shim.Success(m.OK) 133 | } 134 | 135 | func (cc *ChainCode) Synchro() sc.Response { 136 | return shim.Success(m.OK) 137 | } 138 | 139 | // The main function is only relevant in unit test mode. Only included here for completenescc. 140 | func main() { 141 | 142 | // Create a new Smart Contract 143 | err := shim.Start(NewPolicyContract()) 144 | if err != nil { 145 | fmt.Printf("Error creating new Smart Contract: %s", err) 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /client/nodejs/base.js: -------------------------------------------------------------------------------- 1 | //common 2 | const fs = require('fs'); 3 | const path = require('path'); 4 | const ccpPath = path.resolve(__dirname, '..', '..', 'network', 'conn-conf', 'connection-org1.json'); 5 | const ccpJSON = fs.readFileSync(ccpPath, 'utf8'); 6 | const ccp = JSON.parse(ccpJSON); 7 | //fabric SDK 8 | const FabricCAServices = require('fabric-ca-client'); 9 | const { FileSystemWallet, Gateway, X509WalletMixin } = require('fabric-network'); 10 | //const value 11 | const CHANNEL_NAME = 'iot-channel'; 12 | //exports 13 | exports.ccp = ccp; 14 | exports.ccpPath = ccpPath; 15 | exports.path = path; 16 | exports.FabricCAServices = FabricCAServices; 17 | exports.FileSystemWallet = FileSystemWallet; 18 | exports.X509WalletMixin = X509WalletMixin; 19 | exports.Gateway = Gateway; 20 | exports.CHANNEL_NAME = CHANNEL_NAME; 21 | -------------------------------------------------------------------------------- /client/nodejs/enrollAdmin.js: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-License-Identifier: Apache-2.0 3 | */ 4 | 'use strict'; 5 | 6 | const { FabricCAServices, X509WalletMixin, FileSystemWallet, path, ccp } = require('./base') 7 | 8 | async function main() { 9 | try { 10 | 11 | // Create a new CA client for interacting with the CA. 12 | const caInfo = ccp.certificateAuthorities['ca.org1.fabric-iot.edu']; 13 | const caTLSCACerts = caInfo.tlsCACerts.pem; 14 | const ca = new FabricCAServices(caInfo.url, { trustedRoots: caTLSCACerts, verify: false }, caInfo.caName); 15 | 16 | // Create a new file system based wallet for managing identities. 17 | const walletPath = path.join(process.cwd(), 'wallet'); 18 | const wallet = new FileSystemWallet(walletPath); 19 | console.log(`Wallet path: ${walletPath}`); 20 | 21 | // Check to see if we've already enrolled the admin user. 22 | const adminExists = await wallet.exists('admin'); 23 | if (adminExists) { 24 | console.log('An identity for the admin user "admin" already exists in the wallet'); 25 | return; 26 | } 27 | 28 | // Enroll the admin user, and import the new identity into the wallet. 29 | const enrollment = await ca.enroll({ enrollmentID: 'admin', enrollmentSecret: 'adminpw' }); 30 | const identity = X509WalletMixin.createIdentity('Org1MSP', enrollment.certificate, enrollment.key.toBytes()); 31 | await wallet.import('admin', identity); 32 | console.log('Successfully enrolled admin user "admin" and imported it into the wallet'); 33 | 34 | } catch (error) { 35 | console.error(`Failed to enroll admin user "admin": ${error}`); 36 | process.exit(1); 37 | } 38 | } 39 | 40 | main(); 41 | -------------------------------------------------------------------------------- /client/nodejs/init.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | rm -rf wallet 4 | node ./enrollAdmin.js 5 | node ./registerUser.js -------------------------------------------------------------------------------- /client/nodejs/invoke.js: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-License-Identifier: Apache-2.0 3 | */ 4 | 5 | 'use strict'; 6 | 7 | const { ccpPath, path, FileSystemWallet, Gateway, CHANNEL_NAME } = require("./base") 8 | 9 | function resp(status, msg) { 10 | return { status: status, msg: msg } 11 | } 12 | 13 | var isCMD = false 14 | 15 | async function main() { 16 | isCMD = true 17 | try { 18 | const argv = process.argv; 19 | if (argv.length < 5) { 20 | // console.log("[chaincode name] [function name] [arg]"); 21 | console.log('need [chaincode name] [function name] [arg]') 22 | return; 23 | } 24 | // from 2 is args begin 25 | const ccName = argv[2] 26 | const fName = argv[3] 27 | const args = argv.slice(4) //[a,b] to "a b" 28 | 29 | invoke(ccName, fName, args) 30 | } catch (error) { 31 | // console.error(`Failed to evaluate transaction: ${error}`); 32 | process.exit(1); 33 | } 34 | } 35 | async function invoke(ccName, fName, args) { 36 | try { 37 | // Create a new file system based wallet for managing identities. 38 | const walletPath = path.join(process.cwd(), 'wallet'); 39 | const wallet = new FileSystemWallet(walletPath); 40 | if (isCMD) { 41 | console.log(`Wallet path: ${walletPath}`); 42 | } 43 | 44 | // Check to see if we've already enrolled the user. 45 | const user = 'user1' 46 | const userExists = await wallet.exists(user); 47 | if (!userExists) { 48 | if (isCMD) { 49 | console.log(`An identity for the user "${user}" does not exist in the wallet`); 50 | console.log('Run the registerUser.js application before retrying'); 51 | } 52 | return resp(500, 'Run the registerUser.js application before retrying'); 53 | } 54 | 55 | // Create a new gateway for connecting to our peer node. 56 | const gateway = new Gateway(); 57 | await gateway.connect(ccpPath, { wallet, identity: user, discovery: { enabled: true, asLocalhost: true } }); 58 | 59 | // Get the network (channel) our contract is deployed to. 60 | const network = await gateway.getNetwork(CHANNEL_NAME); 61 | 62 | // Get the contract from the network. 63 | const contract = network.getContract(ccName); 64 | 65 | // Evaluate the specified transaction. 66 | // queryCar transaction - requires 1 argument, ex: ('queryCar', 'CAR4') 67 | // queryAllCars transaction - requires no arguments, ex: ('queryAllCars') 68 | if (isCMD) { 69 | console.log(ccName, fName, ...args) 70 | } 71 | switch (fName) { 72 | case "AddURL": 73 | case "GetURL": 74 | case "AddPolicy": 75 | case "DeletePolicy": 76 | case "UpdatePolicy": 77 | case "CheckAccess": 78 | const r1 = await contract.submitTransaction(fName, ...args); 79 | if (isCMD) { 80 | console.log(`Transaction has been submit, result is: ${r1.toString()}`); 81 | 82 | //exit cmd 83 | process.exit(1); 84 | 85 | } 86 | return resp(200, r1.toString()) 87 | break; 88 | default: 89 | // const r2 = await contract.evaluateTransaction(fName, ...args); 90 | if (isCMD) { 91 | console.log(`Transaction has been evaluated, result is: bad cc name`); 92 | } 93 | return resp(400, 'bad cc name') 94 | break; 95 | } 96 | 97 | 98 | } catch (error) { 99 | if (isCMD) { 100 | console.error(`Failed to evaluate transaction: ${error}`); 101 | process.exit(1); 102 | } 103 | return resp(500, error) 104 | } 105 | } 106 | 107 | main(); 108 | 109 | module.exports = { invoke } -------------------------------------------------------------------------------- /client/nodejs/invoke_test.sh: -------------------------------------------------------------------------------- 1 | node invoke.js dc AddURL D100010001 https://test.iot.org/voice00001.mp3 2 | # node invoke.js dc GetURL D100010001 3 | 4 | # node invoke.js pc AddPolicy '{"AS":{"userId":"13800010002","role":"u1","group":"g1"},"AO":{"deviceId":"D100010001","MAC":"00:11:22:33:44:55"},"AP":1,"AE":{"createdTime":1575468182,"endTime":1576468182,"allowedIP":"*.*.*.*"}}' 5 | # node invoke.js pc QueryPolicy da1f08aa8ee250a65057c354b6952e2baf6ae3c9505cb9ca3e5ab4138e56b9d1 6 | 7 | # node invoke.js pc AddPolicy '{"AS":{"userId":"13800010001","role":"u1","group":"g1"},"AO":{"deviceId":"D100010001","MAC":"00:11:22:33:44:55"},"AP":1,"AE":{"createdTime":1575468182,"endTime":1576468182,"allowedIP":"*.*.*.*"}}' 8 | # node invoke.js pc QueryPolicy 40db810e4ccb4cc1f3d5bc5803fb61e863cf05ea7fc2f63165599ef53adf5623 9 | 10 | # node invoke.js ac CheckAccess '{"AS":{"userId":"13800010002","role":"u1","group":"g1"},"AO":{"deviceId":"D100010001","MAC":"00:11:22:33:44:55"}}' 11 | # node invoke.js ac CheckAccess '{"AS":{"userId":"13800010001","role":"u1","group":"g1"},"AO":{"deviceId":"D100010001","MAC":"00:11:22:33:44:55"}}' -------------------------------------------------------------------------------- /client/nodejs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "fabcar", 3 | "version": "1.0.0", 4 | "description": "FabCar application implemented in JavaScript", 5 | "engines": { 6 | "node": ">=8", 7 | "npm": ">=5" 8 | }, 9 | "scripts": { 10 | "lint": "eslint .", 11 | "pretest": "npm run lint", 12 | "test": "nyc mocha --recursive" 13 | }, 14 | "engineStrict": true, 15 | "author": "Hyperledger", 16 | "license": "Apache-2.0", 17 | "dependencies": { 18 | "express": "^4.17.1", 19 | "fabric-ca-client": "~1.4.0", 20 | "fabric-network": "~1.4.0" 21 | }, 22 | "devDependencies": { 23 | "chai": "^4.2.0", 24 | "eslint": "^5.9.0", 25 | "mocha": "^5.2.0", 26 | "nyc": "^13.1.0", 27 | "sinon": "^7.1.1", 28 | "sinon-chai": "^3.3.0" 29 | }, 30 | "nyc": { 31 | "exclude": [ 32 | "coverage/**", 33 | "test/**" 34 | ], 35 | "reporter": [ 36 | "text-summary", 37 | "html" 38 | ], 39 | "all": true, 40 | "check-coverage": true, 41 | "statements": 100, 42 | "branches": 100, 43 | "functions": 100, 44 | "lines": 100 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /client/nodejs/registerUser.js: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-License-Identifier: Apache-2.0 3 | */ 4 | 5 | 'use strict'; 6 | 7 | const { FileSystemWallet, Gateway, X509WalletMixin, ccpPath, path } = require('./base') 8 | 9 | async function main() { 10 | try { 11 | 12 | const user = 'user1' 13 | 14 | // Create a new file system based wallet for managing identities. 15 | const walletPath = path.join(process.cwd(), 'wallet'); 16 | const wallet = new FileSystemWallet(walletPath); 17 | console.log(`Wallet path: ${walletPath}`); 18 | 19 | // Check to see if we've already enrolled the user. 20 | const userExists = await wallet.exists(user); 21 | if (userExists) { 22 | console.log(`An identity for the user "${user}" already exists in the wallet`); 23 | return; 24 | } 25 | 26 | // Check to see if we've already enrolled the admin user. 27 | const adminExists = await wallet.exists('admin'); 28 | if (!adminExists) { 29 | console.log('An identity for the admin user "admin" does not exist in the wallet'); 30 | console.log('Run the enrollAdmin.js application before retrying'); 31 | return; 32 | } 33 | 34 | // Create a new gateway for connecting to our peer node. 35 | const gateway = new Gateway(); 36 | await gateway.connect(ccpPath, { wallet, identity: 'admin', discovery: { enabled: true, asLocalhost: true } }); 37 | 38 | // Get the CA client object from the gateway for interacting with the CA. 39 | const ca = gateway.getClient().getCertificateAuthority(); 40 | const adminIdentity = gateway.getCurrentIdentity(); 41 | 42 | // Register the user, enroll the user, and import the new identity into the wallet. 43 | const secret = await ca.register({ affiliation: 'org1.department1', enrollmentID: user, role: 'client' }, adminIdentity); 44 | const enrollment = await ca.enroll({ enrollmentID: user, enrollmentSecret: secret }); 45 | const userIdentity = X509WalletMixin.createIdentity('Org1MSP', enrollment.certificate, enrollment.key.toBytes()); 46 | await wallet.import(user, userIdentity); 47 | console.log(`Successfully registered and enrolled admin user "${user}" and imported it into the wallet`); 48 | 49 | } catch (error) { 50 | console.error(`Failed to register user "${user}": ${error}`); 51 | process.exit(1); 52 | } 53 | } 54 | 55 | main(); 56 | -------------------------------------------------------------------------------- /client/nodejs/test.js: -------------------------------------------------------------------------------- 1 | // 测试用客户端,测试系统接口性能 2 | 3 | var express = require('express') 4 | var app = express() 5 | 6 | const { invoke } = require("./invoke") 7 | 8 | // respond with "hello world" when a GET request is made to the homepage 9 | app.get('/fabric-iot/test', async function (req, res) { 10 | const cc_name = req.query.cc_name; 11 | const f_name = req.query.f_name; 12 | const args = req.query.args; 13 | // console.log("invoke",cc_name,f_name,args); 14 | if (cc_name == undefined || f_name == undefined || args == undefined) { 15 | res.status(400).send({ status: 400, msg: 'bad params' }); 16 | return 17 | } 18 | const r = await invoke(cc_name, f_name, args.split("|")); 19 | res.status(r.status).send(r); 20 | }) 21 | 22 | const port = 8001 23 | app.listen(port, () => console.log(`Test invoke on port ${port}!`)) -------------------------------------------------------------------------------- /daemon.json: -------------------------------------------------------------------------------- 1 | { 2 | "registry-mirrors": [ 3 | "https://f1z25q5p.mirror.aliyuncs.com", 4 | "https://d8b3zdiw.mirror.aliyuncs.com" 5 | ] 6 | } -------------------------------------------------------------------------------- /docker.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 更新软件 4 | sudo apt-get update 5 | # 安装依赖工具 6 | sudo apt-get install \ 7 | apt-transport-https \ 8 | ca-certificates \ 9 | curl \ 10 | gnupg-agent \ 11 | software-properties-common 12 | 13 | # SET UP THE REPOSITORY 14 | curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - 15 | 16 | sudo add-apt-repository \ 17 | "deb [arch=amd64] https://download.docker.com/linux/ubuntu \ 18 | $(lsb_release -cs) \ 19 | stable" 20 | 21 | # INSTALL DOCKER ENGINE 22 | sudo apt-get update 23 | sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose 24 | 25 | #将当前用户添加至docker用户组 26 | sudo gpasswd -a $USER docker 27 | #更新docker用户组 28 | newgrp docker 29 | 30 | #添加淘宝源 31 | echo "==> 添加淘宝源" 32 | # sudo echo '{ "registry-mirrors": ["https://f1z25q5p.mirror.aliyuncs.com"] }' > /etc/docker/daemon.json 33 | sudo cp daemon.json /etc/docker/ 34 | echo "==> 重启docker以适配" 35 | sudo systemctl daemon-reload 36 | sudo systemctl restart docker -------------------------------------------------------------------------------- /network/cc-install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Exit on first error 4 | set -e 5 | 6 | echo "=================== start ===================" 7 | echo start at:$(date +%Y-%m-%d\ %H:%M:%S) 8 | echo "=============================================" 9 | ./cc.sh install ac 1.0 go/ac Synchro 10 | ./cc.sh install pc 1.0 go/pc Synchro 11 | ./cc.sh install dc 1.0 go/dc Synchro 12 | echo "=================== end ===================" 13 | echo end at: $(date +%Y-%m-%d\ %H:%M:%S) 14 | echo "===========================================" 15 | -------------------------------------------------------------------------------- /network/cc-test.sh: -------------------------------------------------------------------------------- 1 | # upgrade 2 | # shell|action|cc_name|cc_version|cc_src|fname|args 3 | ./cc.sh upgrade pc 1.1 go/dc Synchro 4 | 5 | # install 6 | # shell|action|cc_name|cc_version|cc_src|fname|args 7 | ./cc.sh install pc 1.0 go/ac Synchro 8 | 9 | # invoke 10 | # shell|action|cc_name|cc_version|cc_src|fname|args 11 | # add policy 12 | ./cc.sh invoke pc 1.0 go/pc AddPolicy '"{\"AS\":{\"userId\":\"13800010001\",\"role\":\"u1\",\"group\":\"g1\"},\"AO\":{\"deviceId\":\"D100010001\",\"MAC\":\"00:11:22:33:44:55\"}}"' 13 | # query policy 14 | ./cc.sh invoke pc 1.0 go/pc QueryPolicy '"40db810e4ccb4cc1f3d5bc5803fb61e863cf05ea7fc2f63165599ef53adf5623"' 15 | # abe 16 | ./cc.sh invoke abe 0.1 go/abe CheckAccess '"My secret code","((0 AND 1) OR (2 AND 3)) AND 4","0 1 3 4"' -------------------------------------------------------------------------------- /network/cc-upgrade.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Exit on first error 4 | set -e 5 | 6 | ./cc.sh upgrade ac 1.2 go/ac Synchro -------------------------------------------------------------------------------- /network/cc.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Exit on first error 4 | set -e 5 | 6 | # don't rewrite paths for Windows Git Bash users 7 | export MSYS_NO_PATHCONV=1 8 | starttime=$(date +%s) 9 | # use golang as programing language 10 | CC_RUNTIME_LANGUAGE=golang 11 | CC_SRC_PATH=github.com/newham/fabric-iot/chaincode/go/pc 12 | CC_NAME=PC 13 | CC_VERSION=1.0 14 | CC_INVOKE_FUNC_NAME="Synchro" 15 | ARGS='' 16 | # client container's name 17 | CLI=cli 18 | # action 19 | ACTION=install 20 | 21 | # set needed values 22 | CONFIG_ROOT=/opt/gopath/src/github.com/hyperledger/fabric/peer 23 | ORG1_MSPCONFIGPATH=${CONFIG_ROOT}/crypto/peerOrganizations/org1.fabric-iot.edu/users/Admin@org1.fabric-iot.edu/msp 24 | ORG1_TLS_ROOTCERT_FILE=${CONFIG_ROOT}/crypto/peerOrganizations/org1.fabric-iot.edu/peers/peer0.org1.fabric-iot.edu/tls/ca.crt 25 | ORG2_MSPCONFIGPATH=${CONFIG_ROOT}/crypto/peerOrganizations/org2.fabric-iot.edu/users/Admin@org2.fabric-iot.edu/msp 26 | ORG2_TLS_ROOTCERT_FILE=${CONFIG_ROOT}/crypto/peerOrganizations/org2.fabric-iot.edu/peers/peer0.org2.fabric-iot.edu/tls/ca.crt 27 | ORDERER_TLS_ROOTCERT_FILE=${CONFIG_ROOT}/crypto/ordererOrganizations/fabric-iot.edu/orderers/orderer.fabric-iot.edu/msp/tlscacerts/tlsca.fabric-iot.edu-cert.pem 28 | 29 | 30 | if [ -n $1 -a -n $2 -a -n $3 -a -n $4 ]; then 31 | ACTION=$1 32 | CC_NAME=$2 33 | CC_VERSION=$3 34 | CC_SRC_PATH="github.com/newham/fabric-iot/chaincode/$4" 35 | if [ ! $5 = '' ]; then 36 | CC_INVOKE_FUNC_NAME=$5 37 | fi 38 | if [ ! $6 = '' ]; then 39 | ARGS=$6 40 | fi 41 | echo $ACTION ${CC_NAME}:${CC_VERSION} $CC_SRC_PATH $CC_INVOKE_FUNC_NAME $ARGS 42 | else 43 | echo './cc.sh ["install"/"upgrade"] [cc name] [cc version] [cc src path] [fname]' 44 | exit 1 45 | fi 46 | 47 | 48 | # 1:org 2:peer 3:port 4:ORG1_MSPCONFIGPATH 5:ORG1_TLS_ROOTCERT_FILE 49 | function installCC() { 50 | if [ ${1} = 1 ]; then 51 | MSPCONFIGPATH=$ORG1_MSPCONFIGPATH 52 | TLS_ROOTCERT_FILE=$ORG1_TLS_ROOTCERT_FILE 53 | elif [ ${1} = 2 ]; then 54 | MSPCONFIGPATH=$ORG2_MSPCONFIGPATH 55 | TLS_ROOTCERT_FILE=$ORG2_TLS_ROOTCERT_FILE 56 | else 57 | echo "Worng Org,check it" 58 | exit 1 59 | fi 60 | echo "Installing smart contract on peer${2}.org${1}.fabric-iot.edu" 61 | docker exec \ 62 | -e CORE_PEER_LOCALMSPID=Org${1}MSP \ 63 | -e CORE_PEER_ADDRESS=peer${2}.org${1}.fabric-iot.edu:${3} \ 64 | -e CORE_PEER_MSPCONFIGPATH=${MSPCONFIGPATH} \ 65 | -e CORE_PEER_TLS_ROOTCERT_FILE=${TLS_ROOTCERT_FILE} \ 66 | $CLI \ 67 | peer chaincode install \ 68 | -n "$CC_NAME" \ 69 | -v "$CC_VERSION" \ 70 | -p "$CC_SRC_PATH" \ 71 | -l "$CC_RUNTIME_LANGUAGE" 72 | } 73 | 74 | function initCC() { 75 | echo "Instantiating smart contract on iot-channel" 76 | docker exec \ 77 | -e CORE_PEER_LOCALMSPID=Org1MSP \ 78 | -e CORE_PEER_MSPCONFIGPATH=${ORG1_MSPCONFIGPATH} \ 79 | $CLI \ 80 | peer chaincode instantiate \ 81 | -o orderer.fabric-iot.edu:7050 \ 82 | -C iot-channel \ 83 | -n "$CC_NAME" \ 84 | -l "$CC_RUNTIME_LANGUAGE" \ 85 | -v "$CC_VERSION" \ 86 | -c '{"Args":[]}' \ 87 | -P "AND('Org1MSP.member','Org2MSP.member')" \ 88 | --tls \ 89 | --cafile ${ORDERER_TLS_ROOTCERT_FILE} \ 90 | --peerAddresses peer0.org1.fabric-iot.edu:7051 \ 91 | --tlsRootCertFiles ${ORG1_TLS_ROOTCERT_FILE} 92 | 93 | echo "Waiting for contract instantiating..." 94 | process 15 95 | } 96 | 97 | function process() { 98 | for ((i = 1; i <= ${1}; i++)); do 99 | sleep 1 100 | echo -e ">\c" 101 | done 102 | echo 103 | } 104 | 105 | function invokeCC() { 106 | echo "Submitting transaction:${CC_INVOKE_FUNC_NAME} to smart contract on iot-channel" 107 | echo 'ARGS:{"function":"'$CC_INVOKE_FUNC_NAME'","Args":['$ARGS']}' 108 | echo "The transaction is sent to all of the peers so that chaincode is built before receiving the following requests" 109 | docker exec \ 110 | -e CORE_PEER_LOCALMSPID=Org1MSP \ 111 | -e CORE_PEER_MSPCONFIGPATH=${ORG1_MSPCONFIGPATH} \ 112 | $CLI \ 113 | peer chaincode invoke \ 114 | -o orderer.fabric-iot.edu:7050 \ 115 | -C iot-channel \ 116 | -n "$CC_NAME" \ 117 | -c '{"function":"'$CC_INVOKE_FUNC_NAME'","Args":['$ARGS']}' \ 118 | --waitForEvent \ 119 | --tls \ 120 | --cafile ${ORDERER_TLS_ROOTCERT_FILE} \ 121 | --peerAddresses peer0.org1.fabric-iot.edu:7051 \ 122 | --peerAddresses peer1.org1.fabric-iot.edu:8051 \ 123 | --peerAddresses peer0.org2.fabric-iot.edu:9051 \ 124 | --peerAddresses peer1.org2.fabric-iot.edu:10051 \ 125 | --tlsRootCertFiles ${ORG1_TLS_ROOTCERT_FILE} \ 126 | --tlsRootCertFiles ${ORG1_TLS_ROOTCERT_FILE} \ 127 | --tlsRootCertFiles ${ORG2_TLS_ROOTCERT_FILE} \ 128 | --tlsRootCertFiles ${ORG2_TLS_ROOTCERT_FILE} 129 | 130 | } 131 | 132 | function upgradeCC() { 133 | echo "Upgrading smart contract on iot-channel" 134 | docker exec \ 135 | -e CORE_PEER_LOCALMSPID=Org1MSP \ 136 | -e CORE_PEER_MSPCONFIGPATH=${ORG1_MSPCONFIGPATH} \ 137 | $CLI \ 138 | peer chaincode upgrade \ 139 | -o orderer.fabric-iot.edu:7050 \ 140 | -C iot-channel \ 141 | -n "$CC_NAME" \ 142 | -l "$CC_RUNTIME_LANGUAGE" \ 143 | -v "$CC_VERSION" \ 144 | -c '{"Args":[]}' \ 145 | -P "AND('Org1MSP.member','Org2MSP.member')" \ 146 | --tls \ 147 | --cafile ${ORDERER_TLS_ROOTCERT_FILE} \ 148 | --peerAddresses peer0.org1.fabric-iot.edu:7051 \ 149 | --tlsRootCertFiles ${ORG1_TLS_ROOTCERT_FILE} 150 | 151 | echo "Waiting for instantiation request to be committed ..." 152 | sleep 15 153 | } 154 | 155 | # set -x 156 | 157 | function deployCC(){ 158 | # install cc 159 | installCC 1 0 7051 160 | installCC 1 1 8051 161 | installCC 2 0 9051 162 | installCC 2 1 10051 163 | } 164 | 165 | # init 166 | if [ $ACTION = 'install' ]; then 167 | deployCC 168 | initCC 169 | invokeCC # 调用 Synchro 方法,为 chaincode 背书 170 | elif [ $ACTION = 'upgrade' ]; then 171 | deployCC 172 | upgradeCC 173 | invokeCC # 调用 Synchro 方法,为 chaincode 背书 174 | elif [ $ACTION = 'invoke' ]; then 175 | invokeCC 176 | fi 177 | # try 178 | # if [ ! $CC_INVOKE_FUNC_NAME = '' ]; then 179 | # invokeCC 180 | # fi 181 | 182 | echo "done" 183 | 184 | # set +x -------------------------------------------------------------------------------- /network/ccp-generate.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | . env.sh 4 | 5 | function one_line_pem { 6 | echo "`awk 'NF {sub(/\\n/, ""); printf "%s\\\\\\\n",$0;}' $1`" 7 | } 8 | 9 | function json_ccp { 10 | local PP=$(one_line_pem $5) 11 | local CP=$(one_line_pem $6) 12 | sed -e "s/\${ORG}/$1/" \ 13 | -e "s/\${P0PORT}/$2/" \ 14 | -e "s/\${P1PORT}/$3/" \ 15 | -e "s/\${CAPORT}/$4/" \ 16 | -e "s#\${PEERPEM}#$PP#" \ 17 | -e "s#\${CAPEM}#$CP#" \ 18 | $CONN_CONF_PATH/ccp-template.json 19 | } 20 | 21 | function yaml_ccp { 22 | local PP=$(one_line_pem $5) 23 | local CP=$(one_line_pem $6) 24 | sed -e "s/\${ORG}/$1/" \ 25 | -e "s/\${P0PORT}/$2/" \ 26 | -e "s/\${P1PORT}/$3/" \ 27 | -e "s/\${CAPORT}/$4/" \ 28 | -e "s#\${PEERPEM}#$PP#" \ 29 | -e "s#\${CAPEM}#$CP#" \ 30 | $CONN_CONF_PATH/ccp-template.yaml | sed -e $'s/\\\\n/\\\n /g' 31 | } 32 | 33 | ORG=1 34 | P0PORT=7051 35 | P1PORT=8051 36 | CAPORT=7054 37 | PEERPEM=crypto-config/peerOrganizations/org1.fabric-iot.edu/tlsca/tlsca.org1.fabric-iot.edu-cert.pem 38 | CAPEM=crypto-config/peerOrganizations/org1.fabric-iot.edu/ca/ca.org1.fabric-iot.edu-cert.pem 39 | 40 | echo "$(json_ccp $ORG $P0PORT $P1PORT $CAPORT $PEERPEM $CAPEM)" > $CONN_CONF_PATH/connection-org1.json 41 | echo "$(yaml_ccp $ORG $P0PORT $P1PORT $CAPORT $PEERPEM $CAPEM)" > $CONN_CONF_PATH/connection-org1.yaml 42 | 43 | ORG=2 44 | P0PORT=9051 45 | P1PORT=10051 46 | CAPORT=8054 47 | PEERPEM=crypto-config/peerOrganizations/org2.fabric-iot.edu/tlsca/tlsca.org2.fabric-iot.edu-cert.pem 48 | CAPEM=crypto-config/peerOrganizations/org2.fabric-iot.edu/ca/ca.org2.fabric-iot.edu-cert.pem 49 | 50 | echo "$(json_ccp $ORG $P0PORT $P1PORT $CAPORT $PEERPEM $CAPEM)" > $CONN_CONF_PATH/connection-org2.json 51 | echo "$(yaml_ccp $ORG $P0PORT $P1PORT $CAPORT $PEERPEM $CAPEM)" > $CONN_CONF_PATH/connection-org2.yaml 52 | -------------------------------------------------------------------------------- /network/channel-artifacts/readme.md: -------------------------------------------------------------------------------- 1 | **this folder contains certs** -------------------------------------------------------------------------------- /network/clear-docker.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 默认筛选关键词 4 | key=iot 5 | # 输入关键词 6 | if [ -n "$1" ] ;then 7 | key="$1" 8 | fi 9 | 10 | # 取得所有符合条件的容器名 11 | containers=$(docker ps -a |grep $key |awk '{print $1}') 12 | if [ ! -n "$containers" ] ;then 13 | echo "no containers" 14 | else 15 | # 删除停止的容器 16 | docker rm $containers 17 | fi 18 | 19 | # 取得所有符合条件的镜像名 20 | imgs=$(docker images |grep $key |awk '{print $3}') 21 | if [ ! -n "$imgs" ] ;then 22 | echo "no imgs" 23 | else 24 | # 删除镜像 25 | docker rmi -f $imgs 26 | fi 27 | -------------------------------------------------------------------------------- /network/compose-files/base/docker-compose-base.yaml: -------------------------------------------------------------------------------- 1 | # Copyright IBM Corp. All Rights Reserved. 2 | # 3 | # SPDX-License-Identifier: Apache-2.0 4 | # 5 | 6 | version: '2' 7 | 8 | services: 9 | 10 | orderer.fabric-iot.edu: 11 | container_name: orderer.fabric-iot.edu 12 | extends: 13 | file: peer-base.yaml 14 | service: orderer-base 15 | volumes: 16 | - ../../channel-artifacts/genesis.block:/var/hyperledger/orderer/orderer.genesis.block 17 | - ../../crypto-config/ordererOrganizations/fabric-iot.edu/orderers/orderer.fabric-iot.edu/msp:/var/hyperledger/orderer/msp 18 | - ../../crypto-config/ordererOrganizations/fabric-iot.edu/orderers/orderer.fabric-iot.edu/tls/:/var/hyperledger/orderer/tls 19 | - orderer.fabric-iot.edu:/var/hyperledger/production/orderer 20 | ports: 21 | - 7050:7050 22 | 23 | peer0.org1.fabric-iot.edu: 24 | container_name: peer0.org1.fabric-iot.edu 25 | extends: 26 | file: peer-base.yaml 27 | service: peer-base 28 | environment: 29 | - CORE_PEER_ID=peer0.org1.fabric-iot.edu 30 | - CORE_PEER_ADDRESS=peer0.org1.fabric-iot.edu:7051 31 | - CORE_PEER_LISTENADDRESS=0.0.0.0:7051 32 | - CORE_PEER_CHAINCODEADDRESS=peer0.org1.fabric-iot.edu:7052 33 | - CORE_PEER_CHAINCODELISTENADDRESS=0.0.0.0:7052 34 | - CORE_PEER_GOSSIP_BOOTSTRAP=peer1.org1.fabric-iot.edu:8051 35 | - CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer0.org1.fabric-iot.edu:7051 36 | - CORE_PEER_LOCALMSPID=Org1MSP 37 | volumes: 38 | - /var/run/:/host/var/run/ 39 | - ../../crypto-config/peerOrganizations/org1.fabric-iot.edu/peers/peer0.org1.fabric-iot.edu/msp:/etc/hyperledger/fabric/msp 40 | - ../../crypto-config/peerOrganizations/org1.fabric-iot.edu/peers/peer0.org1.fabric-iot.edu/tls:/etc/hyperledger/fabric/tls 41 | - peer0.org1.fabric-iot.edu:/var/hyperledger/production 42 | ports: 43 | - 7051:7051 44 | 45 | peer1.org1.fabric-iot.edu: 46 | container_name: peer1.org1.fabric-iot.edu 47 | extends: 48 | file: peer-base.yaml 49 | service: peer-base 50 | environment: 51 | - CORE_PEER_ID=peer1.org1.fabric-iot.edu 52 | - CORE_PEER_ADDRESS=peer1.org1.fabric-iot.edu:8051 53 | - CORE_PEER_LISTENADDRESS=0.0.0.0:8051 54 | - CORE_PEER_CHAINCODEADDRESS=peer1.org1.fabric-iot.edu:8052 55 | - CORE_PEER_CHAINCODELISTENADDRESS=0.0.0.0:8052 56 | - CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer1.org1.fabric-iot.edu:8051 57 | - CORE_PEER_GOSSIP_BOOTSTRAP=peer0.org1.fabric-iot.edu:7051 58 | - CORE_PEER_LOCALMSPID=Org1MSP 59 | volumes: 60 | - /var/run/:/host/var/run/ 61 | - ../../crypto-config/peerOrganizations/org1.fabric-iot.edu/peers/peer1.org1.fabric-iot.edu/msp:/etc/hyperledger/fabric/msp 62 | - ../../crypto-config/peerOrganizations/org1.fabric-iot.edu/peers/peer1.org1.fabric-iot.edu/tls:/etc/hyperledger/fabric/tls 63 | - peer1.org1.fabric-iot.edu:/var/hyperledger/production 64 | 65 | ports: 66 | - 8051:8051 67 | 68 | peer0.org2.fabric-iot.edu: 69 | container_name: peer0.org2.fabric-iot.edu 70 | extends: 71 | file: peer-base.yaml 72 | service: peer-base 73 | environment: 74 | - CORE_PEER_ID=peer0.org2.fabric-iot.edu 75 | - CORE_PEER_ADDRESS=peer0.org2.fabric-iot.edu:9051 76 | - CORE_PEER_LISTENADDRESS=0.0.0.0:9051 77 | - CORE_PEER_CHAINCODEADDRESS=peer0.org2.fabric-iot.edu:9052 78 | - CORE_PEER_CHAINCODELISTENADDRESS=0.0.0.0:9052 79 | - CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer0.org2.fabric-iot.edu:9051 80 | - CORE_PEER_GOSSIP_BOOTSTRAP=peer1.org2.fabric-iot.edu:10051 81 | - CORE_PEER_LOCALMSPID=Org2MSP 82 | volumes: 83 | - /var/run/:/host/var/run/ 84 | - ../../crypto-config/peerOrganizations/org2.fabric-iot.edu/peers/peer0.org2.fabric-iot.edu/msp:/etc/hyperledger/fabric/msp 85 | - ../../crypto-config/peerOrganizations/org2.fabric-iot.edu/peers/peer0.org2.fabric-iot.edu/tls:/etc/hyperledger/fabric/tls 86 | - peer0.org2.fabric-iot.edu:/var/hyperledger/production 87 | ports: 88 | - 9051:9051 89 | 90 | peer1.org2.fabric-iot.edu: 91 | container_name: peer1.org2.fabric-iot.edu 92 | extends: 93 | file: peer-base.yaml 94 | service: peer-base 95 | environment: 96 | - CORE_PEER_ID=peer1.org2.fabric-iot.edu 97 | - CORE_PEER_ADDRESS=peer1.org2.fabric-iot.edu:10051 98 | - CORE_PEER_LISTENADDRESS=0.0.0.0:10051 99 | - CORE_PEER_CHAINCODEADDRESS=peer1.org2.fabric-iot.edu:10052 100 | - CORE_PEER_CHAINCODELISTENADDRESS=0.0.0.0:10052 101 | - CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer1.org2.fabric-iot.edu:10051 102 | - CORE_PEER_GOSSIP_BOOTSTRAP=peer0.org2.fabric-iot.edu:9051 103 | - CORE_PEER_LOCALMSPID=Org2MSP 104 | volumes: 105 | - /var/run/:/host/var/run/ 106 | - ../../crypto-config/peerOrganizations/org2.fabric-iot.edu/peers/peer1.org2.fabric-iot.edu/msp:/etc/hyperledger/fabric/msp 107 | - ../../crypto-config/peerOrganizations/org2.fabric-iot.edu/peers/peer1.org2.fabric-iot.edu/tls:/etc/hyperledger/fabric/tls 108 | - peer1.org2.fabric-iot.edu:/var/hyperledger/production 109 | ports: 110 | - 10051:10051 111 | -------------------------------------------------------------------------------- /network/compose-files/base/peer-base.yaml: -------------------------------------------------------------------------------- 1 | # Copyright IBM Corp. All Rights Reserved. 2 | # 3 | # SPDX-License-Identifier: Apache-2.0 4 | # 5 | 6 | version: '2' 7 | 8 | services: 9 | peer-base: 10 | image: hyperledger/fabric-peer:$IMAGE_TAG 11 | environment: 12 | - CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock 13 | # the following setting starts chaincode containers on the same 14 | # bridge network as the peers 15 | # https://docs.docker.com/compose/networking/ 16 | - CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=${COMPOSE_PROJECT_NAME}_bc_net 17 | - FABRIC_LOGGING_SPEC=INFO 18 | #- FABRIC_LOGGING_SPEC=DEBUG 19 | - CORE_PEER_TLS_ENABLED=true 20 | - CORE_PEER_GOSSIP_USELEADERELECTION=true 21 | - CORE_PEER_GOSSIP_ORGLEADER=false 22 | - CORE_PEER_PROFILE_ENABLED=true 23 | - CORE_PEER_TLS_CERT_FILE=/etc/hyperledger/fabric/tls/server.crt 24 | - CORE_PEER_TLS_KEY_FILE=/etc/hyperledger/fabric/tls/server.key 25 | - CORE_PEER_TLS_ROOTCERT_FILE=/etc/hyperledger/fabric/tls/ca.crt 26 | working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer 27 | command: peer node start 28 | 29 | orderer-base: 30 | image: hyperledger/fabric-orderer:$IMAGE_TAG 31 | environment: 32 | - FABRIC_LOGGING_SPEC=INFO 33 | - ORDERER_GENERAL_LISTENADDRESS=0.0.0.0 34 | - ORDERER_GENERAL_GENESISMETHOD=file 35 | - ORDERER_GENERAL_GENESISFILE=/var/hyperledger/orderer/orderer.genesis.block 36 | - ORDERER_GENERAL_LOCALMSPID=OrdererMSP 37 | - ORDERER_GENERAL_LOCALMSPDIR=/var/hyperledger/orderer/msp 38 | # enabled TLS 39 | - ORDERER_GENERAL_TLS_ENABLED=true 40 | - ORDERER_GENERAL_TLS_PRIVATEKEY=/var/hyperledger/orderer/tls/server.key 41 | - ORDERER_GENERAL_TLS_CERTIFICATE=/var/hyperledger/orderer/tls/server.crt 42 | - ORDERER_GENERAL_TLS_ROOTCAS=[/var/hyperledger/orderer/tls/ca.crt] 43 | - ORDERER_KAFKA_TOPIC_REPLICATIONFACTOR=1 44 | - ORDERER_KAFKA_VERBOSE=true 45 | - ORDERER_GENERAL_CLUSTER_CLIENTCERTIFICATE=/var/hyperledger/orderer/tls/server.crt 46 | - ORDERER_GENERAL_CLUSTER_CLIENTPRIVATEKEY=/var/hyperledger/orderer/tls/server.key 47 | - ORDERER_GENERAL_CLUSTER_ROOTCAS=[/var/hyperledger/orderer/tls/ca.crt] 48 | working_dir: /opt/gopath/src/github.com/hyperledger/fabric 49 | command: orderer 50 | 51 | -------------------------------------------------------------------------------- /network/compose-files/docker-compose-ca.yaml: -------------------------------------------------------------------------------- 1 | # Copyright IBM Corp. All Rights Reserved. 2 | # 3 | # SPDX-License-Identifier: Apache-2.0 4 | # 5 | 6 | version: '2' 7 | 8 | networks: 9 | bc_net: 10 | 11 | services: 12 | ca0: 13 | image: hyperledger/fabric-ca:$IMAGE_TAG 14 | environment: 15 | - FABRIC_CA_HOME=/etc/hyperledger/fabric-ca-server 16 | - FABRIC_CA_SERVER_CA_NAME=ca-org1 17 | - FABRIC_CA_SERVER_TLS_ENABLED=true 18 | - FABRIC_CA_SERVER_TLS_CERTFILE=/etc/hyperledger/fabric-ca-server-config/ca.org1.fabric-iot.edu-cert.pem 19 | - FABRIC_CA_SERVER_TLS_KEYFILE=/etc/hyperledger/fabric-ca-server-config/${CA1_PRIVATE_KEY} 20 | - FABRIC_CA_SERVER_PORT=7054 21 | ports: 22 | - "7054:7054" 23 | command: sh -c 'fabric-ca-server start --ca.certfile /etc/hyperledger/fabric-ca-server-config/ca.org1.fabric-iot.edu-cert.pem --ca.keyfile /etc/hyperledger/fabric-ca-server-config/${CA1_PRIVATE_KEY} -b admin:adminpw -d' 24 | volumes: 25 | - ./../crypto-config/peerOrganizations/org1.fabric-iot.edu/ca/:/etc/hyperledger/fabric-ca-server-config 26 | container_name: ca_peerOrg1 27 | networks: 28 | - bc_net 29 | 30 | ca1: 31 | image: hyperledger/fabric-ca:$IMAGE_TAG 32 | environment: 33 | - FABRIC_CA_HOME=/etc/hyperledger/fabric-ca-server 34 | - FABRIC_CA_SERVER_CA_NAME=ca-org2 35 | - FABRIC_CA_SERVER_TLS_ENABLED=true 36 | - FABRIC_CA_SERVER_TLS_CERTFILE=/etc/hyperledger/fabric-ca-server-config/ca.org2.fabric-iot.edu-cert.pem 37 | - FABRIC_CA_SERVER_TLS_KEYFILE=/etc/hyperledger/fabric-ca-server-config/${CA2_PRIVATE_KEY} 38 | - FABRIC_CA_SERVER_PORT=8054 39 | ports: 40 | - "8054:8054" 41 | command: sh -c 'fabric-ca-server start --ca.certfile /etc/hyperledger/fabric-ca-server-config/ca.org2.fabric-iot.edu-cert.pem --ca.keyfile /etc/hyperledger/fabric-ca-server-config/${CA2_PRIVATE_KEY} -b admin:adminpw -d' 42 | volumes: 43 | - ./../crypto-config/peerOrganizations/org2.fabric-iot.edu/ca/:/etc/hyperledger/fabric-ca-server-config 44 | container_name: ca_peerOrg2 45 | networks: 46 | - bc_net -------------------------------------------------------------------------------- /network/compose-files/docker-compose-cli.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 | orderer.fabric-iot.edu: 10 | peer0.org1.fabric-iot.edu: 11 | peer1.org1.fabric-iot.edu: 12 | peer0.org2.fabric-iot.edu: 13 | peer1.org2.fabric-iot.edu: 14 | 15 | networks: 16 | bc_net: 17 | 18 | services: 19 | 20 | orderer.fabric-iot.edu: 21 | extends: 22 | file: base/docker-compose-base.yaml 23 | service: orderer.fabric-iot.edu 24 | container_name: orderer.fabric-iot.edu 25 | networks: 26 | - bc_net 27 | 28 | peer0.org1.fabric-iot.edu: 29 | container_name: peer0.org1.fabric-iot.edu 30 | extends: 31 | file: base/docker-compose-base.yaml 32 | service: peer0.org1.fabric-iot.edu 33 | networks: 34 | - bc_net 35 | 36 | peer1.org1.fabric-iot.edu: 37 | container_name: peer1.org1.fabric-iot.edu 38 | extends: 39 | file: base/docker-compose-base.yaml 40 | service: peer1.org1.fabric-iot.edu 41 | networks: 42 | - bc_net 43 | 44 | peer0.org2.fabric-iot.edu: 45 | container_name: peer0.org2.fabric-iot.edu 46 | extends: 47 | file: base/docker-compose-base.yaml 48 | service: peer0.org2.fabric-iot.edu 49 | networks: 50 | - bc_net 51 | 52 | peer1.org2.fabric-iot.edu: 53 | container_name: peer1.org2.fabric-iot.edu 54 | extends: 55 | file: base/docker-compose-base.yaml 56 | service: peer1.org2.fabric-iot.edu 57 | networks: 58 | - bc_net 59 | 60 | cli: 61 | container_name: cli 62 | image: hyperledger/fabric-tools:$IMAGE_TAG 63 | tty: true 64 | stdin_open: true 65 | environment: 66 | - SYS_CHANNEL=$SYS_CHANNEL 67 | - GOPATH=/opt/gopath 68 | - CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock 69 | #- FABRIC_LOGGING_SPEC=DEBUG 70 | - FABRIC_LOGGING_SPEC=INFO 71 | - CORE_PEER_ID=cli 72 | - CORE_PEER_ADDRESS=peer0.org1.fabric-iot.edu:7051 73 | - CORE_PEER_LOCALMSPID=Org1MSP 74 | - CORE_PEER_TLS_ENABLED=true 75 | - CORE_PEER_TLS_CERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.fabric-iot.edu/peers/peer0.org1.fabric-iot.edu/tls/server.crt 76 | - CORE_PEER_TLS_KEY_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.fabric-iot.edu/peers/peer0.org1.fabric-iot.edu/tls/server.key 77 | - CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.fabric-iot.edu/peers/peer0.org1.fabric-iot.edu/tls/ca.crt 78 | - CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.fabric-iot.edu/users/Admin@org1.fabric-iot.edu/msp 79 | working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer 80 | command: /bin/bash 81 | volumes: 82 | - /var/run/:/host/var/run/ 83 | - ./../../chaincode/:/opt/gopath/src/github.com/newham/fabric-iot/chaincode 84 | - ./../crypto-config:/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ 85 | - ./../scripts:/opt/gopath/src/github.com/hyperledger/fabric/peer/scripts/ 86 | - ./../channel-artifacts:/opt/gopath/src/github.com/hyperledger/fabric/peer/channel-artifacts 87 | depends_on: 88 | - orderer.fabric-iot.edu 89 | - peer0.org1.fabric-iot.edu 90 | - peer1.org1.fabric-iot.edu 91 | - peer0.org2.fabric-iot.edu 92 | - peer1.org2.fabric-iot.edu 93 | networks: 94 | - bc_net 95 | -------------------------------------------------------------------------------- /network/compose-files/docker-compose-couch.yaml: -------------------------------------------------------------------------------- 1 | # Copyright IBM Corp. All Rights Reserved. 2 | # 3 | # SPDX-License-Identifier: Apache-2.0 4 | # 5 | 6 | version: '2' 7 | 8 | networks: 9 | bc_net: 10 | 11 | services: 12 | couchdb0: 13 | container_name: couchdb0 14 | image: hyperledger/fabric-couchdb 15 | # Populate the COUCHDB_USER and COUCHDB_PASSWORD to set an admin user and password 16 | # for CouchDB. This will prevent CouchDB from operating in an "Admin Party" mode. 17 | environment: 18 | - COUCHDB_USER= 19 | - COUCHDB_PASSWORD= 20 | # Comment/Uncomment the port mapping if you want to hide/expose the CouchDB service, 21 | # for example map it to utilize Fauxton User Interface in dev environments. 22 | ports: 23 | - "5984:5984" 24 | networks: 25 | - bc_net 26 | 27 | peer0.org1.fabric-iot.edu: 28 | environment: 29 | - CORE_LEDGER_STATE_STATEDATABASE=CouchDB 30 | - CORE_LEDGER_STATE_COUCHDBCONFIG_COUCHDBADDRESS=couchdb0:5984 31 | # The CORE_LEDGER_STATE_COUCHDBCONFIG_USERNAME and CORE_LEDGER_STATE_COUCHDBCONFIG_PASSWORD 32 | # provide the credentials for ledger to connect to CouchDB. The username and password must 33 | # match the username and password set for the associated CouchDB. 34 | - CORE_LEDGER_STATE_COUCHDBCONFIG_USERNAME= 35 | - CORE_LEDGER_STATE_COUCHDBCONFIG_PASSWORD= 36 | depends_on: 37 | - couchdb0 38 | 39 | couchdb1: 40 | container_name: couchdb1 41 | image: hyperledger/fabric-couchdb 42 | # Populate the COUCHDB_USER and COUCHDB_PASSWORD to set an admin user and password 43 | # for CouchDB. This will prevent CouchDB from operating in an "Admin Party" mode. 44 | environment: 45 | - COUCHDB_USER= 46 | - COUCHDB_PASSWORD= 47 | # Comment/Uncomment the port mapping if you want to hide/expose the CouchDB service, 48 | # for example map it to utilize Fauxton User Interface in dev environments. 49 | ports: 50 | - "6984:5984" 51 | networks: 52 | - bc_net 53 | 54 | peer1.org1.fabric-iot.edu: 55 | environment: 56 | - CORE_LEDGER_STATE_STATEDATABASE=CouchDB 57 | - CORE_LEDGER_STATE_COUCHDBCONFIG_COUCHDBADDRESS=couchdb1:5984 58 | # The CORE_LEDGER_STATE_COUCHDBCONFIG_USERNAME and CORE_LEDGER_STATE_COUCHDBCONFIG_PASSWORD 59 | # provide the credentials for ledger to connect to CouchDB. The username and password must 60 | # match the username and password set for the associated CouchDB. 61 | - CORE_LEDGER_STATE_COUCHDBCONFIG_USERNAME= 62 | - CORE_LEDGER_STATE_COUCHDBCONFIG_PASSWORD= 63 | depends_on: 64 | - couchdb1 65 | 66 | couchdb2: 67 | container_name: couchdb2 68 | image: hyperledger/fabric-couchdb 69 | # Populate the COUCHDB_USER and COUCHDB_PASSWORD to set an admin user and password 70 | # for CouchDB. This will prevent CouchDB from operating in an "Admin Party" mode. 71 | environment: 72 | - COUCHDB_USER= 73 | - COUCHDB_PASSWORD= 74 | # Comment/Uncomment the port mapping if you want to hide/expose the CouchDB service, 75 | # for example map it to utilize Fauxton User Interface in dev environments. 76 | ports: 77 | - "7984:5984" 78 | networks: 79 | - bc_net 80 | 81 | peer0.org2.fabric-iot.edu: 82 | environment: 83 | - CORE_LEDGER_STATE_STATEDATABASE=CouchDB 84 | - CORE_LEDGER_STATE_COUCHDBCONFIG_COUCHDBADDRESS=couchdb2:5984 85 | # The CORE_LEDGER_STATE_COUCHDBCONFIG_USERNAME and CORE_LEDGER_STATE_COUCHDBCONFIG_PASSWORD 86 | # provide the credentials for ledger to connect to CouchDB. The username and password must 87 | # match the username and password set for the associated CouchDB. 88 | - CORE_LEDGER_STATE_COUCHDBCONFIG_USERNAME= 89 | - CORE_LEDGER_STATE_COUCHDBCONFIG_PASSWORD= 90 | depends_on: 91 | - couchdb2 92 | 93 | couchdb3: 94 | container_name: couchdb3 95 | image: hyperledger/fabric-couchdb 96 | # Populate the COUCHDB_USER and COUCHDB_PASSWORD to set an admin user and password 97 | # for CouchDB. This will prevent CouchDB from operating in an "Admin Party" mode. 98 | environment: 99 | - COUCHDB_USER= 100 | - COUCHDB_PASSWORD= 101 | # Comment/Uncomment the port mapping if you want to hide/expose the CouchDB service, 102 | # for example map it to utilize Fauxton User Interface in dev environments. 103 | ports: 104 | - "8984:5984" 105 | networks: 106 | - bc_net 107 | 108 | peer1.org2.fabric-iot.edu: 109 | environment: 110 | - CORE_LEDGER_STATE_STATEDATABASE=CouchDB 111 | - CORE_LEDGER_STATE_COUCHDBCONFIG_COUCHDBADDRESS=couchdb3:5984 112 | # The CORE_LEDGER_STATE_COUCHDBCONFIG_USERNAME and CORE_LEDGER_STATE_COUCHDBCONFIG_PASSWORD 113 | # provide the credentials for ledger to connect to CouchDB. The username and password must 114 | # match the username and password set for the associated CouchDB. 115 | - CORE_LEDGER_STATE_COUCHDBCONFIG_USERNAME= 116 | - CORE_LEDGER_STATE_COUCHDBCONFIG_PASSWORD= 117 | depends_on: 118 | - couchdb3 119 | -------------------------------------------------------------------------------- /network/compose-files/docker-compose-e2e-template.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 | orderer.fabric-iot.edu: 10 | peer0.org1.fabric-iot.edu: 11 | peer1.org1.fabric-iot.edu: 12 | peer0.org2.fabric-iot.edu: 13 | peer1.org2.fabric-iot.edu: 14 | 15 | networks: 16 | bc_net: 17 | services: 18 | ca0: 19 | image: hyperledger/fabric-ca:$IMAGE_TAG 20 | environment: 21 | - FABRIC_CA_HOME=/etc/hyperledger/fabric-ca-server 22 | - FABRIC_CA_SERVER_CA_NAME=ca-org1 23 | - FABRIC_CA_SERVER_TLS_ENABLED=true 24 | - FABRIC_CA_SERVER_TLS_CERTFILE=/etc/hyperledger/fabric-ca-server-config/ca.org1.fabric-iot.edu-cert.pem 25 | - FABRIC_CA_SERVER_TLS_KEYFILE=/etc/hyperledger/fabric-ca-server-config/CA1_PRIVATE_KEY 26 | ports: 27 | - "7054:7054" 28 | command: sh -c 'fabric-ca-server start --ca.certfile /etc/hyperledger/fabric-ca-server-config/ca.org1.fabric-iot.edu-cert.pem --ca.keyfile /etc/hyperledger/fabric-ca-server-config/CA1_PRIVATE_KEY -b admin:adminpw -d' 29 | volumes: 30 | - ./../crypto-config/peerOrganizations/org1.fabric-iot.edu/ca/:/etc/hyperledger/fabric-ca-server-config 31 | container_name: ca_peerOrg1 32 | networks: 33 | - bc_net 34 | 35 | ca1: 36 | image: hyperledger/fabric-ca:$IMAGE_TAG 37 | environment: 38 | - FABRIC_CA_HOME=/etc/hyperledger/fabric-ca-server 39 | - FABRIC_CA_SERVER_CA_NAME=ca-org2 40 | - FABRIC_CA_SERVER_TLS_ENABLED=true 41 | - FABRIC_CA_SERVER_TLS_CERTFILE=/etc/hyperledger/fabric-ca-server-config/ca.org2.fabric-iot.edu-cert.pem 42 | - FABRIC_CA_SERVER_TLS_KEYFILE=/etc/hyperledger/fabric-ca-server-config/CA2_PRIVATE_KEY 43 | ports: 44 | - "8054:7054" 45 | command: sh -c 'fabric-ca-server start --ca.certfile /etc/hyperledger/fabric-ca-server-config/ca.org2.fabric-iot.edu-cert.pem --ca.keyfile /etc/hyperledger/fabric-ca-server-config/CA2_PRIVATE_KEY -b admin:adminpw -d' 46 | volumes: 47 | - ./../crypto-config/peerOrganizations/org2.fabric-iot.edu/ca/:/etc/hyperledger/fabric-ca-server-config 48 | container_name: ca_peerOrg2 49 | networks: 50 | - bc_net 51 | 52 | orderer.fabric-iot.edu: 53 | extends: 54 | file: base/docker-compose-base.yaml 55 | service: orderer.fabric-iot.edu 56 | container_name: orderer.fabric-iot.edu 57 | networks: 58 | - bc_net 59 | 60 | peer0.org1.fabric-iot.edu: 61 | container_name: peer0.org1.fabric-iot.edu 62 | extends: 63 | file: base/docker-compose-base.yaml 64 | service: peer0.org1.fabric-iot.edu 65 | networks: 66 | - bc_net 67 | 68 | peer1.org1.fabric-iot.edu: 69 | container_name: peer1.org1.fabric-iot.edu 70 | extends: 71 | file: base/docker-compose-base.yaml 72 | service: peer1.org1.fabric-iot.edu 73 | networks: 74 | - bc_net 75 | 76 | peer0.org2.fabric-iot.edu: 77 | container_name: peer0.org2.fabric-iot.edu 78 | extends: 79 | file: base/docker-compose-base.yaml 80 | service: peer0.org2.fabric-iot.edu 81 | networks: 82 | - bc_net 83 | 84 | peer1.org2.fabric-iot.edu: 85 | container_name: peer1.org2.fabric-iot.edu 86 | extends: 87 | file: base/docker-compose-base.yaml 88 | service: peer1.org2.fabric-iot.edu 89 | networks: 90 | - bc_net 91 | -------------------------------------------------------------------------------- /network/compose-files/docker-compose-kafka.yaml: -------------------------------------------------------------------------------- 1 | # Copyright IBM Corp. All Rights Reserved. 2 | # 3 | # SPDX-License-Identifier: Apache-2.0 4 | # 5 | 6 | 7 | # NOTE: This is not the way a Kafka cluster would normally be deployed in production, as it is not secure 8 | # and is not fault tolerant. This example is a toy deployment that is only meant to exercise the Kafka code path 9 | # of the ordering service. 10 | 11 | version: '2' 12 | 13 | networks: 14 | bc_net: 15 | 16 | services: 17 | zookeeper.fabric-iot.edu: 18 | container_name: zookeeper.fabric-iot.edu 19 | image: hyperledger/fabric-zookeeper:$IMAGE_TAG 20 | environment: 21 | ZOOKEEPER_CLIENT_PORT: 32181 22 | ZOOKEEPER_TICK_TIME: 2000 23 | networks: 24 | - bc_net 25 | 26 | kafka.fabric-iot.edu: 27 | container_name: kafka.fabric-iot.edu 28 | image: hyperledger/fabric-kafka:$IMAGE_TAG 29 | depends_on: 30 | - zookeeper.fabric-iot.edu 31 | environment: 32 | - KAFKA_BROKER_ID=1 33 | - KAFKA_ZOOKEEPER_CONNECT=zookeeper.fabric-iot.edu:2181 34 | - KAFKA_ADVERTISED_LISTENERS=PLAINTEXT://kafka.fabric-iot.edu:9092 35 | - KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR=1 36 | - KAFKA_MESSAGE_MAX_BYTES=1048576 # 1 * 1024 * 1024 B 37 | - KAFKA_REPLICA_FETCH_MAX_BYTES=1048576 # 1 * 1024 * 1024 B 38 | - KAFKA_UNCLEAN_LEADER_ELECTION_ENABLE=false 39 | - KAFKA_LOG_RETENTION_MS=-1 40 | - KAFKA_MIN_INSYNC_REPLICAS=1 41 | - KAFKA_DEFAULT_REPLICATION_FACTOR=1 42 | networks: 43 | - bc_net 44 | -------------------------------------------------------------------------------- /network/configtx.yaml: -------------------------------------------------------------------------------- 1 | # Copyright IBM Corp. All Rights Reserved. 2 | # 3 | # SPDX-License-Identifier: Apache-2.0 4 | # 5 | 6 | --- 7 | ################################################################################ 8 | # 9 | # Section: Organizations 10 | # 11 | # - This section defines the different organizational identities which will 12 | # be referenced later in the configuration. 13 | # 14 | ################################################################################ 15 | Organizations: 16 | 17 | # SampleOrg defines an MSP using the sampleconfig. It should never be used 18 | # in production but may be used as a template for other definitions 19 | - &OrdererOrg 20 | # DefaultOrg defines the organization which is used in the sampleconfig 21 | # of the fabric.git development environment 22 | Name: OrdererOrg 23 | 24 | # ID to load the MSP definition as 25 | ID: OrdererMSP 26 | 27 | # MSPDir is the filesystem path which contains the MSP configuration 28 | MSPDir: crypto-config/ordererOrganizations/fabric-iot.edu/msp 29 | 30 | # Policies defines the set of policies at this level of the config tree 31 | # For organization policies, their canonical path is usually 32 | # /Channel/// 33 | Policies: 34 | Readers: 35 | Type: Signature 36 | Rule: "OR('OrdererMSP.member')" 37 | Writers: 38 | Type: Signature 39 | Rule: "OR('OrdererMSP.member')" 40 | Admins: 41 | Type: Signature 42 | Rule: "OR('OrdererMSP.admin')" 43 | 44 | - &Org1 45 | # DefaultOrg defines the organization which is used in the sampleconfig 46 | # of the fabric.git development environment 47 | Name: Org1MSP 48 | 49 | # ID to load the MSP definition as 50 | ID: Org1MSP 51 | 52 | MSPDir: crypto-config/peerOrganizations/org1.fabric-iot.edu/msp 53 | 54 | # Policies defines the set of policies at this level of the config tree 55 | # For organization policies, their canonical path is usually 56 | # /Channel/// 57 | Policies: 58 | Readers: 59 | Type: Signature 60 | Rule: "OR('Org1MSP.admin', 'Org1MSP.peer', 'Org1MSP.client')" 61 | Writers: 62 | Type: Signature 63 | Rule: "OR('Org1MSP.admin', 'Org1MSP.client')" 64 | Admins: 65 | Type: Signature 66 | Rule: "OR('Org1MSP.admin')" 67 | 68 | # leave this flag set to true. 69 | AnchorPeers: 70 | # AnchorPeers defines the location of peers which can be used 71 | # for cross org gossip communication. Note, this value is only 72 | # encoded in the genesis block in the Application section context 73 | - Host: peer0.org1.fabric-iot.edu 74 | Port: 7051 75 | 76 | - &Org2 77 | # DefaultOrg defines the organization which is used in the sampleconfig 78 | # of the fabric.git development environment 79 | Name: Org2MSP 80 | 81 | # ID to load the MSP definition as 82 | ID: Org2MSP 83 | 84 | MSPDir: crypto-config/peerOrganizations/org2.fabric-iot.edu/msp 85 | 86 | # Policies defines the set of policies at this level of the config tree 87 | # For organization policies, their canonical path is usually 88 | # /Channel/// 89 | Policies: 90 | Readers: 91 | Type: Signature 92 | Rule: "OR('Org2MSP.admin', 'Org2MSP.peer', 'Org2MSP.client')" 93 | Writers: 94 | Type: Signature 95 | Rule: "OR('Org2MSP.admin', 'Org2MSP.client')" 96 | Admins: 97 | Type: Signature 98 | Rule: "OR('Org2MSP.admin')" 99 | 100 | AnchorPeers: 101 | # AnchorPeers defines the location of peers which can be used 102 | # for cross org gossip communication. Note, this value is only 103 | # encoded in the genesis block in the Application section context 104 | - Host: peer0.org2.fabric-iot.edu 105 | Port: 9051 106 | 107 | ################################################################################ 108 | # 109 | # SECTION: Capabilities 110 | # 111 | # - This section defines the capabilities of fabric network. This is a new 112 | # concept as of v1.1.0 and should not be utilized in mixed networks with 113 | # v1.0.x peers and orderers. Capabilities define features which must be 114 | # present in a fabric binary for that binary to safely participate in the 115 | # fabric network. For instance, if a new MSP type is added, newer binaries 116 | # might recognize and validate the signatures from this type, while older 117 | # binaries without this support would be unable to validate those 118 | # transactions. This could lead to different versions of the fabric binaries 119 | # having different world states. Instead, defining a capability for a channel 120 | # informs those binaries without this capability that they must cease 121 | # processing transactions until they have been upgraded. For v1.0.x if any 122 | # capabilities are defined (including a map with all capabilities turned off) 123 | # then the v1.0.x peer will deliberately crash. 124 | # 125 | ################################################################################ 126 | Capabilities: 127 | # Channel capabilities apply to both the orderers and the peers and must be 128 | # supported by both. 129 | # Set the value of the capability to true to require it. 130 | Channel: &ChannelCapabilities 131 | # V1.4.3 for Channel is a catchall flag for behavior which has been 132 | # determined to be desired for all orderers and peers running at the v1.4.3 133 | # level, but which would be incompatible with orderers and peers from 134 | # prior releases. 135 | # Prior to enabling V1.4.3 channel capabilities, ensure that all 136 | # orderers and peers on a channel are at v1.4.3 or later. 137 | V1_4_3: true 138 | # V1.3 for Channel enables the new non-backwards compatible 139 | # features and fixes of fabric v1.3 140 | V1_3: false 141 | # V1.1 for Channel enables the new non-backwards compatible 142 | # features and fixes of fabric v1.1 143 | V1_1: false 144 | 145 | # Orderer capabilities apply only to the orderers, and may be safely 146 | # used with prior release peers. 147 | # Set the value of the capability to true to require it. 148 | Orderer: &OrdererCapabilities 149 | # V1.4.2 for Orderer is a catchall flag for behavior which has been 150 | # determined to be desired for all orderers running at the v1.4.2 151 | # level, but which would be incompatible with orderers from prior releases. 152 | # Prior to enabling V1.4.2 orderer capabilities, ensure that all 153 | # orderers on a channel are at v1.4.2 or later. 154 | V1_4_2: true 155 | # V1.1 for Orderer enables the new non-backwards compatible 156 | # features and fixes of fabric v1.1 157 | V1_1: false 158 | 159 | # Application capabilities apply only to the peer network, and may be safely 160 | # used with prior release orderers. 161 | # Set the value of the capability to true to require it. 162 | Application: &ApplicationCapabilities 163 | # V1.4.2 for Application enables the new non-backwards compatible 164 | # features and fixes of fabric v1.4.2. 165 | V1_4_2: true 166 | # V1.3 for Application enables the new non-backwards compatible 167 | # features and fixes of fabric v1.3. 168 | V1_3: false 169 | # V1.2 for Application enables the new non-backwards compatible 170 | # features and fixes of fabric v1.2 (note, this need not be set if 171 | # later version capabilities are set) 172 | V1_2: false 173 | # V1.1 for Application enables the new non-backwards compatible 174 | # features and fixes of fabric v1.1 (note, this need not be set if 175 | # later version capabilities are set). 176 | V1_1: false 177 | 178 | ################################################################################ 179 | # 180 | # SECTION: Application 181 | # 182 | # - This section defines the values to encode into a config transaction or 183 | # genesis block for application related parameters 184 | # 185 | ################################################################################ 186 | Application: &ApplicationDefaults 187 | 188 | # Organizations is the list of orgs which are defined as participants on 189 | # the application side of the network 190 | Organizations: 191 | 192 | # Policies defines the set of policies at this level of the config tree 193 | # For Application policies, their canonical path is 194 | # /Channel/Application/ 195 | Policies: 196 | Readers: 197 | Type: ImplicitMeta 198 | Rule: "ANY Readers" 199 | Writers: 200 | Type: ImplicitMeta 201 | Rule: "ANY Writers" 202 | Admins: 203 | Type: ImplicitMeta 204 | Rule: "MAJORITY Admins" 205 | 206 | Capabilities: 207 | <<: *ApplicationCapabilities 208 | ################################################################################ 209 | # 210 | # SECTION: Orderer 211 | # 212 | # - This section defines the values to encode into a config transaction or 213 | # genesis block for orderer related parameters 214 | # 215 | ################################################################################ 216 | Orderer: &OrdererDefaults 217 | 218 | # Orderer Type: The orderer implementation to start 219 | # Available types are "solo" and "kafka" 220 | OrdererType: solo 221 | 222 | Addresses: 223 | - orderer.fabric-iot.edu:7050 224 | 225 | # Batch Timeout: The amount of time to wait before creating a batch 226 | BatchTimeout: 2s 227 | 228 | # Batch Size: Controls the number of messages batched into a block 229 | BatchSize: 230 | 231 | # Max Message Count: The maximum number of messages to permit in a batch 232 | MaxMessageCount: 10 233 | 234 | # Absolute Max Bytes: The absolute maximum number of bytes allowed for 235 | # the serialized messages in a batch. 236 | AbsoluteMaxBytes: 99 MB 237 | 238 | # Preferred Max Bytes: The preferred maximum number of bytes allowed for 239 | # the serialized messages in a batch. A message larger than the preferred 240 | # max bytes will result in a batch larger than preferred max bytes. 241 | PreferredMaxBytes: 512 KB 242 | 243 | Kafka: 244 | # Brokers: A list of Kafka brokers to which the orderer connects 245 | # NOTE: Use IP:port notation 246 | Brokers: 247 | - 127.0.0.1:9092 248 | 249 | # Organizations is the list of orgs which are defined as participants on 250 | # the orderer side of the network 251 | Organizations: 252 | 253 | # Policies defines the set of policies at this level of the config tree 254 | # For Orderer policies, their canonical path is 255 | # /Channel/Orderer/ 256 | Policies: 257 | Readers: 258 | Type: ImplicitMeta 259 | Rule: "ANY Readers" 260 | Writers: 261 | Type: ImplicitMeta 262 | Rule: "ANY Writers" 263 | Admins: 264 | Type: ImplicitMeta 265 | Rule: "MAJORITY Admins" 266 | # BlockValidation specifies what signatures must be included in the block 267 | # from the orderer for the peer to validate it. 268 | BlockValidation: 269 | Type: ImplicitMeta 270 | Rule: "ANY Writers" 271 | 272 | ################################################################################ 273 | # 274 | # CHANNEL 275 | # 276 | # This section defines the values to encode into a config transaction or 277 | # genesis block for channel related parameters. 278 | # 279 | ################################################################################ 280 | Channel: &ChannelDefaults 281 | # Policies defines the set of policies at this level of the config tree 282 | # For Channel policies, their canonical path is 283 | # /Channel/ 284 | Policies: 285 | # Who may invoke the 'Deliver' API 286 | Readers: 287 | Type: ImplicitMeta 288 | Rule: "ANY Readers" 289 | # Who may invoke the 'Broadcast' API 290 | Writers: 291 | Type: ImplicitMeta 292 | Rule: "ANY Writers" 293 | # By default, who may modify elements at this config level 294 | Admins: 295 | Type: ImplicitMeta 296 | Rule: "MAJORITY Admins" 297 | 298 | # Capabilities describes the channel level capabilities, see the 299 | # dedicated Capabilities section elsewhere in this file for a full 300 | # description 301 | Capabilities: 302 | <<: *ChannelCapabilities 303 | 304 | ################################################################################ 305 | # 306 | # Profile 307 | # 308 | # - Different configuration profiles may be encoded here to be specified 309 | # as parameters to the configtxgen tool 310 | # 311 | ################################################################################ 312 | Profiles: 313 | 314 | TwoOrgsOrdererGenesis: 315 | <<: *ChannelDefaults 316 | Orderer: 317 | <<: *OrdererDefaults 318 | Organizations: 319 | - *OrdererOrg 320 | Capabilities: 321 | <<: *OrdererCapabilities 322 | Consortiums: 323 | SampleConsortium: 324 | Organizations: 325 | - *Org1 326 | - *Org2 327 | TwoOrgsChannel: 328 | Consortium: SampleConsortium 329 | <<: *ChannelDefaults 330 | Application: 331 | <<: *ApplicationDefaults 332 | Organizations: 333 | - *Org1 334 | - *Org2 335 | Capabilities: 336 | <<: *ApplicationCapabilities 337 | 338 | SampleDevModeKafka: 339 | <<: *ChannelDefaults 340 | Capabilities: 341 | <<: *ChannelCapabilities 342 | Orderer: 343 | <<: *OrdererDefaults 344 | OrdererType: kafka 345 | Kafka: 346 | Brokers: 347 | - kafka.fabric-iot.edu:9092 348 | 349 | Organizations: 350 | - *OrdererOrg 351 | Capabilities: 352 | <<: *OrdererCapabilities 353 | Application: 354 | <<: *ApplicationDefaults 355 | Organizations: 356 | - <<: *OrdererOrg 357 | Consortiums: 358 | SampleConsortium: 359 | Organizations: 360 | - *Org1 361 | - *Org2 362 | 363 | SampleMultiNodeEtcdRaft: 364 | <<: *ChannelDefaults 365 | Capabilities: 366 | <<: *ChannelCapabilities 367 | Orderer: 368 | <<: *OrdererDefaults 369 | OrdererType: etcdraft 370 | EtcdRaft: 371 | Consenters: 372 | - Host: orderer.fabric-iot.edu 373 | Port: 7050 374 | ClientTLSCert: crypto-config/ordererOrganizations/fabric-iot.edu/orderers/orderer.fabric-iot.edu/tls/server.crt 375 | ServerTLSCert: crypto-config/ordererOrganizations/fabric-iot.edu/orderers/orderer.fabric-iot.edu/tls/server.crt 376 | - Host: orderer2.fabric-iot.edu 377 | Port: 7050 378 | ClientTLSCert: crypto-config/ordererOrganizations/fabric-iot.edu/orderers/orderer2.fabric-iot.edu/tls/server.crt 379 | ServerTLSCert: crypto-config/ordererOrganizations/fabric-iot.edu/orderers/orderer2.fabric-iot.edu/tls/server.crt 380 | - Host: orderer3.fabric-iot.edu 381 | Port: 7050 382 | ClientTLSCert: crypto-config/ordererOrganizations/fabric-iot.edu/orderers/orderer3.fabric-iot.edu/tls/server.crt 383 | ServerTLSCert: crypto-config/ordererOrganizations/fabric-iot.edu/orderers/orderer3.fabric-iot.edu/tls/server.crt 384 | - Host: orderer4.fabric-iot.edu 385 | Port: 7050 386 | ClientTLSCert: crypto-config/ordererOrganizations/fabric-iot.edu/orderers/orderer4.fabric-iot.edu/tls/server.crt 387 | ServerTLSCert: crypto-config/ordererOrganizations/fabric-iot.edu/orderers/orderer4.fabric-iot.edu/tls/server.crt 388 | - Host: orderer5.fabric-iot.edu 389 | Port: 7050 390 | ClientTLSCert: crypto-config/ordererOrganizations/fabric-iot.edu/orderers/orderer5.fabric-iot.edu/tls/server.crt 391 | ServerTLSCert: crypto-config/ordererOrganizations/fabric-iot.edu/orderers/orderer5.fabric-iot.edu/tls/server.crt 392 | Addresses: 393 | - orderer.fabric-iot.edu:7050 394 | - orderer2.fabric-iot.edu:7050 395 | - orderer3.fabric-iot.edu:7050 396 | - orderer4.fabric-iot.edu:7050 397 | - orderer5.fabric-iot.edu:7050 398 | 399 | Organizations: 400 | - *OrdererOrg 401 | Capabilities: 402 | <<: *OrdererCapabilities 403 | Application: 404 | <<: *ApplicationDefaults 405 | Organizations: 406 | - <<: *OrdererOrg 407 | Consortiums: 408 | SampleConsortium: 409 | Organizations: 410 | - *Org1 411 | - *Org2 412 | -------------------------------------------------------------------------------- /network/conn-conf/ccp-template.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "first-network-org${ORG}", 3 | "version": "1.0.0", 4 | "client": { 5 | "organization": "Org${ORG}", 6 | "connection": { 7 | "timeout": { 8 | "peer": { 9 | "endorser": "300" 10 | } 11 | } 12 | } 13 | }, 14 | "organizations": { 15 | "Org${ORG}": { 16 | "mspid": "Org${ORG}MSP", 17 | "peers": [ 18 | "peer0.org${ORG}.fabric-iot.edu", 19 | "peer1.org${ORG}.fabric-iot.edu" 20 | ], 21 | "certificateAuthorities": [ 22 | "ca.org${ORG}.fabric-iot.edu" 23 | ] 24 | } 25 | }, 26 | "peers": { 27 | "peer0.org${ORG}.fabric-iot.edu": { 28 | "url": "grpcs://localhost:${P0PORT}", 29 | "tlsCACerts": { 30 | "pem": "${PEERPEM}" 31 | }, 32 | "grpcOptions": { 33 | "ssl-target-name-override": "peer0.org${ORG}.fabric-iot.edu", 34 | "hostnameOverride": "peer0.org${ORG}.fabric-iot.edu" 35 | } 36 | }, 37 | "peer1.org${ORG}.fabric-iot.edu": { 38 | "url": "grpcs://localhost:${P1PORT}", 39 | "tlsCACerts": { 40 | "pem": "${PEERPEM}" 41 | }, 42 | "grpcOptions": { 43 | "ssl-target-name-override": "peer1.org${ORG}.fabric-iot.edu", 44 | "hostnameOverride": "peer1.org${ORG}.fabric-iot.edu" 45 | } 46 | } 47 | }, 48 | "certificateAuthorities": { 49 | "ca.org${ORG}.fabric-iot.edu": { 50 | "url": "https://localhost:${CAPORT}", 51 | "caName": "ca-org${ORG}", 52 | "tlsCACerts": { 53 | "pem": "${CAPEM}" 54 | }, 55 | "httpOptions": { 56 | "verify": false 57 | } 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /network/conn-conf/ccp-template.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | name: first-network-org${ORG} 3 | version: 1.0.0 4 | client: 5 | organization: Org${ORG} 6 | connection: 7 | timeout: 8 | peer: 9 | endorser: '300' 10 | organizations: 11 | Org${ORG}: 12 | mspid: Org${ORG}MSP 13 | peers: 14 | - peer0.org${ORG}.fabric-iot.edu 15 | - peer1.org${ORG}.fabric-iot.edu 16 | certificateAuthorities: 17 | - ca.org${ORG}.fabric-iot.edu 18 | peers: 19 | peer0.org${ORG}.fabric-iot.edu: 20 | url: grpcs://localhost:${P0PORT} 21 | tlsCACerts: 22 | pem: | 23 | ${PEERPEM} 24 | grpcOptions: 25 | ssl-target-name-override: peer0.org${ORG}.fabric-iot.edu 26 | hostnameOverride: peer0.org${ORG}.fabric-iot.edu 27 | peer1.org${ORG}.fabric-iot.edu: 28 | url: grpcs://localhost:${P1PORT} 29 | tlsCACerts: 30 | pem: | 31 | ${PEERPEM} 32 | grpcOptions: 33 | ssl-target-name-override: peer1.org${ORG}.fabric-iot.edu 34 | hostnameOverride: peer1.org${ORG}.fabric-iot.edu 35 | certificateAuthorities: 36 | ca.org${ORG}.fabric-iot.edu: 37 | url: https://localhost:${CAPORT} 38 | caName: ca-org${ORG} 39 | tlsCACerts: 40 | pem: | 41 | ${CAPEM} 42 | httpOptions: 43 | verify: false 44 | -------------------------------------------------------------------------------- /network/crypto-config.yaml: -------------------------------------------------------------------------------- 1 | # Copyright IBM Corp. All Rights Reserved. 2 | # 3 | # SPDX-License-Identifier: Apache-2.0 4 | # 5 | 6 | # --------------------------------------------------------------------------- 7 | # "OrdererOrgs" - Definition of organizations managing orderer nodes 8 | # --------------------------------------------------------------------------- 9 | OrdererOrgs: 10 | # --------------------------------------------------------------------------- 11 | # Orderer 12 | # --------------------------------------------------------------------------- 13 | - Name: Orderer 14 | Domain: fabric-iot.edu 15 | EnableNodeOUs: true 16 | # --------------------------------------------------------------------------- 17 | # "Specs" - See PeerOrgs below for complete description 18 | # --------------------------------------------------------------------------- 19 | Specs: 20 | - Hostname: orderer 21 | - Hostname: orderer2 22 | - Hostname: orderer3 23 | - Hostname: orderer4 24 | - Hostname: orderer5 25 | 26 | # --------------------------------------------------------------------------- 27 | # "PeerOrgs" - Definition of organizations managing peer nodes 28 | # --------------------------------------------------------------------------- 29 | PeerOrgs: 30 | # --------------------------------------------------------------------------- 31 | # Org1 32 | # --------------------------------------------------------------------------- 33 | - Name: Org1 34 | Domain: org1.fabric-iot.edu 35 | EnableNodeOUs: true 36 | # --------------------------------------------------------------------------- 37 | # "Specs" 38 | # --------------------------------------------------------------------------- 39 | # Uncomment this section to enable the explicit definition of hosts in your 40 | # configuration. Most users will want to use Template, below 41 | # 42 | # Specs is an array of Spec entries. Each Spec entry consists of two fields: 43 | # - Hostname: (Required) The desired hostname, sans the domain. 44 | # - CommonName: (Optional) Specifies the template or explicit override for 45 | # the CN. By default, this is the template: 46 | # 47 | # "{{.Hostname}}.{{.Domain}}" 48 | # 49 | # which obtains its values from the Spec.Hostname and 50 | # Org.Domain, respectively. 51 | # --------------------------------------------------------------------------- 52 | # Specs: 53 | # - Hostname: foo # implicitly "foo.org1.fabric-iot.edu" 54 | # CommonName: foo27.org5.fabric-iot.edu # overrides Hostname-based FQDN set above 55 | # - Hostname: bar 56 | # - Hostname: baz 57 | # --------------------------------------------------------------------------- 58 | # "Template" 59 | # --------------------------------------------------------------------------- 60 | # Allows for the definition of 1 or more hosts that are created sequentially 61 | # from a template. By default, this looks like "peer%d" from 0 to Count-1. 62 | # You may override the number of nodes (Count), the starting index (Start) 63 | # or the template used to construct the name (Hostname). 64 | # 65 | # Note: Template and Specs are not mutually exclusive. You may define both 66 | # sections and the aggregate nodes will be created for you. Take care with 67 | # name collisions 68 | # --------------------------------------------------------------------------- 69 | Template: 70 | Count: 2 71 | # Start: 5 72 | # Hostname: {{.Prefix}}{{.Index}} # default 73 | # --------------------------------------------------------------------------- 74 | # "Users" 75 | # --------------------------------------------------------------------------- 76 | # Count: The number of user accounts _in addition_ to Admin 77 | # --------------------------------------------------------------------------- 78 | Users: 79 | Count: 1 80 | # --------------------------------------------------------------------------- 81 | # Org2: See "Org1" for full specification 82 | # --------------------------------------------------------------------------- 83 | - Name: Org2 84 | Domain: org2.fabric-iot.edu 85 | EnableNodeOUs: true 86 | Template: 87 | Count: 2 88 | Users: 89 | Count: 1 90 | -------------------------------------------------------------------------------- /network/down.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # import env 4 | . env.sh 5 | 6 | # Obtain CONTAINER_IDS and remove them 7 | # TODO Might want to make this optional - could clear other containers 8 | function clearContainers() { 9 | CONTAINER_IDS=$(docker ps -a | awk '($2 ~ /dev-peer*.*.fabric-iot.*/) {print $1}') 10 | if [ -z "$CONTAINER_IDS" -o "$CONTAINER_IDS" == " " ]; then 11 | echo "---- No containers available for deletion ----" 12 | else 13 | docker rm -f $CONTAINER_IDS 14 | fi 15 | } 16 | 17 | # Delete any images that were generated as a part of this setup 18 | # specifically the following images are often left behind: 19 | # TODO list generated image naming patterns 20 | function removeUnwantedImages() { 21 | DOCKER_IMAGE_IDS=$(docker images | awk '($1 ~ /dev-peer*.*.*.*c.*/) {print $3}') 22 | if [ -z "$DOCKER_IMAGE_IDS" -o "$DOCKER_IMAGE_IDS" == " " ]; then 23 | echo "---- No images available for deletion ----" 24 | else 25 | docker rmi -f $DOCKER_IMAGE_IDS 26 | fi 27 | } 28 | 29 | MODE="down" 30 | 31 | # Tear down running network 32 | function networkDown() { 33 | # stop org3 containers also in addition to org1 and org2, in case we were running sample to add org3 34 | # stop kafka and zookeeper containers in case we're running with kafka consensus-type 35 | # docker-compose -f $COMPOSE_FILE -f $COMPOSE_FILE_COUCH -f $COMPOSE_FILE_KAFKA -f $COMPOSE_FILE_RAFT2 -f $COMPOSE_FILE_CA -f $COMPOSE_FILE_ORG3 down --volumes --remove-orphans 36 | # we delete $COMPOSE_FILE_RAFT2 , $COMPOSE_FILE_ORG3 37 | docker-compose -f $COMPOSE_FILE -f $COMPOSE_FILE_COUCH -f $COMPOSE_FILE_KAFKA -f $COMPOSE_FILE_CA down --volumes --remove-orphans 38 | 39 | # Don't remove the generated artifacts -- note, the ledgers are always removed 40 | if [ "$MODE" != "restart" ]; then 41 | # Bring down the network, deleting the volumes 42 | #Delete any ledger backups 43 | docker run -v $PWD:/tmp/first-network --rm hyperledger/fabric-tools:$IMAGETAG rm -Rf /tmp/first-network/ledgers-backup 44 | #Cleanup the chaincode containers 45 | clearContainers 46 | #Cleanup images 47 | removeUnwantedImages 48 | # remove orderer block and other channel configuration transactions and certs 49 | rm -rf channel-artifacts/*.block channel-artifacts/*.tx crypto-config ./org3-artifacts/crypto-config/ channel-artifacts/org3.json 50 | # remove the docker-compose yaml file that was customized to the example 51 | rm -f compose-files/docker-compose-e2e.yaml 52 | fi 53 | } 54 | 55 | networkDown -------------------------------------------------------------------------------- /network/env.sh: -------------------------------------------------------------------------------- 1 | # Set default value 2 | # Obtain the OS and Architecture string that will be used to select the correct 3 | # native binaries for your platform, e.g., darwin-amd64 or linux-amd64 4 | OS_ARCH=$(echo "$(uname -s | tr '[:upper:]' '[:lower:]' | sed 's/mingw64_nt.*/windows/')-$(uname -m | sed 's/x86_64/amd64/g')" | awk '{print tolower($0)}') 5 | # timeout duration - the duration the CLI should wait for a response from 6 | # another container before giving up 7 | CLI_TIMEOUT=10 8 | # default for delay between commands 9 | CLI_DELAY=3 10 | # compose files path 11 | COMPOSE_FILE_PATH=compose-files 12 | # use this as the default docker-compose yaml definition 13 | COMPOSE_FILE=$COMPOSE_FILE_PATH/docker-compose-cli.yaml 14 | # 15 | COMPOSE_FILE_COUCH=$COMPOSE_FILE_PATH/docker-compose-couch.yaml 16 | # org3 docker compose file 17 | COMPOSE_FILE_ORG3=$COMPOSE_FILE_PATH/docker-compose-org3.yaml 18 | # kafka and zookeeper compose file 19 | COMPOSE_FILE_KAFKA=$COMPOSE_FILE_PATH/docker-compose-kafka.yaml 20 | # two additional etcd/raft orderers 21 | COMPOSE_FILE_RAFT2=$COMPOSE_FILE_PATH/docker-compose-etcdraft2.yaml 22 | # certificate authorities compose file 23 | COMPOSE_FILE_CA=$COMPOSE_FILE_PATH/docker-compose-ca.yaml 24 | # 25 | # use golang as the default language for chaincode 26 | LANGUAGE=golang 27 | # default image tag 28 | IMAGETAG="latest" 29 | # Versions of fabric known not to work with this release of first-network 30 | BLACKLISTED_VERSIONS="^1\.0\. ^1\.1\.0-preview ^1\.1\.0-alpha" 31 | # channel name 32 | CHANNEL_NAME="iot-channel" 33 | # system channem name 34 | SYS_CHANNEL="iot-sys-channel" 35 | # set exports 36 | export COMPOSE_PROJECT_NAME=iot 37 | export IMAGE_TAG=$IMAGE_TAG 38 | export SYS_CHANNEL=$SYS_CHANNEL 39 | # conn conf 40 | CONN_CONF_PATH=conn-conf 41 | # default consensus type,[kafka,solo,etcdraft] 42 | CONSENSUS_TYPE="kafka" -------------------------------------------------------------------------------- /network/generate.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | . env.sh 3 | 4 | export VERBOSE=false 5 | export FABRIC_CFG_PATH=${PWD} 6 | 7 | # Generates Org certs using cryptogen tool 8 | function generateCerts() { 9 | which cryptogen 10 | if [ "$?" -ne 0 ]; then 11 | echo "cryptogen tool not found. exiting" 12 | exit 1 13 | fi 14 | echo 15 | echo "##########################################################" 16 | echo "##### Generate certificates using cryptogen tool #########" 17 | echo "##########################################################" 18 | 19 | if [ -d "crypto-config" ]; then 20 | rm -Rf crypto-config 21 | fi 22 | set -x 23 | cryptogen generate --config=./crypto-config.yaml 24 | res=$? 25 | set +x 26 | if [ $res -ne 0 ]; then 27 | echo "Failed to generate certificates..." 28 | exit 1 29 | fi 30 | echo 31 | echo "Generate CCP files for Org1 and Org2" 32 | ./ccp-generate.sh 33 | } 34 | 35 | function replacePrivateKey() { 36 | # sed on MacOSX does not support -i flag with a null extension. We will use 37 | # 't' for our back-up's extension and delete it at the end of the function 38 | ARCH=$(uname -s | grep Darwin) 39 | if [ "$ARCH" == "Darwin" ]; then 40 | OPTS="-it" 41 | else 42 | OPTS="-i" 43 | fi 44 | 45 | # Copy the template to the file that will be modified to add the private key 46 | cp $CONN_CONF_PATH/docker-compose-e2e-template.yaml $CONN_CONF_PATH/docker-compose-e2e.yaml 47 | 48 | # The next steps will replace the template's contents with the 49 | # actual values of the private key file names for the two CAs. 50 | CURRENT_DIR=$PWD 51 | cd crypto-config/peerOrganizations/org1.fabric-iot.edu/ca/ 52 | PRIV_KEY=$(ls *_sk) 53 | cd "$CURRENT_DIR" 54 | sed $OPTS "s/CA1_PRIVATE_KEY/${PRIV_KEY}/g" $CONN_CONF_PATH/docker-compose-e2e.yaml 55 | cd crypto-config/peerOrganizations/org2.fabric-iot.edu/ca/ 56 | PRIV_KEY=$(ls *_sk) 57 | cd "$CURRENT_DIR" 58 | sed $OPTS "s/CA2_PRIVATE_KEY/${PRIV_KEY}/g" $CONN_CONF_PATH/docker-compose-e2e.yaml 59 | # If MacOSX, remove the temporary backup of the docker-compose file 60 | if [ "$ARCH" == "Darwin" ]; then 61 | rm $CONN_CONF_PATH/docker-compose-e2e.yamlt 62 | fi 63 | } 64 | 65 | # Generate orderer genesis block, channel configuration transaction and 66 | # anchor peer update transactions 67 | function generateChannelArtifacts() { 68 | which configtxgen 69 | if [ "$?" -ne 0 ]; then 70 | echo "configtxgen tool not found. exiting" 71 | exit 1 72 | fi 73 | 74 | echo "##########################################################" 75 | echo "######### Generating Orderer Genesis block ##############" 76 | echo "##########################################################" 77 | # Note: For some unknown reason (at least for now) the block file can't be 78 | # named orderer.genesis.block or the orderer will fail to launch! 79 | echo "CONSENSUS_TYPE="$CONSENSUS_TYPE 80 | set -x 81 | if [ "$CONSENSUS_TYPE" == "solo" ]; then 82 | configtxgen -profile TwoOrgsOrdererGenesis -channelID $SYS_CHANNEL -outputBlock ./channel-artifacts/genesis.block 83 | elif [ "$CONSENSUS_TYPE" == "kafka" ]; then 84 | configtxgen -profile SampleDevModeKafka -channelID $SYS_CHANNEL -outputBlock ./channel-artifacts/genesis.block 85 | elif [ "$CONSENSUS_TYPE" == "etcdraft" ]; then 86 | configtxgen -profile SampleMultiNodeEtcdRaft -channelID $SYS_CHANNEL -outputBlock ./channel-artifacts/genesis.block 87 | else 88 | set +x 89 | echo "unrecognized CONSESUS_TYPE='$CONSENSUS_TYPE'. exiting" 90 | exit 1 91 | fi 92 | res=$? 93 | set +x 94 | if [ $res -ne 0 ]; then 95 | echo "Failed to generate orderer genesis block..." 96 | exit 1 97 | fi 98 | echo 99 | echo "#################################################################" 100 | echo "### Generating channel configuration transaction 'channel.tx' ###" 101 | echo "#################################################################" 102 | set -x 103 | configtxgen -profile TwoOrgsChannel -outputCreateChannelTx ./channel-artifacts/channel.tx -channelID $CHANNEL_NAME 104 | res=$? 105 | set +x 106 | if [ $res -ne 0 ]; then 107 | echo "Failed to generate channel configuration transaction..." 108 | exit 1 109 | fi 110 | 111 | echo 112 | echo "#################################################################" 113 | echo "####### Generating anchor peer update for Org1MSP ##########" 114 | echo "#################################################################" 115 | set -x 116 | configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org1MSPanchors.tx -channelID $CHANNEL_NAME -asOrg Org1MSP 117 | res=$? 118 | set +x 119 | if [ $res -ne 0 ]; then 120 | echo "Failed to generate anchor peer update for Org1MSP..." 121 | exit 1 122 | fi 123 | 124 | echo 125 | echo "#################################################################" 126 | echo "####### Generating anchor peer update for Org2MSP ##########" 127 | echo "#################################################################" 128 | set -x 129 | configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate \ 130 | ./channel-artifacts/Org2MSPanchors.tx -channelID $CHANNEL_NAME -asOrg Org2MSP 131 | res=$? 132 | set +x 133 | if [ $res -ne 0 ]; then 134 | echo "Failed to generate anchor peer update for Org2MSP..." 135 | exit 1 136 | fi 137 | echo 138 | } 139 | 140 | ##利用cryptogen生成新的Certs文件 141 | generateCerts 142 | ##根据e2e模版yaml生成新的yaml,并将生成的Cert文件替换到yaml的CA节点的路径中 143 | replacePrivateKey 144 | ##利用configtxgen生成创世区块、创建通道 145 | generateChannelArtifacts 146 | 147 | echo "========= All GOOD, [fabric-iot] execution completed =========== " 148 | -------------------------------------------------------------------------------- /network/restart.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # import env 4 | . env.sh 5 | 6 | # settings 7 | CERTIFICATE_AUTHORITIES="true" 8 | # not install chaincode 9 | NO_CHAINCODE="true" 10 | # use couchdb 11 | IF_COUCHDB="couchdb" 12 | 13 | # Do some basic sanity checking to make sure that the appropriate versions of fabric 14 | # binaries/images are available. In the future, additional checking for the presence 15 | # of go or other items could be added. 16 | function checkPrereqs() { 17 | # Note, we check configtxlator externally because it does not require a config file, and peer in the 18 | # docker image because of FAB-8551 that makes configtxlator return 'development version' in docker 19 | LOCAL_VERSION=$(configtxlator version | sed -ne 's/ Version: //p') 20 | DOCKER_IMAGE_VERSION=$(docker run --rm hyperledger/fabric-tools:$IMAGETAG peer version | sed -ne 's/ Version: //p' | head -1) 21 | 22 | echo "LOCAL_VERSION=$LOCAL_VERSION" 23 | echo "DOCKER_IMAGE_VERSION=$DOCKER_IMAGE_VERSION" 24 | 25 | if [ "$LOCAL_VERSION" != "$DOCKER_IMAGE_VERSION" ]; then 26 | echo "=================== WARNING ===================" 27 | echo " Local fabric binaries and docker images are " 28 | echo " out of sync. This may cause problems. " 29 | echo "===============================================" 30 | fi 31 | 32 | for UNSUPPORTED_VERSION in $BLACKLISTED_VERSIONS; do 33 | echo "$LOCAL_VERSION" | grep -q $UNSUPPORTED_VERSION 34 | if [ $? -eq 0 ]; then 35 | echo "ERROR! Local Fabric binary version of $LOCAL_VERSION does not match this newer version of [fabric-iot] and is unsupported. Either move to a later version of Fabric or checkout an earlier version of fabric-samples." 36 | exit 1 37 | fi 38 | 39 | echo "$DOCKER_IMAGE_VERSION" | grep -q $UNSUPPORTED_VERSION 40 | if [ $? -eq 0 ]; then 41 | echo "ERROR! Fabric Docker image version of $DOCKER_IMAGE_VERSION does not match this newer version of [fabric-iot] and is unsupported. Either move to a later version of Fabric or checkout an earlier version of fabric-samples." 42 | exit 1 43 | fi 44 | done 45 | } 46 | 47 | # Generate the needed certificates, the genesis block and start the network. 48 | function networkUp() { 49 | checkPrereqs 50 | # generate artifacts if they don't exist 51 | if [ ! -d "crypto-config" ]; then 52 | ./generate.sh 53 | fi 54 | COMPOSE_FILES="-f ${COMPOSE_FILE}" 55 | if [ "${CERTIFICATE_AUTHORITIES}" == "true" ]; then 56 | COMPOSE_FILES="${COMPOSE_FILES} -f ${COMPOSE_FILE_CA}" 57 | export CA1_PRIVATE_KEY=$(cd crypto-config/peerOrganizations/org1.fabric-iot.edu/ca && ls *_sk) 58 | export CA2_PRIVATE_KEY=$(cd crypto-config/peerOrganizations/org2.fabric-iot.edu/ca && ls *_sk) 59 | fi 60 | if [ "${CONSENSUS_TYPE}" == "kafka" ]; then 61 | COMPOSE_FILES="${COMPOSE_FILES} -f ${COMPOSE_FILE_KAFKA}" 62 | elif [ "${CONSENSUS_TYPE}" == "etcdraft" ]; then 63 | COMPOSE_FILES="${COMPOSE_FILES} -f ${COMPOSE_FILE_RAFT2}" 64 | fi 65 | if [ "${IF_COUCHDB}" == "couchdb" ]; then 66 | COMPOSE_FILES="${COMPOSE_FILES} -f ${COMPOSE_FILE_COUCH}" 67 | fi 68 | IMAGE_TAG=$IMAGETAG docker-compose ${COMPOSE_FILES} up -d 2>&1 69 | docker ps -a 70 | if [ $? -ne 0 ]; then 71 | echo "ERROR !!!! Unable to start network" 72 | exit 1 73 | fi 74 | 75 | if [ "$CONSENSUS_TYPE" == "kafka" ]; then 76 | sleep 1 77 | echo "Sleeping 10s to allow $CONSENSUS_TYPE cluster to complete booting" 78 | sleep 9 79 | fi 80 | 81 | if [ "$CONSENSUS_TYPE" == "etcdraft" ]; then 82 | sleep 1 83 | echo "Sleeping 15s to allow $CONSENSUS_TYPE cluster to complete booting" 84 | sleep 14 85 | fi 86 | } 87 | 88 | function chaincodeUp(){ 89 | DOCKER_IMAGE_IDS=$(docker ps -a | awk '($2 ~ /dev-peer*.*.*.*c.*/) {print $1}') 90 | docker restart $DOCKER_IMAGE_IDS 91 | } 92 | 93 | networkUp 94 | chaincodeUp -------------------------------------------------------------------------------- /network/scripts/script.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo 4 | echo " ____ _____ _ ____ _____ " 5 | echo "/ ___| |_ _| / \ | _ \ |_ _|" 6 | echo "\___ \ | | / _ \ | |_) | | | " 7 | echo " ___) | | | / ___ \ | _ < | | " 8 | echo "|____/ |_| /_/ \_\ |_| \_\ |_| " 9 | echo 10 | echo "Build [fabric-iot] end-to-end test" 11 | echo 12 | CHANNEL_NAME="$1" 13 | DELAY="$2" 14 | LANGUAGE="$3" 15 | TIMEOUT="$4" 16 | VERBOSE="$5" 17 | NO_CHAINCODE="$6" 18 | : ${CHANNEL_NAME:="iot-channel"} 19 | : ${DELAY:="3"} 20 | : ${LANGUAGE:="golang"} 21 | : ${TIMEOUT:="10"} 22 | : ${VERBOSE:="false"} 23 | : ${NO_CHAINCODE:="true"} 24 | LANGUAGE=`echo "$LANGUAGE" | tr [:upper:] [:lower:]` 25 | COUNTER=1 26 | MAX_RETRY=10 27 | 28 | echo "Channel name : "$CHANNEL_NAME 29 | 30 | # import utils 31 | . scripts/utils.sh 32 | 33 | createChannel() { 34 | setGlobals 0 1 35 | 36 | if [ -z "$CORE_PEER_TLS_ENABLED" -o "$CORE_PEER_TLS_ENABLED" = "false" ]; then 37 | set -x 38 | peer channel create -o orderer.fabric-iot.edu:7050 -c $CHANNEL_NAME -f ./channel-artifacts/channel.tx >&log.txt 39 | res=$? 40 | set +x 41 | else 42 | set -x 43 | peer channel create -o orderer.fabric-iot.edu:7050 -c $CHANNEL_NAME -f ./channel-artifacts/channel.tx --tls $CORE_PEER_TLS_ENABLED --cafile $ORDERER_CA >&log.txt 44 | res=$? 45 | set +x 46 | fi 47 | cat log.txt 48 | verifyResult $res "Channel creation failed" 49 | echo "===================== Channel '$CHANNEL_NAME' created ===================== " 50 | echo 51 | } 52 | 53 | joinChannel () { 54 | for org in 1 2; do 55 | for peer in 0 1; do 56 | joinChannelWithRetry $peer $org 57 | echo "===================== peer${peer}.org${org} joined channel '$CHANNEL_NAME' ===================== " 58 | sleep $DELAY 59 | echo 60 | done 61 | done 62 | } 63 | 64 | ## Create channel 65 | echo "Creating channel..." 66 | createChannel 67 | 68 | # Waiting for channel created 69 | echo "Waiting for channel created:" 70 | for((i=1;i<=10;i++)) 71 | do 72 | sleep 1 73 | echo -e ">\c" 74 | done 75 | echo 76 | 77 | ## Join all the peers to the channel 78 | echo "Having all peers join the channel..." 79 | joinChannel 80 | 81 | ## Set the anchor peers for each org in the channel 82 | echo "Updating anchor peers for org1..." 83 | updateAnchorPeers 0 1 84 | echo "Updating anchor peers for org2..." 85 | updateAnchorPeers 0 2 86 | 87 | echo 88 | echo "========= All GOOD, [fabric-iot] execution completed =========== " 89 | echo 90 | 91 | echo 92 | echo " _____ _ _ ____ " 93 | echo "| ____| | \ | | | _ \ " 94 | echo "| _| | \| | | | | | " 95 | echo "| |___ | |\ | | |_| | " 96 | echo "|_____| |_| \_| |____/ " 97 | echo 98 | 99 | exit 0 100 | -------------------------------------------------------------------------------- /network/scripts/utils.sh: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright IBM Corp All Rights Reserved 3 | # 4 | # SPDX-License-Identifier: Apache-2.0 5 | # 6 | 7 | # This is a collection of bash functions used by different scripts 8 | 9 | ORDERER_CA=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/fabric-iot.edu/orderers/orderer.fabric-iot.edu/msp/tlscacerts/tlsca.fabric-iot.edu-cert.pem 10 | PEER0_ORG1_CA=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.fabric-iot.edu/peers/peer0.org1.fabric-iot.edu/tls/ca.crt 11 | PEER0_ORG2_CA=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.fabric-iot.edu/peers/peer0.org2.fabric-iot.edu/tls/ca.crt 12 | PEER0_ORG3_CA=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org3.fabric-iot.edu/peers/peer0.org3.fabric-iot.edu/tls/ca.crt 13 | 14 | # verify the result of the end-to-end test 15 | verifyResult() { 16 | if [ $1 -ne 0 ]; then 17 | echo "!!!!!!!!!!!!!!! "$2" !!!!!!!!!!!!!!!!" 18 | echo "========= ERROR !!! FAILED to execute End-2-End Scenario ===========" 19 | echo 20 | exit 1 21 | fi 22 | } 23 | 24 | # Set OrdererOrg.Admin globals 25 | setOrdererGlobals() { 26 | CORE_PEER_LOCALMSPID="OrdererMSP" 27 | CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/fabric-iot.edu/orderers/orderer.fabric-iot.edu/msp/tlscacerts/tlsca.fabric-iot.edu-cert.pem 28 | CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/fabric-iot.edu/users/Admin@fabric-iot.edu/msp 29 | } 30 | 31 | setGlobals() { 32 | PEER=$1 33 | ORG=$2 34 | if [ $ORG -eq 1 ]; then 35 | CORE_PEER_LOCALMSPID="Org1MSP" 36 | CORE_PEER_TLS_ROOTCERT_FILE=$PEER0_ORG1_CA 37 | CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.fabric-iot.edu/users/Admin@org1.fabric-iot.edu/msp 38 | if [ $PEER -eq 0 ]; then 39 | CORE_PEER_ADDRESS=peer0.org1.fabric-iot.edu:7051 40 | else 41 | CORE_PEER_ADDRESS=peer1.org1.fabric-iot.edu:8051 42 | fi 43 | elif [ $ORG -eq 2 ]; then 44 | CORE_PEER_LOCALMSPID="Org2MSP" 45 | CORE_PEER_TLS_ROOTCERT_FILE=$PEER0_ORG2_CA 46 | CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.fabric-iot.edu/users/Admin@org2.fabric-iot.edu/msp 47 | if [ $PEER -eq 0 ]; then 48 | CORE_PEER_ADDRESS=peer0.org2.fabric-iot.edu:9051 49 | else 50 | CORE_PEER_ADDRESS=peer1.org2.fabric-iot.edu:10051 51 | fi 52 | 53 | elif [ $ORG -eq 3 ]; then 54 | CORE_PEER_LOCALMSPID="Org3MSP" 55 | CORE_PEER_TLS_ROOTCERT_FILE=$PEER0_ORG3_CA 56 | CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org3.fabric-iot.edu/users/Admin@org3.fabric-iot.edu/msp 57 | if [ $PEER -eq 0 ]; then 58 | CORE_PEER_ADDRESS=peer0.org3.fabric-iot.edu:11051 59 | else 60 | CORE_PEER_ADDRESS=peer1.org3.fabric-iot.edu:12051 61 | fi 62 | else 63 | echo "================== ERROR !!! ORG Unknown ==================" 64 | fi 65 | 66 | if [ "$VERBOSE" == "true" ]; then 67 | env | grep CORE 68 | fi 69 | } 70 | 71 | updateAnchorPeers() { 72 | PEER=$1 73 | ORG=$2 74 | setGlobals $PEER $ORG 75 | 76 | if [ -z "$CORE_PEER_TLS_ENABLED" -o "$CORE_PEER_TLS_ENABLED" = "false" ]; then 77 | set -x 78 | peer channel update -o orderer.fabric.com:7050 -c $CHANNEL_NAME -f ./channel-artifacts/${CORE_PEER_LOCALMSPID}anchors.tx >&log.txt 79 | res=$? 80 | set +x 81 | else 82 | set -x 83 | peer channel update -o orderer.fabric-iot.edu:7050 -c $CHANNEL_NAME -f ./channel-artifacts/${CORE_PEER_LOCALMSPID}anchors.tx --tls $CORE_PEER_TLS_ENABLED --cafile $ORDERER_CA >&log.txt 84 | res=$? 85 | set +x 86 | fi 87 | cat log.txt 88 | verifyResult $res "Anchor peer update failed" 89 | echo "===================== Anchor peers updated for org '$CORE_PEER_LOCALMSPID' on channel '$CHANNEL_NAME' ===================== " 90 | sleep $DELAY 91 | echo 92 | } 93 | 94 | ## Sometimes Join takes time hence RETRY at least 5 times 95 | joinChannelWithRetry() { 96 | PEER=$1 97 | ORG=$2 98 | setGlobals $PEER $ORG 99 | 100 | set -x 101 | peer channel join -b $CHANNEL_NAME.block >&log.txt 102 | res=$? 103 | set +x 104 | cat log.txt 105 | if [ $res -ne 0 -a $COUNTER -lt $MAX_RETRY ]; then 106 | COUNTER=$(expr $COUNTER + 1) 107 | echo "peer${PEER}.org${ORG} failed to join the channel, Retry after $DELAY seconds" 108 | sleep $DELAY 109 | joinChannelWithRetry $PEER $ORG 110 | else 111 | COUNTER=1 112 | fi 113 | verifyResult $res "After $MAX_RETRY attempts, peer${PEER}.org${ORG} has failed to join channel '$CHANNEL_NAME' " 114 | } 115 | 116 | installChaincode() { 117 | PEER=$1 118 | ORG=$2 119 | setGlobals $PEER $ORG 120 | VERSION=${3:-1.0} 121 | set -x 122 | peer chaincode install -n mycc -v ${VERSION} -l ${LANGUAGE} -p ${CC_SRC_PATH} >&log.txt 123 | res=$? 124 | set +x 125 | cat log.txt 126 | verifyResult $res "Chaincode installation on peer${PEER}.org${ORG} has failed" 127 | echo "===================== Chaincode is installed on peer${PEER}.org${ORG} ===================== " 128 | echo 129 | } 130 | 131 | instantiateChaincode() { 132 | PEER=$1 133 | ORG=$2 134 | setGlobals $PEER $ORG 135 | VERSION=${3:-1.0} 136 | 137 | # while 'peer chaincode' command can get the orderer endpoint from the peer 138 | # (if join was successful), let's supply it directly as we know it using 139 | # the "-o" option 140 | if [ -z "$CORE_PEER_TLS_ENABLED" -o "$CORE_PEER_TLS_ENABLED" = "false" ]; then 141 | set -x 142 | peer chaincode instantiate -o orderer.fabric-iot.edu:7050 -C $CHANNEL_NAME -n mycc -l ${LANGUAGE} -v ${VERSION} -c '{"Args":["init","a","100","b","200"]}' -P "AND ('Org1MSP.peer','Org2MSP.peer')" >&log.txt 143 | res=$? 144 | set +x 145 | else 146 | set -x 147 | peer chaincode instantiate -o orderer.fabric-iot.edu:7050 --tls $CORE_PEER_TLS_ENABLED --cafile $ORDERER_CA -C $CHANNEL_NAME -n mycc -l ${LANGUAGE} -v 1.0 -c '{"Args":["init","a","100","b","200"]}' -P "AND ('Org1MSP.peer','Org2MSP.peer')" >&log.txt 148 | res=$? 149 | set +x 150 | fi 151 | cat log.txt 152 | verifyResult $res "Chaincode instantiation on peer${PEER}.org${ORG} on channel '$CHANNEL_NAME' failed" 153 | echo "===================== Chaincode is instantiated on peer${PEER}.org${ORG} on channel '$CHANNEL_NAME' ===================== " 154 | echo 155 | } 156 | 157 | upgradeChaincode() { 158 | PEER=$1 159 | ORG=$2 160 | setGlobals $PEER $ORG 161 | 162 | set -x 163 | peer chaincode upgrade -o orderer.fabric-iot.edu:7050 --tls $CORE_PEER_TLS_ENABLED --cafile $ORDERER_CA -C $CHANNEL_NAME -n mycc -v 2.0 -c '{"Args":["init","a","90","b","210"]}' -P "AND ('Org1MSP.peer','Org2MSP.peer','Org3MSP.peer')" 164 | res=$? 165 | set +x 166 | cat log.txt 167 | verifyResult $res "Chaincode upgrade on peer${PEER}.org${ORG} has failed" 168 | echo "===================== Chaincode is upgraded on peer${PEER}.org${ORG} on channel '$CHANNEL_NAME' ===================== " 169 | echo 170 | } 171 | 172 | chaincodeQuery() { 173 | PEER=$1 174 | ORG=$2 175 | setGlobals $PEER $ORG 176 | EXPECTED_RESULT=$3 177 | echo "===================== Querying on peer${PEER}.org${ORG} on channel '$CHANNEL_NAME'... ===================== " 178 | local rc=1 179 | local starttime=$(date +%s) 180 | 181 | # continue to poll 182 | # we either get a successful response, or reach TIMEOUT 183 | while 184 | test "$(($(date +%s) - starttime))" -lt "$TIMEOUT" -a $rc -ne 0 185 | do 186 | sleep $DELAY 187 | echo "Attempting to Query peer${PEER}.org${ORG} ...$(($(date +%s) - starttime)) secs" 188 | set -x 189 | peer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args":["query","a"]}' >&log.txt 190 | res=$? 191 | set +x 192 | test $res -eq 0 && VALUE=$(cat log.txt | awk '/Query Result/ {print $NF}') 193 | test "$VALUE" = "$EXPECTED_RESULT" && let rc=0 194 | # removed the string "Query Result" from peer chaincode query command 195 | # result. as a result, have to support both options until the change 196 | # is merged. 197 | test $rc -ne 0 && VALUE=$(cat log.txt | egrep '^[0-9]+$') 198 | test "$VALUE" = "$EXPECTED_RESULT" && let rc=0 199 | done 200 | echo 201 | cat log.txt 202 | if test $rc -eq 0; then 203 | echo "===================== Query successful on peer${PEER}.org${ORG} on channel '$CHANNEL_NAME' ===================== " 204 | else 205 | echo "!!!!!!!!!!!!!!! Query result on peer${PEER}.org${ORG} is INVALID !!!!!!!!!!!!!!!!" 206 | echo "================== ERROR !!! FAILED to execute End-2-End Scenario ==================" 207 | echo 208 | exit 1 209 | fi 210 | } 211 | 212 | # fetchChannelConfig 213 | # Writes the current channel config for a given channel to a JSON file 214 | fetchChannelConfig() { 215 | CHANNEL=$1 216 | OUTPUT=$2 217 | 218 | setOrdererGlobals 219 | 220 | echo "Fetching the most recent configuration block for the channel" 221 | if [ -z "$CORE_PEER_TLS_ENABLED" -o "$CORE_PEER_TLS_ENABLED" = "false" ]; then 222 | set -x 223 | peer channel fetch config config_block.pb -o orderer.fabric-iot.edu:7050 -c $CHANNEL --cafile $ORDERER_CA 224 | set +x 225 | else 226 | set -x 227 | peer channel fetch config config_block.pb -o orderer.fabric-iot.edu:7050 -c $CHANNEL --tls --cafile $ORDERER_CA 228 | set +x 229 | fi 230 | 231 | echo "Decoding config block to JSON and isolating config to ${OUTPUT}" 232 | set -x 233 | configtxlator proto_decode --input config_block.pb --type common.Block | jq .data.data[0].payload.data.config >"${OUTPUT}" 234 | set +x 235 | } 236 | 237 | # signConfigtxAsPeerOrg 238 | # Set the peerOrg admin of an org and signing the config update 239 | signConfigtxAsPeerOrg() { 240 | PEERORG=$1 241 | TX=$2 242 | setGlobals 0 $PEERORG 243 | set -x 244 | peer channel signconfigtx -f "${TX}" 245 | set +x 246 | } 247 | 248 | # createConfigUpdate 249 | # Takes an original and modified config, and produces the config update tx 250 | # which transitions between the two 251 | createConfigUpdate() { 252 | CHANNEL=$1 253 | ORIGINAL=$2 254 | MODIFIED=$3 255 | OUTPUT=$4 256 | 257 | set -x 258 | configtxlator proto_encode --input "${ORIGINAL}" --type common.Config >original_config.pb 259 | configtxlator proto_encode --input "${MODIFIED}" --type common.Config >modified_config.pb 260 | configtxlator compute_update --channel_id "${CHANNEL}" --original original_config.pb --updated modified_config.pb >config_update.pb 261 | configtxlator proto_decode --input config_update.pb --type common.ConfigUpdate >config_update.json 262 | echo '{"payload":{"header":{"channel_header":{"channel_id":"'$CHANNEL'", "type":2}},"data":{"config_update":'$(cat config_update.json)'}}}' | jq . >config_update_in_envelope.json 263 | configtxlator proto_encode --input config_update_in_envelope.json --type common.Envelope >"${OUTPUT}" 264 | set +x 265 | } 266 | 267 | # parsePeerConnectionParameters $@ 268 | # Helper function that takes the parameters from a chaincode operation 269 | # (e.g. invoke, query, instantiate) and checks for an even number of 270 | # peers and associated org, then sets $PEER_CONN_PARMS and $PEERS 271 | parsePeerConnectionParameters() { 272 | # check for uneven number of peer and org parameters 273 | if [ $(($# % 2)) -ne 0 ]; then 274 | exit 1 275 | fi 276 | 277 | PEER_CONN_PARMS="" 278 | PEERS="" 279 | while [ "$#" -gt 0 ]; do 280 | setGlobals $1 $2 281 | PEER="peer$1.org$2" 282 | PEERS="$PEERS $PEER" 283 | PEER_CONN_PARMS="$PEER_CONN_PARMS --peerAddresses $CORE_PEER_ADDRESS" 284 | if [ -z "$CORE_PEER_TLS_ENABLED" -o "$CORE_PEER_TLS_ENABLED" = "true" ]; then 285 | TLSINFO=$(eval echo "--tlsRootCertFiles \$PEER$1_ORG$2_CA") 286 | PEER_CONN_PARMS="$PEER_CONN_PARMS $TLSINFO" 287 | fi 288 | # shift by two to get the next pair of peer/org parameters 289 | shift 290 | shift 291 | done 292 | # remove leading space for output 293 | PEERS="$(echo -e "$PEERS" | sed -e 's/^[[:space:]]*//')" 294 | } 295 | 296 | # chaincodeInvoke ... 297 | # Accepts as many peer/org pairs as desired and requests endorsement from each 298 | chaincodeInvoke() { 299 | parsePeerConnectionParameters $@ 300 | res=$? 301 | verifyResult $res "Invoke transaction failed on channel '$CHANNEL_NAME' due to uneven number of peer and org parameters " 302 | 303 | # while 'peer chaincode' command can get the orderer endpoint from the 304 | # peer (if join was successful), let's supply it directly as we know 305 | # it using the "-o" option 306 | if [ -z "$CORE_PEER_TLS_ENABLED" -o "$CORE_PEER_TLS_ENABLED" = "false" ]; then 307 | set -x 308 | peer chaincode invoke -o orderer.fabric-iot.edu:7050 -C $CHANNEL_NAME -n mycc $PEER_CONN_PARMS -c '{"Args":["invoke","a","b","10"]}' >&log.txt 309 | res=$? 310 | set +x 311 | else 312 | set -x 313 | peer chaincode invoke -o orderer.fabric-iot.edu:7050 --tls $CORE_PEER_TLS_ENABLED --cafile $ORDERER_CA -C $CHANNEL_NAME -n mycc $PEER_CONN_PARMS -c '{"Args":["invoke","a","b","10"]}' >&log.txt 314 | res=$? 315 | set +x 316 | fi 317 | cat log.txt 318 | verifyResult $res "Invoke execution on $PEERS failed " 319 | echo "===================== Invoke transaction successful on $PEERS on channel '$CHANNEL_NAME' ===================== " 320 | echo 321 | } 322 | -------------------------------------------------------------------------------- /network/up.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # import env 4 | . env.sh 5 | 6 | # settings 7 | CERTIFICATE_AUTHORITIES="true" 8 | # not install chaincode 9 | NO_CHAINCODE="true" 10 | # use couchdb 11 | IF_COUCHDB="couchdb" 12 | 13 | # Do some basic sanity checking to make sure that the appropriate versions of fabric 14 | # binaries/images are available. In the future, additional checking for the presence 15 | # of go or other items could be added. 16 | function checkPrereqs() { 17 | # Note, we check configtxlator externally because it does not require a config file, and peer in the 18 | # docker image because of FAB-8551 that makes configtxlator return 'development version' in docker 19 | LOCAL_VERSION=$(configtxlator version | sed -ne 's/ Version: //p') 20 | DOCKER_IMAGE_VERSION=$(docker run --rm hyperledger/fabric-tools:$IMAGETAG peer version | sed -ne 's/ Version: //p' | head -1) 21 | 22 | echo "LOCAL_VERSION=$LOCAL_VERSION" 23 | echo "DOCKER_IMAGE_VERSION=$DOCKER_IMAGE_VERSION" 24 | 25 | if [ "$LOCAL_VERSION" != "$DOCKER_IMAGE_VERSION" ]; then 26 | echo "=================== WARNING ===================" 27 | echo " Local fabric binaries and docker images are " 28 | echo " out of sync. This may cause problems. " 29 | echo "===============================================" 30 | fi 31 | 32 | for UNSUPPORTED_VERSION in $BLACKLISTED_VERSIONS; do 33 | echo "$LOCAL_VERSION" | grep -q $UNSUPPORTED_VERSION 34 | if [ $? -eq 0 ]; then 35 | echo "ERROR! Local Fabric binary version of $LOCAL_VERSION does not match this newer version of [fabric-iot] and is unsupported. Either move to a later version of Fabric or checkout an earlier version of fabric-samples." 36 | exit 1 37 | fi 38 | 39 | echo "$DOCKER_IMAGE_VERSION" | grep -q $UNSUPPORTED_VERSION 40 | if [ $? -eq 0 ]; then 41 | echo "ERROR! Fabric Docker image version of $DOCKER_IMAGE_VERSION does not match this newer version of [fabric-iot] and is unsupported. Either move to a later version of Fabric or checkout an earlier version of fabric-samples." 42 | exit 1 43 | fi 44 | done 45 | } 46 | 47 | # Generate the needed certificates, the genesis block and start the network. 48 | function networkUp() { 49 | checkPrereqs 50 | # generate artifacts if they don't exist 51 | if [ ! -d "crypto-config" ]; then 52 | ./generate.sh 53 | fi 54 | COMPOSE_FILES="-f ${COMPOSE_FILE}" 55 | if [ "${CERTIFICATE_AUTHORITIES}" == "true" ]; then 56 | COMPOSE_FILES="${COMPOSE_FILES} -f ${COMPOSE_FILE_CA}" 57 | export CA1_PRIVATE_KEY=$(cd crypto-config/peerOrganizations/org1.fabric-iot.edu/ca && ls *_sk) 58 | export CA2_PRIVATE_KEY=$(cd crypto-config/peerOrganizations/org2.fabric-iot.edu/ca && ls *_sk) 59 | fi 60 | if [ "${CONSENSUS_TYPE}" == "kafka" ]; then 61 | COMPOSE_FILES="${COMPOSE_FILES} -f ${COMPOSE_FILE_KAFKA}" 62 | elif [ "${CONSENSUS_TYPE}" == "etcdraft" ]; then 63 | COMPOSE_FILES="${COMPOSE_FILES} -f ${COMPOSE_FILE_RAFT2}" 64 | fi 65 | if [ "${IF_COUCHDB}" == "couchdb" ]; then 66 | COMPOSE_FILES="${COMPOSE_FILES} -f ${COMPOSE_FILE_COUCH}" 67 | fi 68 | IMAGE_TAG=$IMAGETAG docker-compose ${COMPOSE_FILES} up -d 2>&1 69 | docker ps -a 70 | if [ $? -ne 0 ]; then 71 | echo "ERROR !!!! Unable to start network" 72 | exit 1 73 | fi 74 | 75 | if [ "$CONSENSUS_TYPE" == "kafka" ]; then 76 | sleep 1 77 | echo "Sleeping 15s to allow $CONSENSUS_TYPE cluster to complete booting" 78 | for i in {1..15} 79 | do 80 | echo -n '>' 81 | sleep 1 82 | done 83 | echo ' kafka maybe ready' 84 | fi 85 | 86 | if [ "$CONSENSUS_TYPE" == "etcdraft" ]; then 87 | sleep 1 88 | echo "Sleeping 15s to allow $CONSENSUS_TYPE cluster to complete booting" 89 | for i in {1..15} 90 | do 91 | echo -n '>' 92 | sleep 1 93 | done 94 | echo ' etcdraft maybe ready' 95 | fi 96 | } 97 | 98 | function runScript() { 99 | # now run the end to end script 100 | docker exec cli scripts/script.sh $CHANNEL_NAME $CLI_DELAY $LANGUAGE $CLI_TIMEOUT $VERBOSE $NO_CHAINCODE 101 | if [ $? -ne 0 ]; then 102 | echo "ERROR !!!! Test failed" 103 | exit 1 104 | fi 105 | } 106 | 107 | networkUp 108 | runScript -------------------------------------------------------------------------------- /test/consensus/kafka/kafak_test.go: -------------------------------------------------------------------------------- 1 | package kafka 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | "time" 7 | ) 8 | 9 | func TestKafka(t *testing.T) { 10 | for j := 10; j <= 500; j += 20 { 11 | start := time.Now().UnixNano() 12 | Kafka(j) 13 | end := time.Now().UnixNano() 14 | fmt.Printf("%-4d%.2f\n", j, float32(end-start)/1e6) 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /test/consensus/kafka/kafka.go: -------------------------------------------------------------------------------- 1 | package kafka 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "strconv" 7 | "time" 8 | 9 | mqtt "github.com/eclipse/paho.mqtt.golang" 10 | ) 11 | 12 | const ( 13 | TOPIC = "/test/kafka" 14 | HOST = "tcp://localhost:1883" 15 | ) 16 | 17 | func Kafka(n int) { 18 | 19 | sn := make(chan bool) 20 | //start order 21 | go NewOrder(TOPIC, HOST, n).Rank(sn) 22 | <-sn 23 | //log.Println("Order started") 24 | //start peer 25 | ss := make(chan bool, n) 26 | sg := make(chan bool) 27 | for i := 0; i < n; i++ { 28 | go NewPeer(TOPIC, HOST).Submit(ss, sg) 29 | } 30 | //now wait all peer started 31 | for i := 0; i < n; i++ { 32 | <-ss 33 | } 34 | //log.Println("All peer started") 35 | //let all peer to submit Transaction 36 | close(sg) 37 | //wait order finish 38 | <-sn 39 | } 40 | 41 | func Wait() { 42 | sn := make(chan int) 43 | <-sn 44 | } 45 | 46 | /************* MQTTCli *************/ 47 | type MQTTCli struct { 48 | id string 49 | c mqtt.Client 50 | } 51 | 52 | func NewMQTTCli(host string) *MQTTCli { 53 | mc := &MQTTCli{} 54 | mc.Connect(host) 55 | return mc 56 | } 57 | 58 | func (mc *MQTTCli) ID() string { 59 | return mc.id 60 | } 61 | func (mc *MQTTCli) Pub(topic string, msg interface{}) { 62 | // //log.Println("pub:", topic, msg) 63 | token := mc.c.Publish(topic, 1, false, msg) 64 | if token.Error() != nil { 65 | //log.Println(token.Error().Error()) 66 | } 67 | } 68 | 69 | func (mc *MQTTCli) Sub(topic string, f func(client mqtt.Client, message mqtt.Message)) { 70 | if token := mc.c.Subscribe(topic, 0, f); token.Wait() && token.Error() != nil { 71 | fmt.Println(token.Error()) 72 | } 73 | } 74 | 75 | func (mc *MQTTCli) Connect(host string) { 76 | mc.id = strconv.FormatInt(time.Now().UnixNano(), 10) 77 | opts := mqtt.NewClientOptions().AddBroker(host).SetClientID(mc.id) 78 | mc.c = mqtt.NewClient(opts) 79 | if token := mc.c.Connect(); token.Wait() && token.Error() != nil { 80 | panic(token.Error()) 81 | } 82 | } 83 | 84 | /************* Peer *************/ 85 | type Peer struct { 86 | topic string 87 | mc *MQTTCli 88 | } 89 | 90 | func (p *Peer) Submit(ss, sg chan bool) { 91 | p.mc.Sub(p.topic+"/call", func(client mqtt.Client, message mqtt.Message) { 92 | //sleep cost time 93 | CostTime() 94 | if string(message.Payload()) == "confirm" { 95 | p.mc.Pub(p.topic+"/back", "ok") 96 | } 97 | }) 98 | ss <- true 99 | //log.Println("Peer", p.mc.id, "started") 100 | // all peer have started, now can pub 101 | if _, ok := <-sg; !ok { 102 | p.mc.Pub(p.topic, NewTransaction(p.mc.id).Bytes()) 103 | } 104 | 105 | } 106 | 107 | func NewPeer(topic string, host string) *Peer { 108 | return &Peer{topic, NewMQTTCli(host)} 109 | } 110 | 111 | /************* Order *************/ 112 | type Order struct { 113 | topic string 114 | mc *MQTTCli 115 | cNum int 116 | lock bool 117 | } 118 | 119 | func NewOrder(topic string, host string, cNum int) *Order { 120 | return &Order{topic: topic, mc: NewMQTTCli(host), cNum: cNum, lock: false} 121 | } 122 | 123 | func (o *Order) Rank(c chan bool) { 124 | o.mc.Sub(o.topic, func(client mqtt.Client, message mqtt.Message) { 125 | GetTransaction(message.Payload()) 126 | if o.lock { 127 | //log.Println("Order rank:", t.PID, "at", t.Timestamp, "->reject") 128 | return 129 | } 130 | //only recesive 1 submit 131 | o.lock = true 132 | //log.Println("Order rank:", t.PID, "at", t.Timestamp, "->receive") 133 | //sent to other clients 134 | o.mc.Pub(o.topic+"/call", "confirm") 135 | }) 136 | //log.Println("Order sub:", o.topic) 137 | o.mc.Sub(o.topic+"/back", func(client mqtt.Client, message mqtt.Message) { 138 | if b := message.Payload(); b != nil && string(b) == "ok" { 139 | CostTime() 140 | //log.Println("Order received:", string(b)) 141 | o.cNum -= 1 142 | } 143 | if o.cNum == 0 { 144 | c <- true 145 | } 146 | }) 147 | //log.Println("Order sub:", o.topic+"/back") 148 | c <- true 149 | } 150 | 151 | /************* Transaction *************/ 152 | type Transaction struct { 153 | PID string 154 | Timestamp int64 155 | } 156 | 157 | func GetTransaction(b []byte) *Transaction { 158 | t := &Transaction{} 159 | if err := json.Unmarshal(b, t); err != nil { 160 | return nil 161 | } 162 | return t 163 | } 164 | 165 | func (t *Transaction) Bytes() []byte { 166 | b, err := json.Marshal(t) 167 | if err != nil { 168 | return nil 169 | } 170 | return b 171 | } 172 | 173 | func NewTransaction(pid string) *Transaction { 174 | return &Transaction{pid, time.Now().Unix()} 175 | } 176 | 177 | func CostTime() { 178 | time.Sleep(time.Microsecond * 500) 179 | } 180 | -------------------------------------------------------------------------------- /test/consensus/pow/pow.go: -------------------------------------------------------------------------------- 1 | package pow 2 | 3 | import ( 4 | "encoding/json" 5 | 6 | "github.com/newham/goblockchain/core" 7 | 8 | mqtt "github.com/eclipse/paho.mqtt.golang" 9 | "github.com/newham/fabric-iot/test/consensus/kafka" 10 | ) 11 | 12 | const ( 13 | TOPIC = "/test/pow" 14 | HOST = "tcp://localhost:1883" 15 | ) 16 | 17 | func PoW(n, nBit int) { 18 | ss := make(chan bool, n) 19 | sg := make(chan bool) 20 | done := make(chan string, 1) 21 | for i := 0; i < n; i++ { 22 | go NewNode(TOPIC, HOST, n, nBit).Mine(ss, sg, done) 23 | } 24 | //now wait all node started 25 | for i := 0; i < n; i++ { 26 | <-ss 27 | } 28 | // log.Println("All node started") 29 | //let all node to submit Transaction 30 | close(sg) 31 | //wait finish 32 | // log.Println("Winner is:", <-done) 33 | } 34 | 35 | type Msg struct { 36 | ID string 37 | Block core.Block 38 | } 39 | 40 | func (m Msg) Bytes() []byte { 41 | bts, err := json.Marshal(m) 42 | if err != nil { 43 | println(err.Error()) 44 | } 45 | return bts 46 | } 47 | 48 | type Node struct { 49 | topic string 50 | mc *kafka.MQTTCli 51 | cNum int 52 | cfNum int 53 | nBit int 54 | } 55 | 56 | func NewNode(topic string, host string, cNum, nBit int) *Node { 57 | return &Node{topic, kafka.NewMQTTCli(host), cNum, 0, nBit} 58 | } 59 | 60 | func (n *Node) Mine(ss, sg chan bool, done chan string) { 61 | n.mc.Sub(n.topic+"/mine", func(client mqtt.Client, message mqtt.Message) { 62 | //receive other's block 63 | // core.NewProofOfWork(core.NewBlock(nil, nil, nBit)) 64 | b := message.Payload() 65 | msg := &Msg{} 66 | err := json.Unmarshal(b, msg) 67 | if err != nil { 68 | // log.Println(err.Error()) 69 | } 70 | ok, _ := core.NewProofOfWork(&msg.Block).Validate(msg.Block.Nonce) 71 | if ok { 72 | n.mc.Pub(n.topic+"/to/"+msg.ID, "ok") 73 | } 74 | }) 75 | n.mc.Sub(n.topic+"/to/"+n.mc.ID(), func(client mqtt.Client, message mqtt.Message) { 76 | if string(message.Payload()) == "ok" { 77 | n.cfNum++ 78 | } 79 | if n.cfNum > n.cNum/2 { 80 | done <- n.mc.ID() 81 | } 82 | }) 83 | ss <- true 84 | // log.Println("Node", n.mc.ID(), "started") 85 | if _, ok := <-sg; !ok { 86 | nb := core.NewGenesisBlock(n.mc.ID(), n.nBit) 87 | //start to pow 88 | nonce, _ := core.NewProofOfWork(nb).Work() 89 | nb.Nonce = nonce 90 | // log.Println("Node", n.mc.ID(), "minded:", nonce) 91 | msg := Msg{n.mc.ID(), *nb} 92 | //pub to all 93 | n.mc.Pub(n.topic+"/mine", msg.Bytes()) 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /test/consensus/pow/pow_test.go: -------------------------------------------------------------------------------- 1 | package pow 2 | 3 | import ( 4 | "fmt" 5 | "strconv" 6 | "testing" 7 | "time" 8 | 9 | "github.com/newham/goblockchain/core" 10 | ) 11 | 12 | func TestPoW(t *testing.T) { 13 | nBit := 16 14 | for j := 5; j <= 100; j += 5 { 15 | start := time.Now().UnixNano() 16 | PoW(j, nBit) 17 | end := time.Now().UnixNano() 18 | fmt.Printf("%.2f\n", float32(end-start)/1e6) 19 | } 20 | } 21 | 22 | func TestNBit(t *testing.T) { 23 | for i := 1; i <= 23; i++ { 24 | start := time.Now().UnixNano() 25 | id := strconv.FormatInt(time.Now().UnixNano(), 10) 26 | nb := core.NewGenesisBlock(id, i) 27 | //start to pow 28 | nonce, hash := core.NewProofOfWork(nb).Work() 29 | end := time.Now().UnixNano() 30 | fmt.Printf("%-4d%s %-10d %x %.6f\n", i, id, nonce, hash, float32(end-start)/1e9) 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /test/tps/test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/sha256" 5 | "fmt" 6 | "log" 7 | "math/rand" 8 | "net/http" 9 | "os" 10 | "strconv" 11 | "strings" 12 | "time" 13 | 14 | "github.com/newham/hamtask" 15 | ) 16 | 17 | var BASE_URL = "http://localhost:8001/fabric-iot/test" 18 | 19 | func main() { 20 | ccName, fName, n := GetArgs() 21 | if n == -1 { 22 | println("please input client count") 23 | return 24 | } 25 | start := time.Now().Unix() 26 | // start := time.Now().UnixNano() 27 | if ccName == "dc" { 28 | if fName == "AddURL" { 29 | Loop(1, n, TestDCAddURL) 30 | } else if fName == "GetURL" { 31 | Loop(1, n, TestDCGetURL) 32 | } 33 | } else if ccName == "pc" { 34 | if fName == "AddPolicy" { 35 | Loop(1, n, TestPCAddPolicy) 36 | } else if fName == "QueryPolicy" { 37 | Loop(1, n, TestPCQueryPolicy) 38 | } else if fName == "DeletePolicy" { 39 | Loop(1, n, TestPCDeletePolicy) 40 | } else if fName == "UpdatePolicy" { 41 | Loop(1, n, TestPCUpdatePolicy) 42 | } 43 | } else if ccName == "ac" { 44 | if fName == "CheckAccess" { 45 | Loop(1, n, TestACCheckAccess) 46 | } 47 | } else { 48 | println("please input [cc_name] [f_name] [n]") 49 | } 50 | 51 | end := time.Now().Unix() 52 | println("cost time:", end-start, "second") //(end-start)/int64(time.Millisecond) 53 | } 54 | 55 | func GetArgs() (string, string, int) { 56 | args := os.Args 57 | if len(args) > 3 { 58 | cc_name := args[1] 59 | f_name := args[2] 60 | n, err := strconv.Atoi(args[3]) 61 | if err != nil { 62 | println("bad count") 63 | return "", "", -1 64 | } 65 | return cc_name, f_name, n 66 | } 67 | return "", "", -1 68 | } 69 | 70 | func Loop(loop int, n int, f func(c chan int, n int)) { 71 | c := make(chan int) 72 | for i := 0; i < loop; i++ { 73 | go func() { 74 | f(c, n) 75 | }() 76 | } 77 | //waite 78 | for i := 0; i < loop; i++ { 79 | <-c 80 | } 81 | } 82 | 83 | func TestPCAddPolicy(c chan int, n int) { 84 | TestCC(c, n, func(i int) string { 85 | return GetURL("pc", "AddPolicy", GetPolicyReq(i, 1, 1, 1)) 86 | }) 87 | } 88 | 89 | func GetPolicyReq(i, r, g, AP int) string { 90 | now := time.Now().Unix() 91 | policyStr := fmt.Sprintf(`{"AS":{"userId":"%s","role":"u%d","group":"g%d"},"AO":{"deviceId":"%s","MAC":"%s"},"AP":%d,"AE":{"createdTime":%d,"endTime":%d,"allowedIP":"*.*.*.*"}}`, GetUserID(i), r, g, GetDeviceID(i), RandomMac(), AP, now, now+100000) 92 | return policyStr 93 | } 94 | 95 | func TestPCQueryPolicy(c chan int, n int) { 96 | TestCC(c, n, func(i int) string { 97 | return GetURL("pc", "QueryPolicy", GetPolicyID(i)) 98 | }) 99 | } 100 | 101 | func GetPolicyID(i int) string { 102 | return GetSHA256(GetUserID(i), GetDeviceID(i)) 103 | } 104 | 105 | func GetSHA256(args ...string) string { 106 | return fmt.Sprintf("%x", sha256.Sum256([]byte(strings.Join(args, "")))) 107 | } 108 | 109 | func TestPCDeletePolicy(c chan int, n int) { 110 | TestCC(c, n, func(i int) string { 111 | return GetURL("pc", "DeletePolicy", GetPolicyID(i)) 112 | }) 113 | } 114 | 115 | func TestPCUpdatePolicy(c chan int, n int) { 116 | TestCC(c, n, func(i int) string { 117 | return GetURL("pc", "UpdatePolicy", GetPolicyReq(i, 1, 1, 0)) 118 | }) 119 | } 120 | 121 | func TestACCheckAccess(c chan int, n int) { 122 | i := 0 123 | hamtask.NewSimpleWorker(n, func(i int, d hamtask.Data) { 124 | url := d.String() 125 | _, err := http.Get(url) 126 | if err != nil { 127 | log.Println("Error", err.Error()) 128 | return 129 | } 130 | // println(resp.Status) 131 | 132 | }, func() hamtask.Data { 133 | i++ 134 | return hamtask.String(GetURL("ac", "CheckAccess", GetACRequest(i))) 135 | }, n).Start() 136 | c <- 1 137 | } 138 | 139 | func TestDCGetURL(c chan int, n int) { 140 | 141 | TestCC(c, n, func(i int) string { 142 | return GetURL("dc", "GetURL", GetDeviceID(i)) 143 | }) 144 | } 145 | 146 | func TestDCAddURL(c chan int, n int) { 147 | i := 0 148 | hamtask.NewSimpleWorker(n, func(i int, d hamtask.Data) { 149 | url := d.String() 150 | _, err := http.Get(url) 151 | if err != nil { 152 | log.Println("Error", err.Error()) 153 | return 154 | } 155 | // println(resp.Status) 156 | 157 | }, func() hamtask.Data { 158 | i++ 159 | return hamtask.String(GetURL("dc", "AddURL", GetDeviceID(i), "https://test"+GetDeviceID(i)+".res")) 160 | }, n).Start() 161 | c <- 1 162 | } 163 | 164 | func TestCC(c chan int, n int, f func(int) string) { 165 | i := 0 166 | hamtask.NewSimpleWorker(n, func(i int, d hamtask.Data) { 167 | url := d.String() 168 | _, err := http.Get(url) 169 | if err != nil { 170 | log.Println("Error", err.Error()) 171 | return 172 | } 173 | // println(resp.Status) 174 | 175 | }, func() hamtask.Data { 176 | i++ 177 | return hamtask.String(f(i)) 178 | }, n).Start() 179 | c <- 1 180 | } 181 | 182 | func GetACRequest(i int) string { 183 | return fmt.Sprintf(`{"AS":{"userId":"%s","role":"u1","group":"g1"},"AO":{"deviceId":"%s","MAC":"00:11:22:33:44:55"}}`, GetUserID(i), GetDeviceID(i)) 184 | } 185 | 186 | func GetID(i int) int { 187 | return i + 10000 188 | } 189 | 190 | func GetUserID(i int) string { 191 | return strconv.Itoa(GetID(i)) 192 | } 193 | 194 | func GetDeviceID(i int) string { 195 | return fmt.Sprintf("D%d", GetID(i)) 196 | } 197 | 198 | func GetURL(cc_name, f_name string, args ...string) string { 199 | return fmt.Sprintf("%s?cc_name=%s&f_name=%s&args=%s", BASE_URL, cc_name, f_name, strings.Join(args, "|")) 200 | } 201 | 202 | func RandomX(N, n int) string { 203 | ip := []string{} 204 | for i := 0; i < N; i++ { 205 | r := rand.New(rand.NewSource(time.Now().UnixNano())) 206 | ip = append(ip, strconv.FormatInt(int64(r.Intn(n)), 16)) 207 | } 208 | return strings.Join(ip, ":") 209 | } 210 | 211 | func RandomMac() string { 212 | return RandomX(6, 64) 213 | } 214 | 215 | func RandomIPv6() string { 216 | return RandomX(8, 65536) 217 | } 218 | --------------------------------------------------------------------------------