简介
- Hyperledger Fabric是分布式账本解决方案的平台,以模块化架构为基础,提供高度的机密性,弹性,灵活性和可扩展性。它旨在支持不同组件的可插拔实现,并适应经济生态系统中存在的复杂性性。
- Hyperledger Fabric提供独
特的弹性和可扩展架构,区别于其他区块链解决方案。在未来的规划中,对于企业区块链将完全建立在审核且开源架构之上; Hyperledger Fabric是你最好的起点。
官方英文版教程:
http://hyperledger-fabric.readthedocs.io/en/latest/index.html
1. 运行e2e_cli初始化脚本
在上一篇中我们已经下载整个Fabric项目,其中包含了这里需要用到的e2e_cli:
/opt/gopath/src/github.com/hyperledger/fabric/examples/e2e_cli
在这里我们需要执行的文件是network_setup.sh
$ ./network_setup.sh up
在执行之前我,让我们先看一下所执行的方法:
....
....
function networkUp () {
if [ -f "./crypto-config" ]; then
echo "crypto-config directory already exists."
else
#Generate all the artifacts that includes org certs, orderer genesis block,
# channel configuration transaction
source generateArtifacts.sh $CH_NAME
fi
if [ "${IF_COUCHDB}" == "couchdb" ]; then
CHANNEL_NAME=$CH_NAME TIMEOUT=$CLI_TIMEOUT docker-compose -f $COMPOSE_FILE -f $COMPOSE_FILE_COUCH up -d 2>&1
else
CHANNEL_NAME=$CH_NAME TIMEOUT=$CLI_TIMEOUT docker-compose -f $COMPOSE_FILE up -d 2>&1
fi
if [ $? -ne 0 ]; then
echo "ERROR !!!! Unable to pull the images "
exit 1
fi
docker logs -f cli
}
...
...
#Create the network using docker compose
if [ "${UP_DOWN}" == "up" ]; then
networkUp
elif [ "${UP_DOWN}" == "down" ]; then ## Clear the network
networkDown
elif [ "${UP_DOWN}" == "restart" ]; then ## Restart the network
networkDown
networkUp
else
printHelp
exit 1
fi
可以看到这个文件共有3种功能,创建、清理、重启网络;
创建Fabric网络主要包含了如下动作:
- 1 编译生成Fabric公私钥、证书的程序,程序在目录:
/opt/gopath/src/github.com/hyperledger/fabric/release/linux-amd64/bin
- 2 基于configtx.yaml生成创世区块和通道相关信息,并保存在channel-artifacts文件夹。
- 3 基于crypto-config.yaml生成公私钥和证书信息,并保存在crypto-config文件夹中。
- 4 基于docker-compose-cli.yaml启动1Orderer+2org*2Peer+1CLI的Fabric容器。
- 5 在CLI启动的时候,会运行scripts/script.sh文件,这个脚本文件包含了创建Channel,加入Channel,安装Example02,运行Example02等功能。
$ ./network_setup.sh up
如果不出意外将会看到如下内容,可以开始下一步测试。
此处在阿里云Centos中创建Channel失败,腾讯云中并无问题,原因尚未调查清楚。
2. 测试运行
接下来让我们尝试着调用一些定义好的方法看看Fabric能实现怎样的效果。
在e2e这个例子中,channel名字是mychannel,chaincode的名字是mycc。我们首先进入CLI,我们重新打开一个命令行窗口,输入:
$ docker exec -it cli bash
运行以下命令可以查询a账户的余额:
$ peer chaincode query -C mychannel -n mycc -c '{"Args":["query","a"]}'
mychannel与mycc都是提前在配置中定义好的channel与chaincode实例名;'{"Args":["query","a"]}'
这里的query
最终指向的是/opt/gopath/src/github.com/hyperledger/fabric/examples/e2e_cli/examples/chaincode/go/chaincode_example02/chaincode_example02.go
这个Go源码中的query
方法;mycc可以理解为这个文件的实例名;
Go是编译语言,所以这个路径只是他的源码,如果想要自己定义则需要重新安装、实例化、添加peer(之后的文章会讲到如何安装、更新、操作chaincode,还有chaincode的版本控制等等)。
接着来看一下chaincode_example02.go
有什么内容:
.......
//这个方法并不是上边我们调用Query时触发的;
//它是再我们实例化chaincode时触发的,接下来会说它的调用地方
func (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface) pb.Response {
fmt.Println("ex02 Init")
_, args := stub.GetFunctionAndParameters()
var A, B string // Entities
var Aval, Bval int // Asset holdings
var err error
if len(args) != 4 {
return shim.Error("Incorrect number of arguments. Expecting 4")
}
// Initialize the chaincode
A = args[0]
Aval, err = strconv.Atoi(args[1])
if err != nil {
return shim.Error("Expecting integer value for asset holding")
}
B = args[2]
Bval, err = strconv.Atoi(args[3])
if err != nil {
return shim.Error("Expecting integer value for asset holding")
}
fmt.Printf("Aval = %d, Bval = %d\n", Aval, Bval)
// Write the state to the ledger
err = stub.PutState(A, []byte(strconv.Itoa(Aval)))
if err != nil {
return shim.Error(err.Error())
}
err = stub.PutState(B, []byte(strconv.Itoa(Bval)))
if err != nil {
return shim.Error(err.Error())
}
return shim.Success(nil)
}
.......
//这个就是刚才我们查询所调用到的方法
//内容非常简单,接收一个参数,然后GetState()返回对应的值
// query callback representing the query of a chaincode
func (t *SimpleChaincode) query(stub shim.ChaincodeStubInterface, args []string) pb.Response {
var A string // Entities
var err error
if len(args) != 1 {
return shim.Error("Incorrect number of arguments. Expecting name of the person to query")
}
A = args[0]
// Get the state from the ledger
Avalbytes, err := stub.GetState(A)
if err != nil {
jsonResp := "{\"Error\":\"Failed to get state for " + A + "\"}"
return shim.Error(jsonResp)
}
if Avalbytes == nil {
jsonResp := "{\"Error\":\"Nil amount for " + A + "\"}"
return shim.Error(jsonResp)
}
jsonResp := "{\"Name\":\"" + A + "\",\"Amount\":\"" + string(Avalbytes) + "\"}"
fmt.Printf("Query Response:%s\n", jsonResp)
return shim.Success(Avalbytes)
}
.......
这段代码我们看到了刚才query
所调用的具体方法以及具体内容,但是有个问题,我们并没有执行任何插入的操作,怎么会查询到值?
/opt/gopath/src/github.com/hyperledger/fabric/examples/e2e_cli/scripts/script.sh
这个脚本是再我们初始化的时候出发执行的,其种有一段代码:
instantiateChaincode () {
PEER=$1
setGlobals $PEER
# while 'peer chaincode' command can get the orderer endpoint from the peer (if join was successful),
# lets supply it directly as we know it using the "-o" option
if [ -z "$CORE_PEER_TLS_ENABLED" -o "$CORE_PEER_TLS_ENABLED" = "false" ]; then
peer chaincode instantiate -o orderer.example.com:7050 -C $CHANNEL_NAME -n mycc -v 1.0 -c '{"Args":["init","a","100","b","200"]}' -P "OR ('Org1MSP.member','Org2MSP.member')" >&log.txt
else
peer chaincode instantiate -o orderer.example.com:7050 --tls $CORE_PEER_TLS_ENABLED --cafile $ORDERER_CA -C $CHANNEL_NAME -n mycc -v 1.0 -c '{"Args":["init","a","100","b","200"]}' -P "OR ('Org1MSP.member','Org2MSP.member')" >&log.txt
fi
res=$?
cat log.txt
verifyResult $res "Chaincode instantiation on PEER$PEER on channel '$CHANNEL_NAME' failed"
echo "===================== Chaincode Instantiation on PEER$PEER on channel '$CHANNEL_NAME' is successful ===================== "
echo
}
看这方法名字就知道它是要实例化的我们的chaincode;
这里需要注意的是开启tls与不开启调用的方式是不一样的;
peer chaincode instantiate -o orderer.example.com:7050 -C $CHANNEL_NAME -n mycc -v 1.0 -c '{"Args":["init","a","100","b","200"]}' -P "OR ('Org1MSP.member','Org2MSP.member')" >&log.txt
可以看到这里定义了实例名mycc;并且调用的上边chaincode_example02.go
中的初始化方法,还传入了4个值;对比上边chaincode_example02.go
中,这4个值即代表了插入key=a,value=100;key=b,value=200这两组数据,这就是我们刚刚查询值的由来。
在chaincode_example02.go
中还有一个invoke
方法,可以用以下方式调用:
$ peer chaincode invoke -o orderer.example.com:7050 --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/examples/e2e_cli/crypto-config/ordererOrganizations/example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n mycc -c '{"Args":["invoke","a","b","30"]}'
参照chaincode_example02.go
中的源码很易容理解这里指的是a向b转账30。还有其他的方法,有兴趣可以依次尝试调用。
由于我的Fabric换了一套多节点实例没有e2e的环境,所以不能贴出具体执行结果,大家可以自己尝试。
到此基本上一切正常,运行exit命令退出cli容器。
关闭此Fabric网络的方法在开启时有过介绍。
这里只是简单的配置一个Fabric网络并调用已经安装好的chaincode,在实际场景中还需要更多的知识储备。需要了解可能诸如nodejs-SDK,用nodejs来触发Fabric网络种的各种方法,实现各自的业务场景;其次还需要学习Golang,主要是为了编写chaincode,满足我们的各种需求。
下一篇将介绍如何使用Nodejs调用chaincode,以及Nodejs-SDK
.
.
.
.
.
.
.
【本文章出自NM1024.com,转载请注明作者出处。】
>>转载请注明原文链接地址:Hyperledger-Fabric安装开发部署(二)测试运行
请问博主是在云环境搭建区块链运行环境,然后本地windows开发对吗?看了您后面的文章!
是的, windows 仅作为开发,有条件也可以使用linux桌面版