【我的区块链之路】- Hyperledger fabric的简单入门(四)链码的编写及调试

【我的区块链之路】- Hyperledger fabric的简单入门(四)链码的编写及调试
      之前的文章中我们有讲过了fabric的一些核心的配置文件的选项说明,讲过fabric 的网络启动的步骤,那么,我们会在这篇文章中讲述如何的编写链码,及本地调试链码,及发布链码调用链码等等操作!

【注意】首先,我们在编写链码之前需要下载几个依赖库:
1、github.com/hyperledger/fabric/core/chaincode/shim
2、github.com/hyperledger/fabric/protos/peer
其中,一个最基本的空链码结构为如下所示:

package myChainCode
 
import (
    "github.com/hyperledger/fabric/core/chaincode/shim"
    "github.com/hyperledger/fabric/protos/peer"
    "fmt"
)
 
 
type FirstChainCode struct {
}
 
/**
实例化/升级链码时调用的方法
 */
func (self *FirstChainCode)Init(stub shim.ChaincodeStubInterface) peer.Response {
    return peer.Response{}
}
 
/**
客户端/cli使用Query或者Invoke的方式调用链码时调用的方法
 */
func (self *FirstChainCode)Invoke(stub shim.ChaincodeStubInterface) peer.Response {
    return peer.Response{}
}
 
func main() {
    if err := shim.Start(new(FirstChainCode)); nil != err {
        fmt.Printf("实例化链码失败,err := %n", err.Error())
    }
}
先来讲解下链码文件的结构:

首先,上述是每个链码文件都需要实现 ChainCode 接口

在源码包的  github.com/hyperledger/fabric/core/chaincode/shim/interfaces.go 中的 ChainCode 接口为:

package shim
 
import (
    "github.com/golang/protobuf/ptypes/timestamp"
 
    "github.com/hyperledger/fabric/protos/ledger/queryresult"
    pb "github.com/hyperledger/fabric/protos/peer"
)
 
// Chaincode interface must be implemented by all chaincodes. The fabric runs
// the transactions by calling these functions as specified.
type Chaincode interface {
    // Init is called during Instantiate transaction after the chaincode container
    // has been established for the first time, allowing the chaincode to
    // initialize its internal data
    Init(stub ChaincodeStubInterface) pb.Response
 
    // Invoke is called to update or query the ledger in a proposal transaction.
    // Updated state variables are not committed to the ledger until the
    // transaction is committed.
    Invoke(stub ChaincodeStubInterface) pb.Response
}
其中,

1、当链码收到 实例化 (instantiate) 或者 升级 (upgrade) 类型交易时,Init 方法会被调用;

2、当链码收到 调用 (invoke) 或者 查询 (query)类型交易时, Invoke 方法会被调用;

下面我们在看一个稍微完善点的链码:

package main
 
import (
    "github.com/hyperledger/fabric/core/chaincode/shim"
    "github.com/hyperledger/fabric/protos/peer"
    "fmt"
)
 
type SimpleChaincode struct {
}
 
/**
实例化/升级链码时被自动调用
 -c '{"Args":["Hello","World"]'
*/
func (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface) peer.Response {
    // 获取参数
    //args := stub.GetStringArgs()
    _, args := stub.GetFunctionAndParameters()
    // 判断参数长度是否为2个
    if len(args) != 2 {
        return shim.Error("指定了错误的参数个数")
    }
 
    // 通过调用PutState方法将数据保存在账本中
    err := stub.PutState(args[0], []byte(args[1]))
    if err != nil {
        return shim.Error("保存数据时发生错误...")
    }
    return shim.Success("链码实例化成功~")
 
}
 
/**
对账本数据进行操作时被自动调用(query, invoke)
peer chaincode query -n hello -C myc -c '{"Args":["queryData","Hello"]}'
*/
func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface) peer.Response {
    // 获取调用链码时传递的参数内容(包括要调用的函数名及参数)
    fun, args := stub.GetFunctionAndParameters()
    if fun == "queryData" {
        return queryData(stub, args)
    }
    return shim.Error("非法操作, 指定功能不能实现")
}
 
