Fabric:关于链码的编写及部署的问题记录

2024-08-21 14:36

本文主要是介绍Fabric:关于链码的编写及部署的问题记录,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

本篇主要记录里在链码的编写及配置过程中遇到的问题及解决方法。

1. Init方法

  在Hyperledger Fabric中,链码的Init()方法是一个可选的方法,它主要用于链码实例化时执行一些初始化操作。如果希望账本的初始化方法可以在链码部署完成时执行,则可以将相关方法的执行放到Init()方法中。举例如下:

func (s *SmartContract) Init(ctx contractapi.TransactionContextInterface) error {//账本初始化操作err := s.InitLedger(ctx)if err != nil {return err}return nil
}
func (s *SmartContract) InitLedger(ctx contractapi.TransactionContextInterface) error {assets := []Asset{{ID: "asset1", Color: "blue", Size: 5, Owner: "Tomoko", AppraisedValue: 300},{ID: "asset2", Color: "red", Size: 5, Owner: "Brad", AppraisedValue: 400},{ID: "asset3", Color: "green", Size: 10, Owner: "Jin Soo", AppraisedValue: 500},{ID: "asset4", Color: "yellow", Size: 10, Owner: "Max", AppraisedValue: 600},{ID: "asset5", Color: "black", Size: 15, Owner: "Adriana", AppraisedValue: 700},{ID: "asset6", Color: "white", Size: 15, Owner: "Michel", AppraisedValue: 800},}for _, asset := range assets {assetJSON, err := json.Marshal(asset)if err != nil {return err}err = ctx.GetStub().PutState(asset.ID, assetJSON)if err != nil {return fmt.Errorf("failed to put to world state. %v", err)}}return nil
}

但关于这种写法,有以下几点需要说明:

  • 这种利用Init()方法进行账本初始化的操作不一定能生效,在用Fabric-gateway-go调用链码时能生效,但使用Peer CLI调用链码时不生效,仍然需要使用peer invoke命令执行InitLedger方法。原因暂时不明。
  • 虽然在fabric-contract-api-go的官方文档中的Init方法的返回类型为peer.Response。假如按照这种返回类型编写Init写法,具体如下:
func (s *SmartContract) Init(ctx contractapi.TransactionContextInterface) peer.Response {err := s.InitLedger(ctx)if err != nil {return peer.Response{Status:500,Message: "账本初始化失败",}}return peer.Response{Status:200,Message: "账本初始化成功",}
}

则在链码部署时会提示如下错误: Error creating business chaincode: Cannot use metadata. Metadata did not match schema:components.schemas..required: Array must have at least 1 items(需要进入链码所在的docker容器中才能该错误提示信息)

2. 链码返回类型

如果希望链码返回由多个JSON串组成的数组时,如果用[][]byte,则可能产生Error: endorsement failure during query. response: status:500 message:"Error handling success response. Value did not match schema:\n1. return: Invalid type. Expected: array, given: string" 。这种情况下,最后将返回类型改成[]string。具体案例如下:

func (s *SmartContract) GetTableAllItems(ctx contractapi.TransactionContextInterface, tableName string) ([]string, error) {query := `{"selector":{"docType":"` + tableName + `"}}`resultsIterator, err := ctx.GetStub().GetQueryResult(query)if err != nil {return nil, err}defer resultsIterator.Close()var tableItems []stringfor resultsIterator.HasNext() {queryResponse, err := resultsIterator.Next()if err != nil {return nil, err}tableItems = append(tableItems, string(queryResponse.Value))}return tableItems, nil
}

3. Struct、byte和string等的互相转换

  在Hyperledger Fabric的链码编写中,通常都遇到JSON串的编码、解码等问题,这里就涉及到很多bytestring及其数组的相互转换问题。这里就以简单的go语言代码为例做一个简单的说明。

3.1 Struct转化为JSON串和string类型

Go语言中用[]byte表示JSON串。从Struct变量到JSON串和string类型的转换举例如下:

