2017-01-05

本文记录介绍Fabric V0.6 Chaincode开发环境搭建

准备介绍

  • Windows 7 64bit 192.168.1.106
  • VMware Workstation 12.1 : Ubuntu 14.04 64bit 192.168.78.130
  • Ubuntu 14.04 由iso安装,安装之后装了vim
  • vmware的ubuntu最好安装vmware-tools 这样你本地的maven仓库可以共享到虚拟机, 然后到容器,这样在编译java chaincode时可以复用本地包

安装docker

  • 可以通过网络百度安装方法,Fabric开发官方推荐是1.12+
  • 或者通过下载本文中的安装附件,在dockerDEB目录中通过dpkg -i *.deb

安装docker-compose

  • 安装pip,在pipDEB目录中dpkg -i *.deb
  • pip install –upgrade pip
  • pip install behave nose docker-compose

下载docker镜像,可以从官方pull

  • docker pull hyperledger/fabric-peer:latest
  • docker pull hyperledger/fabric-membersrvc:latest
  • 在下载附件FabricDockerImages目录中通过命令导入
  • docker load < fabric-peer.tar
  • docker load < fabric-membersrvc.tar
  • docker tag hyperledger/fabric-membersrvc:x86_64-0.6.1-preview hyperledger/fabric-membersrvc:latest
  • membersrvc导入默认tag是0.6.1的,tag为lattest后续docker-compose中用latest
root@fabric:~# docker images
REPOSITORY                      TAG                    IMAGE ID            CREATED             SIZE
hyperledger/fabric-membersrvc   latest                 b3654d32e4f9        11 weeks ago        1.417 GB
hyperledger/fabric-membersrvc   x86_64-0.6.1-preview   b3654d32e4f9        11 weeks ago        1.417 GB
hyperledger/fabric-peer         latest                 21cb00fb27f4        11 weeks ago        1.424 GB

编辑docker-compose文件

  • 在deploy目录vim docker-compose.yml
membersrvc:
  image: hyperledger/fabric-membersrvc
  ports:
    - "7054:7054"
  command: membersrvc
vp0:
  image: hyperledger/fabric-peer
  ports:
    - "7050:7050"
    - "7051:7051"
    - "7053:7053"
  volumes:
    - /root/deploy/share:/mnt
    - /mnt/hgfs:/mnt2
  environment:
    - CORE_PEER_ADDRESSAUTODETECT=true
    - CORE_VM_ENDPOINT=unix:///var/run/docker.sock
    - CORE_LOGGING_LEVEL=DEBUG
    - CORE_PEER_ID=vp0
    - CORE_PEER_PKI_ECA_PADDR=membersrvc:7054
    - CORE_PEER_PKI_TCA_PADDR=membersrvc:7054
    - CORE_PEER_PKI_TLSCA_PADDR=membersrvc:7054
    - CORE_SECURITY_ENABLED=true
    - CORE_SECURITY_ENROLLID=test_vp0
    - CORE_SECURITY_ENROLLSECRET=MwYpmSRjupbT
  links:
    - membersrvc
  command: sh -c "sleep 5; peer node start --peer-chaincodedev"
  • 上述中volumes主要是映射两个ubuntu中目录到容器中
  • /root/deploy/share:/mnt里面有gradle,jdk8,maven
  • /mnt/hgfs:/mnt2里面是Windows上的maven仓库共享到ubuntu里面,再通过这个传递到容器中

由ubuntu共享到容器中

apache-maven-3.3.9  gradle-3.3  jdk1.8.0_92  profile

#用于在容器中引用的环境变量
vim profile
export TERM=linux
export PATH=$PATH:/mnt/gradle-3.3/bin

export JAVA_HOME=/mnt/jdk1.8.0_92
export JRE_HOME=${JAVA_HOME}/jre
export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib
export PATH=${JAVA_HOME}/bin:$PATH

export M2_HOME=/mnt/apache-maven-3.3.9
export M2=$M2_HOME/bin
export PATH=$M2:$PATH

启动区块链

  • 在ubuntu上deploy目录docker-compose up 会自动启动镜像,当前SSH终端会被日志冲刷
  • 在新SSH终端上查看
