表象:Return schema invalid. required items must be unique [recovered]

虽然 Fabric v2.2 已经发布了很久了,但之前因为项目历史问题,一直使用的都是 Fabric v1.4.8,所以智能合约也一直使用的都是 github.com/hyperledger/fabric/core/chaincode/shim 包。

在合约开发过程中,我一般都是使用下面的接口格式来定义合约的业务逻辑:

func create(stub shim.ChaincodeStubInterface, payload string) ([]byte, error)

在开发 Fabric v2.2 的智能合约时, 使用 github.com/hyperledger/fabric-contract-api-go/contractapi 替换 github.com/hyperledger/fabric/core/chaincode/shim,接口格式如下:

func create(ctx contractapi.TransactionContextInterface, payload string) ([]byte, error)

然而这样的接口在合约示例化的时候翻车了:

Error compiling schema for SmartContract [create]. Return schema invalid. required items must be unique [recovered]

翻阅 github.com/hyperledger/fabric-contract-api-go 时,在其使用教程发现一些限制:

  • 合同的函数只能接受以下类型的参数:

    • string
    • bool
    • int(包括 int8、int16、int32 和 int64)
    • uint(包括 uint8、uint16、uint32 和 uint64)
    • float32
    • float64
    • time.Time
    • 任何允许类型的数组/切片
    • 结构体(其公共字段全部属于允许类型或另一个结构体)
    • 指向结构体的指针
    • 具有键类型为 string 和值为任何允许类型的映射
    • interface{}(仅当直接传入时才允许,在通过事务调用时将接收一个 string 类型)
  • 合同的函数还可以接受事务上下文,前提是:
    • 它作为第一个参数传入
    • 二选一:
      • 它要么是类型为 *contractapi.TransactionContext 的对象,要么是在链码中定义的自定义事务上下文,用于合同的使用
      • 它是一个接口,用于合同的事务上下文类型符合该接口,例如 contractapi.TransactionContextInterface
  • 合同的函数只能返回零、一个或两个值:
    • 如果函数被定义为返回零值,那么对该合同函数的所有调用将返回成功响应
    • 如果函数被定义为返回一个值,那么该值可以是参数列表中列出的任何允许类型之一(除了 interface{}),或者是错误。
    • 如果函数被定义为返回两个值,那么第一个值可以是参数列表中列出的任何允许类型之一(除了 interface{}),第二个值必须是错误。

仔细阅读会发现 func create(ctx contractapi.TransactionContextInterface, payload string) ([]byte, error) 并没有违法上面的规则,但示例化的时候就是无法通过。

上面的报错信息也明确说了是返回值不对,那就改下接口的返回值:

func create(ctx contractapi.TransactionContextInterface, payload string) (string, error)
func create(ctx contractapi.TransactionContextInterface, payload string) (*Company, error)
func create(ctx contractapi.TransactionContextInterface, payload string) (int, error)

修改后在进行实例化,这次不再报错了。

但是明明之前的也没有违反规则,为什么会报错呢?想不通为什么,所以准备给官方提个Issue,万一真是个bug呢?

结果就在issues里发现了这个Possible issues with byte[] as return type,一看日期Oct 20, 2021,快两年了也没官方的回应......

结论

最后搜了一圈也没找到原因,查看源码,感觉问题可能是出在 contractFunctionReturns,具体还得等研究完源码之后才能有答案

type contractChaincodeContract struct {
info metadata.InfoMetadata
functions map[string]*internal.ContractFunction
unknownTransaction *internal.TransactionHandler
beforeTransaction *internal.TransactionHandler
afterTransaction *internal.TransactionHandler
transactionContextHandler reflect.Type
} // ContractChaincode a struct to meet the chaincode interface and provide routing of calls to contracts
type ContractChaincode struct {
DefaultContract string
contracts map[string]contractChaincodeContract
metadata metadata.ContractChaincodeMetadata
Info metadata.InfoMetadata
TransactionSerializer serializer.TransactionSerializer
} // ContractFunction contains a description of a function so that it can be called by a chaincode
type ContractFunction struct {
function reflect.Value
callType CallType
params contractFunctionParams
returns contractFunctionReturns
} type contractFunctionReturns struct {
success reflect.Type
error bool
}

声明:本作品采用署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)进行许可,使用时请注明出处。

Author: mengbin

blog: mengbin

Github: mengbin92

cnblogs: 恋水无意