package mainimport ("encoding/json""fmt"
)type User struct {UserID string `json:"customerID"`Name   string `json:"name"`Age    int    `json:"age"`Email  string `json:"email"`
}func main() {usersList := []User{{UserID: "user1", Name: "Alice", Age: 25, Email: "alice@example.com"},{UserID: "user2", Name: "Bob", Age: 30, Email: "bob@example.com"},{UserID: "user3", Name: "Charlie", Age: -5, Email: "charlie@example.com"},{UserID: "user4", Name: "David", Age: 40, Email: "david@@example.com"},{UserID: "user5", Name: "Eve", Age: 35, Email: "eve@example,com"},}//将Struct数组转换成JSON串,返回类型为[]byteuserListJson, err := json.Marshal(usersList)if err != nil {fmt.Println(err)}//将[]byte转换为stringfmt.Println(string(userListJson))//将单独的Struct变量转换成JSON串,返回类型仍然为[]byteuserJson, err := json.Marshal(usersList[0])fmt.Println(string(userJson))
}

代码执行结果如下:

[{"customerID":"user1","name":"Alice","age":25,"email":"alice@example.com"},{"customerID":"user2","name":"Bob","age":30,"email":"bob@example.com"},{"customerID":"user3","name":"Charlie","age":-5,"email":"charlie@example.com"},{"customerID":"user4","name":"David","age":40,"email":"david@@example.com"},{"customerID":"user5","name":"Eve","age":35,"email":"eve@example,com"}]
{"customerID":"user1","name":"Alice","age":25,"email":"alice@example.com"}

从上述代码中可以看到,无论是单独的Struct变量还是Struct变量组成的数组,使用json.Marshal()方法生成的JSON串都是[]byte类型。

3.2 JSON串转化为Struct变量

这里先用string类型保存JSON串,再转化为Struct变量。其具体代码如下:

package mainimport ("encoding/json""fmt"
)type User struct {UserID    string `json:"customerID"`UserName  string `json:"name"`UserAge   int    `json:"age"`UserEmail string `json:"email"`
}func main() {userString := `[{"customerID":"user1","name":"Alice","age":25,"email":"alice@example.com"},{"customerID":"user2","name":"Bob","age":30,"email":"bob@example.com"}]`userJSON := []byte(userString)var user []Usererr := json.Unmarshal(userJSON, &user)if err != nil {fmt.Println(err)}fmt.Println(user)
}

其代码执行结果如下:

[{user1 Alice 25 alice@example.com} {user2 Bob 30 bob@example.com}]

3.3 json.Indent方法

在Go语言中,json.Indent是一个非常有用的函数,用于将原本压缩或者未格式化的JSON数据进行缩进处理,使其更加易读。它将JSON数据格式化为带有缩进和换行的形式,方便进行调试或展示。

package mainimport ("bytes""encoding/json""fmt"
)func main() {userString := `[{"customerID":"user1","name":"Alice","age":25,"email":"alice@example.com"},{"customerID":"user2","name":"Bob","age":30,"email":"bob@example.com"}]`userJSON := []byte(userString)var prettyJSON bytes.Buffererr := json.Indent(&prettyJSON, userJSON, "", "  ")if err != nil {fmt.Println(err)}fmt.Println(prettyJSON.String())
}

其代码执行结果如下:

[{"customerID": "user1","name": "Alice","age": 25,"email": "alice@example.com"},{"customerID": "user2","name": "Bob","age": 30,"email": "bob@example.com"}
]

这篇关于Fabric:关于链码的编写及部署的问题记录的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1093438

相关文章

闲置电脑也能活出第二春?鲁大师AiNAS让你动动手指就能轻松部署

对于大多数人而言,在这个“数据爆炸”的时代或多或少都遇到过存储告急的情况,这使得“存储焦虑”不再是个别现象,而将会是随着软件的不断臃肿而越来越普遍的情况。从不少手机厂商都开始将存储上限提升至1TB可以见得,我们似乎正处在互联网信息飞速增长的阶段,对于存储的需求也将会不断扩大。对于苹果用户而言,这一问题愈发严峻,毕竟512GB和1TB版本的iPhone可不是人人都消费得起的,因此成熟的外置存储方案开

好题——hdu2522(小数问题:求1/n的第一个循环节)