root@fabric:~# docker ps
CONTAINER ID        IMAGE                           COMMAND                  CREATED             STATUS              PORTS                                                      NAMES
ed8e587b50dc        hyperledger/fabric-peer         "sh -c 'sleep 5; peer"   41 minutes ago      Up 41 minutes       0.0.0.0:7050-7051->7050-7051/tcp, 0.0.0.0:7053->7053/tcp   deploy_vp0_1
b9d05b3d5937        hyperledger/fabric-membersrvc   "membersrvc"             41 minutes ago      Up 41 minutes       0.0.0.0:7054->7054/tcp                                     deploy_membersrvc_1
  • 接入容器
docker exec -ti ed8e587b50dc /bin/bash
  • 接入容器后,因为我们把ubuntu上的share共享到容器的/mnt目录此时我们可以查看使用
$source /mnt/profile

root@ed8e587b50dc:~# java -version
java version "1.8.0_92"
Java(TM) SE Runtime Environment (build 1.8.0_92-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.92-b14, mixed mode)

root@ed8e587b50dc:~# gradle -v

------------------------------------------------------------
Gradle 3.3
------------------------------------------------------------

Build time:   2017-01-03 15:31:04 UTC
Revision:     075893a3d0798c0c1f322899b41ceca82e4e134b

Groovy:       2.4.7
Ant:          Apache Ant(TM) version 1.9.6 compiled on June 29 2015
JVM:          1.8.0_92 (Oracle Corporation 25.92-b14)
OS:           Linux 4.4.0-31-generic amd64

#maven的环境变量和使用是可选的,因为java chaincode使用gradle编译
root@ed8e587b50dc:~# mvn --version
Apache Maven 3.3.9 (bb52d8502b132ec0a5a3f4c09453c07478323dc5; 2015-11-10T16:41:47+00:00)
Maven home: /mnt/apache-maven-3.3.9
Java version: 1.8.0_92, vendor: Oracle Corporation
Java home: /mnt/jdk1.8.0_92/jre
Default locale: en_US, platform encoding: ANSI_X3.4-1968
OS name: "linux", version: "4.4.0-31-generic", arch: "amd64", family: "unix"

编译Java chaincode

  • 在容器中区块链节点已经运行,并预制了用户,容器中GOPATH在启动中已设置好。
#如果使用maven本地库映射进去会有一定加速,也可以不映射进去直接在线下载
cd $GOPATH/src/github.com/hyperledger/fabric/core/chaincode/shim/java
gradle -b build.gradle clean
gradle -b build.gradle build

cd $GOPATH/src/github.com/hyperledger/fabric/examples/chaincode/java/SimpleSample
gradle -b build.gradle build
    
gradle -b build.gradle run

You are using Gradle 3.3:  This version of the protobuf plugin works with Gradle version 2.12+
The TaskInputs.source(Object) method has been deprecated and is scheduled to be removed in Gradle 4.0. Please use TaskInputs.file(Object).skipWhenEmpty() instead.
:examples:chaincode:java:SimpleSample:compileJava UP-TO-DATE
:examples:chaincode:java:SimpleSample:processResources UP-TO-DATE
:examples:chaincode:java:SimpleSample:classes UP-TO-DATE
:examples:chaincode:java:SimpleSample:run
Jan 05, 2017 3:50:45 PM io.grpc.internal.TransportSet$1 call
INFO: Created transport io.grpc.netty.NettyClientTransport@165e8b88(/127.0.0.1:7051) for /127.0.0.1:7051
Jan 05, 2017 3:50:46 PM io.grpc.internal.TransportSet$TransportListener transportReady
INFO: Transport io.grpc.netty.NettyClientTransport@165e8b88(/127.0.0.1:7051) for /127.0.0.1:7051 is ready
Jan 05, 2017 3:52:10 PM example.SimpleSample run
INFO: In run, function:init
Jan 05, 2017 3:53:31 PM example.SimpleSample run
INFO: In run, function:transfer
in transfer
Transfer a>b am='10' new values='90','210'
Transfer complete
null
Jan 05, 2017 3:53:49 PM example.SimpleSample run
INFO: In run, function:transfer
in transfer
Transfer a>b am='10' new values='80','220'
Transfer complete
null
Jan 05, 2017 3:53:50 PM example.SimpleSample run
INFO: In run, function:transfer
in transfer
Transfer a>b am='10' new values='70','230'
Transfer complete
null
> Building 75% > :examples:chaincode:java:SimpleSample:run

再新建SSH终端,接入容器,部署chaincode、调动chaincode处理交易、查询账户

docker exec -ti ed8e587b50dc /bin/bash

