一次跑通 fabric 小汽車例子
Docker 部分
docker --version # 檢測docker安裝 sudo systemctl start docker # 啟動守護程序 sudo usermod -a -G docker $USER # 添加當前用戶到docker用戶組 docker-compose --version # 檢測docker-compose安裝
上面沒有出現問題Docker部分准備完成
Golang 部分
go env # 查看golang環境變量 go env -w GOPROXY=https://goproxy.cn,direct # 更換go代理,也就是換國內源
一定要設置好GOPATH,GOROOT等相關變量。
Java 部分
本次sdk采用fabric-gateway-java v1.4,這個庫是fabric-java-sdk的高級庫
sudo dnf install maven cd /etc/maven code settings.xml # 把146行內容替換成下面的內容,更換為阿里源 mvn -v # 檢測是否安裝成功
更換阿里源
<mirrors> <!-- mirror | Specifies a repository mirror site to use instead of a given repository. The repository that | this mirror serves has an ID that matches the mirrorOf element of this mirror. IDs are used | for inheritance and direct lookup purposes, and must be unique across the set of mirrors. | <mirror> <id>mirrorId</id> <mirrorOf>repositoryId</mirrorOf> <name>Human Readable Name for this Mirror.</name> <url>http://my.repository.com/repo/path</url> </mirror> --> <mirror> <id>alimaven</id> <name>aliyun maven</name> <url>http://maven.aliyun.com/nexus/content/groups/public/</url> <mirrorOf>central</mirrorOf> </mirror> </mirrors>
fabric 安裝部分
cd ~ export mypn=ska # 這里設置一個環境變量,ska換成你自己的項目名 mkdir -p src/solo-dev-env/$mypn # 創建項目目錄 cd ./src/solo-dev-env/$mypn # 進入目錄, curl -sSL https://bit.ly/2ysbOFE | bash # 使用最新發布版本
cd ../../ tree ./solo-dev-env -L 3 docker images
這個過程會很漫長主要是docker鏡像安裝預計有12G
docker一定要用國內源,否則等到死
如果執行 網絡安裝錯誤可以執行下面步驟
# 如果出錯,復制附錄內容,在文章目錄, #執行 code bootstrap.sh 把內容粘貼進去,然后保存, #然后執行 sudo chmod +x ./bootstrap.sh 執行腳本 ./bootstrap.sh # 完整如下 cd ~ export mypn=ska # 這里設置一個環境變量,ska換成你自己的項目名 mkdir -p src/solo-dev-env/$mypn # 創建項目目錄 cd ./src/solo-dev-env/$mypn # 進入目錄 # 上面是之前操作的,不用執行了,直接執行下面部分 code bootstrap.sh # 復制附錄內容保存。 sudo chmod +x ./bootstrap.sh ./bootstrap.sh cd ../../ tree ./solo-dev-env -L 3 docker images
目錄
solo-dev-env/ └── ska ├── fabric-samples ---------------------------------> clone 的倉庫 │ ├── bin ---------------------------------> 下載的二進制文件都在里面 │ ├── chaincode │ ├── chaincode-docker-devmode │ ├── ci │ ├── CODE_OF_CONDUCT.md │ ├── CODEOWNERS │ ├── commercial-paper │ ├── config │ ├── CONTRIBUTING.md │ ├── fabcar ---------------------------------> 要跑的例子使用的是測試網 │ ├── first-network -----------------------------> 被淘汰的例子 │ ├── high-throughput │ ├── interest_rate_swaps │ ├── LICENSE │ ├── MAINTAINERS.md │ ├── off_chain_data │ ├── README.md │ ├── SECURITY.md │ └── test-network -----------------------------> 新出的測試網
Docker 鏡像
REPOSITORY TAG IMAGE ID CREATED SIZE hyperledger/fabric-tools 2.1 bf6ec47ac5fd 8 days ago 522MB hyperledger/fabric-tools 2.1.0 bf6ec47ac5fd 8 days ago 522MB hyperledger/fabric-tools latest bf6ec47ac5fd 8 days ago 522MB hyperledger/fabric-peer 2.1 4136ba27e279 8 days ago 56.6MB hyperledger/fabric-peer 2.1.0 4136ba27e279 8 days ago 56.6MB hyperledger/fabric-peer latest 4136ba27e279 8 days ago 56.6MB hyperledger/fabric-orderer 2.1 af4fdf2df06c 8 days ago 39.4MB hyperledger/fabric-orderer 2.1.0 af4fdf2df06c 8 days ago 39.4MB hyperledger/fabric-orderer latest af4fdf2df06c 8 days ago 39.4MB hyperledger/fabric-ccenv 2.1 eefa22c7b7e7 8 days ago 554MB hyperledger/fabric-ccenv 2.1.0 eefa22c7b7e7 8 days ago 554MB hyperledger/fabric-ccenv latest eefa22c7b7e7 8 days ago 554MB hyperledger/fabric-baseos 2.1 52bb8d969801 8 days ago 6.94MB hyperledger/fabric-baseos 2.1.0 52bb8d969801 8 days ago 6.94MB hyperledger/fabric-baseos latest 52bb8d969801 8 days ago 6.94MB hyperledger/fabric-nodeenv 2.1 8f2b5101881b 9 days ago 292MB hyperledger/fabric-nodeenv 2.1.0 8f2b5101881b 9 days ago 292MB hyperledger/fabric-nodeenv latest 8f2b5101881b 9 days ago 292MB hyperledger/fabric-javaenv 2.1 3e83cbc5b332 10 days ago 505MB hyperledger/fabric-javaenv 2.1.0 3e83cbc5b332 10 days ago 505MB hyperledger/fabric-javaenv latest 3e83cbc5b332 10 days ago 505MB hyperledger/fabric-ca 1.4 3b96a893c1e4 8 weeks ago 150MB hyperledger/fabric-ca 1.4.6 3b96a893c1e4 8 weeks ago 150MB hyperledger/fabric-ca latest 3b96a893c1e4 8 weeks ago 150MB hyperledger/fabric-tools 2.0.0 639ab50feac9 2 months ago 514MB hyperledger/fabric-zookeeper 0.4 ede9389347db 5 months ago 276MB hyperledger/fabric-zookeeper 0.4.18 ede9389347db 5 months ago 276MB hyperledger/fabric-zookeeper latest ede9389347db 5 months ago 276MB hyperledger/fabric-kafka 0.4 caaae0474ef2 5 months ago 270MB hyperledger/fabric-kafka 0.4.18 caaae0474ef2 5 months ago 270MB hyperledger/fabric-kafka latest caaae0474ef2 5 months ago 270MB hyperledger/fabric-couchdb 0.4 d369d4eaa0fd 5 months ago 261MB hyperledger/fabric-couchdb 0.4.18 d369d4eaa0fd 5 months ago 261MB hyperledger/fabric-couchdb latest d369d4eaa0fd 5 months ago 261MB hyperledger/fabric-couchdb 0.4.16 5a66d69b7d4d 6 months ago 261MB
啟動測試網
cd ~/src/solo-dev-env/$mypn/fabric-samples/test-network/ ./network.sh up # 啟動測試網絡
./network.sh createChannel # 創建通道,默認名字mychannel ./network.sh deployCC # 部署合約 ./network.sh down #清理網絡
上面應該不會出現什么問題,出現問題大多數是Dokcer權限和golang代理。
這些只是檢測這個測試環境已經搭建好了,下面准備fabcar
啟動fabcar
cd ~/src/solo-dev-env/$mypn/fabric-samples/fabcar ./startFabric.sh
cd ~ mkdir -p src/java/MVN/project # 創建java項目目錄 cd src/java/MVN/project mkdir github.com # 創建github庫目錄 cd github.com git clone -b release-1.4 https://github.com/hyperledger/fabric-gateway-java.git # clone 1.4 sdk cd fabric-gateway-java export ORG_HYPERLEDGER_FABRIC_SDK_CONNECTIONS_SSL_SSLPROVIDER=JDK # 設置SSL mvn install # 安裝到本地倉庫,可以在本地倉庫 ~/.m2 中找到,安裝好后就可以 Ctrl + C,不執行Test cd ../../ mvn archetype:generate # 創建mvn項目 7 # 模板版本 cn.edu.zzuli # 組ID fabricIecTest # 項目名 1.0 # 版本號 cn.edu.zzuli # 包名 cd ./fabricIecTest code pom.xml # 更改為下面內容 mvn clean cd ./src/main/java/cn/edu/zzuli code EnrollAdmin.java # 內容如下 code RegisterUser.java # 內容如下 code App.java # 內容如下 cd ../../../../../../../ code ./fabricIecTest # 執行這些代碼
pom.xml
<properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <!-- 標明版本號 --> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> <!-- 添加依賴 --> <dependency> <groupId>org.hyperledger.fabric</groupId> <artifactId>fabric-gateway-java</artifactId> <version>1.4.2</version> </dependency> </dependencies>
EnrollAdmin.java
package cn.edu.zzuli; import java.nio.file.Paths; import java.util.Properties; import org.hyperledger.fabric.gateway.Wallet; import org.hyperledger.fabric.gateway.Wallet.Identity; import org.hyperledger.fabric.sdk.Enrollment; import org.hyperledger.fabric.sdk.security.CryptoSuite; import org.hyperledger.fabric.sdk.security.CryptoSuiteFactory; import org.hyperledger.fabric_ca.sdk.EnrollmentRequest; import org.hyperledger.fabric_ca.sdk.HFCAClient; public class EnrollAdmin { static { System.setProperty("org.hyperledger.fabric.sdk.service_discovery.as_localhost", "true"); } public static void main(String[] args) throws Exception { // Create a CA client for interacting with the CA. Properties props = new Properties(); // 注意帶 $ 變量 props.put("pemFile", "/home/$USER/src/solo-dev-env/$mypn/fabric-samples/test-network/organizations/peerOrganizations/org1.example.com/ca/ca.org1.example.com-cert.pem"); props.put("allowAllHostNames", "true"); HFCAClient caClient = HFCAClient.createNewInstance("https://localhost:7054", props); CryptoSuite cryptoSuite = CryptoSuiteFactory.getDefault().getCryptoSuite(); caClient.setCryptoSuite(cryptoSuite); // Create a wallet for managing identities Wallet wallet = Wallet.createFileSystemWallet(Paths.get("wallet")); // Check to see if we've already enrolled the admin user. boolean adminExists = wallet.exists("admin"); if (adminExists) { System.out.println("An identity for the admin user \"admin\" already exists in the wallet"); return; } // Enroll the admin user, and import the new identity into the wallet. final EnrollmentRequest enrollmentRequestTLS = new EnrollmentRequest(); enrollmentRequestTLS.addHost("localhost"); enrollmentRequestTLS.setProfile("tls"); Enrollment enrollment = caClient.enroll("admin", "adminpw", enrollmentRequestTLS); Identity user = Identity.createIdentity("Org1MSP", enrollment.getCert(), enrollment.getKey()); wallet.put("admin", user); System.out.println("Successfully enrolled user \"admin\" and imported it into the wallet"); } }
RegisterUser.java
package cn.edu.zzuli; import java.nio.file.Paths; import java.security.PrivateKey; import java.util.Properties; import java.util.Set; import org.hyperledger.fabric.gateway.Wallet; import org.hyperledger.fabric.gateway.Wallet.Identity; import org.hyperledger.fabric.sdk.Enrollment; import org.hyperledger.fabric.sdk.User; import org.hyperledger.fabric.sdk.security.CryptoSuite; import org.hyperledger.fabric.sdk.security.CryptoSuiteFactory; import org.hyperledger.fabric_ca.sdk.HFCAClient; import org.hyperledger.fabric_ca.sdk.RegistrationRequest; public class RegisterUser { static { System.setProperty("org.hyperledger.fabric.sdk.service_discovery.as_localhost", "true"); } public static void main(String[] args)throws Exception { //創建用於與CA進行交互的CA客戶端。 Properties props = new Properties(); // 注意帶 $ 變量 props.put("pemFile", "/home/$USER/src/solo-dev-env/$mypn/fabric-samples/test-network/organizations/peerOrganizations/org1.example.com/ca/ca.org1.example.com-cert.pem"); props.put("allowAllHostNames", "true"); HFCAClient caClient = HFCAClient.createNewInstance("https://localhost:7054", props); CryptoSuite cryptoSuite = CryptoSuiteFactory.getDefault().getCryptoSuite(); caClient.setCryptoSuite(cryptoSuite); // 創建一個用於管理身份的錢包 Wallet wallet = Wallet.createFileSystemWallet(Paths.get("wallet")); // 檢查我們是否已經注冊了該用戶。 boolean userExists = wallet.exists("appUser"); if (userExists) { System.out.println("An identity for the user \"appUser\" already exists in the wallet"); return; } userExists = wallet.exists("admin"); if (!userExists) { System.out.println("\"admin\" needs to be enrolled and added to the wallet first"); return; } Identity adminIdentity = wallet.get("admin"); User admin = new User() { @Override public String getName() { return "admin"; } @Override public Set<String> getRoles() { return null; } @Override public String getAccount() { return null; } @Override public String getAffiliation() { return "org1.department1"; } @Override public Enrollment getEnrollment() { return new Enrollment() { @Override public PrivateKey getKey() { return adminIdentity.getPrivateKey(); } @Override public String getCert() { return adminIdentity.getCertificate(); } }; } @Override public String getMspId() { return "Org1MSP"; } }; // 注冊用戶,加入用戶,並將新身份導入錢包。 RegistrationRequest registrationRequest = new RegistrationRequest("appUser"); registrationRequest.setAffiliation("org1.department1"); registrationRequest.setEnrollmentID("appUser"); String enrollmentSecret = caClient.register(registrationRequest, admin); Enrollment enrollment = caClient.enroll("appUser", enrollmentSecret); Identity user = Identity.createIdentity("Org1MSP", enrollment.getCert(), enrollment.getKey()); wallet.put("appUser", user); System.out.println("Successfully enrolled user \"appUser\" and imported it into the wallet"); } }
App.java
package cn.edu.zzuli; import java.nio.file.Path; import java.nio.file.Paths; import org.hyperledger.fabric.gateway.Contract; import org.hyperledger.fabric.gateway.Gateway; import org.hyperledger.fabric.gateway.Network; import org.hyperledger.fabric.gateway.Wallet; /** * Hello world! * */ public class App { static { System.setProperty("org.hyperledger.fabric.sdk.service_discovery.as_localhost", "true"); } public static void main( String[] args ) throws Exception { // Load a file system based wallet for managing identities. Path walletPath = Paths.get("wallet"); Wallet wallet = Wallet.createFileSystemWallet(walletPath); // 注意帶 $ 的變量 String yamlPath = "/home/$USER/src/solo-dev-env/$mypn/fabric-samples/test-network/organizations/peerOrganizations/org1.example.com/connection-org1.yaml"; Path networkConfigPath = Paths.get(yamlPath); Gateway.Builder builder = Gateway.createBuilder(); builder.identity(wallet, "appUser").networkConfig(networkConfigPath).discovery(true); // create a gateway connection try (Gateway gateway = builder.connect()) { // get the network and contract Network network = gateway.getNetwork("mychannel"); Contract contract = network.getContract("fabcar"); byte[] result; result = contract.evaluateTransaction("queryAllCars"); System.out.println(new String(result)); contract.submitTransaction("createCar", "CAR10", "VW", "Polo", "Grey", "Mary"); result = contract.evaluateTransaction("queryCar", "CAR10"); System.out.println(new String(result)); contract.submitTransaction("changeCarOwner", "CAR10", "Archie"); result = contract.evaluateTransaction("queryCar", "CAR10"); System.out.println(new String(result)); } } }
附錄
bootstrap.sh
#!/bin/bash # # Copyright IBM Corp. All Rights Reserved. # # SPDX-License-Identifier: Apache-2.0 # # if version not passed in, default to latest released version VERSION=2.1.0 # if ca version not passed in, default to latest released version CA_VERSION=1.4.6 # current version of thirdparty images (couchdb, kafka and zookeeper) released THIRDPARTY_IMAGE_VERSION=0.4.18 ARCH=$(echo "$(uname -s|tr '[:upper:]' '[:lower:]'|sed 's/mingw64_nt.*/windows/')-$(uname -m | sed 's/x86_64/amd64/g')") MARCH=$(uname -m) printHelp() { echo "Usage: bootstrap.sh [version [ca_version [thirdparty_version]]] [options]" echo echo "options:" echo "-h : this help" echo "-d : bypass docker image download" echo "-s : bypass fabric-samples repo clone" echo "-b : bypass download of platform-specific binaries" echo echo "e.g. bootstrap.sh 2.1.0 1.4.6 0.4.18 -s" echo "would download docker images and binaries for Fabric v2.1.0 and Fabric CA v1.4.6" } # dockerPull() pulls docker images from fabric and chaincode repositories # note, if a docker image doesn't exist for a requested release, it will simply # be skipped, since this script doesn't terminate upon errors. dockerPull() { #three_digit_image_tag is passed in, e.g. "1.4.6" three_digit_image_tag=$1 shift #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 two_digit_image_tag=$(echo $three_digit_image_tag | cut -d'.' -f1,2) while [[ $# -gt 0 ]] do image_name="$1" echo "====> hyperledger/fabric-$image_name:$three_digit_image_tag" docker pull "hyperledger/fabric-$image_name:$three_digit_image_tag" docker tag "hyperledger/fabric-$image_name:$three_digit_image_tag" "hyperledger/fabric-$image_name" docker tag "hyperledger/fabric-$image_name:$three_digit_image_tag" "hyperledger/fabric-$image_name:$two_digit_image_tag" shift done } cloneSamplesRepo() { # clone (if needed) hyperledger/fabric-samples and checkout corresponding # version to the binaries and docker images to be downloaded if [ -d first-network ]; then # if we are in the fabric-samples repo, checkout corresponding version echo "===> Checking out v${VERSION} of hyperledger/fabric-samples" git checkout v${VERSION} elif [ -d fabric-samples ]; then # if fabric-samples repo already cloned and in current directory, # cd fabric-samples and checkout corresponding version echo "===> Checking out v${VERSION} of hyperledger/fabric-samples" cd fabric-samples && git checkout v${VERSION} else echo "===> Cloning hyperledger/fabric-samples repo and checkout v${VERSION}" git clone -b master https://github.com/hyperledger/fabric-samples.git && cd fabric-samples && git checkout v${VERSION} fi } # This will download the .tar.gz download() { local BINARY_FILE=$1 local URL=$2 echo "===> Downloading: " "${URL}" curl -L --retry 5 --retry-delay 3 "${URL}" | tar xz || rc=$? if [ -n "$rc" ]; then echo "==> There was an error downloading the binary file." return 22 else echo "==> Done." fi } pullBinaries() { echo "===> Downloading version ${FABRIC_TAG} platform specific fabric binaries" download "${BINARY_FILE}" "https://github.com/hyperledger/fabric/releases/download/v${VERSION}/${BINARY_FILE}" if [ $? -eq 22 ]; then echo echo "------> ${FABRIC_TAG} platform specific fabric binary is not available to download <----" echo exit fi echo "===> Downloading version ${CA_TAG} platform specific fabric-ca-client binary" download "${CA_BINARY_FILE}" "https://github.com/hyperledger/fabric-ca/releases/download/v${CA_VERSION}/${CA_BINARY_FILE}" if [ $? -eq 22 ]; then echo echo "------> ${CA_TAG} fabric-ca-client binary is not available to download (Available from 1.1.0-rc1) <----" echo exit fi } pullDockerImages() { command -v docker >& /dev/null NODOCKER=$? if [ "${NODOCKER}" == 0 ]; then FABRIC_IMAGES=(peer orderer ccenv tools) case "$VERSION" in 1.*) FABRIC_IMAGES+=(javaenv) shift ;; 2.*) FABRIC_IMAGES+=(nodeenv baseos javaenv) shift ;; esac echo "FABRIC_IMAGES:" "${FABRIC_IMAGES[@]}" echo "===> Pulling fabric Images" dockerPull "${FABRIC_TAG}" "${FABRIC_IMAGES[@]}" echo "===> Pulling fabric ca Image" CA_IMAGE=(ca) dockerPull "${CA_TAG}" "${CA_IMAGE[@]}" echo "===> Pulling thirdparty docker images" THIRDPARTY_IMAGES=(zookeeper kafka couchdb) dockerPull "${THIRDPARTY_TAG}" "${THIRDPARTY_IMAGES[@]}" echo echo "===> List out hyperledger docker images" docker images | grep hyperledger else echo "=========================================================" echo "Docker not installed, bypassing download of Fabric images" echo "=========================================================" fi } DOCKER=true SAMPLES=true BINARIES=true # Parse commandline args pull out # version and/or ca-version strings first if [ -n "$1" ] && [ "${1:0:1}" != "-" ]; then VERSION=$1;shift if [ -n "$1" ] && [ "${1:0:1}" != "-" ]; then CA_VERSION=$1;shift if [ -n "$1" ] && [ "${1:0:1}" != "-" ]; then THIRDPARTY_IMAGE_VERSION=$1;shift fi fi fi # prior to 1.2.0 architecture was determined by uname -m if [[ $VERSION =~ ^1\.[0-1]\.* ]]; then export FABRIC_TAG=${MARCH}-${VERSION} export CA_TAG=${MARCH}-${CA_VERSION} export THIRDPARTY_TAG=${MARCH}-${THIRDPARTY_IMAGE_VERSION} else # starting with 1.2.0, multi-arch images will be default : "${CA_TAG:="$CA_VERSION"}" : "${FABRIC_TAG:="$VERSION"}" : "${THIRDPARTY_TAG:="$THIRDPARTY_IMAGE_VERSION"}" fi BINARY_FILE=hyperledger-fabric-${ARCH}-${VERSION}.tar.gz CA_BINARY_FILE=hyperledger-fabric-ca-${ARCH}-${CA_VERSION}.tar.gz # then parse opts while getopts "h?dsb" opt; do case "$opt" in h|\?) printHelp exit 0 ;; d) DOCKER=false ;; s) SAMPLES=false ;; b) BINARIES=false ;; esac done if [ "$SAMPLES" == "true" ]; then echo echo "Clone hyperledger/fabric-samples repo" echo cloneSamplesRepo fi if [ "$BINARIES" == "true" ]; then echo echo "Pull Hyperledger Fabric binaries" echo pullBinaries fi if [ "$DOCKER" == "true" ]; then echo echo "Pull Hyperledger Fabric docker images" echo pullDockerImages fi