Hyperledger Fabric学习(七)智能合约(链码)

早过忘川 提交于 2020-08-11 11:12:39

智能合约(链码)

1、概述

      链码的编写需要自定义struct,实现shim包Chaincode接口的两个方法:

type Chaincode interface {
  Init(stub ChaincodeStubInterface) pb.Response
  Invoke(stub ChaincodeStubInterface) pb.Response
}

      链码的生命周期包括链码安装、实例化、升级等。其中链码的实例化和升级都会调用Init()方法,链码的invoke、query调用方式都只会调用Invoke()方法。
在shim包中,fabric给我们提供了ChaincodeStubInterface接口,在该接口中,我们可以使用接口中的方法实现具体的链码业务。

      特别说明一句,如果链码方法最后返回的pb.Response是shim.Error(),那么所有的操作,包括数据插入、数据删除、创建复合键、发送事件、调用其他链码等都是无效的,即一次链码的调用具有事务性,如果返回shim.Success()则所有操作都成功,否则所有操作都失败。

2、接口描述

1)参数解析

  • 直接获取所有参数
    • 字节数组[]byte形式
/*
     args := stub.GetArgs()
       - args 所有参数的[]byte形式
*/  
GetArgs() [][]byte
  • 字符串string形式
/*
     args := stub.GetStringArgs()
       - args 所有参数的[]string形式
*/  
GetStringArgs() []string
  • 获取方法名和调用参数(string格式)
/*
    functionName, args := stub.GetFunctionAndParameters()
      - functionName 方法名
      - args         方法名后面的所有参数
*/ 
GetFunctionAndParameters() (functionName string,args []string)

2)复合键操作

  • 创建复合键
/*
    compositeKey, err := stub.CreateCompositeKey(objectType, attributes)
     - objectType用于分类,放在compositeKey中的最前面,无实际含义
     - attributes是一个slice,会拼接成string类型,接在objectType后面
*/
CreateCompositeKey(objectType string, attributes []string) (string, error)
  • 分割复合键
/*
    key, compositeKeys, err := stub.SplitCompositeKey(iterator.Next().Key)
      - iterator为查询复合键的迭代器,Next()方法返回下一个复合键对象,Key标识该
        对象的复合键;
      - compositeKeys,[]string类型,得到即为创建复合键时的attributes值
*/  
SplitCompositeKey(compositeKey string) (string, []string, error)
  • 查询复合键
    • 查询所有结果
/*
    iterator, err := stub.GetStateByPartialCompositeKey(objectType, keys)
      - keys用于筛选
        * 当keys为空时,返回该objectType下的所有复合键;
        * 当keys不为空时,需要按照顺序,依次填入字段,即按照最左匹配原则,筛选出符               
          合条件的复合键;
*/
GetStateByPartialCompositeKey(objectType string, keys []string) (StateQueryIteratorInterface, error)
  • 分页展示结果(仅couchDB支持)
GetStateByPartialCompositeKeyWithPagination(objectType string, keys []string, pageSize int32, bookmark string) (StateQueryIteratorInterface, *pb.QueryResponseMetadata, error)

3)账本数据处理

  • 查询数据
    • 查询单个数据
/*
    data, err := stub.GetState(key)
*/
GetState(key string) ([]byte, error)
  • 查询范围内的数据
    • 查询所有结果
/*
    iterator, err :=stub.GetStateByRange(startKey, endKey)
      - startKey, endKey为查询的范围边界,注意是左闭右开, [startKey, endKey),即查询的结果是不包括endKey的值;
*/
GetStateByRange(startKey, endKey string) (StateQueryIteratorInterface, error)
* 分页展示结果(仅couchDB支持)
GetStateByRangeWithPagination(startKey, endKey string, pageSize int32, bookmark string) (StateQueryIteratorInterface, *pb.QueryResponseMetadata, error)
  • 条件查询(仅couchDB支持)
    • 查询所有结果(仅couchDB支持)
/*
    iterator, err := stub.GetQueryResult(query)
      - query为富查询语句
*/
GetQueryResult(query string) (StateQueryIteratorInterface, error)
* 分页展示结果(仅couchDB支持)
/*
   iterator, metadata, err := stub.GetQueryResultWithPagination(query, pageSize, bookmark)
*/
GetQueryResultWithPagination(query string, pageSize int32, bookmark string) (StateQueryIteratorInterface, *pb.QueryResponseMetadata, error)
  • 插入数据
/*
    err := stub.PutState(key, value)
*/
PutState(key string, value []byte) error
  • 删除数据
/*
    err := stub.DelState(key)
*/
DelState(key string) error
  • 查询数据修改的历史记录
/*
    iterator, err := stub.GetHistoryForKey(key)
*/
GetHistoryForKey(key string) (HistoryQueryIteratorInterface, error)

4)交易信息

  • 获取交易ID
GetTxID() string
  • 获取ChannelID
GetChannelID() string
  • 获取交易创建的时间戳
GetTxTimestamp() (*timestamp.Timestamp, error)
  • 获取交易提交者的身份信息
GetCreator() ([]byte, error)
  • 获取交易的临时信息
GetTransient() (map[string][]byte, error)

5) 发送事件

/*
    err := stub.SetEvent(key, value)
    注:sdk监听链码时,会根据正则表达式对key值进行筛选,value值将会传给链码的监听对象;
*/
SetEvent(name string, payload []byte) error

6)私有数据处理 (略)

7)调用其他链码

/*
    resp := stub.InvokeChaincode(chaincodeName, args, channel)
*/
InvokeChaincode(chaincodeName string, args [][]byte, channel string) pb.Response

3、其他接口补充

1)数据状态查询结果迭代器接口(StateQueryIteratorInterface)

  • 判断是否还有元素
HasNext() bool
  • 关闭迭代器
Close() error
  • 获取下一个元素
Next() (*queryresult.KV, error)

2)历史记录查询结果迭代器接口(HistoryQueryIteratorInterface)

  • 判断是否还有元素
HasNext() bool
  • 关闭迭代器
Close() error
  • 获取下一个元素
Next() (*queryresult.KeyModification, error)

4、图解

在这里插入图片描述

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!