好喜欢这题,第一次做小数问题,一开始真心没思路,然后参考了网上的一些资料。 知识点***********************************无限不循环小数即无理数,不能写作两整数之比*****************************(一开始没想到,小学没学好) 此题1/n肯定是一个有限循环小数,了解这些后就能做此题了。 按照除法的机制,用一个函数表示出来就可以了,代码如下

hdu1043(八数码问题,广搜 + hash(实现状态压缩) )

利用康拓展开将一个排列映射成一个自然数,然后就变成了普通的广搜题。 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#inclu

阿里开源语音识别SenseVoiceWindows环境部署

SenseVoice介绍 SenseVoice 专注于高精度多语言语音识别、情感辨识和音频事件检测多语言识别: 采用超过 40 万小时数据训练,支持超过 50 种语言,识别效果上优于 Whisper 模型。富文本识别:具备优秀的情感识别,能够在测试数据上达到和超过目前最佳情感识别模型的效果。支持声音事件检测能力,支持音乐、掌声、笑声、哭声、咳嗽、喷嚏等多种常见人机交互事件进行检测。高效推

购买磨轮平衡机时应该注意什么问题和技巧

在购买磨轮平衡机时,您应该注意以下几个关键点: 平衡精度 平衡精度是衡量平衡机性能的核心指标,直接影响到不平衡量的检测与校准的准确性,从而决定磨轮的振动和噪声水平。高精度的平衡机能显著减少振动和噪声,提高磨削加工的精度。 转速范围 宽广的转速范围意味着平衡机能够处理更多种类的磨轮,适应不同的工作条件和规格要求。 振动监测能力 振动监测能力是评估平衡机性能的重要因素。通过传感器实时监

缓存雪崩问题

缓存雪崩是缓存中大量key失效后当高并发到来时导致大量请求到数据库,瞬间耗尽数据库资源,导致数据库无法使用。 解决方案: 1、使用锁进行控制 2、对同一类型信息的key设置不同的过期时间 3、缓存预热 1. 什么是缓存雪崩 缓存雪崩是指在短时间内,大量缓存数据同时失效,导致所有请求直接涌向数据库,瞬间增加数据库的负载压力,可能导致数据库性能下降甚至崩溃。这种情况往往发生在缓存中大量 k

6.1.数据结构-c/c++堆详解下篇(堆排序,TopK问题)

上篇:6.1.数据结构-c/c++模拟实现堆上篇(向下,上调整算法,建堆,增删数据)-CSDN博客 本章重点 1.使用堆来完成堆排序 2.使用堆解决TopK问题 目录 一.堆排序 1.1 思路 1.2 代码 1.3 简单测试 二.TopK问题 2.1 思路(求最小): 2.2 C语言代码(手写堆) 2.3 C++代码(使用优先级队列 priority_queue)

Node.js学习记录(二)

目录 一、express 1、初识express 2、安装express 3、创建并启动web服务器 4、监听 GET&POST 请求、响应内容给客户端 5、获取URL中携带的查询参数 6、获取URL中动态参数 7、静态资源托管 二、工具nodemon 三、express路由 1、express中路由 2、路由的匹配 3、路由模块化 4、路由模块添加前缀 四、中间件

【VUE】跨域问题的概念,以及解决方法。

目录 1.跨域概念 2.解决方法 2.1 配置网络请求代理 2.2 使用@CrossOrigin 注解 2.3 通过配置文件实现跨域 2.4 添加 CorsWebFilter 来解决跨域问题 1.跨域概念 跨域问题是由于浏览器实施了同源策略,该策略要求请求的域名、协议和端口必须与提供资源的服务相同。如果不相同,则需要服务器显式地允许这种跨域请求。一般在springbo

题目1254:N皇后问题

题目1254:N皇后问题 时间限制:1 秒 内存限制:128 兆 特殊判题:否 题目描述: N皇后问题,即在N*N的方格棋盘内放置了N个皇后,使得它们不相互攻击(即任意2个皇后不允许处在同一排,同一列,也不允许处在同一斜线上。因为皇后可以直走,横走和斜走如下图)。 你的任务是,对于给定的N,求出有多少种合法的放置方法。输出N皇后问题所有不同的摆放情况个数。 输入