表象: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. JVM系统参数

    JVM(Java虚拟机)是Java程序的运行环境,它可以通过一些系统参数进行配置和优化.以下是一些常用的JVM系统参数: 1. -Xmx: 用于设置JVM堆的最大内存大小.例如,-Xmx1g表示将堆的 ...

  2. 在SQL中将特定的数据始终排在第一行

    将特定的数据始终排在第一行 第一种方式: select * from ( select Id,1 num from InquiryPurchaseProduct where Id = 50 union ...

  3. 使用containerd从0搭建k8s(kubernetes)集群

    准备环境 准备两台服务器节点,如果需要安装虚拟机,可以参考<wmware和centos安装过程> 机器名 IP 角色 CPU 内存 centos01 192.168.109.130 mas ...

  4. xpoc漏洞使用与编写 浅尝

    下载地址 https://github.com/chaitin/xpoc/releases 目前最新版本是 0.0.4 可能是我还是不太习惯yaml这种结构的,感觉就很反人类,所以我以前一般都还是po ...

  5. 基于 canal 的 RDS Mysql 数据实时同步到 Es 服务器

    背景 考虑到我们的数据在密码变大,与数据分析的需求,前面我们是一直在使用 Sphinx 来做全文搜索.主要也是这块我们也没有更为核心的Sphinx 开发人员,从而我们在这块的使用上,一直都还是还有比较 ...

  6. Python异步编程之web框架 异步vs同步 Redis并发对比

    测试基本信息 主题:比较异步框架和同步框架在RedisIO操作的性能差异 python版本:python 3.8 数据库:redis 5.0.7 压测工具:locust web框架:同步:flask ...

  7. @Document元注解的使用

    @Documented注解标记的元素,Javadoc工具会将此注解标记元素的注解信息包含在javadoc中.默认,注解信息不会包含在Javadoc中.示例如下: 声明Book注解,并使用@Docume ...

  8. idea设置字体大小(换主题后的字体大小设置)

    如果你是默认主题 直接这样设置字体大小 如果你换了自定义主题 如果你换了自定义主题,那么上面的设置方法会没有作用,我们需要像下面这样设置:

  9. 安装VMware Workstation 16 Pro

    下载 官网:https://www.vmware.com/cn/products/workstation-pro/workstation-pro-evaluation.html 注:我是在新毒霸软件管 ...

  10. docker ps --no-trunc 与 docker ps

    转载请注明出处: docker ps --no-trunc与docker ps之间的区别在于输出结果的格式. docker ps: 默认情况下,docker ps命令以截断的方式显示结果.这意味着容器 ...