Fabric 2.x 智能合约开发记录的更多相关文章

  1. Hyperledger Fabric 智能合约开发及 fabric-sdk-go/fabric-gateway 使用示例

    前言 在上个实验 Hyperledger Fabric 多组织多排序节点部署在多个主机上 中,我们已经实现了多组织多排序节点部署在多个主机上,但到目前为止,我们所有的实验都只是研究了联盟链的网络配置方 ...

  2. Hyperledger Fabric 使用 CouchDB 和复杂智能合约开发

    前言 在上个实验中,我们已经实现了简单智能合约实现及客户端开发,但该实验中智能合约只有基础的增删改查功能,且其中的数据管理功能与传统 MySQL 比相差甚远.本文将在前面实验的基础上,将 Hyperl ...

  3. 智能合约开发环境搭建及Hello World合约

    如果你对于以太坊智能合约开发还没有概念(本文会假设你已经知道这些概念),建议先阅读入门篇. 就先学习任何编程语言一样,入门的第一个程序都是Hello World.今天我们来一步一步从搭建以太坊智能合约 ...

  4. 智能合约开发solidity编程语言开发一个以太坊应用区块链投票实例

    智能合约开发用solidity编程语言部署在以太坊这个区块链平台,本文提供一个官方实战示例快速入门,用例子深入浅出智能合约开发,体会以太坊构建去中心化可信交易技术魅力.智能合约其实是"执行合 ...

  5. NEO智能合约开发(二)再续不可能的任务

      NEO智能合约开发中,应用合约比较简单,是的你没看错,应用合约比较简单. 应用合约三部曲,发布.调用.看结果.除了看结果工具比较缺乏,发布调用neogui最起码可以支撑你测试.   鉴权合约比较麻 ...

  6. 搭建智能合约开发环境Remix IDE及使用

    目前开发智能的IDE, 首推还是Remix, 而Remix官网, 总是由于各种各样的(网络)原因无法使用,本文就来介绍一下如何在本地搭建智能合约开发环境remix-ide并介绍Remix的使用. 写在 ...

  7. [转] 智能合约开发环境搭建及Hello World合约

    [From] http://www.cnblogs.com/tinyxiong/p/7898599.html 如果你对于以太坊智能合约开发还没有概念(本文会假设你已经知道这些概念),建议先阅读入门篇. ...

  8. EOS智能合约开发(四):智能合约部署及调试(附编程示例)

    EOS智能合约开发(一):EOS环境搭建和创建节点 EOS智能合约开发(二):EOS创建和管理钱包 EOS智能合约开发(三):EOS创建和管理账号 部署智能合约的示例代码如下: $ cleos set ...

  9. EOS智能合约开发(三):EOS创建和管理账号

    没有看前面文章的小伙伴可以看一下 EOS智能合约开发(一):EOS环境搭建和启动节点 EOS智能合约开发(二):EOS创建和管理钱包 创建好钱包.密钥之后,接下来你就可以创建账号了,账号是什么?账号保 ...

  10. 以太坊智能合约开发,Web3.js API 中文文档 ethereum web3.js入门说明

    以太坊智能合约开发,Web3.js API 中文文档 ethereum web3.js入门说明 为了让你的Ðapp运行上以太坊,一种选择是使用web3.js library提供的web3.对象.底层实 ...

随机推荐

  1. Ubuntu22.04 安装单机版kubernetes

    前言 上期讲到要实现.net 6框架下的EF Core操作数据库基本增删改查,没有及时兑现.没有兑现的原因就是因为安装kubernetes.安装kubernetes的过程是灾难性的,也是十分顺利的.灾 ...

  2. v8 setup

    记录下笔者本人搭建v8环境的过程 环境:处于一些原因笔者选择在kali2023上搭建v8,kali上可以搭建成功但是调试脚本加载有问题,fuck kali,还是ubuntu好,笔者使用了ubuntu2 ...

  3. C端用户体验度量实战篇-京东快递小程序体验度量全面升级

    本文通过介绍体验度量模型升级研究过程.研究方法及研究结果等内容,结合实际C端产品应用,观测新模型运行周期的表现,验证了其在高速发展的业务形态和日益变化的用户需求上的适用性和有效性.我们从体验价值为导向 ...

  4. 使用 Easysearch 还原 Elasticsearch 快照数据

    本文主要验证 Elasticsearch 快照在 Easysearch 中进行数据恢复. 准备测试数据 索引 别名 模版 生命周期策略 创建快照 PUT /_snapshot/my_backup { ...

  5. 4. DI相关内容

    我们先来思考 向一个类中传递数据的方式有几种? 普通方法(set 方法) 构造方法 依赖注入描述了在容器中建立 bean 与 bean 之间的依赖关系的过程,如果 bean 运行需要的是数字或字符串呢 ...

  6. 这问题巧了,SpringMVC 不同参数处理机制引发的思考

    这个问题非常有趣,不是SpringMVC 的问题,是实际开发中混合使用了两种请求方式暴露出来的. 问题场景 功能模块中,提供两个 Http 服务.一个是列表查询(application/json 请求 ...

  7. Redis数据类型之Stream系列一

    一:Stream简介 ​ Redis Stream是5.0版本之后新增的一种数据结构,其结构类似于'仅追加日志'.但也实现了多种操作来克服'仅追加日志'的一些限制,如读取策略(xread,xrange ...

  8. hexo博客生成报错YAMLException: can not read a block mapping entry

    报错信息: YAMLException: can not read a block mapping entry; a multiline key may not b --- title: [转]--I ...

  9. Avalonia中用FluentAvalonia+DialogHost.Avalonia实现界面弹窗和对话框

    Avalonia中用FluentAvalonia+DialogHost.Avalonia实现界面弹窗和对话框 本文是项目中关于 弹窗界面 设计的技术分享,通过 FluentAvalonia+Dialo ...

  10. web系统字典统一中文翻译问题

    几乎每个web系统都离不开各种状态码.订单新建,待支付,未支付,已支付,待发货. 消息已读未读,任务待标记待审批已审批待流转已完成未完成.等等. 复杂一点的,会有多级状态码. 状态码超出3个的,一般都 ...