Fabric 2.x 智能合约开发记录

fabric,智能,合约,开发,记录 · 浏览次数 : 104

小编点评

**问题原因:** 根据您提供的信息, `func create(ctx contractapi.TransactionContextInterface, payload string) (string, error)` 的返回值格式与 `func create(ctx contractapi.TransactionContextInterface, payload string) ([]byte, error)` 的期望格式不同。 **正常接口的期望返回值格式是:** ```go func create(ctx contractapi.TransactionContextInterface, payload string) ([]byte, error) ``` 其中 `([]byte, error)` 表示返回值类型为字节数组和错误类型的元数据。 **示例化时出现错误的原因:** 由于您使用的是 `github.com/hyperledger/fabric-contract-api-go/contractapi` 的版本,该库在 `func create(ctx contractapi.TransactionContextInterface, payload string) (string, error)` 中进行了类型检查,并发现 `payload` 的类型不符合 `([]byte, error)` 的要求。 **解决方案:** 为了解决该问题,您可以将 `payload` 的类型转换为 `[]byte`,并在接口定义中声明返回值类型为 `[]byte`。例如: ```go func create(ctx contractapi.TransactionContextInterface, payload string) ([]byte, error) { return []byte(payload), nil } ``` **其他建议:** * 确保您使用的是与您使用的 Fabric 版本兼容的版本。 * 检查您使用的库版本是否支持您使用的 Fabric 版本。 * 如果您仍然遇到问题,请检查 Fabric 项目的官方文档或社区论坛。

正文

表象: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 智能合约开发记录相似的内容:

Fabric 2.x 智能合约开发记录

表象:Return schema invalid. required items must be unique [recovered] 虽然 Fabric v2.2 已经发布了很久了,但之前因为项目历史问题,一直使用的都是 Fabric v1.4.8,所以智能合约也一直使用的都是 github.co

Fabric区块链浏览器(2)

本文是区块链浏览器系列的第四篇。 在[上一篇文章](https://mengbin.top/2023-08-13-blockBrowser/)介绍如何解析区块数据时,使用`session`对客户端上传的pb文件进行区分,到期后自动删除。 在这片文章中,会着重介绍下认证系统的实现,主要分为三部分: -

从源码中解析fabric区块数据结构(一)

从源码中解析fabric区块数据结构(一) 前言 最近打算基于fabric-sdk-go实现hyperledger fabric浏览器,其中最重要的一步就是解析fabric的上链区块。虽说fabric是Golang实现的,但直到2021年2月1号才发布了第一个稳定版fabric-sdk-go,而且官

Fabric配置块结构解析

本文是区块链浏览器系列的第二篇。 上一篇介绍了交易块中的数据结构,这一篇介绍区块链网络中的配置块数据结构。 这两种区块中数据结构内容的区别主要Payload结构体中的Data域中的内容,接下来将以类图的形式来解析Data域包含的信息: classDiagram class Payload{ Head

Fabric区块链浏览器(1)

本文是区块链浏览器系列的第三篇,本文介绍区块链浏览器的主体部分,即区块数据的解析。 这一版本的[区块链浏览器](https://github.com/mengbin92/browser/tree/gin)是基于[gin](https://github.com/gin-gonic/gin)实现的,只提

Fabric区块链浏览器(3)

本文是区块链浏览器系列的第五篇,项目完整代码在[这里](https://github.com/mengbin92/browser/tree/main)。 在[上一篇文章](https://mengbin.top/2023-08-20-browser2/)中给浏览器增加了简单的用户认证,至此浏览器的基

【Azure Service Fabric】关于Service Fabric的相关问题

问题一:Service Fabric 是否支持Private Link? 在Azure Private Endpoint文档中,罗列出了 Azure 上支持 Private Link 的服务。Service Fabric不在其中。 Azure Private Link availability :h

Hyperledger Fabric系统链码介绍

在Hyperledger Fabric中,LSCC(Lifecycle System Chaincode)、CSCC(Chaincode System Chaincode)、QSCC(Query System Chaincode)、ESCC(Endorsement System Chaincode)

【Azure Fabric Service】Service Fabric 托管群集通过 Connect-ServiceFabricCluster 连接时候报错 CertificatedNotMatched

问题描述 Service Fabric 托管群集, 使用Key Vault中证书,把证书导入到本地安装后,使用该证书的 Thumbprint 作为指令 Connect-ServiceFabricCluster 的 ServerCertThumbprint 和FindValue 的值。结果连接失败,错

[转帖]至强SP简析、FPGA及Fabric版本揭秘

https://zhuanlan.zhihu.com/p/387076957 作者注:在英特尔推出至强可扩展处理器(Skylake)及平台当天到一周之内,我先后发表了图说和架构解析的文章,又在2017年8月9日以此文对新至强产品线构成进行比较详细的介绍。 某冰冰曾经说过:我能承受多大的诋毁,就能承受