/**
自定义方法
*/
func queryData(stub shim.ChaincodeStubInterface, args []string) peer.Response {
    // 检查传递的参数个数是否为1外
    if len(args) != 1 {
        return shim.Error("只能指定相应的Key")
    }
    // 根据指定的Key调用GetState方法查询数据
    result, err := stub.GetState(args[0])
    if err != nil {
        return shim.Error("根据指定的 " + args[0] + " 查询数据时发生错误")
    }
    if result == nil {
        return shim.Error("根据指定的 " + args[0] + " 没有查询到相应的数据")
    }
    // 返回查询结果
    return shim.Success(result)
}
 
func main() {
    if err := shim.Start(new(SimpleChaincode)); nil != err {
        fmt.Printf("链码启动失败: %v", err)
    }
}
以上就是我们的链码的编写,其中【stub shim.ChaincodeStubInterface 为我们提供了操作 账本的API,具体请参考相关资料】下面我们来查看链码的本地调试及 远端的安装部署

首先,我们要本地调试的话需要具备可以启动简单的本地fabric网络的配置,我这里就直接用了fabric-sample提供的 chaincode 目录来存放本地链码,使用 chaincode-docker-devmode 目录来运行链码,【为什么这么做呢,首先,我们在Hyperledger fabric的简单入门(一)fabric-samples的下载及自动启动网络脚本演示 一文中就有说明了 chaincode 和 chaincode-docker-devmode 的作用,且在 chaincode-docker-devmode 中的 docker-compose-simple.yaml 中就能看到,该本地测试环境所引用的链码是 挂载了 chaincode  到容器的】

步骤:

1、先进入 chaincode-docker-devmode 启动本地测试网络 :docker-compose -f docker-compose-simple.yaml up 

2、进入对应的链码所在目录【当然进入到chaincode容器中的对应挂载的目录也是可以的】,如:/fabric-samples/chaincode/sacc 执行go build 把链码编译成go的可执行文件【或者直接把可执行文件拖到这里面来】;

3、在 链码容器 【注意: 一定是去到容器里面启动链码哦】的 对应的链码的可执行文件所在的目录,如:/opt/gopath/src/chaincode/sacc

这时候我们需要手动启动链码:CORE_PEER_ADDRESS=peer:7052 CORE_CHAINCODE_ID_NAME=mycc:0 ./sacc 【其中,CORE_PEER_ADDRESS 和 docker-compose-simple.yaml 中peer 的CORE_PEER_ADDRESS 端口不一样,为什么是这样,请查看之前的Hyperledger fabric的简单入门(三)fabric主要配置文件细讲 中的 peer 的配置文件 core.yaml 讲解自明 】

启动链码显示:

链码启动成功!【当然,正式环境链码的启动是有Endorser节点来启动链码容器启动的】

升级链码,在没有关闭本地网络的情况下,升级链码需要,把更改的的执行文件替换(当然不替换也是可以的需要不同名) 且在链码容器中启动链码时,指定 新的版本号【一般是网上叠加的版本号】和指定新的执行文件:

CORE_PEER_ADDRESS=peer:7052 CORE_CHAINCODE_ID_NAME=mycc:2 ./sacc

OK,这时候我们就可以,启动一个客户端来调用对应的链码了,步骤和正常的链码调用一直,如:

安装 -> 实例化 /升级 ->  调用

peer chaincode install -p chaincodedev/chaincode/sacc -n mycc -v 0


peer chaincode instantiate -n mycc -v 0 -c '{"Args":["a","10"]}' -C myc


peer chaincode invoke -n mycc -c '{"Args":["set", "a", "20"]}' -C myc
 

【注意】本地环境中默认通道为 myc;且本地环境安装及实例化/升级等都不需要一大堆 --tls --msp 等等参数
 

OK,以上就是我们在本地环境测试链码的方式,正式环境是如何操作链码的,请参考【Hyperledger fabric的简单入门(二)单机演示fabric网络启动全过程】最后面操作链码那部分!
————————————————
版权声明:本文为CSDN博主「GavinXujiacan」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_25870633/article/details/81751101

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AI周红伟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值