上一章步步分析了hyperledger fabric搭建网络节点和创建channel。本章基于章节2部署官方示例的智能的合约,也会一步步做分析。
老规矩,先给出官方示例的下载网址:https://github.com/hyperledger/fabric-samples
上图是我上一章搭建的fabric测试网,我创建了6个org节点,1个order节点。
在fabric中智能合约叫做chaincode。
第一步:打包chaincode
什么是打包chaincode,就是打包你写的contract,你可以使用go,java,nodejs开发contract,这些代码需要按照特定格式建项,然后通过bin里面的peer
命令工具打包。
CC_NAME=mychannel
CC_SRC_PATH=你的智能合约代码地址
CC_RUNTIME_LANGUAGE=javascript # or go, java, typescript
CC_VERSION=1.0
peer lifecycle chaincode package ${CC_NAME}.tar.gz --path ${CC_SRC_PATH} --lang ${CC_RUNTIME_LANGUAGE} --label ${CC_NAME}_${CC_VERSION}
打包出一个tar.gz文件,这个就是fabric节点可以用来安装的chaincode安装包。
注意本章所有名词:chaincode=contract=智能合约,我不知道为啥IBM要把这个叫做chaincode,我更喜欢智能合约叫法,contract。
第二步:安装chaincode
# 为orgX设置环境变量
export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
export CORE_PEER_ADDRESS=localhost:7051
peer lifecycle chaincode install ${CC_NAME}.tar.gz
注意,hyperledger给的bin下peer
命令用途很多,可以拿来装chaincode,但是需要设置terminal级别的环境变量,这也是我要吐槽的,为啥不能直接通过config文件或者option来执行呢,这种操作很想ssl常用的远程连接操作。
如果你现在是为org2,3,4…安装chaincode,那么你需要修改成他们的环境变量,指向其他org的加密文件地址,这些加密文件也就是我们上一章用cryptogen
创建的,用于org的鉴权,都在organizations目录下,里面是节点的数字证书。
第三步:同意chaincode
给每个节点安装完chaincode之后还需要节点同意这些合约,也就是approve操作,这一点其实也是很累赘的,我觉得可以简略成:安装即同意,没必要整这么一个环节,既然节点安装了这份合约(chaincode)就等于默认同意了。Farbic里很多的操作命令我都觉很鸡肋。。。
# 设置当前org环境变量
export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
export CORE_PEER_ADDRESS=localhost:7051
ORDERER_CA=${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
PACKAGE_ID= #上一个步骤安装chaincode获得的id码
peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile "$ORDERER_CA" --channelID mychannel --name fabcar --version 1 --package-id ${PACKAGE_ID} --sequence 1 --init-require
注意所有用到peer
命令工具的地方都需要配置当前节点的环境变量,跟上一步骤一样。当然你有org2,3,4…的话需要重复上述shell并且更改环境变量指向对应org加密文件地址,
第四步:Commit Chaincode
额。。。这一步我个人觉得也是鸡肋步骤,节点都安装了,同意了合约居然还要commit,而且commit的步骤很复杂,我也是醉了。但官方文档是这么写的,我们就按部就班吧。
parsePeerConnectionParameters() {
PEER_CONN_PARMS=()
PEERS=""
while [ "$#" -gt 0 ]; do
setGlobals $1
PEER="peer0.org$1"
## Set peer addresses
if [ -z "$PEERS" ]
then
PEERS="$PEER"
else
PEERS="$PEERS $PEER"
fi
PEER_CONN_PARMS=("${PEER_CONN_PARMS[@]}" --peerAddresses $CORE_PEER_ADDRESS)
## Set path to TLS certificate
ORG=$1
CA="${PWD}/organizations/peerOrganizations/org${ORG}.example.com/peers/peer0.org${ORG}.example.com/tls/ca.crt"
TLSINFO=(--tlsRootCertFiles $CA)
PEER_CONN_PARMS=("${PEER_CONN_PARMS[@]}" "${TLSINFO[@]}")
# shift by one to get to the next organization
shift
done
}
ORDERER_CA=${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
peer lifecycle chaincode commit -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile "$ORDERER_CA" --channelID mychannel --name ${CC_NAME} "${PEER_CONN_PARMS[@]}" --version 1 --sequence 1 --init-require
这里用到一个自定义的shell函数,并不完成,这里其实就是遍历出了所有peer节点的tlsRoorCertFiles
,实际命令行很长,shell最终输出的命令如下:
peer lifecycle chaincode commit -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem --channelID mychannel --name fabcar --peerAddresses localhost:7051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --version 1 --sequence 1 --init-required
源代码中,我实际一共使用了6个org节点,这里我简化为2个,命令格式一样的。
这里简单做个解释:这个commit操作呢其实就是类似org向order汇报接受chaincode的结果,所以命令的结构是order节点+org1+org2…这个样子,后面有多少个org通过了合约就接多少个org,附上org的tlsRootCertFiles
。
第五步:执行合约初始化代码invoke(非必要)
这一步是执行一下chaincode里的init函数,不是必要的,但是用户在读写合约的时候也是要执行一下的,所以这一步可以归结到部署合约过程中。
还是使用peer
工具执行invoke
peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n fabcar --peerAddresses localhost:7051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --isInit -c '{"function":"initLedger","Args":[]}'
这段命令跟前面的是一样的格式,只是执行了function initLedger
,也就是初始化账本。