peer network login jim
#询问密码是输入 6avZQLwcUe9b, jim 和 6avZQLwcUe9b为预制

#deploy,invoke,query
peer chaincode deploy -u jim -l java -n SimpleSample -c '{"Args": ["init", "a","100", "b", "200"]}'

peer chaincode invoke -u jim -l java -n SimpleSample -c '{"Args": ["transfer", "a", "b", "10"]}'
16:33:14.451 [logging] LoggingInit -> DEBU 001 Setting default logging level to DEBUG for command 'chaincode'
16:33:14.453 [chaincodeCmd] getChaincodeSpecification -> INFO 002 Local user 'jim' is already logged in. Retrieving login token.
16:33:15.012 [chaincodeCmd] chaincodeInvokeOrQuery -> INFO 003 Successfully invoked transaction: chaincodeSpec:<type:JAVA chaincodeID:<name:"SimpleSample" > ctorMsg:<args:"transfer" args:"a" args:"b" args:"10" > secureContext:"jim" > (f7369511-68dd-4793-a77d-5dccbaf2b0b2)
16:33:15.012 [main] main -> INFO 004 Exiting.....

peer chaincode query -u jim -l java -n SimpleSample -c '{ "Args": ["query", "a"]}'
16:33:30.740 [logging] LoggingInit -> DEBU 001 Setting default logging level to DEBUG for command 'chaincode'
16:33:30.742 [chaincodeCmd] getChaincodeSpecification -> INFO 002 Local user 'jim' is already logged in. Retrieving login token.
16:33:31.337 [chaincodeCmd] chaincodeInvokeOrQuery -> INFO 003 Successfully queried transaction: chaincodeSpec:<type:JAVA chaincodeID:<name:"SimpleSample" > ctorMsg:<args:"query" args:"a" > secureContext:"jim" > 
Query Result: {"Name":"a","Amount":"60"}
16:33:31.337 [main] main -> INFO 004 Exiting.....

Rest API (V1.0 REST API将弃用)

root@fabric:~# curl 127.0.0.1:7050/chain
{
    "height": 6,
    "currentBlockHash": "UPlJDYyOBwc+wtbwDqoYUxsqnBerbEeIe/DqEL1KfgXOt5+Whkq6PTalMdgOJeDTd1SpZAkH8+gY1cNtJOt//Q==",
    "previousBlockHash": "xbvUoAaE54XyBg5yQaavC+U4gmQUJg8Hf12cizmB6V1rVWzUBdamxjdPVkNWBJr93K3/Ez/yyBlz5c3gC2BZsw=="
}

curl 127.0.0.1:7050/chain/blocks/1
#如果在windows使用postman 查询,请求发往http://192.168.78.130:7050/chain/blocks/1
  • GET /chain/blocks/{Block}
  • GET /chain
  • POST /chaincode
  • GET /network/peers
  • POST /registrar
  • DELETE /registrar/{enrollmentID}
  • GET /registrar/{enrollmentID}
  • GET /registrar/{enrollmentID}/ecert
  • GET /registrar/{enrollmentID}/tcert
  • GET /transactions/{UUID}

Golang chaincode调用

  • 在容器中或者本地编一个chaincode
#编译在bin目录下生成可执行文件,代码里有main函数
cd $GOPATH/src/github.com/chaincode_example0
go build

#CORE_CHAINCODE_ID_NAME,CORE_PEER_ADDRESS 为环境变量
#linux上用export,dos用set
#程序会启动一个与validating peer的gRPC通道供其调用
CORE_CHAINCODE_ID_NAME=mycc CORE_PEER_ADDRESS=0.0.0.0:7051 ./chaincode_example02
  • 在其它SSH终端中部署chaincode
peer network login jim
#输入密码6avZQLwcUe9b

peer network login jim -p 6avZQLwcUe9b

peer chaincode deploy -u jim -l golang -n mycc -c '{"Args": ["init", "a","100", "b", "200"]}' 
peer chaincode invoke -u jim -l golang -n mycc -c '{"Args": ["transfer", "a", "b", "10"]}'
peer chaincode query -u jim -l golang -n mycc -c '{ "Args": ["query", "a"]}'
peer chaincode query -u jim -l golang -n mycc -c '{"Args": ["query", "b"]}'

小结

  • 耗时在拉取fabric镜像,编译java chaincode最好在容器内编译,尝试在windows编译java失败,报错较多。
  • 参考文档 Hyperledger Fabric