fabric_example
fabric-examples学习笔记
由于docker images下载的速度实在太… 这个时间就先看看examples吧
版本release-1.1
chaincode
Example-01
func main() {
err := shim.Start(new(SimpleChaincode)) if err != nil { fmt.Printf("Error starting Simple chaincode: %s", err) }
}
第一个例子就详细看一下结构,后面的都类似。
main方法里shim.Start(new(结构体))是入口,所有代码实现的部分都是实现这个结构体。这个结构体需要实现的方法
- Init(stub shim.ChaincodeStubInterface) pb.Response
- Invoke(stub shim.ChaincodeStubInterface) pb.Response
在这个例子中,有两个账户及其余额,Init方法为设置两个账户的名字及余额。Invoke方法实现的是从A账户转账到B账户。顾名思义的话,Init为初始化方法,Invoke猜测应该是使用反射,可实现为分发的功能,分发到其他方法中,实现具体相应功能。例如
func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface) pb.Response {
function, args := stub.GetFunctionAndParameters() //获取调用的方法名及其参数
if function == "invoke" {
// Make payment of X units from A to B
return t.invoke(stub, args) //调用相应方法
} else if function == "delete" {
// Deletes an entity from its state
return t.delete(stub, args) //调用相应方法
} else if function == "query" {
// the old "Query" is now implemtned in invoke
return t.query(stub, args) //调用相应方法
}
return shim.Error("Invalid invoke function name. Expecting \"invoke\" \"delete\" \"query\"")
}
好吧其实这是example-02的代码了 - . -
- Example-02
功能上来说的话,01是两个固定的账户,02是账本上的两个账户的操作。第一,操作增多了,有查询删除,实现为在invoke中进行分发,代码如上…第二,牵涉到账本了,看似像一个key-value的数据存储,代码如下
//存
err = stub.PutState(A, []byte(strconv.Itoa(Aval)))
//取
Avalbytes, err := stub.GetState(A)
猜测肯定是数据库方面的了,更深入的之后再看。尤其是stub,shim.ChaincodeStubInterface。这个对象是所有跟上层接轨的接口,其实现需要查看。这里先略过
- Example -03
这个例子中,好像重点在下面这个代码
func (t *SimpleChaincode) query(stub shim.ChaincodeStubInterface, args []string) pb.Response {
···
// Write the state to the ledger - this put is illegal within Run
err = stub.PutState(A, []byte(strconv.Itoa(Aval)))
···
}
意思好像是在query方法中不能进行putState。延伸一下的话,是只有在原始invoke方法中才能进行putState,修改数据库。当然啦,这个小写的invoke方法也是可以实现的
- Example-04
这个例子为example了在链码中调用其他链码,主要api为
response := stub.InvokeChaincode(chainCodeToCall, invokeArgs, channelID)
- Example-05
这个例子也是调用其他链码,但是说明了调用的链码和当前链码不是同一个channel上需要指明channel。这个不是很明白。
使用InvokeChaincode方法,传入的参数依次是 被调用的链码名称,调用参数(包括调用方法和参数), channel name
看4,5test并没有看出来4 5调用的差别…
Test
scc := new(SimpleChaincode) stub := shim.NewMockStub("ex03", scc) res := stub.MockInvoke("1", [][]byte{[]byte("query"), []byte("A"), []byte("345")) if res.Status != shim.OK { fmt.Println("Query failed", string(res.Message)) t.FailNow() }
还有个启动两个链码的
scc := new(SimpleChaincode)
stub := shim.NewMockStub("ex05", scc)
ccEx2 := new(ex02.SimpleChaincode)
stubEx2 := shim.NewMockStub(chaincodeName, ccEx2)
checkInit(t, stubEx2, [][]byte{[]byte("init"), []byte("a"), []byte("222"), []byte("b"), []byte("333")})
//在当前模拟peer,添加chaincode
stub.MockPeerChaincode(chaincodeName, stubEx2)
看官方文档的介绍,Tutorials似乎提供了4个tutorial,分别为Application开发(使用的node sdk)、网络搭建、链码开发、链码操作。作为入门的话,肯定要都过一遍啦~
网络搭建
示例中包含2组,每组2个peer节点,以及1个单独的order服务
首先clone fabric-example仓库,然后找到下载docker images的地方,下载docker-images官方是使用curl … | bash 的一行命令,下载速度很慢,经过网上很多好心人提示,说curl 那个连接其实是一个脚本,直接用网站打开那个连接,复制粘贴脚本到本地,命名*.sh,然后直接运行就好了,这个脚本大概看一下,有3个方法的调用,2个方法都有下载docker images, 还有1个方法是下载二进制文件,这个二进制文件下载后会保存在当前目录下的bin文件夹下。bin里面的内容如下
$ ls
configtxgen configtxlator cryptogen get-docker-images.sh orderer peer
然后把这个bin文件夹拷贝到fabric-example下。
$ cd first-network
$ ./byfn.sh -m generate
如果bin里面内容缺失,这里就会报各种命令不存在。再则,下载的fabric-example的版本应该和二进制可执行文件的版本一致,不然还是会报错..可直接修改下载脚本里的版本。
$ ./byfn.sh -m up
其中,对于版本问题是是严谨。各个版本都要一样。另外,上面提到的那个curl 链接的那个脚本,在fabric仓库下其实是有的,script/bootstrap.sh。可直接拷贝粘贴
然后针对byfn脚本具体分析一下整个过程和结构的吧~
☝️,$ ./byfn.sh -m generate的功能。
使用cryptogen工具来为节点生成加密证书。这些证书可代表节点的身份,被允许签署/验证身份验证进行实体沟通和交易。
- cryptogen通过配置文件进行工作,配置文件中定义了各个节点信息。如crypto-config.yaml
使用命令为cryptogen generate –config=./crypto-config.yaml,成功后会在当前文件夹下生成crypto-config文件夹, 各个证书以节点角色/Domain/…的文件形式存在OrdererOrgs: - Name: Orderer Domain: example.com # --------------------------------------------------------------------------- # "Specs" - See PeerOrgs below for complete description # --------------------------------------------------------------------------- Specs: - Hostname: orderer PeerOrgs: # ----------------------------------------------------- # Org1 # ---------------------------------------------------- - Name: Org1 Domain: org1.example.com Template: Count: 2 Users: Count: 1
- cryptogen通过配置文件进行工作,配置文件中定义了各个节点信息。如crypto-config.yaml
使用configtxgen tool来生成一些部署实体所需要的零件。也需要配置文件,配置文件定义了网络模板。主要零件类型有
- orderer genesis block, orderer服务启动必备,注意的是每个组织的根证书都包含在gensis.block中。
- channel configuration transaction, 该配置在orderer服务启动创建channel时配置channel。这里就已经形成了channel的读写策略(即哪些实体可以读,哪些实体可以写,下同)。
- and two anchor peer transactions - one for each Peer Org. 用于指定在channel中,当前peer组织中都有哪些peer结点。这里就已经形成了组织的读写策略。
最后就是 up启动网络了,最重要的命令即… docker-compose -f $COMPOSE_FILE…, 查看docker-compose-cli.yaml,定义了6个容器服务,其中最后一个为cli, 执行为./scripts/script.sh。查看这个脚本大概为创建channel、加入channel、升级组织配置、安装部署chaincode、调用chaincode…后面每一步应该都会自己搞一次..这里还是先跳过
到这里,我就感觉脑子里放不下东西了已经,很尴尬…先跟着向导继续走吧嗯, 很难受。
具体看了一下cli, 大致是将证书,script等都作为数据卷挂载到容器上,然后在容器上调用script操作。channel的加入,似乎是通过各证书验证身份。链码的部署调用都是通过peer chaincode … 命令进行