预览

Hyperledger Fabric的chaincode开发目前支持Go、Java、Node.js语言,下面以Go语言作为例子,我们先看下面的一个官方提供chaincode模板

···

package main

import (
"github.com/hyperledger/fabric/core/chaincode/shim"
"github.com/hyperledger/fabric/protos/peer"
"fmt"
) type SimpleAsset struct { } func (t *SimpleAsset) Init(stub shim.ChaincodeStubInterface) peer.Response {
args := stub.GetStringArgs()
if len(args) != 2 {
return shim.Error("Incorrect arguments. Expecting a key and a value")
} err := stub.PutState(args[0], []byte(args[1]))
if err != nil {
return shim.Error(fmt.Sprintf("Failed to create asset: %s", args[0]))
}
return shim.Success(nil)
} func (t *SimpleAsset) Invoke(stub shim.ChaincodeStubInterface) peer.Response {
fn, args := stub.GetFunctionAndParameters() var result string
var err error
if fn == "set" {
result, err = set(stub, args)
}else {
result, err = get(stub, args)
}
if err != nil {
return shim.Error(err.Error())
}
return shim.Success([]byte(result))
} func set(stub shim.ChaincodeStubInterface, args []string) (string, error) {
if len(args) != 2 {
return "", fmt.Errorf("Incorrect arguments. Expecting a key and value")
} err := stub.PutState(args[0], []byte(args[1]))
if err != nil {
return "", fmt.Errorf("Failed to set asset: %s", args[0])
}
return args[1], nil
} func get(stub shim.ChaincodeStubInterface, args []string) (string, error) {
if len(args) != 1 {
return "", fmt.Errorf("Incorrect arguments. Expecting a key")
}
value, err := stub.GetState(args[0])
if err != nil {
return "", fmt.Errorf("Failed to get asset: %s with error: %s", args[0], err)
}
if value == nil {
return "", fmt.Errorf("Asset not found: %s", args[0])
}
return string(value), nil
} func main() {
if err := shim.Start(new(SimpleAsset)); err != nil {
fmt.Printf("Error starting SimpleAsset chaincode: %s", err)
}
}

···

我们下面具体看看上面这段代码做了什么。

开发chaincode时我们要实现ChainCode接口,ChainCode里面有Init和Invoke这两个函数。我们在前7行导入了需要的依赖。接着定义了一个名为SimpleAsset的结构体,这个结构体实现了ChainCode接口。另外还有个main函数,作为chaincode的启动入口。

初始化chaincode

接下来,我们实现Init方法

···

func (t *SimpleAsset) Init(stub shim.ChaincodeStubInterface) peer.Response {
args := stub.GetStringArgs()
if len(args) != 2 {
return shim.Error("Incorrect arguments. Expecting a key and a value")
} err := stub.PutState(args[0], []byte(args[1]))
if err != nil {
return shim.Error(fmt.Sprintf("Failed to create asset: %s", args[0]))
}
return shim.Success(nil)
}

···

该方法在chaincode实例化时被调用,可以根据实际需要做一些初始化数据的操作。需要注意的是在chaincode升级时这个Init方法也会被调用。

调用chaincode

接着,我们继续看Invoke方法

···

func (t *SimpleAsset) Invoke(stub shim.ChaincodeStubInterface) peer.Response {
fn, args := stub.GetFunctionAndParameters() var result string
var err error
if fn == "set" {
result, err = set(stub, args)
}else {
result, err = get(stub, args)
}
if err != nil {
return shim.Error(err.Error())
}
return shim.Success([]byte(result))
}

···

Invoke方法主要就是根据传过来的具体参数调用chaincode的其他业务函数。如这里,就是根据传过来的参数fn,如果fn"set"则调用下面的set函数来把数据保存到区块链上(若状态数据库的key存在则是修改操作)。如果fn"get"则调用后面的get函数来获取链上的数据。

shim.ChaincodeStubInterface

上面的chaincode模板中很多地方都用到了ChaincodeStubInterface这个接口,这个接口为我们编写chaincode提供了大量的方法。在这里只介绍几个,想详细了解,可查阅官方文档

获得调用参数

上面的chaincode模板中Init方法用到了GetStringArgs()函数,Invoke方法中用到了GetFunctionAndParameters()函数。这两个函数都是用来解析传入的参数的,除了这两个函数外,ChaincodeStubInterface接口还提供了另外几种函数。

  • GetArgs() [][]byte 以byte数组的数组的形式获得传入的参数列表
  • GetStringArgs() []string 以字符串数组的形式获得传入的参数列表
  • GetFunctionAndParameters() (string, []string) 将字符串数组的参数分为两部分,数组第一个字是Function,剩下的都是Parameter
  • GetArgsSlice() ([]byte, error) 以byte切片的形式获得参数列表

增删改查状态数据库(State Database)

  • PutState(key string, value []byte) error 增改数据

由于状态数据库是个key-value数据库,所以如果key存在就是修改操作,如果key不存在就是增加操作。value是经过JSON序列化后的字符串

  • GetState(key string) ([]byte, error) 根据key获取状态数据库数据
  • DelState(key string) error 根据key删除状态数据库数据

参考链接

https://hyperledger-fabric.readthedocs.io/en/release-1.3/chaincode4ade.html

https://godoc.org/github.com/hyperledger/fabric/core/chaincode/shim#Chaincode

https://godoc.org/github.com/hyperledger/fabric/core/chaincode/shim#ChaincodeStubInterface

Hyperledger Fabric ChainCode开发的更多相关文章

  1. HyperLedger Fabric ChainCode开发——shim.ChaincodeStubInterface用法

    深蓝前几篇博客讲了Fabric的环境搭建,在环境搭建好后,我们就可以进行Fabric的开发工作了.Fabric的开发主要分成2部分,ChainCode链上代码开发和基于SDK的Application开 ...

  2. Hyperledger Fabric chaincode 开发(疑难解答)

    Q&A Q1: 使用fabric release 1.2 进行golang chaincode开发时报错: ..\..\hyperledger\fabric\vendor\github.com ...

  3. Hyperledger Fabric Chaincode for Operators——实操智能合约

    什么是Chaincode(智能合约)? chaincode是一个程序,它是使用Go语言编写的,最终在Java等其他编程语言中实现了指定的接口.chaincode运行在一个被背书peer进程独立出来的安 ...

  4. Hyperledger Fabric Chaincode解析

    首先看下Blockchain结构,除了header指向下一个block的hash value外,block是由一组transaction构成, Transactions --> Blocks - ...

  5. Hyperledger Fabric 1.0 从零开始(十二)——fabric-sdk-java应用

    Hyperledger Fabric 1.0 从零开始(十)--智能合约 Hyperledger Fabric 1.0 从零开始(十一)--CouchDB 上述两章,最近网上各路大神文章云集,方案多多 ...

  6. Hyperledger Fabric 1.0 从零开始(一)

    在HyperLedger/Fabric发布0.6的时候,公司就已经安排了一个团队研究这一块,后来也请IBM的专家组过来培训了一批人,不幸的是,这批人后来全走了,然后1.0就发布了.自从2017年7月H ...

  7. Hyperledger Fabric 1.0 从零开始(十二)——fabric-sdk-java应用【补充】

    在 Hyperledger Fabric 1.0 从零开始(十二)--fabric-sdk-java应用 中我已经把官方sdk具体改良办法,即使用办法发出来了,所有的类及文件都是完整的,在文章的结尾也 ...

  8. Centos7 HyperLedger Fabric 1.4 生产环境部署

    Kafka生产环境部署案例采用三个排序(orderer)服务.四个kafka.三个zookeeper和四个节点(peer)组成,共准备八台服务器,每台服务器对应的服务如下所示: kafka案例网络拓扑 ...

  9. 联盟链IBM的超级账本Hyperledger Fabric框架,JP Morgan’s Quorum

    联盟链IBM的超级账本Hyperledger Fabric框架,JP Morgan’s Quorum JP Morgan’s Quorum https://www.coindesk.com/jpmor ...

随机推荐

  1. deeplearning.ai 神经网络和深度学习 week2 神经网络基础

    1. Logistic回归是用于二分分类的算法. 对于m个样本的训练集,我们可能会习惯于使用for循环一个个处理,但在机器学习中,是把每一个样本写成一个列向量x,然后把m个列向量拼成一个矩阵X.这个矩 ...

  2. Qt HWND转QWidget

    HWND m_hWnd; QWidget *newWidget; newWidget = QWidget::find((WId)m_hWnd): //需要用(WID)

  3. 发现个很有意思的angularjs +grunt 复习项目

    最近作运维工作 docker 接触到一个开源webui dockerui 原项目地址 https://github.com/crosbymichael/dockerui 用angular框架实现,项目 ...

  4. h指数|JCR|ORCID|CCC|Research ID|BKCI|

    h指数有如下缺点: 年龄大且平庸的学者比杰出的青年学者的h-index大.学科之间h指数的评价标准不同.有时候,审稿人暗示作者引用自己文章. 再此处可找到相关信息: JCR上可以查询到影响因子,以下是 ...

  5. h-index|IF|Good story|IPS

    科研论文写作 科研论文写作的关键在于写出研究的重要性. 对科研工作者的评价标准主要以论文为主,可以从论文的定性和定量角度评价.论文的外部评价,包括科学院分区(包括123类):影响因子IF,可以通过we ...

  6. linux下的时区修改

    Centos 7时区问题: 通常使用tzselect命令选择时区,今天在修改centos7的时区的时候,修改完以后时区还是没有发生变化,重启也是没有用的:通过网络的帮助了解到,在Centos和ubun ...

  7. 吴裕雄--天生自然python学习笔记:Python3 File(文件) 方法

    open() 方法 Python open() 方法用于打开一个文件,并返回文件对象,在对文件进行处理过程都需要使用到这个函数,如果该文件无法被打开,会抛出 OSError. 注意:使用 open() ...

  8. MyBatis之一级缓存及其一级缓存失效

    定义: 一级缓存:本地缓存:与数据库同一次会话(sqlSession)期间查询到的数据会放在本地缓存中,如果以后要获取相同的数据直接从缓存中获取,不会再次向数据库查询数据一个SqlSession拥有一 ...

  9. 《软件自动化测试开发-Java和Python测试开发指南》第6次印刷

    2017年1月 第1次印刷 2017年5月 第2次印刷 2017年9月 第3次印刷 2017年11月 第4次印刷 2018年4月 第5次印刷 2018年6月 第6次印刷 欢迎留言,点赞前2名,可获2折 ...

  10. swoole I/O 模型

    I/O即Input/Output,输入和输出的意思.在计算机的世界里,涉及到数据交换的地方,比如磁盘.网络等,就需要I/O接口. 通常,I/O是相对的.比如说你打开浏览器,通过网络I/O获取我们网站的 ...